forked from GNUsocial/gnu-social
		
	
		
			
	
	
		
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			96 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
|   | <?php | ||
|  | 
 | ||
|  | const GRAMMAR_FILE = './zend_language_parser.phpy'; | ||
|  | 
 | ||
|  | const LIB = '(?(DEFINE) | ||
|  |     (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') | ||
|  |     (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") | ||
|  |     (?<string>(?&singleQuotedString)|(?&doubleQuotedString)) | ||
|  |     (?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) | ||
|  |     (?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) | ||
|  | )'; | ||
|  | 
 | ||
|  | const RULE_BLOCK = '(?<name>[a-z_]++):(?<rules>[^\'"/{};]*+(?:(?:(?&string)|(?&comment)|(?&code)|/|})[^\'"/{};]*+)*+);'; | ||
|  | 
 | ||
|  | $usedTerminals = array_flip(array( | ||
|  |     'T_VARIABLE', 'T_STRING', 'T_INLINE_HTML', 'T_ENCAPSED_AND_WHITESPACE', | ||
|  |     'T_LNUMBER', 'T_DNUMBER', 'T_CONSTANT_ENCAPSED_STRING', 'T_STRING_VARNAME', 'T_NUM_STRING' | ||
|  | )); | ||
|  | $unusedNonterminals = array_flip(array( | ||
|  |     'case_separator', 'optional_comma' | ||
|  | )); | ||
|  | 
 | ||
|  | function regex($regex) { | ||
|  |     return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; | ||
|  | } | ||
|  | 
 | ||
|  | function magicSplit($regex, $string) { | ||
|  |     $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); | ||
|  | 
 | ||
|  |     foreach ($pieces as &$piece) { | ||
|  |         $piece = trim($piece); | ||
|  |     } | ||
|  | 
 | ||
|  |     return array_filter($pieces); | ||
|  | } | ||
|  | 
 | ||
|  | echo '<pre>'; | ||
|  | 
 | ||
|  | ////////////////////
 | ||
|  | ////////////////////
 | ||
|  | ////////////////////
 | ||
|  | 
 | ||
|  | list($defs, $ruleBlocks) = magicSplit('%%', file_get_contents(GRAMMAR_FILE)); | ||
|  | 
 | ||
|  | if ('' !== trim(preg_replace(regex(RULE_BLOCK), '', $ruleBlocks))) { | ||
|  |     die('Not all rule blocks were properly recognized!'); | ||
|  | } | ||
|  | 
 | ||
|  | preg_match_all(regex(RULE_BLOCK), $ruleBlocks, $ruleBlocksMatches, PREG_SET_ORDER); | ||
|  | foreach ($ruleBlocksMatches as $match) { | ||
|  |     $ruleBlockName = $match['name']; | ||
|  |     $rules = magicSplit('\|', $match['rules']); | ||
|  | 
 | ||
|  |     foreach ($rules as &$rule) { | ||
|  |         $parts = magicSplit('\s+', $rule); | ||
|  |         $usedParts = array(); | ||
|  | 
 | ||
|  |         foreach ($parts as $part) { | ||
|  |             if ('{' === $part[0]) { | ||
|  |                 preg_match_all('~\$([0-9]+)~', $part, $backReferencesMatches, PREG_SET_ORDER); | ||
|  |                 foreach ($backReferencesMatches as $match) { | ||
|  |                     $usedParts[$match[1]] = true; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         $i = 1; | ||
|  |         foreach ($parts as &$part) { | ||
|  |             if ('/' === $part[0]) { | ||
|  |                 continue; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (isset($usedParts[$i])) { | ||
|  |                 if ('\'' === $part[0] || '{' === $part[0] | ||
|  |                     || (ctype_upper($part[0]) && !isset($usedTerminals[$part])) | ||
|  |                     || (ctype_lower($part[0]) && isset($unusedNonterminals[$part])) | ||
|  |                 ) { | ||
|  |                     $part = '<span style="background-color: red; color: white;">' . $part . '</span>'; | ||
|  |                 } else { | ||
|  |                     $part = '<strong><em>' . $part . '</em></strong>'; | ||
|  |                 } | ||
|  |             } elseif ((ctype_upper($part[0]) && isset($usedTerminals[$part])) | ||
|  |                       || (ctype_lower($part[0]) && !isset($unusedNonterminals[$part])) | ||
|  | 
 | ||
|  |             ) { | ||
|  |                 $part = '<span style="background-color: blue; color: white;">' . $part . '</span>'; | ||
|  |             } | ||
|  | 
 | ||
|  |             ++$i; | ||
|  |         } | ||
|  | 
 | ||
|  |         $rule = implode(' ', $parts); | ||
|  |     } | ||
|  | 
 | ||
|  |     echo $ruleBlockName, ':', "\n", '      ', implode("\n" . '    | ', $rules), "\n", ';', "\n\n"; | ||
|  | } |