Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/Math/src/WikiTexVC/Mhchem/MhchemPatterns.php
Ðазад
<?php /** * Copyright (c) 2023 Johannes Stegmüller * * This file is a port of mhchemParser originally authored by Martin Hensel in javascript/typescript. * The original license for this software can be found in the accompanying LICENSE.mhchemParser-ts.txt file. */ declare( strict_types = 1 ); namespace MediaWiki\Extension\Math\WikiTexVC\Mhchem; use MediaWiki\Extension\Math\WikiTexVC\Mhchem\MhchemRegExp as Reg; use RuntimeException; /** * Contains all matching regex patterns and match functions for mhchemParser in PHP. * * corresponds mostly to the 'patterns' array in line ~207 in mhchemParser.js by Martin Hensel * * @author Johannes Stegmüller * @license GPL-2.0-or-later */ class MhchemPatterns { /** @var array */ private array $patterns; /** * Matching patterns * either regexes or function that return null or {match_:"a", remainder:"bc"} * @return array */ public function getPatterns(): array { return $this->patterns; } /** * @param string $input * @param string|Reg $begExcl * @param string|Reg $begIncl * @param mixed|null $endIncl * @param mixed|null $endExcl * @param string|Reg|null $beg2Excl * @param string|Reg|null $beg2Incl * @param mixed|null $end2Incl * @param mixed|null $end2Excl * @param bool|null $combine */ public function findObserveGroups( $input, $begExcl, $begIncl, $endIncl, $endExcl = null, $beg2Excl = null, $beg2Incl = null, $end2Incl = null, $end2Excl = null, $combine = null ): ?array { $match = $this->matchObsGrInner( $input, $begExcl ); if ( $match === null ) { return null; } $input = substr( $input, strlen( $match ) ); $match = $this->matchObsGrInner( $input, $begIncl ); if ( $match === null ) { return null; } if ( $endIncl === "0" ) { throw new RuntimeException( "error in condition, check next loc " ); } $e = $this->findObserveGroupsInner( $input, strlen( $match ), MhchemUtil::issetJS( $endIncl ) ? $endIncl : $endExcl ); if ( $e === null ) { return null; } $match1 = substr( $input, 0, ( $endIncl ? $e["endMatchEnd"] : $e["endMatchBegin"] ) ); if ( !( MhchemUtil::issetJS( $beg2Excl ) || MhchemUtil::issetJS( $beg2Incl ) ) ) { return [ "match_" => $match1, "remainder" => substr( $input, $e["endMatchEnd"] ) ]; } else { $group2 = $this->findObserveGroups( substr( $input, $e["endMatchEnd"] ), $beg2Excl, $beg2Incl, $end2Incl, $end2Excl ); if ( $group2 === null ) { return null; } $matchRet = [ $match1, $group2["match_"] ]; return [ "match_" => ( $combine ? implode( "", $matchRet ) : $matchRet ), "remainder" => $group2["remainder"] ]; } } /** * @param string $input * @param string|Reg $pattern * @return string|null */ private function matchObsGrInner( string $input, $pattern ) { /** * In javascript this is checking if the incoming pattern is a string, * if not the assumption is that it is of regex type. Since PHP has * strings here. */ if ( !$pattern instanceof Reg ) { // Added this if to catch empty needle for strpos input in PHP if ( !MhchemUtil::issetJS( $pattern ) || str_starts_with( $input, $pattern ) ) { return $pattern; } } elseif ( preg_match( $pattern->getRegExp(), $input, $matches ) ) { return $matches[0]; } return null; } /** * @param string $input * @param int $i * @param string $endChars * @return array|null */ private function findObserveGroupsInner( string $input, $i, $endChars ): ?array { $braces = 0; while ( $i < strlen( $input ) ) { $a = $input[$i]; $match = $this->matchObsGrInner( substr( $input, $i ), $endChars ); if ( $match !== null && $braces === 0 ) { return [ "endMatchBegin" => $i, "endMatchEnd" => $i + strlen( $match ) ]; } elseif ( $a === "{" ) { $braces++; } elseif ( $a === "}" ) { if ( $braces === 0 ) { // Unexpected character throw new RuntimeException( "ExtraCloseMissingOpen: Extra close brace or missing open brace" ); } else { $braces--; } } $i++; } return null; } public function __construct() { $this->patterns = [ 'empty' => new Reg( "/^$/" ), 'else' => new Reg( "/^./" ), 'else2' => new Reg( "/^./" ), 'space' => new Reg( "/^\s/" ), 'space A' => new Reg( "/^\s(?=[A-Z\\\\$])/" ), 'space$' => new Reg( "/^\s$/" ), 'a-z' => new Reg( "/^[a-z]/" ), 'x' => new Reg( "/^x/" ), 'x$' => new Reg( "/^x$/" ), 'i$' => new Reg( "/^i$/" ), 'letters' => new Reg( "/^(?:[a-zA-Z\x{03B1}-\x{03C9}\x{0391}-\x{03A9}?@]|(?:\\\\(?:alpha|beta|gamma|delta|epsilon" . "|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma" . "|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/u" ), '\\greek' => new Reg( "/^\\\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi" . "|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)" . "(?:\s+|\{\}|(?![a-zA-Z]))/" ), 'one lowercase latin letter $' => new Reg( "/^(?:([a-z])(?:$|[^a-zA-Z]))$/" ), '$one lowercase latin letter$ $' => new Reg( "/^\\\$(?:([a-z])(?:$|[^a-zA-Z]))\\\$$/" ), 'one lowercase greek letter $' => new Reg( "/^(?:\\\$?[\x{003B1}-\x{0003C9}]\\\$?|\\\$?\\\\(?:alpha|beta|gamma|" . "delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|" . "phi|chi|psi|omega)\s*\\\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/u" ), 'digits' => new Reg( "/^[0-9]+/" ), '-9.,9' => new Reg( "/^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/" ), '-9.,9 no missing 0' => new Reg( "/^[+\-]?[0-9]+(?:[.,][0-9]+)?/" ), '(-)(9.,9)(e)(99)' => static function ( $input ) { $matches = []; $match = preg_match( "/^(\+\-|\+\/\-|\+|\-|\\\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|" . "[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:(?:([eE])" . "|\s*(\*|x|\\\\times|\x{00D7})\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/u", $input, $matches ); if ( $match && $matches[0] ) { // could also match "" return [ "match_" => array_slice( $matches, 1 ), "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } return null; }, '(-)(9)^(-9)' => new Reg( "/^(\+\-|\+\/\-|\+|\-|\\\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|" . "[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/" ), 'state of aggregation $' => function ( $input ) { // ... or crystal system $a = $this->findObserveGroups( $input, "", new Reg( "/^\([a-z]{1,3}(?=[\),])/" ), ")", "" ); if ( $a && preg_match( "/^($|[\s,;\)\]\}])/", $a["remainder"] ) ) { return $a; } $matches = []; $match = preg_match( "/^(?:\((?:\\\\ca\s?)?\\\$[amothc]\\\$\))/", $input, $matches ); if ( $match ) { return [ "match_" => $matches[0], "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } return null; }, '_{(state of aggregation)}$' => new Reg( "/^_\{(\([a-z]{1,3}\))\}/" ), '{[(' => new Reg( "/^(?:\\\{|\[|\()/" ), ')]}' => new Reg( "/^(?:\)|\]|\\\})/" ), ', ' => new Reg( "/^[,;]\s*/" ), ',' => new Reg( "/^[,;]/" ), '.' => new Reg( "/^[.]/" ), '. __* ' => new Reg( "/^([.\x{22C5}\x{00B7}\x{2022}]|[*])\s*/u" ), '...' => new Reg( "/^\.\.\.(?=$|[^.])/" ), '^{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "^{", "", "", "}" ); }, '^($...$)' => function ( $input ) { return $this->findObserveGroups( $input, "^", "$", "$", "" ); }, '^a' => new Reg( "/^\^([0-9]+|[^\\\_])/u" ), '^\\x{}{}' => function ( $input ) { return $this->findObserveGroups( $input, "^", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "", "", "{", "}", "", true ); }, '^\\x{}' => function ( $input ) { return $this->findObserveGroups( $input, "^", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "" ); }, '^\\x' => new Reg( "/^\^(\\\\[a-zA-Z]+)\s*/" ), '^(-1)' => new Reg( "/^\^(-?\d+)/" ), '\'' => new Reg( "/^'/" ), '_{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "_{", "", "", "}" ); }, '_($...$)' => function ( $input ) { return $this->findObserveGroups( $input, "_", "$", "$", "" ); }, '_9' => new Reg( "/^_([+\-]?[0-9]+|[^\\\\])/" ), '_\\x{}{}' => function ( $input ) { return $this->findObserveGroups( $input, "_", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "", "", "{", "}", "", true ); }, '_\\x{}' => function ( $input ) { return $this->findObserveGroups( $input, "_", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "" ); }, '_\\x' => new Reg( "/^_(\\\\[a-zA-Z]+)\s*/" ), '^_' => new Reg( "/^(?:\^(?=_)|\_(?=\^)|[\^_]$)/" ), '{}^' => new Reg( "/^\{\}(?=\^)/" ), '{}' => new Reg( "/^\{\}/" ), '{...}' => function ( $input ) { return $this->findObserveGroups( $input, "", "{", "}", "" ); }, '{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "{", "", "", "}" ); }, '$...$' => function ( $input ) { return $this->findObserveGroups( $input, "", "\$", "\$", "" ); }, '${(...)}$__$(...)$' => function ( $input ) { return $this->findObserveGroups( $input, "\${", "", "", "}\$" ) ?? $this->findObserveGroups( $input, "\$", "", "", "\$" ); }, '=<>' => new Reg( "/^[=<>]/" ), '#' => new Reg( "/^[#\x{2261}]/u" ), '+' => new Reg( "/^\+/" ), // -space -, -; -] -/ -$ -state-of-aggregation orig: "/^-(?=[\s_},;\]/]|$|\([a-z]+\))/" '-$' => new Reg( "/^-(?=[\s_},;\]\/]|$|\([a-z]+\))/u" ), '-9' => new Reg( "/^-(?=[0-9])/" ), '- orbital overlap' => new Reg( "/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/" ), '-' => new Reg( "/^-/" ), 'pm-operator' => new Reg( "/^(?:\\\\pm|\\\$\\\\pm\\\$|\+-|\+\/-)/" ), 'operator' => new Reg( "/^(?:\+|(?:[\-=<>]|<<|>>|\\\\approx|\\\$\\\\approx\\\$)(?=\s|$|-?[0-9]))/" ), 'arrowUpDown' => new Reg( "/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/" ), '\\bond{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\bond{", "", "", "}" ); }, '->' => new Reg( '/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\x{2192}\x{27F6}\x{21CC}])/u' ), 'CMT' => new Reg( "/^[CMT](?=\[)/" ), '[(...)]' => function ( $input ) { return $this->findObserveGroups( $input, "[", "", "", "]" ); }, '1st-level escape' => new Reg( "/^(&|\\\\\\\\|\\\\hline)\s*/" ), // \\x - but output no space before '\\,' => new Reg( "/^(?:\\\\[,\ ;:])/" ), '\\x{}{}' => function ( $input ) { return $this->findObserveGroups( $input, "", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "", "", "{", "}", "", true ); }, '\\x{}' => function ( $input ) { return $this->findObserveGroups( $input, "", new Reg( "/^\\\\[a-zA-Z]+\{/" ), "}", "" ); }, '\\ca' => new Reg( "/^\\\\ca(?:\s+|(?![a-zA-Z]))/" ), '\\x' => new Reg( "/^(?:\\\\[a-zA-Z]+\s*|\\\\[_&{}%])/" ), // only those with numbers in front, because the others will be formatted correctly anyway 'orbital' => new Reg( "/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/" ), 'others' => new Reg( "/^[\/~|]/" ), '\\frac{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\frac{", "", "", "}", "{", "", "", "}" ); }, '\\overset{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\overset{", "", "", "}", "{", "", "", "}" ); }, '\\underset{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\underset{", "", "", "}", "{", "", "", "}" ); }, '\\underbrace{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\underbrace{", "", "", "}_", "{", "", "", "}" ); }, '\\color{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\color{", "", "", "}" ); }, '\\color{(...)}{(...)}' => function ( $input ) { // ?? instead of || return $this->findObserveGroups( $input, "\\color{", "", "", "}", "{", "", "", "}" ) ?? $this->findObserveGroups( $input, "\\color", "\\", "", new Reg( "/^(?=\{)/" ), "{", "", "", "}" ); }, '\\ce{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\ce{", "", "", "}" ); }, '\\pu{(...)}' => function ( $input ) { return $this->findObserveGroups( $input, "\\pu{", "", "", "}" ); }, 'oxidation$' => new Reg( "/^(?:[+-][IVX]+|(?:\\\\pm|\\\$\\\\pm\\\$|\+-|\+\/-)\s*0)$/" ), 'd-oxidation$' => new Reg( "/^(?:[+-]?[IVX]+|(?:\\\\pm|\\\$\\\\pm\\\$|\+-|\+\/-)\s*0)$/" ), '1/2$' => new Reg( "/^[+\-]?(?:[0-9]+|\\\$[a-z]\\\$|[a-z])\/[0-9]+(?:\\\$[a-z]\\\$|[a-z])?$/" ), 'amount' => function ( $input ) { $matches = []; // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing $match = preg_match( "/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\\\$[a-z]\\\$" . "|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)" . "|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/", $input, $matches ); if ( $match ) { return [ "match_" => $matches[0], "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } $a = $this->findObserveGroups( $input, "", "$", "$", "" ); // e.g. $2n-1$, $-$ if ( MhchemUtil::issetJS( $a ) ) { $matchesI = []; $match = preg_match( "/^\\\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])" . "?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\\\$$/", $a["match_"] ?? "", $matchesI ); if ( $match ) { return [ "match_" => $matchesI[0], "remainder" => substr( $input, strlen( $matchesI[0] ) ) ]; } } return null; }, 'amount2' => function ( $input ) { /* @phan-suppress-next-line PhanInfiniteRecursion, PhanUndeclaredInvokeInCallable */ return $this->patterns['amount']( $input ); }, '(KV letters),' => new Reg( "/^(?:[A-Z][a-z]{0,2}|i)(?=,)/" ), 'formula$' => static function ( $input ) { if ( preg_match( "/^\([a-z]+\)$/", $input ) ) { // state of aggregation = no formula return null; } $matches = []; $match = preg_match( "/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|" . "(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/", $input, $matches ); if ( $match ) { return [ "match_" => $matches[0], "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } return null; }, 'uprightEntities' => new Reg( "/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/" ), '/' => new Reg( "/^\s*(\/)\s*/" ), '//' => new Reg( "/^\s*(\/\/)\s*/" ), '*' => new Reg( "/^\s*[*.]\s*/" ) ]; } /** * Matching function * e.g. match("a", input) will look for the regexp called "a" and see if it matches * returns null or {match_:"a", remainder:"bc"} * @param string $m key for fetching a pattern * @param string $input string to check * @return array|mixed|null information about the match */ public function match( string $m, string $input ) { $pattern = $this->patterns[$m] ?? null; if ( !$pattern ) { // Trying to use non-existing pattern throw new RuntimeException( "MhchemBugP: mhchem bug P. Please report. (" . $m . ")" ); } elseif ( $pattern instanceof Reg ) { $matches = []; $match = preg_match( $pattern->getRegExp(), $input, $matches ); if ( $match ) { if ( count( $matches ) > 2 ) { return [ "match_" => array_slice( $matches, 1 ), "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } else { return [ "match_" => MhchemUtil::issetJS( $matches[1] ?? null ) ? $matches[1] : $matches[0], "remainder" => substr( $input, strlen( $matches[0] ) ) ]; } } return null; } elseif ( is_callable( $pattern ) ) { // $pattern cannot be an instance of MhchemRegExp here, which causes this warning. /* @phan-suppress-next-line PhanUndeclaredInvokeInCallable */ return $this->patterns[$m]( $input ); } else { return null; } } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка