diff --git a/core/oql/build.bash b/core/oql/build.bash deleted file mode 100755 index cff08c526..000000000 --- a/core/oql/build.bash +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -php /usr/share/php/PHP/LexerGenerator/cli.php oql-lexer.plex -php /usr/share/php/PHP/ParserGenerator/cli.php oql-parser.y - diff --git a/core/oql/build.cmd b/core/oql/build.cmd deleted file mode 100644 index 2187cec66..000000000 --- a/core/oql/build.cmd +++ /dev/null @@ -1,3 +0,0 @@ -c:\itop\php-5.2.3\php.exe -q "C:\itop\PHP-5.2.3\PEAR\PHP\LexerGenerator\cli.php" oql-lexer.plex -c:\itop\php-5.2.3\php.exe -q "C:\itop\PHP-5.2.3\PEAR\PHP\ParserGenerator\cli.php" oql-parser.y -pause \ No newline at end of file diff --git a/core/oql/build/PHP/Lempar.php b/core/oql/build/PHP/Lempar.php new file mode 100644 index 000000000..23ba300fd --- /dev/null +++ b/core/oql/build/PHP/Lempar.php @@ -0,0 +1,937 @@ +string = $s->string; + $this->metadata = $s->metadata; + } else { + $this->string = (string) $s; + if ($m instanceof ParseyyToken) { + $this->metadata = $m->metadata; + } elseif (is_array($m)) { + $this->metadata = $m; + } + } + } + + function __toString() + { + return $this->string; + } + + function offsetExists($offset) + { + return isset($this->metadata[$offset]); + } + + function offsetGet($offset) + { + return $this->metadata[$offset]; + } + + function offsetSet($offset, $value) + { + if ($offset === null) { + if (isset($value[0])) { + $x = ($value instanceof ParseyyToken) ? + $value->metadata : $value; + $this->metadata = array_merge($this->metadata, $x); + return; + } + $offset = count($this->metadata); + } + if ($value === null) { + return; + } + if ($value instanceof ParseyyToken) { + if ($value->metadata) { + $this->metadata[$offset] = $value->metadata; + } + } elseif ($value) { + $this->metadata[$offset] = $value; + } + } + + function offsetUnset($offset) + { + unset($this->metadata[$offset]); + } +} + +/** The following structure represents a single element of the + * parser's stack. Information stored includes: + * + * + The state number for the parser at this level of the stack. + * + * + The value of the token stored at this level of the stack. + * (In other words, the "major" token.) + * + * + The semantic value stored at this level of the stack. This is + * the information used by the action routines in the grammar. + * It is sometimes called the "minor" token. + */ +class ParseyyStackEntry +{ + public $stateno; /* The state-number */ + public $major; /* The major token value. This is the code + ** number for the token at this stack level */ + public $minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; + +// code external to the class is included here +%% + +// declare_class is output here +%% +{ +/* First off, code is included which follows the "include_class" declaration +** in the input file. */ +%% + +/* Next is all token values, as class constants +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ +%% + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N < self::YYNSTATE Shift N. That is, +** push the lookahead +** token onto the stack +** and goto state N. +** +** self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE Reduce by rule N-YYNSTATE. +** +** N == self::YYNSTATE+self::YYNRULE A syntax error has occurred. +** +** N == self::YYNSTATE+self::YYNRULE+1 The parser accepts its +** input. (and concludes parsing) +** +** N == self::YYNSTATE+self::YYNRULE+2 No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large static array $yy_action. +** Given state S and lookahead X, the action is computed as +** +** self::$yy_action[self::$yy_shift_ofst[S] + X ] +** +** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value +** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if +** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that +** the action is not in the table and that self::$yy_default[S] should be used instead. +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the static $yy_reduce_ofst array is used in place of +** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of +** self::YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** self::$yy_action A single table containing all actions. +** self::$yy_lookahead A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** self::$yy_shift_ofst For each state, the offset into self::$yy_action for +** shifting terminals. +** self::$yy_reduce_ofst For each state, the offset into self::$yy_action for +** shifting non-terminals after a reduce. +** self::$yy_default Default action for each state. +*/ +%% +/* The next thing included is series of defines which control +** various aspects of the generated parser. +** self::YYNOCODE is a number which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. +** self::YYFALLBACK If defined, this indicates that one or more tokens +** have fall-back values which should be used if the +** original value of the token will not parse. +** self::YYSTACKDEPTH is the maximum depth of the parser's stack. +** self::YYNSTATE the combined number of states. +** self::YYNRULE the number of rules in the grammar +** self::YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +*/ +%% + /** The next table maps tokens into fallback tokens. If a construct + * like the following: + * + * %fallback ID X Y Z. + * + * appears in the grammer, then ID becomes a fallback token for X, Y, + * and Z. Whenever one of the tokens X, Y, or Z is input to the parser + * but it does not parse, the type of the token is changed to ID and + * the parse is retried before an error is thrown. + */ + static public $yyFallback = array( +%% + ); + /** + * Turn parser tracing on by giving a stream to which to write the trace + * and a prompt to preface each trace message. Tracing is turned off + * by making either argument NULL + * + * Inputs: + * + * - A stream resource to which trace output should be written. + * If NULL, then tracing is turned off. + * - A prefix string written at the beginning of every + * line of trace output. If NULL, then tracing is + * turned off. + * + * Outputs: + * + * - None. + * @param resource + * @param string + */ + static function Trace($TraceFILE, $zTracePrompt) + { + if (!$TraceFILE) { + $zTracePrompt = 0; + } elseif (!$zTracePrompt) { + $TraceFILE = 0; + } + self::$yyTraceFILE = $TraceFILE; + self::$yyTracePrompt = $zTracePrompt; + } + + /** + * Output debug information to output (php://output stream) + */ + static function PrintTrace() + { + self::$yyTraceFILE = fopen('php://output', 'w'); + self::$yyTracePrompt = ''; + } + + /** + * @var resource|0 + */ + static public $yyTraceFILE; + /** + * String to prepend to debug output + * @var string|0 + */ + static public $yyTracePrompt; + /** + * @var int + */ + public $yyidx = -1; /* Index of top element in stack */ + /** + * @var int + */ + public $yyerrcnt; /* Shifts left before out of the error */ + /** + * @var array + */ + public $yystack = array(); /* The parser's stack */ + + /** + * For tracing shifts, the names of all terminals and nonterminals + * are required. The following table supplies these names + * @var array + */ + static public $yyTokenName = array( +%% + ); + + /** + * For tracing reduce actions, the names of all rules are required. + * @var array + */ + static public $yyRuleName = array( +%% + ); + + /** + * This function returns the symbolic name associated with a token + * value. + * @param int + * @return string + */ + function tokenName($tokenType) + { + if ($tokenType === 0) { + return 'End of Input'; + } + if ($tokenType > 0 && $tokenType < count(self::$yyTokenName)) { + return self::$yyTokenName[$tokenType]; + } else { + return "Unknown"; + } + } + + /** + * The following function deletes the value associated with a + * symbol. The symbol can be either a terminal or nonterminal. + * @param int the symbol code + * @param mixed the symbol's value + */ + static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are not used + ** inside the C code. + */ +%% + default: break; /* If no destructor action specified: do nothing */ + } + } + + /** + * Pop the parser's stack once. + * + * If there is a destructor routine associated with the token which + * is popped from the stack, then call it. + * + * Return the major token number for the symbol popped. + * @param ParseyyParser + * @return int + */ + function yy_pop_parser_stack() + { + if (!count($this->yystack)) { + return; + } + $yytos = array_pop($this->yystack); + if (self::$yyTraceFILE && $this->yyidx >= 0) { + fwrite(self::$yyTraceFILE, + self::$yyTracePrompt . 'Popping ' . self::$yyTokenName[$yytos->major] . + "\n"); + } + $yymajor = $yytos->major; + self::yy_destructor($yymajor, $yytos->minor); + $this->yyidx--; + return $yymajor; + } + + /** + * Deallocate and destroy a parser. Destructors are all called for + * all stack elements before shutting the parser down. + */ + function __destruct() + { + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + if (is_resource(self::$yyTraceFILE)) { + fclose(self::$yyTraceFILE); + } + } + + /** + * Based on the current state and parser stack, get a list of all + * possible lookahead tokens + * @param int + * @return array + */ + function yy_get_expected_tokens($token) + { + $state = $this->yystack[$this->yyidx]->stateno; + $expected = self::$yyExpectedTokens[$state]; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return $expected; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return array_unique($expected); + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate])) { + $expected += self::$yyExpectedTokens[$nextstate]; + if (in_array($token, + self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new ParseyyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return array_unique($expected); + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return $expected; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + return array_unique($expected); + } + + /** + * Based on the parser state and current parser stack, determine whether + * the lookahead token is possible. + * + * The parser will convert the token value to an error token if not. This + * catches some unusual edge cases where the parser would fail. + * @param int + * @return bool + */ + function yy_is_expected_token($token) + { + if ($token === 0) { + return true; // 0 is not part of this + } + $state = $this->yystack[$this->yyidx]->stateno; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return true; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return true; + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate]) && + in_array($token, self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new ParseyyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + if (!$token) { + // end of input: this is valid + return true; + } + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return false; + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return true; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + + /** + * Find the appropriate action for a parser given the terminal + * look-ahead token iLookAhead. + * + * If the look-ahead token is YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return YY_NO_ACTION. + * @param int The look-ahead token + */ + function yy_find_shift_action($iLookAhead) + { + $stateno = $this->yystack[$this->yyidx]->stateno; + + /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ + if (!isset(self::$yy_shift_ofst[$stateno])) { + // no shift actions + return self::$yy_default[$stateno]; + } + $i = self::$yy_shift_ofst[$stateno]; + if ($i === self::YY_SHIFT_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) + && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) { + if (self::$yyTraceFILE) { + fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " . + self::$yyTokenName[$iLookAhead] . " => " . + self::$yyTokenName[$iFallback] . "\n"); + } + return $this->yy_find_shift_action($iFallback); + } + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Find the appropriate action for a parser given the non-terminal + * look-ahead token $iLookAhead. + * + * If the look-ahead token is self::YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return self::YY_NO_ACTION. + * @param int Current state number + * @param int The look-ahead token + */ + function yy_find_reduce_action($stateno, $iLookAhead) + { + /* $stateno = $this->yystack[$this->yyidx]->stateno; */ + + if (!isset(self::$yy_reduce_ofst[$stateno])) { + return self::$yy_default[$stateno]; + } + $i = self::$yy_reduce_ofst[$stateno]; + if ($i == self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Perform a shift action. + * @param int The new state to shift in + * @param int The major token to shift in + * @param mixed the minor token to shift in + */ + function yy_shift($yyNewState, $yyMajor, $yypMinor) + { + $this->yyidx++; + if ($this->yyidx >= self::YYSTACKDEPTH) { + $this->yyidx--; + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will execute if the parser + ** stack ever overflows */ +%% + return; + } + $yytos = new ParseyyStackEntry; + $yytos->stateno = $yyNewState; + $yytos->major = $yyMajor; + $yytos->minor = $yypMinor; + array_push($this->yystack, $yytos); + if (self::$yyTraceFILE && $this->yyidx > 0) { + fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt, + $yyNewState); + fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt); + for ($i = 1; $i <= $this->yyidx; $i++) { + fprintf(self::$yyTraceFILE, " %s", + self::$yyTokenName[$this->yystack[$i]->major]); + } + fwrite(self::$yyTraceFILE,"\n"); + } + } + + /** + * The following table contains information about every rule that + * is used during the reduce. + * + *
+     * array(
+     *  array(
+     *   int $lhs;         Symbol on the left-hand side of the rule
+     *   int $nrhs;     Number of right-hand side symbols in the rule
+     *  ),...
+     * );
+     * 
+ */ + static public $yyRuleInfo = array( +%% + ); + + /** + * The following table contains a mapping of reduce action to method name + * that handles the reduction. + * + * If a rule is not set, it has no handler. + */ + static public $yyReduceMap = array( +%% + ); + /* Beginning here are the reduction cases. A typical example + ** follows: + ** #line + ** function yy_r0($yymsp){ ... } // User supplied code + ** #line + */ +%% + + /** + * placeholder for the left hand side in a reduce operation. + * + * For a parser with a rule like this: + *
+     * rule(A) ::= B. { A = 1; }
+     * 
+ * + * The parser will translate to something like: + * + * + * function yy_r0(){$this->_retvalue = 1;} + * + */ + private $_retvalue; + + /** + * Perform a reduce action and the shift that must immediately + * follow the reduce. + * + * For a rule such as: + * + *
+     * A ::= B blah C. { dosomething(); }
+     * 
+ * + * This function will first call the action, if any, ("dosomething();" in our + * example), and then it will pop three states from the stack, + * one for each entry on the right-hand side of the expression + * (B, blah, and C in our example rule), and then push the result of the action + * back on to the stack with the resulting state reduced to (as described in the .out + * file) + * @param int Number of the rule by which to reduce + */ + function yy_reduce($yyruleno) + { + //int $yygoto; /* The next state */ + //int $yyact; /* The next action */ + //mixed $yygotominor; /* The LHS of the rule reduced */ + //ParseyyStackEntry $yymsp; /* The top of the parser's stack */ + //int $yysize; /* Amount to pop the stack */ + $yymsp = $this->yystack[$this->yyidx]; + if (self::$yyTraceFILE && $yyruleno >= 0 + && $yyruleno < count(self::$yyRuleName)) { + fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n", + self::$yyTracePrompt, $yyruleno, + self::$yyRuleName[$yyruleno]); + } + + $this->_retvalue = $yy_lefthand_side = null; + if (array_key_exists($yyruleno, self::$yyReduceMap)) { + // call the action + $this->_retvalue = null; + $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}(); + $yy_lefthand_side = $this->_retvalue; + } + $yygoto = self::$yyRuleInfo[$yyruleno]['lhs']; + $yysize = self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= $yysize; + for ($i = $yysize; $i; $i--) { + // pop all of the right-hand side parameters + array_pop($this->yystack); + } + $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto); + if ($yyact < self::YYNSTATE) { + /* If we are not debugging and the reduce action popped at least + ** one element off the stack, then we can push the new element back + ** onto the stack here, and skip the stack overflow test in yy_shift(). + ** That gives a significant speed improvement. */ + if (!self::$yyTraceFILE && $yysize) { + $this->yyidx++; + $x = new ParseyyStackEntry; + $x->stateno = $yyact; + $x->major = $yygoto; + $x->minor = $yy_lefthand_side; + $this->yystack[$this->yyidx] = $x; + } else { + $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + } + } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) { + $this->yy_accept(); + } + } + + /** + * The following code executes when the parse fails + * + * Code from %parse_fail is inserted here + */ + function yy_parse_failed() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser fails */ +%% + } + + /** + * The following code executes when a syntax error first occurs. + * + * %syntax_error code is inserted here + * @param int The major type of the error token + * @param mixed The minor type of the error token + */ + function yy_syntax_error($yymajor, $TOKEN) + { +%% + } + + /** + * The following is executed when the parser accepts + * + * %parse_accept code is inserted here + */ + function yy_accept() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $stack = $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser accepts */ +%% + } + + /** + * The main parser program. + * + * The first argument is the major token number. The second is + * the token value string as scanned from the input. + * + * @param int $yymajor the token number + * @param mixed $yytokenvalue the token value + * @param mixed ... any extra arguments that should be passed to handlers + * + * @return void + */ + function doParse($yymajor, $yytokenvalue) + { +// $yyact; /* The parser action. */ +// $yyendofinput; /* True if we are at the end of input */ + $yyerrorhit = 0; /* True if yymajor has invoked an error */ + + /* (re)initialize the parser, if necessary */ + if ($this->yyidx === null || $this->yyidx < 0) { + /* if ($yymajor == 0) return; // not sure why this was here... */ + $this->yyidx = 0; + $this->yyerrcnt = -1; + $x = new ParseyyStackEntry; + $x->stateno = 0; + $x->major = 0; + $this->yystack = array(); + array_push($this->yystack, $x); + } + $yyendofinput = ($yymajor==0); + + if (self::$yyTraceFILE) { + fprintf( + self::$yyTraceFILE, + "%sInput %s\n", + self::$yyTracePrompt, + self::$yyTokenName[$yymajor] + ); + } + + do { + $yyact = $this->yy_find_shift_action($yymajor); + if ($yymajor < self::YYERRORSYMBOL + && !$this->yy_is_expected_token($yymajor) + ) { + // force a syntax error + $yyact = self::YY_ERROR_ACTION; + } + if ($yyact < self::YYNSTATE) { + $this->yy_shift($yyact, $yymajor, $yytokenvalue); + $this->yyerrcnt--; + if ($yyendofinput && $this->yyidx >= 0) { + $yymajor = 0; + } else { + $yymajor = self::YYNOCODE; + } + } elseif ($yyact < self::YYNSTATE + self::YYNRULE) { + $this->yy_reduce($yyact - self::YYNSTATE); + } elseif ($yyact == self::YY_ERROR_ACTION) { + if (self::$yyTraceFILE) { + fprintf( + self::$yyTraceFILE, + "%sSyntax Error!\n", + self::$yyTracePrompt + ); + } + if (self::YYERRORSYMBOL) { + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if ($this->yyerrcnt < 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $yymx = $this->yystack[$this->yyidx]->major; + if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ) { + if (self::$yyTraceFILE) { + fprintf( + self::$yyTraceFILE, + "%sDiscard input token %s\n", + self::$yyTracePrompt, + self::$yyTokenName[$yymajor] + ); + } + $this->yy_destructor($yymajor, $yytokenvalue); + $yymajor = self::YYNOCODE; + } else { + while ($this->yyidx >= 0 + && $yymx != self::YYERRORSYMBOL + && ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE + ) { + $this->yy_pop_parser_stack(); + } + if ($this->yyidx < 0 || $yymajor==0) { + $this->yy_destructor($yymajor, $yytokenvalue); + $this->yy_parse_failed(); + $yymajor = self::YYNOCODE; + } elseif ($yymx != self::YYERRORSYMBOL) { + $u2 = 0; + $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); + } + } + $this->yyerrcnt = 3; + $yyerrorhit = 1; + } else { + /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if ($this->yyerrcnt <= 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $this->yyerrcnt = 3; + $this->yy_destructor($yymajor, $yytokenvalue); + if ($yyendofinput) { + $this->yy_parse_failed(); + } + $yymajor = self::YYNOCODE; + } + } else { + $this->yy_accept(); + $yymajor = self::YYNOCODE; + } + } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } +} diff --git a/core/oql/build/PHP/LexerGenerator.php b/core/oql/build/PHP/LexerGenerator.php new file mode 100644 index 000000000..f9dd13a6e --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator.php @@ -0,0 +1,332 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category php + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: LexerGenerator.php 294970 2010-02-12 03:46:38Z clockwerx $ + * @since File available since Release 0.1.0 + */ +/** + * The Lexer generation parser + */ +require_once 'PHP/LexerGenerator/Parser.php'; +/** + * Hand-written lexer for lex2php format files + */ +require_once 'PHP/LexerGenerator/Lexer.php'; + +/** + * The basic home class for the lexer generator. A lexer scans text and + * organizes it into tokens for usage by a parser. + * + * Sample Usage: + * + * require_once 'PHP/LexerGenerator.php'; + * $lex = new PHP_LexerGenerator('/path/to/lexerfile.plex'); + * + * + * A file named "/path/to/lexerfile.php" will be created. + * + * File format consists of a PHP file containing specially + * formatted comments like so: + * + * + * /*!lex2php + * {@*} + * + * + * All lexer definition files must contain at least two lex2php comment blocks: + * - 1 regex declaration block + * - 1 or more rule declaration blocks + * + * The first lex2php comment is the regex declaration block and must contain + * several processor instruction as well as defining a name for all + * regular expressions. Processor instructions start with + * a "%" symbol and must be: + * + * - %counter + * - %input + * - %token + * - %value + * - %line + * + * token and counter should define the class variables used to define lexer input + * and the index into the input. token and value should be used to define the class + * variables used to store the token number and its textual value. Finally, line + * should be used to define the class variable used to define the current line number + * of scanning. + * + * For example: + * + * /*!lex2php + * %counter {$this->N} + * %input {$this->data} + * %token {$this->token} + * %value {$this->value} + * %line {%this->linenumber} + * {@*} + * + * + * Patterns consist of an identifier containing an letters or an underscore, and + * a descriptive match pattern. + * + * Descriptive match patterns may either be regular expressions (regexes) or + * quoted literal strings. Here are some examples: + * + *
+ * pattern = "quoted literal"
+ * ANOTHER = /[a-zA-Z_]+/
+ * COMPLEX = @<([a-zA-Z_]+)( +(([a-zA-Z_]+)=((["\'])([^\6]*)\6))+){0,1}>[^<]*@
+ * 
+ * + * Quoted strings must escape the \ and " characters with \" and \\. + * + * Regex patterns must be in Perl-compatible regular expression format (preg). + * special characters (like \t \n or \x3H) can only be used in regexes, all + * \ will be escaped in literal strings. + * + * Sub-patterns may be defined and back-references (like \1) may be used. Any sub- + * patterns detected will be passed to the token handler in the variable + * $yysubmatches. + * + * In addition, lookahead expressions, and once-only expressions are allowed. + * Lookbehind expressions are impossible (scanning always occurs from the + * current position forward), and recursion (?R) can't work and is not allowed. + * + * + * /*!lex2php + * %counter {$this->N} + * %input {$this->data} + * %token {$this->token} + * %value {$this->value} + * %line {%this->linenumber} + * alpha = /[a-zA-Z]/ + * alphaplus = /[a-zA-Z]+/ + * number = /[0-9]/ + * numerals = /[0-9]+/ + * whitespace = /[ \t\n]+/ + * blah = "$\"" + * blahblah = /a\$/ + * GAMEEND = @(?:1\-0|0\-1|1/2\-1/2)@ + * PAWNMOVE = /P?[a-h]([2-7]|[18]\=(Q|R|B|N))|P?[a-h]x[a-h]([2-7]|[18]\=(Q|R|B|N))/ + * {@*} + * + * + * All regexes must be delimited. Any legal preg delimiter can be used (as in @ or / in + * the example above) + * + * Rule lex2php blocks each define a lexer state. You can optionally name the state + * with the %statename processor instruction. State names can be used to transfer to + * a new lexer state with the yybegin() method + * + * + * /*!lexphp + * %statename INITIAL + * blah { + * $this->yybegin(self::INBLAH); + * // note - $this->yybegin(2) would also work + * } + * {@*} + * /*!lex2php + * %statename INBLAH + * ANYTHING { + * $this->yybegin(self::INITIAL); + * // note - $this->yybegin(1) would also work + * } + * {@*} + * + * + * You can maintain a parser state stack simply by using yypushstate() and + * yypopstate() instead of yybegin(): + * + * + * /*!lexphp + * %statename INITIAL + * blah { + * $this->yypushstate(self::INBLAH); + * } + * {@*} + * /*!lex2php + * %statename INBLAH + * ANYTHING { + * $this->yypopstate(); + * // now INBLAH doesn't care where it was called from + * } + * {@*} + * + * + * Code blocks can choose to skip the current token and cycle to the next token by + * returning "false" + * + * + * /*!lex2php + * WHITESPACE { + * return false; + * } + * {@*} + * + * + * If you wish to re-process the current token in a new state, simply return true. + * If you forget to change lexer state, this will cause an unterminated loop, + * so be careful! + * + * + * /*!lex2php + * "(" { + * $this->yypushstate(self::INPARAMS); + * return true; + * } + * {@*} + * + * + * Lastly, if you wish to cycle to the next matching rule, return any value other than + * true, false or null: + * + * + * /*!lex2php + * "{@" ALPHA { + * if ($this->value == '{@internal') { + * return 'more'; + * } + * ... + * } + * "{@internal" { + * ... + * } + * {@*} + * + * + * Note that this procedure is exceptionally inefficient, and it would be far better + * to take advantage of PHP_LexerGenerator's top-down precedence and instead code: + * + * + * /*!lex2php + * "{@internal" { + * ... + * } + * "{@" ALPHA { + * ... + * } + * {@*} + * + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version @package_version@ + * @since Class available since Release 0.1.0 + * @example TestLexer.plex Example lexer source + * @example TestLexer.php Example lexer generated php code + * @example usage.php Example usage of PHP_LexerGenerator + * @example Lexer.plex File_ChessPGN lexer source (complex) + * @example Lexer.php File_ChessPGN lexer generated php code + */ + +class PHP_LexerGenerator +{ + /** + * Plex file lexer. + * @var PHP_LexerGenerator_Lexer + */ + private $_lex; + + /** + * Plex file parser. + * @var PHP_LexerGenerator_Parser + */ + private $_parser; + + /** + * Path to the output PHP file. + * @var string + */ + private $_outfile; + + /** + * Debug flag. When set, Parser trace information is generated. + * @var boolean + */ + public $debug = false; + + /** + * Create a lexer generator and optionally generate a lexer file. + * + * @param string Optional plex file {@see PHP_LexerGenerator::create}. + * @param string Optional output file {@see PHP_LexerGenerator::create}. + */ + function __construct($lexerfile = '', $outfile = '') + { + if ($lexerfile) { + $this -> create($lexerfile, $outfile); + } + } + + /** + * Create a lexer file from its skeleton plex file. + * + * @param string Path to the plex file. + * @param string Optional path to output file. Default is lexerfile with + * extension of ".php". + */ + function create($lexerfile, $outfile = '') + { + $this->_lex = new PHP_LexerGenerator_Lexer(file_get_contents($lexerfile)); + $info = pathinfo($lexerfile); + if ($outfile) { + $this->outfile = $outfile; + } else { + $this->outfile = $info['dirname'] . DIRECTORY_SEPARATOR . + substr($info['basename'], 0, + strlen($info['basename']) - strlen($info['extension'])) . 'php'; + } + $this->_parser = new PHP_LexerGenerator_Parser($this->outfile, $this->_lex); + if ($this -> debug) { + $this->_parser->PrintTrace(); + } + while ($this->_lex->advance($this->_parser)) { + $this->_parser->doParse($this->_lex->token, $this->_lex->value); + } + $this->_parser->doParse(0, 0); + } +} +//$a = new PHP_LexerGenerator('/development/File_ChessPGN/ChessPGN/Lexer.plex'); +?> \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Exception.php b/core/oql/build/PHP/LexerGenerator/Exception.php new file mode 100644 index 000000000..69b3066d2 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Exception.php @@ -0,0 +1,55 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category php + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + */ +require_once 'PEAR/Exception.php'; +/** + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version @package_version@ + * @since File available since Release 0.1.0 + */ +class PHP_LexerGenerator_Exception extends PEAR_Exception {} +?> \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Lexer.php b/core/oql/build/PHP/LexerGenerator/Lexer.php new file mode 100644 index 000000000..8b1731d06 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Lexer.php @@ -0,0 +1,533 @@ + + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Lexer.php 246683 2007-11-22 04:43:52Z instance $ + * @since File available since Release 0.1.0 + */ +require_once 'PHP/LexerGenerator/Parser.php'; +/** + * Token scanner for plex files. + * + * This scanner detects comments beginning with "/*!lex2php" and + * then returns their components (processing instructions, patterns, strings + * action code, and regexes) + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version @package_version@ + * @since Class available since Release 0.1.0 + */ +class PHP_LexerGenerator_Lexer +{ + private $data; + private $N; + private $state; + /** + * Current line number in input + * @var int + */ + public $line; + /** + * Number of scanning errors detected + * @var int + */ + public $errors = 0; + /** + * integer identifier of the current token + * @var int + */ + public $token; + /** + * string content of current token + * @var string + */ + public $value; + + const CODE = PHP_LexerGenerator_Parser::CODE; + const COMMENTEND = PHP_LexerGenerator_Parser::COMMENTEND; + const COMMENTSTART = PHP_LexerGenerator_Parser::COMMENTSTART; + const PATTERN = PHP_LexerGenerator_Parser::PATTERN; + const PHPCODE = PHP_LexerGenerator_Parser::PHPCODE; + const PI = PHP_LexerGenerator_Parser::PI; + const QUOTE = PHP_LexerGenerator_Parser::QUOTE; + const SINGLEQUOTE = PHP_LexerGenerator_Parser::SINGLEQUOTE; + const SUBPATTERN = PHP_LexerGenerator_Parser::SUBPATTERN; + + /** + * prepare scanning + * @param string the input + */ + function __construct($data) + { + $this->data = str_replace("\r\n", "\n", $data); + $this->N = 0; + $this->line = 1; + $this->state = 'Start'; + $this->errors = 0; + } + + /** + * Output an error message + * @param string + */ + private function error($msg) + { + echo 'Error on line ' . $this->line . ': ' . $msg; + $this->errors++; + } + + /** + * Initial scanning state lexer + * @return boolean + */ + private function lexStart() + { + if ($this->N >= strlen($this->data)) { + return false; + } + $a = strpos($this->data, '/*!lex2php' . "\n", $this->N); + if ($a === false) { + $this->value = substr($this->data, $this->N); + $this->N = strlen($this->data); + $this->token = self::PHPCODE; + return true; + } + if ($a > $this->N) { + $this->value = substr($this->data, $this->N, $a - $this->N); + $this->N = $a; + $this->token = self::PHPCODE; + return true; + } + $this->value = '/*!lex2php' . "\n"; + $this->N += 11; // strlen("/*lex2php\n") + $this->token = self::COMMENTSTART; + $this->state = 'Declare'; + return true; + } + + /** + * lexer for top-level canning state after the initial declaration comment + * @return boolean + */ + private function lexStartNonDeclare() + { + if ($this->N >= strlen($this->data)) { + return false; + } + $a = strpos($this->data, '/*!lex2php' . "\n", $this->N); + if ($a === false) { + $this->value = substr($this->data, $this->N); + $this->N = strlen($this->data); + $this->token = self::PHPCODE; + return true; + } + if ($a > $this->N) { + $this->value = substr($this->data, $this->N, $a - $this->N); + $this->N = $a; + $this->token = self::PHPCODE; + return true; + } + $this->value = '/*!lex2php' . "\n"; + $this->N += 11; // strlen("/*lex2php\n") + $this->token = self::COMMENTSTART; + $this->state = 'Rule'; + return true; + } + + /** + * lexer for declaration comment state + * @return boolean + */ + private function lexDeclare() + { + while (true) { + $this -> skipWhitespaceEol(); + if ( + $this->N + 1 >= strlen($this->data) + || $this->data[$this->N] != '/' + || $this->data[$this->N + 1] != '/' + ) { + break; + } + // Skip single-line comment + while ( + $this->N < strlen($this->data) + && $this->data[$this->N] != "\n" + ) { + ++$this->N; + } + } + if ($this->data[$this->N] == '*' && $this->data[$this->N + 1] == '/') { + $this->state = 'StartNonDeclare'; + $this->value = '*/'; + $this->N += 2; + $this->token = self::COMMENTEND; + return true; + } + if (preg_match('/\G%([a-z]+)/', $this->data, $token, null, $this->N)) { + $this->value = $token[1]; + $this->N += strlen($token[1]) + 1; + $this->state = 'DeclarePI'; + $this->token = self::PI; + return true; + } + if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, null, $this->N)) { + $this->value = $token[0]; + $this->token = self::PATTERN; + $this->N += strlen($token[0]); + $this->state = 'DeclareEquals'; + return true; + } + $this->error('expecting declaration of sub-patterns'); + return false; + } + + /** + * lexer for processor instructions within declaration comment + * @return boolean + */ + private function lexDeclarePI() + { + $this -> skipWhitespace(); + if ($this->data[$this->N] == "\n") { + $this->N++; + $this->state = 'Declare'; + $this->line++; + return $this->lexDeclare(); + } + if ($this->data[$this->N] == '{') { + return $this->lexCode(); + } + if (!preg_match("/\G[^\n]+/", $this->data, $token, null, $this->N)) { + $this->error('Unexpected end of file'); + return false; + } + $this->value = $token[0]; + $this->N += strlen($this->value); + $this->token = self::SUBPATTERN; + return true; + } + + /** + * lexer for processor instructions inside rule comments + * @return boolean + */ + private function lexDeclarePIRule() + { + $this -> skipWhitespace(); + if ($this->data[$this->N] == "\n") { + $this->N++; + $this->state = 'Rule'; + $this->line++; + return $this->lexRule(); + } + if ($this->data[$this->N] == '{') { + return $this->lexCode(); + } + if (!preg_match("/\G[^\n]+/", $this->data, $token, null, $this->N)) { + $this->error('Unexpected end of file'); + return false; + } + $this->value = $token[0]; + $this->N += strlen($this->value); + $this->token = self::SUBPATTERN; + return true; + } + + /** + * lexer for the state representing scanning between a pattern and the "=" sign + * @return boolean + */ + private function lexDeclareEquals() + { + $this -> skipWhitespace(); + if ($this->N >= strlen($this->data)) { + $this->error('unexpected end of input, expecting "=" for sub-pattern declaration'); + } + if ($this->data[$this->N] != '=') { + $this->error('expecting "=" for sub-pattern declaration'); + return false; + } + $this->N++; + $this->state = 'DeclareRightside'; + $this -> skipWhitespace(); + if ($this->N >= strlen($this->data)) { + $this->error('unexpected end of file, expecting right side of sub-pattern declaration'); + return false; + } + return $this->lexDeclareRightside(); + } + + /** + * lexer for the right side of a pattern, detects quotes or regexes + * @return boolean + */ + private function lexDeclareRightside() + { + if ($this->data[$this->N] == "\n") { + $this->state = 'lexDeclare'; + $this->N++; + $this->line++; + return $this->lexDeclare(); + } + if ($this->data[$this->N] == '"') { + return $this->lexQuote(); + } + if ($this->data[$this->N] == '\'') { + return $this->lexQuote('\''); + } + $this -> skipWhitespace(); + // match a pattern + $test = $this->data[$this->N]; + $token = $this->N + 1; + $a = 0; + do { + if ($a++) { + $token++; + } + $token = strpos($this->data, $test, $token); + } while ($token !== false && ($this->data[$token - 1] == '\\' + && $this->data[$token - 2] != '\\')); + if ($token === false) { + $this->error('Unterminated regex pattern (started with "' . $test . '"'); + return false; + } + if (substr_count($this->data, "\n", $this->N, $token - $this->N)) { + $this->error('Regex pattern extends over multiple lines'); + return false; + } + $this->value = substr($this->data, $this->N + 1, $token - $this->N - 1); + // unescape the regex marker + // we will re-escape when creating the final regex + $this->value = str_replace('\\' . $test, $test, $this->value); + $this->N = $token + 1; + $this->token = self::SUBPATTERN; + return true; + } + + /** + * lexer for quoted literals + * @return boolean + */ + private function lexQuote($quote = '"') + { + $token = $this->N + 1; + $a = 0; + do { + if ($a++) { + $token++; + } + $token = strpos($this->data, $quote, $token); + } while ($token !== false && $token < strlen($this->data) && + ($this->data[$token - 1] == '\\' && $this->data[$token - 2] != '\\')); + if ($token === false) { + $this->error('unterminated quote'); + return false; + } + if (substr_count($this->data, "\n", $this->N, $token - $this->N)) { + $this->error('quote extends over multiple lines'); + return false; + } + $this->value = substr($this->data, $this->N + 1, $token - $this->N - 1); + $this->value = str_replace('\\'.$quote, $quote, $this->value); + $this->value = str_replace('\\\\', '\\', $this->value); + $this->N = $token + 1; + if ($quote == '\'' ) { + $this->token = self::SINGLEQUOTE; + } else { + $this->token = self::QUOTE; + } + return true; + } + + /** + * lexer for rules + * @return boolean + */ + private function lexRule() + { + while ( + $this->N < strlen($this->data) + && ( + $this->data[$this->N] == ' ' + || $this->data[$this->N] == "\t" + || $this->data[$this->N] == "\n" + ) || ( + $this->N < strlen($this->data) - 1 + && $this->data[$this->N] == '/' + && $this->data[$this->N + 1] == '/' + ) + ) { + if ( $this->data[$this->N] == '/' && $this->data[$this->N + 1] == '/' ) { + // Skip single line comments + $next_newline = strpos($this->data, "\n", $this->N) + 1; + if ($next_newline) { + $this->N = $next_newline; + } else { + $this->N = sizeof($this->data); + } + $this->line++; + } else { + if ($this->data[$this->N] == "\n") { + $this->line++; + } + $this->N++; // skip all whitespace + } + } + + if ($this->N >= strlen($this->data)) { + $this->error('unexpected end of input, expecting rule declaration'); + } + if ($this->data[$this->N] == '*' && $this->data[$this->N + 1] == '/') { + $this->state = 'StartNonDeclare'; + $this->value = '*/'; + $this->N += 2; + $this->token = self::COMMENTEND; + return true; + } + if ($this->data[$this->N] == '\'') { + return $this->lexQuote('\''); + } + if (preg_match('/\G%([a-zA-Z_]+)/', $this->data, $token, null, $this->N)) { + $this->value = $token[1]; + $this->N += strlen($token[1]) + 1; + $this->state = 'DeclarePIRule'; + $this->token = self::PI; + return true; + } + if ($this->data[$this->N] == "{") { + return $this->lexCode(); + } + if ($this->data[$this->N] == '"') { + return $this->lexQuote(); + } + if (preg_match('/\G[a-zA-Z_][a-zA-Z0-9_]*/', $this->data, $token, null, $this->N)) { + $this->value = $token[0]; + $this->N += strlen($token[0]); + $this->token = self::SUBPATTERN; + return true; + } else { + $this->error('expecting token rule (quotes or sub-patterns)'); + return false; + } + } + + /** + * lexer for php code blocks + * @return boolean + */ + private function lexCode() + { + $cp = $this->N + 1; + for ($level = 1; $cp < strlen($this->data) && ($level > 1 || $this->data[$cp] != '}'); $cp++) { + if ($this->data[$cp] == '{') { + $level++; + } elseif ($this->data[$cp] == '}') { + $level--; + } elseif ($this->data[$cp] == '/' && $this->data[$cp + 1] == '/') { + /* Skip C++ style comments */ + $cp += 2; + $z = strpos($this->data, "\n", $cp); + if ($z === false) { + $cp = strlen($this->data); + break; + } + $cp = $z; + } elseif ($this->data[$cp] == "'" || $this->data[$cp] == '"') { + /* String a character literals */ + $startchar = $this->data[$cp]; + $prevc = 0; + for ($cp++; $cp < strlen($this->data) && ($this->data[$cp] != $startchar || $prevc === '\\'); $cp++) { + if ($prevc === '\\') { + $prevc = 0; + } else { + $prevc = $this->data[$cp]; + } + } + } + } + if ($cp >= strlen($this->data)) { + $this->error("PHP code starting on this line is not terminated before the end of the file."); + $this->error++; + return false; + } else { + $this->value = substr($this->data, $this->N + 1, $cp - $this->N - 1); + $this->token = self::CODE; + $this->N = $cp + 1; + return true; + } + } + + /** + * Skip whitespace characters + */ + private function skipWhitespace() { + while ( + $this->N < strlen($this->data) + && ( + $this->data[$this->N] == ' ' + || $this->data[$this->N] == "\t" + ) + ) { + $this->N++; // skip whitespace + } + } + + /** + * Skip whitespace and EOL characters + */ + private function skipWhitespaceEol() { + while ( + $this->N < strlen($this->data) + && ( + $this->data[$this->N] == ' ' + || $this->data[$this->N] == "\t" + || $this->data[$this->N] == "\n" + ) + ) { + if ($this->data[$this->N] == "\n") { + ++$this -> line; + } + $this->N++; // skip whitespace + } + } + + /** + * Primary scanner + * + * In addition to lexing, this properly increments the line number of lexing. + * This calls the proper sub-lexer based on the parser state + * @param unknown_type $parser + * @return unknown + */ + public function advance($parser) + { + if ($this->N >= strlen($this->data)) { + return false; + } + if ($this->{'lex' . $this->state}()) { + $this->line += substr_count($this->value, "\n"); + return true; + } + return false; + } +} +?> \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Parser.out b/core/oql/build/PHP/LexerGenerator/Parser.out new file mode 100644 index 000000000..2db63a6e3 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Parser.out @@ -0,0 +1,492 @@ +State 0: + start ::= * lexfile + lexfile ::= * declare rules + lexfile ::= * declare PHPCODE rules + lexfile ::= * PHPCODE declare rules + lexfile ::= * PHPCODE declare PHPCODE rules + declare ::= * COMMENTSTART declarations COMMENTEND + + PHPCODE shift 17 + COMMENTSTART shift 8 + start accept + lexfile shift 52 + declare shift 6 + +State 1: + rules ::= reset_rules * rule COMMENTEND + rules ::= reset_rules * PI SUBPATTERN rule COMMENTEND + rules ::= reset_rules * rule COMMENTEND PHPCODE + rules ::= reset_rules * PI SUBPATTERN rule COMMENTEND PHPCODE + rule ::= * rule_subpattern CODE + rule ::= * rule rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + PI shift 29 + SUBPATTERN shift 50 + QUOTE shift 51 + rule shift 12 + rule_subpattern shift 18 + +State 2: + rules ::= COMMENTSTART * rule COMMENTEND + rules ::= COMMENTSTART * PI SUBPATTERN rule COMMENTEND + rules ::= COMMENTSTART * rule COMMENTEND PHPCODE + rules ::= COMMENTSTART * PI SUBPATTERN rule COMMENTEND PHPCODE + rule ::= * rule_subpattern CODE + rule ::= * rule rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + PI shift 34 + SUBPATTERN shift 50 + QUOTE shift 51 + rule shift 11 + rule_subpattern shift 18 + +State 3: + rules ::= COMMENTSTART PI SUBPATTERN * rule COMMENTEND + rules ::= COMMENTSTART PI SUBPATTERN * rule COMMENTEND PHPCODE + rule ::= * rule_subpattern CODE + rule ::= * rule rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + SUBPATTERN shift 50 + QUOTE shift 51 + rule shift 10 + rule_subpattern shift 18 + +State 4: + lexfile ::= PHPCODE declare * rules + lexfile ::= PHPCODE declare * PHPCODE rules + rules ::= * COMMENTSTART rule COMMENTEND + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND + rules ::= * COMMENTSTART rule COMMENTEND PHPCODE + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE + rules ::= * reset_rules rule COMMENTEND + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND + rules ::= * reset_rules rule COMMENTEND PHPCODE + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE + reset_rules ::= * rules COMMENTSTART + + PHPCODE shift 7 + COMMENTSTART shift 2 + rules shift 25 + reset_rules shift 1 + +State 5: + rules ::= reset_rules PI SUBPATTERN * rule COMMENTEND + rules ::= reset_rules PI SUBPATTERN * rule COMMENTEND PHPCODE + rule ::= * rule_subpattern CODE + rule ::= * rule rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + SUBPATTERN shift 50 + QUOTE shift 51 + rule shift 13 + rule_subpattern shift 18 + +State 6: + lexfile ::= declare * rules + lexfile ::= declare * PHPCODE rules + rules ::= * COMMENTSTART rule COMMENTEND + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND + rules ::= * COMMENTSTART rule COMMENTEND PHPCODE + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE + rules ::= * reset_rules rule COMMENTEND + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND + rules ::= * reset_rules rule COMMENTEND PHPCODE + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE + reset_rules ::= * rules COMMENTSTART + + PHPCODE shift 9 + COMMENTSTART shift 2 + rules shift 33 + reset_rules shift 1 + +State 7: + lexfile ::= PHPCODE declare PHPCODE * rules + rules ::= * COMMENTSTART rule COMMENTEND + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND + rules ::= * COMMENTSTART rule COMMENTEND PHPCODE + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE + rules ::= * reset_rules rule COMMENTEND + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND + rules ::= * reset_rules rule COMMENTEND PHPCODE + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE + reset_rules ::= * rules COMMENTSTART + + COMMENTSTART shift 2 + rules shift 27 + reset_rules shift 1 + +State 8: + declare ::= COMMENTSTART * declarations COMMENTEND + declarations ::= * processing_instructions pattern_declarations + processing_instructions ::= * PI SUBPATTERN + processing_instructions ::= * PI CODE + processing_instructions ::= * processing_instructions PI SUBPATTERN + processing_instructions ::= * processing_instructions PI CODE + + PI shift 23 + declarations shift 28 + processing_instructions shift 14 + +State 9: + lexfile ::= declare PHPCODE * rules + rules ::= * COMMENTSTART rule COMMENTEND + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND + rules ::= * COMMENTSTART rule COMMENTEND PHPCODE + rules ::= * COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE + rules ::= * reset_rules rule COMMENTEND + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND + rules ::= * reset_rules rule COMMENTEND PHPCODE + rules ::= * reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE + reset_rules ::= * rules COMMENTSTART + + COMMENTSTART shift 2 + rules shift 31 + reset_rules shift 1 + +State 10: + rules ::= COMMENTSTART PI SUBPATTERN rule * COMMENTEND + rules ::= COMMENTSTART PI SUBPATTERN rule * COMMENTEND PHPCODE + rule ::= rule * rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + COMMENTEND shift 30 + SUBPATTERN shift 50 + QUOTE shift 51 + rule_subpattern shift 19 + +State 11: + rules ::= COMMENTSTART rule * COMMENTEND + rules ::= COMMENTSTART rule * COMMENTEND PHPCODE + rule ::= rule * rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + COMMENTEND shift 32 + SUBPATTERN shift 50 + QUOTE shift 51 + rule_subpattern shift 19 + +State 12: + rules ::= reset_rules rule * COMMENTEND + rules ::= reset_rules rule * COMMENTEND PHPCODE + rule ::= rule * rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + COMMENTEND shift 35 + SUBPATTERN shift 50 + QUOTE shift 51 + rule_subpattern shift 19 + +State 13: + rules ::= reset_rules PI SUBPATTERN rule * COMMENTEND + rules ::= reset_rules PI SUBPATTERN rule * COMMENTEND PHPCODE + rule ::= rule * rule_subpattern CODE + rule_subpattern ::= * QUOTE + rule_subpattern ::= * SUBPATTERN + rule_subpattern ::= * rule_subpattern QUOTE + rule_subpattern ::= * rule_subpattern SUBPATTERN + + COMMENTEND shift 24 + SUBPATTERN shift 50 + QUOTE shift 51 + rule_subpattern shift 19 + +State 14: + declarations ::= processing_instructions * pattern_declarations + processing_instructions ::= processing_instructions * PI SUBPATTERN + processing_instructions ::= processing_instructions * PI CODE + pattern_declarations ::= * PATTERN subpattern + pattern_declarations ::= * pattern_declarations PATTERN subpattern + + PI shift 20 + PATTERN shift 16 + pattern_declarations shift 26 + +State 15: + pattern_declarations ::= pattern_declarations PATTERN * subpattern + subpattern ::= * QUOTE + subpattern ::= * SUBPATTERN + subpattern ::= * subpattern QUOTE + subpattern ::= * subpattern SUBPATTERN + + SUBPATTERN shift 36 + QUOTE shift 37 + subpattern shift 21 + +State 16: + pattern_declarations ::= PATTERN * subpattern + subpattern ::= * QUOTE + subpattern ::= * SUBPATTERN + subpattern ::= * subpattern QUOTE + subpattern ::= * subpattern SUBPATTERN + + SUBPATTERN shift 36 + QUOTE shift 37 + subpattern shift 22 + +State 17: + lexfile ::= PHPCODE * declare rules + lexfile ::= PHPCODE * declare PHPCODE rules + declare ::= * COMMENTSTART declarations COMMENTEND + + COMMENTSTART shift 8 + declare shift 4 + +State 18: + rule ::= rule_subpattern * CODE + rule_subpattern ::= rule_subpattern * QUOTE + rule_subpattern ::= rule_subpattern * SUBPATTERN + + SUBPATTERN shift 54 + CODE shift 47 + QUOTE shift 53 + +State 19: + rule ::= rule rule_subpattern * CODE + rule_subpattern ::= rule_subpattern * QUOTE + rule_subpattern ::= rule_subpattern * SUBPATTERN + + SUBPATTERN shift 54 + CODE shift 45 + QUOTE shift 53 + +State 20: + processing_instructions ::= processing_instructions PI * SUBPATTERN + processing_instructions ::= processing_instructions PI * CODE + + SUBPATTERN shift 44 + CODE shift 40 + +State 21: + (12) pattern_declarations ::= pattern_declarations PATTERN subpattern * + subpattern ::= subpattern * QUOTE + subpattern ::= subpattern * SUBPATTERN + + SUBPATTERN shift 38 + QUOTE shift 41 + {default} reduce 12 + +State 22: + (11) pattern_declarations ::= PATTERN subpattern * + subpattern ::= subpattern * QUOTE + subpattern ::= subpattern * SUBPATTERN + + SUBPATTERN shift 38 + QUOTE shift 41 + {default} reduce 11 + +State 23: + processing_instructions ::= PI * SUBPATTERN + processing_instructions ::= PI * CODE + + SUBPATTERN shift 42 + CODE shift 39 + +State 24: + (18) rules ::= reset_rules PI SUBPATTERN rule COMMENTEND * + rules ::= reset_rules PI SUBPATTERN rule COMMENTEND * PHPCODE + + PHPCODE shift 48 + {default} reduce 18 + +State 25: + (3) lexfile ::= PHPCODE declare rules * + reset_rules ::= rules * COMMENTSTART + + COMMENTSTART shift 43 + {default} reduce 3 + +State 26: + (6) declarations ::= processing_instructions pattern_declarations * + pattern_declarations ::= pattern_declarations * PATTERN subpattern + + PATTERN shift 15 + {default} reduce 6 + +State 27: + (4) lexfile ::= PHPCODE declare PHPCODE rules * + reset_rules ::= rules * COMMENTSTART + + COMMENTSTART shift 43 + {default} reduce 4 + +State 28: + declare ::= COMMENTSTART declarations * COMMENTEND + + COMMENTEND shift 55 + +State 29: + rules ::= reset_rules PI * SUBPATTERN rule COMMENTEND + rules ::= reset_rules PI * SUBPATTERN rule COMMENTEND PHPCODE + + SUBPATTERN shift 5 + +State 30: + (14) rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND * + rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND * PHPCODE + + PHPCODE shift 46 + {default} reduce 14 + +State 31: + (2) lexfile ::= declare PHPCODE rules * + reset_rules ::= rules * COMMENTSTART + + COMMENTSTART shift 43 + {default} reduce 2 + +State 32: + (13) rules ::= COMMENTSTART rule COMMENTEND * + rules ::= COMMENTSTART rule COMMENTEND * PHPCODE + + PHPCODE shift 56 + {default} reduce 13 + +State 33: + (1) lexfile ::= declare rules * + reset_rules ::= rules * COMMENTSTART + + COMMENTSTART shift 43 + {default} reduce 1 + +State 34: + rules ::= COMMENTSTART PI * SUBPATTERN rule COMMENTEND + rules ::= COMMENTSTART PI * SUBPATTERN rule COMMENTEND PHPCODE + + SUBPATTERN shift 3 + +State 35: + (17) rules ::= reset_rules rule COMMENTEND * + rules ::= reset_rules rule COMMENTEND * PHPCODE + + PHPCODE shift 49 + {default} reduce 17 + +State 36: + (29) subpattern ::= SUBPATTERN * + + {default} reduce 29 + +State 37: + (28) subpattern ::= QUOTE * + + {default} reduce 28 + +State 38: + (31) subpattern ::= subpattern SUBPATTERN * + + {default} reduce 31 + +State 39: + (8) processing_instructions ::= PI CODE * + + {default} reduce 8 + +State 40: + (10) processing_instructions ::= processing_instructions PI CODE * + + {default} reduce 10 + +State 41: + (30) subpattern ::= subpattern QUOTE * + + {default} reduce 30 + +State 42: + (7) processing_instructions ::= PI SUBPATTERN * + + {default} reduce 7 + +State 43: + (21) reset_rules ::= rules COMMENTSTART * + + {default} reduce 21 + +State 44: + (9) processing_instructions ::= processing_instructions PI SUBPATTERN * + + {default} reduce 9 + +State 45: + (23) rule ::= rule rule_subpattern CODE * + + {default} reduce 23 + +State 46: + (16) rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE * + + {default} reduce 16 + +State 47: + (22) rule ::= rule_subpattern CODE * + + {default} reduce 22 + +State 48: + (20) rules ::= reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE * + + {default} reduce 20 + +State 49: + (19) rules ::= reset_rules rule COMMENTEND PHPCODE * + + {default} reduce 19 + +State 50: + (25) rule_subpattern ::= SUBPATTERN * + + {default} reduce 25 + +State 51: + (24) rule_subpattern ::= QUOTE * + + {default} reduce 24 + +State 52: + (0) start ::= lexfile * + + {default} reduce 0 + +State 53: + (26) rule_subpattern ::= rule_subpattern QUOTE * + + {default} reduce 26 + +State 54: + (27) rule_subpattern ::= rule_subpattern SUBPATTERN * + + {default} reduce 27 + +State 55: + (5) declare ::= COMMENTSTART declarations COMMENTEND * + + {default} reduce 5 + +State 56: + (15) rules ::= COMMENTSTART rule COMMENTEND PHPCODE * + + {default} reduce 15 + diff --git a/core/oql/build/PHP/LexerGenerator/Parser.php b/core/oql/build/PHP/LexerGenerator/Parser.php new file mode 100644 index 000000000..0362ebba2 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Parser.php @@ -0,0 +1,1994 @@ +string = $s->string; + $this->metadata = $s->metadata; + } else { + $this->string = (string) $s; + if ($m instanceof PHP_LexerGenerator_ParseryyToken) { + $this->metadata = $m->metadata; + } elseif (is_array($m)) { + $this->metadata = $m; + } + } + } + + function __toString() + { + return $this->_string; + } + + function offsetExists($offset) + { + return isset($this->metadata[$offset]); + } + + function offsetGet($offset) + { + return $this->metadata[$offset]; + } + + function offsetSet($offset, $value) + { + if ($offset === null) { + if (isset($value[0])) { + $x = ($value instanceof PHP_LexerGenerator_ParseryyToken) ? + $value->metadata : $value; + $this->metadata = array_merge($this->metadata, $x); + return; + } + $offset = count($this->metadata); + } + if ($value === null) { + return; + } + if ($value instanceof PHP_LexerGenerator_ParseryyToken) { + if ($value->metadata) { + $this->metadata[$offset] = $value->metadata; + } + } elseif ($value) { + $this->metadata[$offset] = $value; + } + } + + function offsetUnset($offset) + { + unset($this->metadata[$offset]); + } +} + +/** The following structure represents a single element of the + * parser's stack. Information stored includes: + * + * + The state number for the parser at this level of the stack. + * + * + The value of the token stored at this level of the stack. + * (In other words, the "major" token.) + * + * + The semantic value stored at this level of the stack. This is + * the information used by the action routines in the grammar. + * It is sometimes called the "minor" token. + */ +class PHP_LexerGenerator_ParseryyStackEntry +{ + public $stateno; /* The state-number */ + public $major; /* The major token value. This is the code + ** number for the token at this stack level */ + public $minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; + +// code external to the class is included here +#line 3 "Parser.y" + +/* ?> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category php + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Parser.php 246683 2007-11-22 04:43:52Z instance $ + * @since File available since Release 0.1.0 + */ +/** + * For regular expression validation + */ +require_once 'PHP/LexerGenerator/Regex/Lexer.php'; +require_once 'PHP/LexerGenerator/Regex/Parser.php'; +require_once 'PHP/LexerGenerator/Exception.php'; +/** + * Token parser for plex files. + * + * This parser converts tokens pulled from {@link PHP_LexerGenerator_Lexer} + * into abstract patterns and rules, then creates the output file + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version @package_version@ + * @since Class available since Release 0.1.0 + */ +#line 166 "Parser.php" + +// declare_class is output here +#line 2 "Parser.y" +class PHP_LexerGenerator_Parser#line 171 "Parser.php" +{ +/* First off, code is included which follows the "include_class" declaration +** in the input file. */ +#line 82 "Parser.y" + + private $patterns; + private $out; + private $lex; + private $input; + private $counter; + private $token; + private $value; + private $line; + private $matchlongest; + private $_regexLexer; + private $_regexParser; + private $_patternIndex = 0; + private $_outRuleIndex = 1; + private $caseinsensitive; + private $patternFlags; + private $unicode; + + public $transTable = array( + 1 => self::PHPCODE, + 2 => self::COMMENTSTART, + 3 => self::COMMENTEND, + 4 => self::QUOTE, + 5 => self::SINGLEQUOTE, + 6 => self::PATTERN, + 7 => self::CODE, + 8 => self::SUBPATTERN, + 9 => self::PI, + ); + + function __construct($outfile, $lex) + { + $this->out = fopen($outfile, 'wb'); + if (!$this->out) { + throw new Exception('unable to open lexer output file "' . $outfile . '"'); + } + $this->lex = $lex; + $this->_regexLexer = new PHP_LexerGenerator_Regex_Lexer(''); + $this->_regexParser = new PHP_LexerGenerator_Regex_Parser($this->_regexLexer); + } + + function doLongestMatch($rules, $statename, $ruleindex) + { + fwrite($this->out, ' + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + do { + $rules = array('); + foreach ($rules as $rule) { + fwrite($this->out, ' + \'/\G' . $rule['pattern'] . '/' . $this->patternFlags . ' \','); + } + fwrite($this->out, ' + ); + $match = false; + foreach ($rules as $index => $rule) { + if (preg_match($rule, substr(' . $this->input . ', ' . + $this->counter . '), $yymatches)) { + if ($match) { + if (strlen($yymatches[0]) > strlen($match[0][0])) { + $match = array($yymatches, $index); // matches, token + } + } else { + $match = array($yymatches, $index); + } + } + } + if (!$match) { + throw new Exception(\'Unexpected input at line \' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + ' . $this->token . ' = $match[1]; + ' . $this->value . ' = $match[0][0]; + $yysubmatches = $match[0]; + array_shift($yysubmatches); + if (!$yysubmatches) { + $yysubmatches = array(); + } + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + if ($r === null) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else {'); + fwrite($this->out, ' + $yy_yymore_patterns = array_slice($rules, $this->token, true); + // yymore is needed + do { + if (!isset($yy_yymore_patterns[' . $this->token . '])) { + throw new Exception(\'cannot do yymore for the last token\'); + } + $match = false; + foreach ($yy_yymore_patterns[' . $this->token . '] as $index => $rule) { + if (preg_match(\'/\' . $rule . \'/' . $this->patternFlags . '\', + ' . $this->input . ', $yymatches, null, ' . $this->counter . ')) { + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + if ($match) { + if (strlen($yymatches[0]) > strlen($match[0][0])) { + $match = array($yymatches, $index); // matches, token + } + } else { + $match = array($yymatches, $index); + } + } + } + if (!$match) { + throw new Exception(\'Unexpected input at line \' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + ' . $this->token . ' = $match[1]; + ' . $this->value . ' = $match[0][0]; + $yysubmatches = $match[0]; + array_shift($yysubmatches); + if (!$yysubmatches) { + $yysubmatches = array(); + } + ' . $this->line . ' = substr_count(' . $this->value . ', "\n"); + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}(); + } while ($r !== null || !$r); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else { + // accept + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + return true; + } + } + } while (true); +'); + } + + function doFirstMatch($rules, $statename, $ruleindex) + { + $patterns = array(); + $pattern = '/'; + $ruleMap = array(); + $tokenindex = array(); + $actualindex = 1; + $i = 0; + foreach ($rules as $rule) { + $ruleMap[$i++] = $actualindex; + $tokenindex[$actualindex] = $rule['subpatterns']; + $actualindex += $rule['subpatterns'] + 1; + $patterns[] = '\G(' . $rule['pattern'] . ')'; + } + // Re-index tokencount from zero. + $tokencount = array_values($tokenindex); + $tokenindex = var_export($tokenindex, true); + $tokenindex = explode("\n", $tokenindex); + // indent for prettiness + $tokenindex = implode("\n ", $tokenindex); + $pattern .= implode('|', $patterns); + $pattern .= '/' . $this->patternFlags; + fwrite($this->out, ' + $tokenMap = ' . $tokenindex . '; + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + '); + fwrite($this->out, '$yy_global_pattern = \'' . + $pattern . '\';' . "\n"); + fwrite($this->out, ' + do { + if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, null, ' . + $this->counter . + ')) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception(\'Error: lexing failed because a rule matched\' . + \' an empty string. Input "\' . substr(' . $this->input . ', + ' . $this->counter . ', 5) . \'... state ' . $statename . '\'); + } + next($yymatches); // skip global match + ' . $this->token . ' = key($yymatches); // token number + if ($tokenMap[' . $this->token . ']) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, ' . $this->token . ' + 1, + $tokenMap[' . $this->token . ']); + } else { + $yysubmatches = array(); + } + ' . $this->value . ' = current($yymatches); // token value + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + if ($r === null) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else {'); + fwrite($this->out, ' + $yy_yymore_patterns = array(' . "\n"); + $extra = 0; + for($i = 0; count($patterns); $i++) { + unset($patterns[$i]); + $extra += $tokencount[0]; + array_shift($tokencount); + fwrite($this->out, ' ' . $ruleMap[$i] . ' => array(' . $extra . ', "' . + implode('|', $patterns) . "\"),\n"); + } + fwrite($this->out, ' );' . "\n"); + fwrite($this->out, ' + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[' . $this->token . '][1])) { + throw new Exception(\'cannot do yymore for the last token\'); + } + $yysubmatches = array(); + if (preg_match(\'/\' . $yy_yymore_patterns[' . $this->token . '][1] . \'/' . $this->patternFlags . '\', + ' . $this->input . ', $yymatches, null, ' . $this->counter .')) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + next($yymatches); // skip global match + ' . $this->token . ' += key($yymatches) + $yy_yymore_patterns[' . $this->token . '][0]; // token number + ' . $this->value . ' = current($yymatches); // token value + ' . $this->line . ' = substr_count(' . $this->value . ', "\n"); + if ($tokenMap[' . $this->token . ']) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, ' . $this->token . ' + 1, + $tokenMap[' . $this->token . ']); + } else { + $yysubmatches = array(); + } + } + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + return true; + } + } + } else { + throw new Exception(\'Unexpected input at line\' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + break; + } while (true); +'); + } + + function makeCaseInsensitve($string) + { + return preg_replace('/[a-z]/ie', "'[\\0'.strtoupper('\\0').']'", strtolower($string)); + } + + function outputRules($rules, $statename) + { + if (!$statename) { + $statename = $this -> _outRuleIndex; + } + fwrite($this->out, ' + function yylex' . $this -> _outRuleIndex . '() + {'); + if ($this->matchlongest) { + $ruleMap = array(); + foreach ($rules as $i => $rule) { + $ruleMap[$i] = $i; + } + $this->doLongestMatch($rules, $statename, $this -> _outRuleIndex); + } else { + $ruleMap = array(); + $actualindex = 1; + $i = 0; + foreach ($rules as $rule) { + $ruleMap[$i++] = $actualindex; + $actualindex += $rule['subpatterns'] + 1; + } + $this->doFirstMatch($rules, $statename, $this -> _outRuleIndex); + } + fwrite($this->out, ' + } // end function + +'); + if (is_string($statename)) { + fwrite($this->out, ' + const ' . $statename . ' = ' . $this -> _outRuleIndex . '; +'); + } + foreach ($rules as $i => $rule) { + fwrite($this->out, ' function yy_r' . $this -> _outRuleIndex . '_' . $ruleMap[$i] . '($yy_subpatterns) + { +' . $rule['code'] . +' } +'); + } + $this -> _outRuleIndex++; // for next set of rules + } + + function error($msg) + { + echo 'Error on line ' . $this->lex->line . ': ' , $msg; + } + + function _validatePattern($pattern, $update = false) + { + $this->_regexLexer->reset($pattern, $this->lex->line); + $this->_regexParser->reset($this->_patternIndex, $update); + try { + while ($this->_regexLexer->yylex()) { + $this->_regexParser->doParse( + $this->_regexLexer->token, $this->_regexLexer->value); + } + $this->_regexParser->doParse(0, 0); + } catch (PHP_LexerGenerator_Exception $e) { + $this->error($e->getMessage()); + throw new PHP_LexerGenerator_Exception('Invalid pattern "' . $pattern . '"'); + } + return $this->_regexParser->result; + } +#line 529 "Parser.php" + +/* Next is all token values, as class constants +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ + const PHPCODE = 1; + const COMMENTSTART = 2; + const COMMENTEND = 3; + const PI = 4; + const SUBPATTERN = 5; + const CODE = 6; + const PATTERN = 7; + const QUOTE = 8; + const SINGLEQUOTE = 9; + const YY_NO_ACTION = 99; + const YY_ACCEPT_ACTION = 98; + const YY_ERROR_ACTION = 97; + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N < self::YYNSTATE Shift N. That is, +** push the lookahead +** token onto the stack +** and goto state N. +** +** self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE Reduce by rule N-YYNSTATE. +** +** N == self::YYNSTATE+self::YYNRULE A syntax error has occurred. +** +** N == self::YYNSTATE+self::YYNRULE+1 The parser accepts its +** input. (and concludes parsing) +** +** N == self::YYNSTATE+self::YYNRULE+2 No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large static array $yy_action. +** Given state S and lookahead X, the action is computed as +** +** self::$yy_action[self::$yy_shift_ofst[S] + X ] +** +** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value +** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if +** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that +** the action is not in the table and that self::$yy_default[S] should be used instead. +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the static $yy_reduce_ofst array is used in place of +** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of +** self::YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** self::$yy_action A single table containing all actions. +** self::$yy_lookahead A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** self::$yy_shift_ofst For each state, the offset into self::$yy_action for +** shifting terminals. +** self::$yy_reduce_ofst For each state, the offset into self::$yy_action for +** shifting non-terminals after a reduce. +** self::$yy_default Default action for each state. +*/ + const YY_SZ_ACTTAB = 91; +static public $yy_action = array( + /* 0 */ 25, 50, 49, 31, 49, 54, 53, 54, 53, 35, + /* 10 */ 11, 49, 18, 22, 54, 53, 14, 59, 51, 28, + /* 20 */ 55, 57, 58, 59, 47, 1, 55, 57, 32, 15, + /* 30 */ 49, 29, 49, 54, 53, 54, 53, 30, 52, 49, + /* 40 */ 42, 46, 54, 53, 98, 56, 5, 13, 38, 18, + /* 50 */ 49, 43, 40, 54, 53, 12, 39, 18, 3, 37, + /* 60 */ 36, 17, 7, 8, 2, 10, 33, 18, 9, 2, + /* 70 */ 41, 44, 1, 24, 16, 34, 45, 27, 60, 48, + /* 80 */ 4, 1, 2, 1, 20, 19, 21, 26, 23, 6, + /* 90 */ 7, + ); + static public $yy_lookahead = array( + /* 0 */ 3, 1, 5, 4, 5, 8, 9, 8, 9, 3, + /* 10 */ 19, 5, 21, 4, 8, 9, 7, 5, 6, 14, + /* 20 */ 8, 9, 3, 5, 6, 20, 8, 9, 3, 7, + /* 30 */ 5, 4, 5, 8, 9, 8, 9, 3, 1, 5, + /* 40 */ 5, 6, 8, 9, 11, 12, 13, 19, 5, 21, + /* 50 */ 5, 8, 9, 8, 9, 19, 5, 21, 5, 8, + /* 60 */ 9, 1, 2, 1, 2, 19, 14, 21, 1, 2, + /* 70 */ 5, 6, 20, 15, 16, 14, 2, 14, 1, 1, + /* 80 */ 5, 20, 2, 20, 18, 21, 18, 17, 4, 13, + /* 90 */ 2, +); + const YY_SHIFT_USE_DFLT = -4; + const YY_SHIFT_MAX = 35; + static public $yy_shift_ofst = array( + /* 0 */ 60, 27, -1, 45, 45, 62, 67, 84, 80, 80, + /* 10 */ 34, 25, -3, 6, 51, 51, 9, 88, 12, 18, + /* 20 */ 43, 43, 65, 35, 19, 0, 22, 74, 74, 75, + /* 30 */ 78, 53, 77, 74, 74, 37, +); + const YY_REDUCE_USE_DFLT = -10; + const YY_REDUCE_MAX = 17; + static public $yy_reduce_ofst = array( + /* 0 */ 33, 28, -9, 46, 36, 52, 63, 58, 61, 5, + /* 10 */ 64, 64, 64, 64, 66, 68, 70, 76, +); + static public $yyExpectedTokens = array( + /* 0 */ array(1, 2, ), + /* 1 */ array(4, 5, 8, 9, ), + /* 2 */ array(4, 5, 8, 9, ), + /* 3 */ array(5, 8, 9, ), + /* 4 */ array(5, 8, 9, ), + /* 5 */ array(1, 2, ), + /* 6 */ array(1, 2, ), + /* 7 */ array(4, ), + /* 8 */ array(2, ), + /* 9 */ array(2, ), + /* 10 */ array(3, 5, 8, 9, ), + /* 11 */ array(3, 5, 8, 9, ), + /* 12 */ array(3, 5, 8, 9, ), + /* 13 */ array(3, 5, 8, 9, ), + /* 14 */ array(5, 8, 9, ), + /* 15 */ array(5, 8, 9, ), + /* 16 */ array(4, 7, ), + /* 17 */ array(2, ), + /* 18 */ array(5, 6, 8, 9, ), + /* 19 */ array(5, 6, 8, 9, ), + /* 20 */ array(5, 8, 9, ), + /* 21 */ array(5, 8, 9, ), + /* 22 */ array(5, 6, ), + /* 23 */ array(5, 6, ), + /* 24 */ array(3, ), + /* 25 */ array(1, ), + /* 26 */ array(7, ), + /* 27 */ array(2, ), + /* 28 */ array(2, ), + /* 29 */ array(5, ), + /* 30 */ array(1, ), + /* 31 */ array(5, ), + /* 32 */ array(1, ), + /* 33 */ array(2, ), + /* 34 */ array(2, ), + /* 35 */ array(1, ), + /* 36 */ array(), + /* 37 */ array(), + /* 38 */ array(), + /* 39 */ array(), + /* 40 */ array(), + /* 41 */ array(), + /* 42 */ array(), + /* 43 */ array(), + /* 44 */ array(), + /* 45 */ array(), + /* 46 */ array(), + /* 47 */ array(), + /* 48 */ array(), + /* 49 */ array(), + /* 50 */ array(), + /* 51 */ array(), + /* 52 */ array(), + /* 53 */ array(), + /* 54 */ array(), + /* 55 */ array(), + /* 56 */ array(), + /* 57 */ array(), + /* 58 */ array(), + /* 59 */ array(), + /* 60 */ array(), +); + static public $yy_default = array( + /* 0 */ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + /* 10 */ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + /* 20 */ 72, 73, 97, 97, 97, 79, 67, 64, 65, 97, + /* 30 */ 75, 97, 74, 62, 63, 78, 92, 91, 96, 93, + /* 40 */ 95, 70, 68, 94, 71, 82, 69, 84, 77, 87, + /* 50 */ 81, 83, 80, 86, 85, 88, 61, 89, 66, 90, + /* 60 */ 76, +); +/* The next thing included is series of defines which control +** various aspects of the generated parser. +** self::YYNOCODE is a number which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. +** self::YYFALLBACK If defined, this indicates that one or more tokens +** have fall-back values which should be used if the +** original value of the token will not parse. +** self::YYSTACKDEPTH is the maximum depth of the parser's stack. +** self::YYNSTATE the combined number of states. +** self::YYNRULE the number of rules in the grammar +** self::YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +*/ + const YYNOCODE = 23; + const YYSTACKDEPTH = 100; + const YYNSTATE = 61; + const YYNRULE = 36; + const YYERRORSYMBOL = 10; + const YYERRSYMDT = 'yy0'; + const YYFALLBACK = 0; + /** The next table maps tokens into fallback tokens. If a construct + * like the following: + * + * %fallback ID X Y Z. + * + * appears in the grammer, then ID becomes a fallback token for X, Y, + * and Z. Whenever one of the tokens X, Y, or Z is input to the parser + * but it does not parse, the type of the token is changed to ID and + * the parse is retried before an error is thrown. + */ + static public $yyFallback = array( + ); + /** + * Turn parser tracing on by giving a stream to which to write the trace + * and a prompt to preface each trace message. Tracing is turned off + * by making either argument NULL + * + * Inputs: + * + * - A stream resource to which trace output should be written. + * If NULL, then tracing is turned off. + * - A prefix string written at the beginning of every + * line of trace output. If NULL, then tracing is + * turned off. + * + * Outputs: + * + * - None. + * @param resource + * @param string + */ + static function Trace($TraceFILE, $zTracePrompt) + { + if (!$TraceFILE) { + $zTracePrompt = 0; + } elseif (!$zTracePrompt) { + $TraceFILE = 0; + } + self::$yyTraceFILE = $TraceFILE; + self::$yyTracePrompt = $zTracePrompt; + } + + /** + * Output debug information to output (php://output stream) + */ + static function PrintTrace() + { + self::$yyTraceFILE = fopen('php://output', 'w'); + self::$yyTracePrompt = ''; + } + + /** + * @var resource|0 + */ + static public $yyTraceFILE; + /** + * String to prepend to debug output + * @var string|0 + */ + static public $yyTracePrompt; + /** + * @var int + */ + public $yyidx; /* Index of top element in stack */ + /** + * @var int + */ + public $yyerrcnt; /* Shifts left before out of the error */ + /** + * @var array + */ + public $yystack = array(); /* The parser's stack */ + + /** + * For tracing shifts, the names of all terminals and nonterminals + * are required. The following table supplies these names + * @var array + */ + static public $yyTokenName = array( + '$', 'PHPCODE', 'COMMENTSTART', 'COMMENTEND', + 'PI', 'SUBPATTERN', 'CODE', 'PATTERN', + 'QUOTE', 'SINGLEQUOTE', 'error', 'start', + 'lexfile', 'declare', 'rules', 'declarations', + 'processing_instructions', 'pattern_declarations', 'subpattern', 'rule', + 'reset_rules', 'rule_subpattern', + ); + + /** + * For tracing reduce actions, the names of all rules are required. + * @var array + */ + static public $yyRuleName = array( + /* 0 */ "start ::= lexfile", + /* 1 */ "lexfile ::= declare rules", + /* 2 */ "lexfile ::= declare PHPCODE rules", + /* 3 */ "lexfile ::= PHPCODE declare rules", + /* 4 */ "lexfile ::= PHPCODE declare PHPCODE rules", + /* 5 */ "declare ::= COMMENTSTART declarations COMMENTEND", + /* 6 */ "declarations ::= processing_instructions pattern_declarations", + /* 7 */ "processing_instructions ::= PI SUBPATTERN", + /* 8 */ "processing_instructions ::= PI CODE", + /* 9 */ "processing_instructions ::= processing_instructions PI SUBPATTERN", + /* 10 */ "processing_instructions ::= processing_instructions PI CODE", + /* 11 */ "pattern_declarations ::= PATTERN subpattern", + /* 12 */ "pattern_declarations ::= pattern_declarations PATTERN subpattern", + /* 13 */ "rules ::= COMMENTSTART rule COMMENTEND", + /* 14 */ "rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND", + /* 15 */ "rules ::= COMMENTSTART rule COMMENTEND PHPCODE", + /* 16 */ "rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE", + /* 17 */ "rules ::= reset_rules rule COMMENTEND", + /* 18 */ "rules ::= reset_rules PI SUBPATTERN rule COMMENTEND", + /* 19 */ "rules ::= reset_rules rule COMMENTEND PHPCODE", + /* 20 */ "rules ::= reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE", + /* 21 */ "reset_rules ::= rules COMMENTSTART", + /* 22 */ "rule ::= rule_subpattern CODE", + /* 23 */ "rule ::= rule rule_subpattern CODE", + /* 24 */ "rule_subpattern ::= QUOTE", + /* 25 */ "rule_subpattern ::= SINGLEQUOTE", + /* 26 */ "rule_subpattern ::= SUBPATTERN", + /* 27 */ "rule_subpattern ::= rule_subpattern QUOTE", + /* 28 */ "rule_subpattern ::= rule_subpattern SINGLEQUOTE", + /* 29 */ "rule_subpattern ::= rule_subpattern SUBPATTERN", + /* 30 */ "subpattern ::= QUOTE", + /* 31 */ "subpattern ::= SINGLEQUOTE", + /* 32 */ "subpattern ::= SUBPATTERN", + /* 33 */ "subpattern ::= subpattern QUOTE", + /* 34 */ "subpattern ::= subpattern SINGLEQUOTE", + /* 35 */ "subpattern ::= subpattern SUBPATTERN", + ); + + /** + * This function returns the symbolic name associated with a token + * value. + * @param int + * @return string + */ + function tokenName($tokenType) + { + if ($tokenType === 0) { + return 'End of Input'; + } + if ($tokenType > 0 && $tokenType < count(self::$yyTokenName)) { + return self::$yyTokenName[$tokenType]; + } else { + return "Unknown"; + } + } + + /** + * The following function deletes the value associated with a + * symbol. The symbol can be either a terminal or nonterminal. + * @param int the symbol code + * @param mixed the symbol's value + */ + static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are not used + ** inside the C code. + */ + default: break; /* If no destructor action specified: do nothing */ + } + } + + /** + * Pop the parser's stack once. + * + * If there is a destructor routine associated with the token which + * is popped from the stack, then call it. + * + * Return the major token number for the symbol popped. + * @param PHP_LexerGenerator_ParseryyParser + * @return int + */ + function yy_pop_parser_stack() + { + if (!count($this->yystack)) { + return; + } + $yytos = array_pop($this->yystack); + if (self::$yyTraceFILE && $this->yyidx >= 0) { + fwrite(self::$yyTraceFILE, + self::$yyTracePrompt . 'Popping ' . self::$yyTokenName[$yytos->major] . + "\n"); + } + $yymajor = $yytos->major; + self::yy_destructor($yymajor, $yytos->minor); + $this->yyidx--; + return $yymajor; + } + + /** + * Deallocate and destroy a parser. Destructors are all called for + * all stack elements before shutting the parser down. + */ + function __destruct() + { + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + if (is_resource(self::$yyTraceFILE)) { + fclose(self::$yyTraceFILE); + } + } + + /** + * Based on the current state and parser stack, get a list of all + * possible lookahead tokens + * @param int + * @return array + */ + function yy_get_expected_tokens($token) + { + $state = $this->yystack[$this->yyidx]->stateno; + $expected = self::$yyExpectedTokens[$state]; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return $expected; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return array_unique($expected); + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate])) { + $expected += self::$yyExpectedTokens[$nextstate]; + if (in_array($token, + self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new PHP_LexerGenerator_ParseryyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return array_unique($expected); + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return $expected; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + return array_unique($expected); + } + + /** + * Based on the parser state and current parser stack, determine whether + * the lookahead token is possible. + * + * The parser will convert the token value to an error token if not. This + * catches some unusual edge cases where the parser would fail. + * @param int + * @return bool + */ + function yy_is_expected_token($token) + { + if ($token === 0) { + return true; // 0 is not part of this + } + $state = $this->yystack[$this->yyidx]->stateno; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return true; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return true; + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate]) && + in_array($token, self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new PHP_LexerGenerator_ParseryyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + if (!$token) { + // end of input: this is valid + return true; + } + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return false; + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return true; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + + /** + * Find the appropriate action for a parser given the terminal + * look-ahead token iLookAhead. + * + * If the look-ahead token is YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return YY_NO_ACTION. + * @param int The look-ahead token + */ + function yy_find_shift_action($iLookAhead) + { + $stateno = $this->yystack[$this->yyidx]->stateno; + + /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ + if (!isset(self::$yy_shift_ofst[$stateno])) { + // no shift actions + return self::$yy_default[$stateno]; + } + $i = self::$yy_shift_ofst[$stateno]; + if ($i === self::YY_SHIFT_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) + && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) { + if (self::$yyTraceFILE) { + fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " . + self::$yyTokenName[$iLookAhead] . " => " . + self::$yyTokenName[$iFallback] . "\n"); + } + return $this->yy_find_shift_action($iFallback); + } + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Find the appropriate action for a parser given the non-terminal + * look-ahead token $iLookAhead. + * + * If the look-ahead token is self::YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return self::YY_NO_ACTION. + * @param int Current state number + * @param int The look-ahead token + */ + function yy_find_reduce_action($stateno, $iLookAhead) + { + /* $stateno = $this->yystack[$this->yyidx]->stateno; */ + + if (!isset(self::$yy_reduce_ofst[$stateno])) { + return self::$yy_default[$stateno]; + } + $i = self::$yy_reduce_ofst[$stateno]; + if ($i == self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Perform a shift action. + * @param int The new state to shift in + * @param int The major token to shift in + * @param mixed the minor token to shift in + */ + function yy_shift($yyNewState, $yyMajor, $yypMinor) + { + $this->yyidx++; + if ($this->yyidx >= self::YYSTACKDEPTH) { + $this->yyidx--; + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will execute if the parser + ** stack ever overflows */ + return; + } + $yytos = new PHP_LexerGenerator_ParseryyStackEntry; + $yytos->stateno = $yyNewState; + $yytos->major = $yyMajor; + $yytos->minor = $yypMinor; + array_push($this->yystack, $yytos); + if (self::$yyTraceFILE && $this->yyidx > 0) { + fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt, + $yyNewState); + fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt); + for($i = 1; $i <= $this->yyidx; $i++) { + fprintf(self::$yyTraceFILE, " %s", + self::$yyTokenName[$this->yystack[$i]->major]); + } + fwrite(self::$yyTraceFILE,"\n"); + } + } + + /** + * The following table contains information about every rule that + * is used during the reduce. + * + *
+     * array(
+     *  array(
+     *   int $lhs;         Symbol on the left-hand side of the rule
+     *   int $nrhs;     Number of right-hand side symbols in the rule
+     *  ),...
+     * );
+     * 
+ */ + static public $yyRuleInfo = array( + array( 'lhs' => 11, 'rhs' => 1 ), + array( 'lhs' => 12, 'rhs' => 2 ), + array( 'lhs' => 12, 'rhs' => 3 ), + array( 'lhs' => 12, 'rhs' => 3 ), + array( 'lhs' => 12, 'rhs' => 4 ), + array( 'lhs' => 13, 'rhs' => 3 ), + array( 'lhs' => 15, 'rhs' => 2 ), + array( 'lhs' => 16, 'rhs' => 2 ), + array( 'lhs' => 16, 'rhs' => 2 ), + array( 'lhs' => 16, 'rhs' => 3 ), + array( 'lhs' => 16, 'rhs' => 3 ), + array( 'lhs' => 17, 'rhs' => 2 ), + array( 'lhs' => 17, 'rhs' => 3 ), + array( 'lhs' => 14, 'rhs' => 3 ), + array( 'lhs' => 14, 'rhs' => 5 ), + array( 'lhs' => 14, 'rhs' => 4 ), + array( 'lhs' => 14, 'rhs' => 6 ), + array( 'lhs' => 14, 'rhs' => 3 ), + array( 'lhs' => 14, 'rhs' => 5 ), + array( 'lhs' => 14, 'rhs' => 4 ), + array( 'lhs' => 14, 'rhs' => 6 ), + array( 'lhs' => 20, 'rhs' => 2 ), + array( 'lhs' => 19, 'rhs' => 2 ), + array( 'lhs' => 19, 'rhs' => 3 ), + array( 'lhs' => 21, 'rhs' => 1 ), + array( 'lhs' => 21, 'rhs' => 1 ), + array( 'lhs' => 21, 'rhs' => 1 ), + array( 'lhs' => 21, 'rhs' => 2 ), + array( 'lhs' => 21, 'rhs' => 2 ), + array( 'lhs' => 21, 'rhs' => 2 ), + array( 'lhs' => 18, 'rhs' => 1 ), + array( 'lhs' => 18, 'rhs' => 1 ), + array( 'lhs' => 18, 'rhs' => 1 ), + array( 'lhs' => 18, 'rhs' => 2 ), + array( 'lhs' => 18, 'rhs' => 2 ), + array( 'lhs' => 18, 'rhs' => 2 ), + ); + + /** + * The following table contains a mapping of reduce action to method name + * that handles the reduction. + * + * If a rule is not set, it has no handler. + */ + static public $yyReduceMap = array( + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 8 => 7, + 9 => 9, + 10 => 9, + 11 => 11, + 12 => 12, + 13 => 13, + 14 => 14, + 15 => 15, + 16 => 16, + 17 => 17, + 18 => 18, + 19 => 19, + 20 => 20, + 21 => 21, + 22 => 22, + 23 => 23, + 24 => 24, + 25 => 25, + 26 => 26, + 27 => 27, + 28 => 28, + 29 => 29, + 30 => 30, + 31 => 31, + 32 => 32, + 33 => 33, + 34 => 34, + 35 => 35, + ); + /* Beginning here are the reduction cases. A typical example + ** follows: + ** #line + ** function yy_r0($yymsp){ ... } // User supplied code + ** #line + */ +#line 438 "Parser.y" + function yy_r1(){ + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + foreach ($this->yystack[$this->yyidx + 0]->minor as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } + } +#line 1352 "Parser.php" +#line 472 "Parser.y" + function yy_r2(){ + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + if (strlen($this->yystack[$this->yyidx + -1]->minor)) { + fwrite($this->out, $this->yystack[$this->yyidx + -1]->minor); + } + foreach ($this->yystack[$this->yyidx + 0]->minor as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } + } +#line 1391 "Parser.php" +#line 509 "Parser.y" + function yy_r3(){ + if (strlen($this->yystack[$this->yyidx + -2]->minor)) { + fwrite($this->out, $this->yystack[$this->yyidx + -2]->minor); + } + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + foreach ($this->yystack[$this->yyidx + 0]->minor as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } + } +#line 1430 "Parser.php" +#line 546 "Parser.y" + function yy_r4(){ + if (strlen($this->yystack[$this->yyidx + -3]->minor)) { + fwrite($this->out, $this->yystack[$this->yyidx + -3]->minor); + } + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + if (strlen($this->yystack[$this->yyidx + -1]->minor)) { + fwrite($this->out, $this->yystack[$this->yyidx + -1]->minor); + } + foreach ($this->yystack[$this->yyidx + 0]->minor as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } + } +#line 1472 "Parser.php" +#line 587 "Parser.y" + function yy_r5(){ + $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; + $this->patterns = $this->yystack[$this->yyidx + -1]->minor['patterns']; + $this->_patternIndex = 1; + } +#line 1479 "Parser.php" +#line 593 "Parser.y" + function yy_r6(){ + $expected = array( + 'counter' => true, + 'input' => true, + 'token' => true, + 'value' => true, + 'line' => true, + ); + foreach ($this->yystack[$this->yyidx + -1]->minor as $pi) { + if (isset($expected[$pi['pi']])) { + unset($expected[$pi['pi']]); + continue; + } + if (count($expected)) { + throw new Exception('Processing Instructions "' . + implode(', ', array_keys($expected)) . '" must be defined'); + } + } + $expected = array( + 'caseinsensitive' => true, + 'counter' => true, + 'input' => true, + 'token' => true, + 'value' => true, + 'line' => true, + 'matchlongest' => true, + 'unicode' => true, + ); + foreach ($this->yystack[$this->yyidx + -1]->minor as $pi) { + if (isset($expected[$pi['pi']])) { + $this->{$pi['pi']} = $pi['definition']; + if ($pi['pi'] == 'matchlongest') { + $this->matchlongest = true; + } + continue; + } + $this->error('Unknown processing instruction %' . $pi['pi'] . + ', should be one of "' . implode(', ', array_keys($expected)) . '"'); + } + $this->patternFlags = ($this->caseinsensitive ? 'i' : '') + . ($this->unicode ? 'u' : ''); + $this->_retvalue = array('patterns' => $this->yystack[$this->yyidx + 0]->minor, 'pis' => $this->yystack[$this->yyidx + -1]->minor); + $this->_patternIndex = 1; + } +#line 1525 "Parser.php" +#line 638 "Parser.y" + function yy_r7(){ + $this->_retvalue = array(array('pi' => $this->yystack[$this->yyidx + -1]->minor, 'definition' => $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1530 "Parser.php" +#line 644 "Parser.y" + function yy_r9(){ + $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; + $this->_retvalue[] = array('pi' => $this->yystack[$this->yyidx + -1]->minor, 'definition' => $this->yystack[$this->yyidx + 0]->minor); + } +#line 1536 "Parser.php" +#line 653 "Parser.y" + function yy_r11(){ + $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor => $this->yystack[$this->yyidx + 0]->minor); + // reset internal indicator of where we are in a pattern + $this->_patternIndex = 0; + } +#line 1543 "Parser.php" +#line 658 "Parser.y" + function yy_r12(){ + $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; + if (isset($this->_retvalue[$this->yystack[$this->yyidx + -1]->minor])) { + throw new Exception('Pattern "' . $this->yystack[$this->yyidx + -1]->minor . '" is already defined as "' . + $this->_retvalue[$this->yystack[$this->yyidx + -1]->minor] . '", cannot redefine as "' . $this->yystack[$this->yyidx + 0]->minor->string . '"'); + } + $this->_retvalue[$this->yystack[$this->yyidx + -1]->minor] = $this->yystack[$this->yyidx + 0]->minor; + // reset internal indicator of where we are in a pattern declaration + $this->_patternIndex = 0; + } +#line 1555 "Parser.php" +#line 669 "Parser.y" + function yy_r13(){ + $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -1]->minor, 'code' => '', 'statename' => '')); + } +#line 1560 "Parser.php" +#line 672 "Parser.y" + function yy_r14(){ + if ($this->yystack[$this->yyidx + -3]->minor != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . $this->yystack[$this->yyidx + -3]->minor . ').'); + } + $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -1]->minor, 'code' => '', 'statename' => $this->yystack[$this->yyidx + -2]->minor)); + } +#line 1569 "Parser.php" +#line 679 "Parser.y" + function yy_r15(){ + $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -2]->minor, 'code' => $this->yystack[$this->yyidx + 0]->minor, 'statename' => '')); + } +#line 1574 "Parser.php" +#line 682 "Parser.y" + function yy_r16(){ + if ($this->yystack[$this->yyidx + -4]->minor != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . $this->yystack[$this->yyidx + -4]->minor . ').'); + } + $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -2]->minor, 'code' => $this->yystack[$this->yyidx + 0]->minor, 'statename' => $this->yystack[$this->yyidx + -3]->minor)); + $this->_patternIndex = 1; + } +#line 1584 "Parser.php" +#line 690 "Parser.y" + function yy_r17(){ + $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; + $this->_retvalue[] = array('rules' => $this->yystack[$this->yyidx + -1]->minor, 'code' => '', 'statename' => ''); + $this->_patternIndex = 1; + } +#line 1591 "Parser.php" +#line 695 "Parser.y" + function yy_r18(){ + if ($this->yystack[$this->yyidx + -3]->minor != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . $this->yystack[$this->yyidx + -3]->minor . ').'); + } + $this->_retvalue = $this->yystack[$this->yyidx + -4]->minor; + $this->_retvalue[] = array('rules' => $this->yystack[$this->yyidx + -1]->minor, 'code' => '', 'statename' => $this->yystack[$this->yyidx + -2]->minor); + } +#line 1601 "Parser.php" +#line 703 "Parser.y" + function yy_r19(){ + $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor; + $this->_retvalue[] = array('rules' => $this->yystack[$this->yyidx + -2]->minor, 'code' => $this->yystack[$this->yyidx + 0]->minor, 'statename' => ''); + } +#line 1607 "Parser.php" +#line 707 "Parser.y" + function yy_r20(){ + if ($this->yystack[$this->yyidx + -4]->minor != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . $this->yystack[$this->yyidx + -4]->minor . ').'); + } + $this->_retvalue = $this->yystack[$this->yyidx + -5]->minor; + $this->_retvalue[] = array('rules' => $this->yystack[$this->yyidx + -2]->minor, 'code' => $this->yystack[$this->yyidx + 0]->minor, 'statename' => $this->yystack[$this->yyidx + -3]->minor); + } +#line 1617 "Parser.php" +#line 716 "Parser.y" + function yy_r21(){ + $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; + $this->_patternIndex = 1; + } +#line 1623 "Parser.php" +#line 721 "Parser.y" + function yy_r22(){ + $name = $this->yystack[$this->yyidx + -1]->minor[1]; + $this->yystack[$this->yyidx + -1]->minor = $this->yystack[$this->yyidx + -1]->minor[0]; + $this->yystack[$this->yyidx + -1]->minor = $this->_validatePattern($this->yystack[$this->yyidx + -1]->minor); + $this->_patternIndex += $this->yystack[$this->yyidx + -1]->minor['subpatterns'] + 1; + if (@preg_match('/' . str_replace('/', '\\/', $this->yystack[$this->yyidx + -1]->minor['pattern']) . '/', '')) { + $this->error('Rule "' . $name . '" can match the empty string, this will break lexing'); + } + $this->_retvalue = array(array('pattern' => str_replace('/', '\\/', $this->yystack[$this->yyidx + -1]->minor->string), 'code' => $this->yystack[$this->yyidx + 0]->minor, 'subpatterns' => $this->yystack[$this->yyidx + -1]->minor['subpatterns'])); + } +#line 1635 "Parser.php" +#line 731 "Parser.y" + function yy_r23(){ + $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; + $name = $this->yystack[$this->yyidx + -1]->minor[1]; + $this->yystack[$this->yyidx + -1]->minor = $this->yystack[$this->yyidx + -1]->minor[0]; + $this->yystack[$this->yyidx + -1]->minor = $this->_validatePattern($this->yystack[$this->yyidx + -1]->minor); + $this->_patternIndex += $this->yystack[$this->yyidx + -1]->minor['subpatterns'] + 1; + if (@preg_match('/' . str_replace('/', '\\/', $this->yystack[$this->yyidx + -1]->minor['pattern']) . '/', '')) { + $this->error('Rule "' . $name . '" can match the empty string, this will break lexing'); + } + $this->_retvalue[] = array('pattern' => str_replace('/', '\\/', $this->yystack[$this->yyidx + -1]->minor->string), 'code' => $this->yystack[$this->yyidx + 0]->minor, 'subpatterns' => $this->yystack[$this->yyidx + -1]->minor['subpatterns']); + } +#line 1648 "Parser.php" +#line 743 "Parser.y" + function yy_r24(){ + $this->_retvalue = array(preg_quote($this->yystack[$this->yyidx + 0]->minor, '/'), $this->yystack[$this->yyidx + 0]->minor); + } +#line 1653 "Parser.php" +#line 746 "Parser.y" + function yy_r25(){ + $this->_retvalue = array($this->makeCaseInsensitve(preg_quote($this->yystack[$this->yyidx + 0]->minor, '/')), $this->yystack[$this->yyidx + 0]->minor); + } +#line 1658 "Parser.php" +#line 749 "Parser.y" + function yy_r26(){ + if (!isset($this->patterns[$this->yystack[$this->yyidx + 0]->minor])) { + $this->error('Undefined pattern "' . $this->yystack[$this->yyidx + 0]->minor . '" used in rules'); + throw new Exception('Undefined pattern "' . $this->yystack[$this->yyidx + 0]->minor . '" used in rules'); + } + $this->_retvalue = array($this->patterns[$this->yystack[$this->yyidx + 0]->minor], $this->yystack[$this->yyidx + 0]->minor); + } +#line 1667 "Parser.php" +#line 756 "Parser.y" + function yy_r27(){ + $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor[0] . preg_quote($this->yystack[$this->yyidx + 0]->minor, '/'), $this->yystack[$this->yyidx + -1]->minor[1] . ' ' . $this->yystack[$this->yyidx + 0]->minor); + } +#line 1672 "Parser.php" +#line 759 "Parser.y" + function yy_r28(){ + $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor[0] . $this->makeCaseInsensitve(preg_quote($this->yystack[$this->yyidx + 0]->minor, '/')), $this->yystack[$this->yyidx + -1]->minor[1] . ' ' . $this->yystack[$this->yyidx + 0]->minor); + } +#line 1677 "Parser.php" +#line 762 "Parser.y" + function yy_r29(){ + if (!isset($this->patterns[$this->yystack[$this->yyidx + 0]->minor])) { + $this->error('Undefined pattern "' . $this->yystack[$this->yyidx + 0]->minor . '" used in rules'); + throw new Exception('Undefined pattern "' . $this->yystack[$this->yyidx + 0]->minor . '" used in rules'); + } + $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor[0] . $this->patterns[$this->yystack[$this->yyidx + 0]->minor], $this->yystack[$this->yyidx + -1]->minor[1] . ' ' . $this->yystack[$this->yyidx + 0]->minor); + } +#line 1686 "Parser.php" +#line 770 "Parser.y" + function yy_r30(){ + $this->_retvalue = preg_quote($this->yystack[$this->yyidx + 0]->minor, '/'); + } +#line 1691 "Parser.php" +#line 773 "Parser.y" + function yy_r31(){ + $this->_retvalue = $this->makeCaseInsensitve(preg_quote($this->yystack[$this->yyidx + 0]->minor, '/')); + } +#line 1696 "Parser.php" +#line 776 "Parser.y" + function yy_r32(){ + // increment internal sub-pattern counter + // adjust back-references in pattern based on previous pattern + $test = $this->_validatePattern($this->yystack[$this->yyidx + 0]->minor, true); + $this->_patternIndex += $test['subpatterns']; + $this->_retvalue = $test['pattern']; + } +#line 1705 "Parser.php" +#line 783 "Parser.y" + function yy_r33(){ + $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . preg_quote($this->yystack[$this->yyidx + 0]->minor, '/'); + } +#line 1710 "Parser.php" +#line 786 "Parser.y" + function yy_r34(){ + $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . $this->makeCaseInsensitve(preg_quote($this->yystack[$this->yyidx + 0]->minor, '/')); + } +#line 1715 "Parser.php" +#line 789 "Parser.y" + function yy_r35(){ + // increment internal sub-pattern counter + // adjust back-references in pattern based on previous pattern + $test = $this->_validatePattern($this->yystack[$this->yyidx + 0]->minor, true); + $this->_patternIndex += $test['subpatterns']; + $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . $test['pattern']; + } +#line 1724 "Parser.php" + + /** + * placeholder for the left hand side in a reduce operation. + * + * For a parser with a rule like this: + *
+     * rule(A) ::= B. { A = 1; }
+     * 
+ * + * The parser will translate to something like: + * + * + * function yy_r0(){$this->_retvalue = 1;} + * + */ + private $_retvalue; + + /** + * Perform a reduce action and the shift that must immediately + * follow the reduce. + * + * For a rule such as: + * + *
+     * A ::= B blah C. { dosomething(); }
+     * 
+ * + * This function will first call the action, if any, ("dosomething();" in our + * example), and then it will pop three states from the stack, + * one for each entry on the right-hand side of the expression + * (B, blah, and C in our example rule), and then push the result of the action + * back on to the stack with the resulting state reduced to (as described in the .out + * file) + * @param int Number of the rule by which to reduce + */ + function yy_reduce($yyruleno) + { + //int $yygoto; /* The next state */ + //int $yyact; /* The next action */ + //mixed $yygotominor; /* The LHS of the rule reduced */ + //PHP_LexerGenerator_ParseryyStackEntry $yymsp; /* The top of the parser's stack */ + //int $yysize; /* Amount to pop the stack */ + $yymsp = $this->yystack[$this->yyidx]; + if (self::$yyTraceFILE && $yyruleno >= 0 + && $yyruleno < count(self::$yyRuleName)) { + fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n", + self::$yyTracePrompt, $yyruleno, + self::$yyRuleName[$yyruleno]); + } + + $this->_retvalue = $yy_lefthand_side = null; + if (array_key_exists($yyruleno, self::$yyReduceMap)) { + // call the action + $this->_retvalue = null; + $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}(); + $yy_lefthand_side = $this->_retvalue; + } + $yygoto = self::$yyRuleInfo[$yyruleno]['lhs']; + $yysize = self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= $yysize; + for($i = $yysize; $i; $i--) { + // pop all of the right-hand side parameters + array_pop($this->yystack); + } + $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto); + if ($yyact < self::YYNSTATE) { + /* If we are not debugging and the reduce action popped at least + ** one element off the stack, then we can push the new element back + ** onto the stack here, and skip the stack overflow test in yy_shift(). + ** That gives a significant speed improvement. */ + if (!self::$yyTraceFILE && $yysize) { + $this->yyidx++; + $x = new PHP_LexerGenerator_ParseryyStackEntry; + $x->stateno = $yyact; + $x->major = $yygoto; + $x->minor = $yy_lefthand_side; + $this->yystack[$this->yyidx] = $x; + } else { + $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + } + } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) { + $this->yy_accept(); + } + } + + /** + * The following code executes when the parse fails + * + * Code from %parse_fail is inserted here + */ + function yy_parse_failed() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser fails */ + } + + /** + * The following code executes when a syntax error first occurs. + * + * %syntax_error code is inserted here + * @param int The major type of the error token + * @param mixed The minor type of the error token + */ + function yy_syntax_error($yymajor, $TOKEN) + { +#line 70 "Parser.y" + + echo "Syntax Error on line " . $this->lex->line . ": token '" . + $this->lex->value . "' while parsing rule:"; + foreach ($this->yystack as $entry) { + echo $this->tokenName($entry->major) . ' '; + } + foreach ($this->yy_get_expected_tokens($yymajor) as $token) { + $expect[] = self::$yyTokenName[$token]; + } + throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN + . '), expected one of: ' . implode(',', $expect)); +#line 1849 "Parser.php" + } + + /** + * The following is executed when the parser accepts + * + * %parse_accept code is inserted here + */ + function yy_accept() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $stack = $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser accepts */ + } + + /** + * The main parser program. + * + * The first argument is the major token number. The second is + * the token value string as scanned from the input. + * + * @param int the token number + * @param mixed the token value + * @param mixed any extra arguments that should be passed to handlers + */ + function doParse($yymajor, $yytokenvalue) + { +// $yyact; /* The parser action. */ +// $yyendofinput; /* True if we are at the end of input */ + $yyerrorhit = 0; /* True if yymajor has invoked an error */ + + /* (re)initialize the parser, if necessary */ + if ($this->yyidx === null || $this->yyidx < 0) { + /* if ($yymajor == 0) return; // not sure why this was here... */ + $this->yyidx = 0; + $this->yyerrcnt = -1; + $x = new PHP_LexerGenerator_ParseryyStackEntry; + $x->stateno = 0; + $x->major = 0; + $this->yystack = array(); + array_push($this->yystack, $x); + } + $yyendofinput = ($yymajor==0); + + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sInput %s\n", + self::$yyTracePrompt, self::$yyTokenName[$yymajor]); + } + + do { + $yyact = $this->yy_find_shift_action($yymajor); + if ($yymajor < self::YYERRORSYMBOL && + !$this->yy_is_expected_token($yymajor)) { + // force a syntax error + $yyact = self::YY_ERROR_ACTION; + } + if ($yyact < self::YYNSTATE) { + $this->yy_shift($yyact, $yymajor, $yytokenvalue); + $this->yyerrcnt--; + if ($yyendofinput && $this->yyidx >= 0) { + $yymajor = 0; + } else { + $yymajor = self::YYNOCODE; + } + } elseif ($yyact < self::YYNSTATE + self::YYNRULE) { + $this->yy_reduce($yyact - self::YYNSTATE); + } elseif ($yyact == self::YY_ERROR_ACTION) { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sSyntax Error!\n", + self::$yyTracePrompt); + } + if (self::YYERRORSYMBOL) { + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if ($this->yyerrcnt < 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $yymx = $this->yystack[$this->yyidx]->major; + if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){ + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sDiscard input token %s\n", + self::$yyTracePrompt, self::$yyTokenName[$yymajor]); + } + $this->yy_destructor($yymajor, $yytokenvalue); + $yymajor = self::YYNOCODE; + } else { + while ($this->yyidx >= 0 && + $yymx != self::YYERRORSYMBOL && + ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE + ){ + $this->yy_pop_parser_stack(); + } + if ($this->yyidx < 0 || $yymajor==0) { + $this->yy_destructor($yymajor, $yytokenvalue); + $this->yy_parse_failed(); + $yymajor = self::YYNOCODE; + } elseif ($yymx != self::YYERRORSYMBOL) { + $u2 = 0; + $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); + } + } + $this->yyerrcnt = 3; + $yyerrorhit = 1; + } else { + /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if ($this->yyerrcnt <= 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $this->yyerrcnt = 3; + $this->yy_destructor($yymajor, $yytokenvalue); + if ($yyendofinput) { + $this->yy_parse_failed(); + } + $yymajor = self::YYNOCODE; + } + } else { + $this->yy_accept(); + $yymajor = self::YYNOCODE; + } + } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Parser.y b/core/oql/build/PHP/LexerGenerator/Parser.y new file mode 100644 index 000000000..cfa96d688 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Parser.y @@ -0,0 +1,795 @@ +%name PHP_LexerGenerator_Parser +%declare_class {class PHP_LexerGenerator_Parser} +%include { +/* ?> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category php + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Parser.y 246683 2007-11-22 04:43:52Z instance $ + * @since File available since Release 0.1.0 + */ +/** + * For regular expression validation + */ +require_once 'PHP/LexerGenerator/Regex/Lexer.php'; +require_once 'PHP/LexerGenerator/Regex/Parser.php'; +require_once 'PHP/LexerGenerator/Exception.php'; +/** + * Token parser for plex files. + * + * This parser converts tokens pulled from {@link PHP_LexerGenerator_Lexer} + * into abstract patterns and rules, then creates the output file + * @package PHP_LexerGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version @package_version@ + * @since Class available since Release 0.1.0 + */ +} +%syntax_error { + echo "Syntax Error on line " . $this->lex->line . ": token '" . + $this->lex->value . "' while parsing rule:"; + foreach ($this->yystack as $entry) { + echo $this->tokenName($entry->major) . ' '; + } + foreach ($this->yy_get_expected_tokens($yymajor) as $token) { + $expect[] = self::$yyTokenName[$token]; + } + throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN + . '), expected one of: ' . implode(',', $expect)); +} +%include_class { + private $patterns; + private $out; + private $lex; + private $input; + private $counter; + private $token; + private $value; + private $line; + private $matchlongest; + private $_regexLexer; + private $_regexParser; + private $_patternIndex = 0; + private $_outRuleIndex = 1; + private $caseinsensitive; + private $patternFlags; + private $unicode; + + public $transTable = array( + 1 => self::PHPCODE, + 2 => self::COMMENTSTART, + 3 => self::COMMENTEND, + 4 => self::QUOTE, + 5 => self::SINGLEQUOTE, + 6 => self::PATTERN, + 7 => self::CODE, + 8 => self::SUBPATTERN, + 9 => self::PI, + ); + + function __construct($outfile, $lex) + { + $this->out = fopen($outfile, 'wb'); + if (!$this->out) { + throw new Exception('unable to open lexer output file "' . $outfile . '"'); + } + $this->lex = $lex; + $this->_regexLexer = new PHP_LexerGenerator_Regex_Lexer(''); + $this->_regexParser = new PHP_LexerGenerator_Regex_Parser($this->_regexLexer); + } + + function doLongestMatch($rules, $statename, $ruleindex) + { + fwrite($this->out, ' + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + do { + $rules = array('); + foreach ($rules as $rule) { + fwrite($this->out, ' + \'/\G' . $rule['pattern'] . '/' . $this->patternFlags . ' \','); + } + fwrite($this->out, ' + ); + $match = false; + foreach ($rules as $index => $rule) { + if (preg_match($rule, substr(' . $this->input . ', ' . + $this->counter . '), $yymatches)) { + if ($match) { + if (strlen($yymatches[0]) > strlen($match[0][0])) { + $match = array($yymatches, $index); // matches, token + } + } else { + $match = array($yymatches, $index); + } + } + } + if (!$match) { + throw new Exception(\'Unexpected input at line \' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + ' . $this->token . ' = $match[1]; + ' . $this->value . ' = $match[0][0]; + $yysubmatches = $match[0]; + array_shift($yysubmatches); + if (!$yysubmatches) { + $yysubmatches = array(); + } + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + if ($r === null) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else {'); + fwrite($this->out, ' + $yy_yymore_patterns = array_slice($rules, $this->token, true); + // yymore is needed + do { + if (!isset($yy_yymore_patterns[' . $this->token . '])) { + throw new Exception(\'cannot do yymore for the last token\'); + } + $match = false; + foreach ($yy_yymore_patterns[' . $this->token . '] as $index => $rule) { + if (preg_match(\'/\' . $rule . \'/' . $this->patternFlags . '\', + ' . $this->input . ', $yymatches, null, ' . $this->counter . ')) { + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + if ($match) { + if (strlen($yymatches[0]) > strlen($match[0][0])) { + $match = array($yymatches, $index); // matches, token + } + } else { + $match = array($yymatches, $index); + } + } + } + if (!$match) { + throw new Exception(\'Unexpected input at line \' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + ' . $this->token . ' = $match[1]; + ' . $this->value . ' = $match[0][0]; + $yysubmatches = $match[0]; + array_shift($yysubmatches); + if (!$yysubmatches) { + $yysubmatches = array(); + } + ' . $this->line . ' = substr_count(' . $this->value . ', "\n"); + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}(); + } while ($r !== null || !$r); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else { + // accept + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + return true; + } + } + } while (true); +'); + } + + function doFirstMatch($rules, $statename, $ruleindex) + { + $patterns = array(); + $pattern = '/'; + $ruleMap = array(); + $tokenindex = array(); + $actualindex = 1; + $i = 0; + foreach ($rules as $rule) { + $ruleMap[$i++] = $actualindex; + $tokenindex[$actualindex] = $rule['subpatterns']; + $actualindex += $rule['subpatterns'] + 1; + $patterns[] = '\G(' . $rule['pattern'] . ')'; + } + // Re-index tokencount from zero. + $tokencount = array_values($tokenindex); + $tokenindex = var_export($tokenindex, true); + $tokenindex = explode("\n", $tokenindex); + // indent for prettiness + $tokenindex = implode("\n ", $tokenindex); + $pattern .= implode('|', $patterns); + $pattern .= '/' . $this->patternFlags; + fwrite($this->out, ' + $tokenMap = ' . $tokenindex . '; + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + '); + fwrite($this->out, '$yy_global_pattern = \'' . + $pattern . '\';' . "\n"); + fwrite($this->out, ' + do { + if (preg_match($yy_global_pattern,' . $this->input . ', $yymatches, null, ' . + $this->counter . + ')) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception(\'Error: lexing failed because a rule matched\' . + \' an empty string. Input "\' . substr(' . $this->input . ', + ' . $this->counter . ', 5) . \'... state ' . $statename . '\'); + } + next($yymatches); // skip global match + ' . $this->token . ' = key($yymatches); // token number + if ($tokenMap[' . $this->token . ']) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, ' . $this->token . ' + 1, + $tokenMap[' . $this->token . ']); + } else { + $yysubmatches = array(); + } + ' . $this->value . ' = current($yymatches); // token value + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + if ($r === null) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else {'); + fwrite($this->out, ' + $yy_yymore_patterns = array(' . "\n"); + $extra = 0; + for($i = 0; count($patterns); $i++) { + unset($patterns[$i]); + $extra += $tokencount[0]; + array_shift($tokencount); + fwrite($this->out, ' ' . $ruleMap[$i] . ' => array(' . $extra . ', "' . + implode('|', $patterns) . "\"),\n"); + } + fwrite($this->out, ' );' . "\n"); + fwrite($this->out, ' + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[' . $this->token . '][1])) { + throw new Exception(\'cannot do yymore for the last token\'); + } + $yysubmatches = array(); + if (preg_match(\'/\' . $yy_yymore_patterns[' . $this->token . '][1] . \'/' . $this->patternFlags . '\', + ' . $this->input . ', $yymatches, null, ' . $this->counter .')) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns + next($yymatches); // skip global match + ' . $this->token . ' += key($yymatches) + $yy_yymore_patterns[' . $this->token . '][0]; // token number + ' . $this->value . ' = current($yymatches); // token value + ' . $this->line . ' = substr_count(' . $this->value . ', "\n"); + if ($tokenMap[' . $this->token . ']) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, ' . $this->token . ' + 1, + $tokenMap[' . $this->token . ']); + } else { + $yysubmatches = array(); + } + } + $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + if (' . $this->counter . ' >= strlen(' . $this->input . ')) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + ' . $this->counter . ' += strlen(' . $this->value . '); + ' . $this->line . ' += substr_count(' . $this->value . ', "\n"); + return true; + } + } + } else { + throw new Exception(\'Unexpected input at line\' . ' . $this->line . ' . + \': \' . ' . $this->input . '[' . $this->counter . ']); + } + break; + } while (true); +'); + } + + function makeCaseInsensitve($string) + { + return preg_replace('/[a-z]/ie', "'[\\0'.strtoupper('\\0').']'", strtolower($string)); + } + + function outputRules($rules, $statename) + { + if (!$statename) { + $statename = $this -> _outRuleIndex; + } + fwrite($this->out, ' + function yylex' . $this -> _outRuleIndex . '() + {'); + if ($this->matchlongest) { + $ruleMap = array(); + foreach ($rules as $i => $rule) { + $ruleMap[$i] = $i; + } + $this->doLongestMatch($rules, $statename, $this -> _outRuleIndex); + } else { + $ruleMap = array(); + $actualindex = 1; + $i = 0; + foreach ($rules as $rule) { + $ruleMap[$i++] = $actualindex; + $actualindex += $rule['subpatterns'] + 1; + } + $this->doFirstMatch($rules, $statename, $this -> _outRuleIndex); + } + fwrite($this->out, ' + } // end function + +'); + if (is_string($statename)) { + fwrite($this->out, ' + const ' . $statename . ' = ' . $this -> _outRuleIndex . '; +'); + } + foreach ($rules as $i => $rule) { + fwrite($this->out, ' function yy_r' . $this -> _outRuleIndex . '_' . $ruleMap[$i] . '($yy_subpatterns) + { +' . $rule['code'] . +' } +'); + } + $this -> _outRuleIndex++; // for next set of rules + } + + function error($msg) + { + echo 'Error on line ' . $this->lex->line . ': ' , $msg; + } + + function _validatePattern($pattern, $update = false) + { + $this->_regexLexer->reset($pattern, $this->lex->line); + $this->_regexParser->reset($this->_patternIndex, $update); + try { + while ($this->_regexLexer->yylex()) { + $this->_regexParser->doParse( + $this->_regexLexer->token, $this->_regexLexer->value); + } + $this->_regexParser->doParse(0, 0); + } catch (PHP_LexerGenerator_Exception $e) { + $this->error($e->getMessage()); + throw new PHP_LexerGenerator_Exception('Invalid pattern "' . $pattern . '"'); + } + return $this->_regexParser->result; + } +} + +start ::= lexfile. + +lexfile ::= declare rules(B). { + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + foreach (B as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } +} +lexfile ::= declare(D) PHPCODE(B) rules(C). { + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + if (strlen(B)) { + fwrite($this->out, B); + } + foreach (C as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } +} +lexfile ::= PHPCODE(B) declare(D) rules(C). { + if (strlen(B)) { + fwrite($this->out, B); + } + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + foreach (C as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } +} +lexfile ::= PHPCODE(A) declare(D) PHPCODE(B) rules(C). { + if (strlen(A)) { + fwrite($this->out, A); + } + fwrite($this->out, ' + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{\'yylex\' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + +'); + if (strlen(B)) { + fwrite($this->out, B); + } + foreach (C as $rule) { + $this->outputRules($rule['rules'], $rule['statename']); + if ($rule['code']) { + fwrite($this->out, $rule['code']); + } + } +} + +declare(A) ::= COMMENTSTART declarations(B) COMMENTEND. { + A = B; + $this->patterns = B['patterns']; + $this->_patternIndex = 1; +} + +declarations(A) ::= processing_instructions(B) pattern_declarations(C). { + $expected = array( + 'counter' => true, + 'input' => true, + 'token' => true, + 'value' => true, + 'line' => true, + ); + foreach (B as $pi) { + if (isset($expected[$pi['pi']])) { + unset($expected[$pi['pi']]); + continue; + } + if (count($expected)) { + throw new Exception('Processing Instructions "' . + implode(', ', array_keys($expected)) . '" must be defined'); + } + } + $expected = array( + 'caseinsensitive' => true, + 'counter' => true, + 'input' => true, + 'token' => true, + 'value' => true, + 'line' => true, + 'matchlongest' => true, + 'unicode' => true, + ); + foreach (B as $pi) { + if (isset($expected[$pi['pi']])) { + $this->{$pi['pi']} = $pi['definition']; + if ($pi['pi'] == 'matchlongest') { + $this->matchlongest = true; + } + continue; + } + $this->error('Unknown processing instruction %' . $pi['pi'] . + ', should be one of "' . implode(', ', array_keys($expected)) . '"'); + } + $this->patternFlags = ($this->caseinsensitive ? 'i' : '') + . ($this->unicode ? 'u' : ''); + A = array('patterns' => C, 'pis' => B); + $this->_patternIndex = 1; +} + +processing_instructions(A) ::= PI(B) SUBPATTERN(C). { + A = array(array('pi' => B, 'definition' => C)); +} +processing_instructions(A) ::= PI(B) CODE(C). { + A = array(array('pi' => B, 'definition' => C)); +} +processing_instructions(A) ::= processing_instructions(P) PI(B) SUBPATTERN(C). { + A = P; + A[] = array('pi' => B, 'definition' => C); +} +processing_instructions(A) ::= processing_instructions(P) PI(B) CODE(C). { + A = P; + A[] = array('pi' => B, 'definition' => C); +} + +pattern_declarations(A) ::= PATTERN(B) subpattern(C). { + A = array(B => C); + // reset internal indicator of where we are in a pattern + $this->_patternIndex = 0; +} +pattern_declarations(A) ::= pattern_declarations(B) PATTERN(C) subpattern(D). { + A = B; + if (isset(A[C])) { + throw new Exception('Pattern "' . C . '" is already defined as "' . + A[C] . '", cannot redefine as "' . D->string . '"'); + } + A[C] = D; + // reset internal indicator of where we are in a pattern declaration + $this->_patternIndex = 0; +} + +rules(A) ::= COMMENTSTART rule(B) COMMENTEND. { + A = array(array('rules' => B, 'code' => '', 'statename' => '')); +} +rules(A) ::= COMMENTSTART PI(P) SUBPATTERN(S) rule(B) COMMENTEND. { + if (P != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . P . ').'); + } + A = array(array('rules' => B, 'code' => '', 'statename' => S)); +} +rules(A) ::= COMMENTSTART rule(B) COMMENTEND PHPCODE(C). { + A = array(array('rules' => B, 'code' => C, 'statename' => '')); +} +rules(A) ::= COMMENTSTART PI(P) SUBPATTERN(S) rule(B) COMMENTEND PHPCODE(C). { + if (P != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . P . ').'); + } + A = array(array('rules' => B, 'code' => C, 'statename' => S)); + $this->_patternIndex = 1; +} +rules(A) ::= reset_rules(R) rule(B) COMMENTEND. { + A = R; + A[] = array('rules' => B, 'code' => '', 'statename' => ''); + $this->_patternIndex = 1; +} +rules(A) ::= reset_rules(R) PI(P) SUBPATTERN(S) rule(B) COMMENTEND. { + if (P != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . P . ').'); + } + A = R; + A[] = array('rules' => B, 'code' => '', 'statename' => S); +} +rules(A) ::= reset_rules(R) rule(B) COMMENTEND PHPCODE(C). { + A = R; + A[] = array('rules' => B, 'code' => C, 'statename' => ''); +} +rules(A) ::= reset_rules(R) PI(P) SUBPATTERN(S) rule(B) COMMENTEND PHPCODE(C). { + if (P != 'statename') { + throw new Exception('Error: only %statename processing instruction ' . + 'is allowed in rule sections (found ' . P . ').'); + } + A = R; + A[] = array('rules' => B, 'code' => C, 'statename' => S); +} + +reset_rules(A) ::= rules(R) COMMENTSTART. { + A = R; + $this->_patternIndex = 1; +} + +rule(A) ::= rule_subpattern(B) CODE(C). { + $name = B[1]; + B = B[0]; + B = $this->_validatePattern(B); + $this->_patternIndex += B['subpatterns'] + 1; + if (@preg_match('/' . str_replace('/', '\\/', B['pattern']) . '/', '')) { + $this->error('Rule "' . $name . '" can match the empty string, this will break lexing'); + } + A = array(array('pattern' => str_replace('/', '\\/', B->string), 'code' => C, 'subpatterns' => B['subpatterns'])); +} +rule(A) ::= rule(R) rule_subpattern(B) CODE(C).{ + A = R; + $name = B[1]; + B = B[0]; + B = $this->_validatePattern(B); + $this->_patternIndex += B['subpatterns'] + 1; + if (@preg_match('/' . str_replace('/', '\\/', B['pattern']) . '/', '')) { + $this->error('Rule "' . $name . '" can match the empty string, this will break lexing'); + } + A[] = array('pattern' => str_replace('/', '\\/', B->string), 'code' => C, 'subpatterns' => B['subpatterns']); +} + +rule_subpattern(A) ::= QUOTE(B). { + A = array(preg_quote(B, '/'), B); +} +rule_subpattern(A) ::= SINGLEQUOTE(B). { + A = array($this->makeCaseInsensitve(preg_quote(B, '/')), B); +} +rule_subpattern(A) ::= SUBPATTERN(B). { + if (!isset($this->patterns[B])) { + $this->error('Undefined pattern "' . B . '" used in rules'); + throw new Exception('Undefined pattern "' . B . '" used in rules'); + } + A = array($this->patterns[B], B); +} +rule_subpattern(A) ::= rule_subpattern(B) QUOTE(C). { + A = array(B[0] . preg_quote(C, '/'), B[1] . ' ' . C); +} +rule_subpattern(A) ::= rule_subpattern(B) SINGLEQUOTE(C). { + A = array(B[0] . $this->makeCaseInsensitve(preg_quote(C, '/')), B[1] . ' ' . C); +} +rule_subpattern(A) ::= rule_subpattern(B) SUBPATTERN(C). { + if (!isset($this->patterns[C])) { + $this->error('Undefined pattern "' . C . '" used in rules'); + throw new Exception('Undefined pattern "' . C . '" used in rules'); + } + A = array(B[0] . $this->patterns[C], B[1] . ' ' . C); +} + +subpattern(A) ::= QUOTE(B). { + A = preg_quote(B, '/'); +} +subpattern(A) ::= SINGLEQUOTE(B). { + A = $this->makeCaseInsensitve(preg_quote(B, '/')); +} +subpattern(A) ::= SUBPATTERN(B). { + // increment internal sub-pattern counter + // adjust back-references in pattern based on previous pattern + $test = $this->_validatePattern(B, true); + $this->_patternIndex += $test['subpatterns']; + A = $test['pattern']; +} +subpattern(A) ::= subpattern(B) QUOTE(C). { + A = B . preg_quote(C, '/'); +} +subpattern(A) ::= subpattern(B) SINGLEQUOTE(C). { + A = B . $this->makeCaseInsensitve(preg_quote(C, '/')); +} +subpattern(A) ::= subpattern(B) SUBPATTERN(C). { + // increment internal sub-pattern counter + // adjust back-references in pattern based on previous pattern + $test = $this->_validatePattern(C, true); + $this->_patternIndex += $test['subpatterns']; + A = B . $test['pattern']; +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Regex/Lexer.php b/core/oql/build/PHP/LexerGenerator/Regex/Lexer.php new file mode 100644 index 000000000..f21839d50 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Regex/Lexer.php @@ -0,0 +1,1028 @@ +input = $data; + $this->N = 0; + } + + function reset($data, $line) + { + $this->input = $data; + $this->N = 0; + // passed in from parent parser + $this->line = $line; + $this->yybegin(self::INITIAL); + } + + + private $_yy_state = 1; + private $_yy_stack = array(); + + function yylex() + { + return $this->{'yylex' . $this->_yy_state}(); + } + + function yypushstate($state) + { + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + } + + function yypopstate() + { + $this->_yy_state = array_pop($this->_yy_stack); + } + + function yybegin($state) + { + $this->_yy_state = $state; + } + + + + function yylex1() + { + $tokenMap = array ( + 1 => 0, + 2 => 0, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 0, + 8 => 0, + 9 => 0, + 10 => 0, + 11 => 0, + 12 => 0, + 13 => 0, + 14 => 0, + 15 => 0, + 16 => 0, + 17 => 0, + 18 => 0, + 19 => 0, + 20 => 0, + 21 => 0, + 22 => 0, + 23 => 0, + ); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + $yy_global_pattern = '/\G(\\\\\\\\)|\G([^[\\\\^$.|()?*+{}]+)|\G(\\\\[][{}*.^$|?()+])|\G(\\[)|\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)/'; + + do { + if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->input, + $this->N, 5) . '... state INITIAL'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + $this->value = current($yymatches); // token value + $r = $this->{'yy_r1_' . $this->token}($yysubmatches); + if ($r === null) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + $yy_yymore_patterns = array( + 1 => array(0, "\G([^[\\\\^$.|()?*+{}]+)|\G(\\\\[][{}*.^$|?()+])|\G(\\[)|\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 2 => array(0, "\G(\\\\[][{}*.^$|?()+])|\G(\\[)|\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 3 => array(0, "\G(\\[)|\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 4 => array(0, "\G(\\|)|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 5 => array(0, "\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 6 => array(0, "\G(\\\\[0-9][0-9])|\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 7 => array(0, "\G(\\\\[abBGcedDsSwW0C]|\\\\c\\\\)|\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 8 => array(0, "\G(\\^)|\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 9 => array(0, "\G(\\\\A)|\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 10 => array(0, "\G(\\))|\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 11 => array(0, "\G(\\$)|\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 12 => array(0, "\G(\\*\\?|\\+\\?|[*?+]|\\{[0-9]+\\}|\\{[0-9]+,\\}|\\{[0-9]+,[0-9]+\\})|\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 13 => array(0, "\G(\\\\[zZ])|\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 14 => array(0, "\G(\\(\\?)|\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 15 => array(0, "\G(\\()|\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 16 => array(0, "\G(\\.)|\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 17 => array(0, "\G(\\\\[1-9])|\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 18 => array(0, "\G(\\\\p\\{\\^?..?\\}|\\\\P\\{..?\\}|\\\\X)|\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 19 => array(0, "\G(\\\\p\\{C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 20 => array(0, "\G(\\\\p\\{\\^C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?\\})|\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 21 => array(0, "\G(\\\\p[CLMNPSZ])|\G(\\\\)"), + 22 => array(0, "\G(\\\\)"), + 23 => array(0, ""), + ); + + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[$this->token][1])) { + throw new Exception('cannot do yymore for the last token'); + } + $yysubmatches = array(); + if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/', + $this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + next($yymatches); // skip global match + $this->token += key($yymatches) + $yy_yymore_patterns[$this->token][0]; // token number + $this->value = current($yymatches); // token value + $this->line = substr_count($this->value, "\n"); + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + } + $r = $this->{'yy_r1_' . $this->token}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + return true; + } + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->input[$this->N]); + } + break; + } while (true); + + } // end function + + + const INITIAL = 1; + function yy_r1_1($yy_subpatterns) + { + + $this->token = self::ESCAPEDBACKSLASH; + } + function yy_r1_2($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r1_3($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_4($yy_subpatterns) + { + + $this->token = self::OPENCHARCLASS; + $this->yybegin(self::CHARACTERCLASSSTART); + } + function yy_r1_5($yy_subpatterns) + { + + $this->token = self::BAR; + } + function yy_r1_6($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r1_7($yy_subpatterns) + { + + $this->token = self::COULDBEBACKREF; + } + function yy_r1_8($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_9($yy_subpatterns) + { + + $this->token = self::MATCHSTART; + } + function yy_r1_10($yy_subpatterns) + { + + $this->token = self::MATCHSTART; + } + function yy_r1_11($yy_subpatterns) + { + + $this->token = self::CLOSEPAREN; + $this->yybegin(self::INITIAL); + } + function yy_r1_12($yy_subpatterns) + { + + $this->token = self::MATCHEND; + } + function yy_r1_13($yy_subpatterns) + { + + $this->token = self::MULTIPLIER; + } + function yy_r1_14($yy_subpatterns) + { + + $this->token = self::MATCHEND; + } + function yy_r1_15($yy_subpatterns) + { + + $this->token = self::OPENASSERTION; + $this->yybegin(self::ASSERTION); + } + function yy_r1_16($yy_subpatterns) + { + + $this->token = self::OPENPAREN; + } + function yy_r1_17($yy_subpatterns) + { + + $this->token = self::FULLSTOP; + } + function yy_r1_18($yy_subpatterns) + { + + $this->token = self::BACKREFERENCE; + } + function yy_r1_19($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_20($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_21($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_22($yy_subpatterns) + { + + $this->token = self::CONTROLCHAR; + } + function yy_r1_23($yy_subpatterns) + { + + return false; + } + + + function yylex2() + { + $tokenMap = array ( + 1 => 0, + 2 => 0, + 3 => 0, + ); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + $yy_global_pattern = '/\G(\\^)|\G(\\])|\G(.)/'; + + do { + if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->input, + $this->N, 5) . '... state CHARACTERCLASSSTART'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + $this->value = current($yymatches); // token value + $r = $this->{'yy_r2_' . $this->token}($yysubmatches); + if ($r === null) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + $yy_yymore_patterns = array( + 1 => array(0, "\G(\\])|\G(.)"), + 2 => array(0, "\G(.)"), + 3 => array(0, ""), + ); + + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[$this->token][1])) { + throw new Exception('cannot do yymore for the last token'); + } + $yysubmatches = array(); + if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/', + $this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + next($yymatches); // skip global match + $this->token += key($yymatches) + $yy_yymore_patterns[$this->token][0]; // token number + $this->value = current($yymatches); // token value + $this->line = substr_count($this->value, "\n"); + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + } + $r = $this->{'yy_r2_' . $this->token}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + return true; + } + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->input[$this->N]); + } + break; + } while (true); + + } // end function + + + const CHARACTERCLASSSTART = 2; + function yy_r2_1($yy_subpatterns) + { + + $this->token = self::NEGATE; + } + function yy_r2_2($yy_subpatterns) + { + + $this->yybegin(self::CHARACTERCLASS); + $this->token = self::TEXT; + } + function yy_r2_3($yy_subpatterns) + { + + $this->yybegin(self::CHARACTERCLASS); + return true; + } + + + function yylex3() + { + $tokenMap = array ( + 1 => 0, + 2 => 0, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 0, + 8 => 0, + 9 => 0, + 10 => 0, + 11 => 0, + ); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + $yy_global_pattern = '/\G(\\\\\\\\)|\G(\\])|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)/'; + + do { + if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->input, + $this->N, 5) . '... state CHARACTERCLASS'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + $this->value = current($yymatches); // token value + $r = $this->{'yy_r3_' . $this->token}($yysubmatches); + if ($r === null) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + $yy_yymore_patterns = array( + 1 => array(0, "\G(\\])|\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 2 => array(0, "\G(\\\\[frnt]|\\\\x[0-9a-fA-F][0-9a-fA-F]?|\\\\[0-7][0-7][0-7]|\\\\x\\{[0-9a-fA-F]+\\})|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 3 => array(0, "\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 4 => array(0, "\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 5 => array(0, "\G(\\\\[1-9])|\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 6 => array(0, "\G(\\\\[]\.\-\^])|\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 7 => array(0, "\G(-(?!]))|\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 8 => array(0, "\G([^\-\\\\])|\G(\\\\)|\G(.)"), + 9 => array(0, "\G(\\\\)|\G(.)"), + 10 => array(0, "\G(.)"), + 11 => array(0, ""), + ); + + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[$this->token][1])) { + throw new Exception('cannot do yymore for the last token'); + } + $yysubmatches = array(); + if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/', + $this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + next($yymatches); // skip global match + $this->token += key($yymatches) + $yy_yymore_patterns[$this->token][0]; // token number + $this->value = current($yymatches); // token value + $this->line = substr_count($this->value, "\n"); + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + } + $r = $this->{'yy_r3_' . $this->token}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + return true; + } + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->input[$this->N]); + } + break; + } while (true); + + } // end function + + + const CHARACTERCLASS = 3; + function yy_r3_1($yy_subpatterns) + { + + $this->token = self::ESCAPEDBACKSLASH; + } + function yy_r3_2($yy_subpatterns) + { + + $this->yybegin(self::INITIAL); + $this->token = self::CLOSECHARCLASS; + } + function yy_r3_3($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r3_4($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r3_5($yy_subpatterns) + { + + $this->token = self::COULDBEBACKREF; + } + function yy_r3_6($yy_subpatterns) + { + + $this->token = self::BACKREFERENCE; + } + function yy_r3_7($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r3_8($yy_subpatterns) + { + + $this->token = self::HYPHEN; + $this->yybegin(self::RANGE); + } + function yy_r3_9($yy_subpatterns) + { + + $this->token = self::TEXT; + } + function yy_r3_10($yy_subpatterns) + { + + return false; // ignore escaping of normal text + } + function yy_r3_11($yy_subpatterns) + { + + $this->token = self::TEXT; + } + + + function yylex4() + { + $tokenMap = array ( + 1 => 0, + 2 => 0, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 0, + ); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + $yy_global_pattern = '/\G(\\\\\\\\)|\G(\\\\\\])|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)/'; + + do { + if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->input, + $this->N, 5) . '... state RANGE'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + $this->value = current($yymatches); // token value + $r = $this->{'yy_r4_' . $this->token}($yysubmatches); + if ($r === null) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + $yy_yymore_patterns = array( + 1 => array(0, "\G(\\\\\\])|\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)"), + 2 => array(0, "\G(\\\\[bacedDsSwW0C]|\\\\c\\\\|\\\\x\\{[0-9a-fA-F]+\\}|\\\\[0-7][0-7][0-7]|\\\\x[0-9a-fA-F][0-9a-fA-F]?)|\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)"), + 3 => array(0, "\G(\\\\[0-9][0-9])|\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)"), + 4 => array(0, "\G(\\\\[1-9])|\G([^\-\\\\])|\G(\\\\)"), + 5 => array(0, "\G([^\-\\\\])|\G(\\\\)"), + 6 => array(0, "\G(\\\\)"), + 7 => array(0, ""), + ); + + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[$this->token][1])) { + throw new Exception('cannot do yymore for the last token'); + } + $yysubmatches = array(); + if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/', + $this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + next($yymatches); // skip global match + $this->token += key($yymatches) + $yy_yymore_patterns[$this->token][0]; // token number + $this->value = current($yymatches); // token value + $this->line = substr_count($this->value, "\n"); + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + } + $r = $this->{'yy_r4_' . $this->token}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + return true; + } + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->input[$this->N]); + } + break; + } while (true); + + } // end function + + + const RANGE = 4; + function yy_r4_1($yy_subpatterns) + { + + $this->token = self::ESCAPEDBACKSLASH; + } + function yy_r4_2($yy_subpatterns) + { + + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); + } + function yy_r4_3($yy_subpatterns) + { + + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); + } + function yy_r4_4($yy_subpatterns) + { + + $this->token = self::COULDBEBACKREF; + } + function yy_r4_5($yy_subpatterns) + { + + $this->token = self::BACKREFERENCE; + } + function yy_r4_6($yy_subpatterns) + { + + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); + } + function yy_r4_7($yy_subpatterns) + { + + return false; // ignore escaping of normal text + } + + + function yylex5() + { + $tokenMap = array ( + 1 => 0, + 2 => 0, + 3 => 0, + 4 => 0, + 5 => 0, + 6 => 0, + 7 => 0, + 8 => 0, + 9 => 0, + 10 => 0, + 11 => 0, + 12 => 0, + 13 => 0, + ); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + $yy_global_pattern = '/\G([imsxUX]+-[imsxUX]+|[imsxUX]+|-[imsxUX]+)|\G(:)|\G(\\))|\G(P<[^>]+>)|\G(<=)|\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)/'; + + do { + if (preg_match($yy_global_pattern,$this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + if (!count($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . + ' an empty string. Input "' . substr($this->input, + $this->N, 5) . '... state ASSERTION'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + $this->value = current($yymatches); // token value + $r = $this->{'yy_r5_' . $this->token}($yysubmatches); + if ($r === null) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } elseif ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + $yy_yymore_patterns = array( + 1 => array(0, "\G(:)|\G(\\))|\G(P<[^>]+>)|\G(<=)|\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 2 => array(0, "\G(\\))|\G(P<[^>]+>)|\G(<=)|\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 3 => array(0, "\G(P<[^>]+>)|\G(<=)|\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 4 => array(0, "\G(<=)|\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 5 => array(0, "\G()|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 6 => array(0, "\G(=)|\G(!)|\G(>)|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 7 => array(0, "\G(!)|\G(>)|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 8 => array(0, "\G(>)|\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 9 => array(0, "\G(\\(\\?)|\G(#[^)]+)|\G(R)|\G(.)"), + 10 => array(0, "\G(#[^)]+)|\G(R)|\G(.)"), + 11 => array(0, "\G(R)|\G(.)"), + 12 => array(0, "\G(.)"), + 13 => array(0, ""), + ); + + // yymore is needed + do { + if (!strlen($yy_yymore_patterns[$this->token][1])) { + throw new Exception('cannot do yymore for the last token'); + } + $yysubmatches = array(); + if (preg_match('/' . $yy_yymore_patterns[$this->token][1] . '/', + $this->input, $yymatches, null, $this->N)) { + $yysubmatches = $yymatches; + $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns + next($yymatches); // skip global match + $this->token += key($yymatches) + $yy_yymore_patterns[$this->token][0]; // token number + $this->value = current($yymatches); // token value + $this->line = substr_count($this->value, "\n"); + if ($tokenMap[$this->token]) { + // extract sub-patterns for passing to lex function + $yysubmatches = array_slice($yysubmatches, $this->token + 1, + $tokenMap[$this->token]); + } else { + $yysubmatches = array(); + } + } + $r = $this->{'yy_r5_' . $this->token}($yysubmatches); + } while ($r !== null && !is_bool($r)); + if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } elseif ($r === false) { + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->N >= strlen($this->input)) { + return false; // end of input + } + // skip this token + continue; + } else { + // accept + $this->N += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + return true; + } + } + } else { + throw new Exception('Unexpected input at line' . $this->line . + ': ' . $this->input[$this->N]); + } + break; + } while (true); + + } // end function + + + const ASSERTION = 5; + function yy_r5_1($yy_subpatterns) + { + + $this->token = self::INTERNALOPTIONS; + } + function yy_r5_2($yy_subpatterns) + { + + $this->token = self::COLON; + $this->yybegin(self::INITIAL); + } + function yy_r5_3($yy_subpatterns) + { + + $this->token = self::CLOSEPAREN; + $this->yybegin(self::INITIAL); + } + function yy_r5_4($yy_subpatterns) + { + + $this->token = self::PATTERNNAME; + $this->yybegin(self::INITIAL); + } + function yy_r5_5($yy_subpatterns) + { + + $this->token = self::POSITIVELOOKBEHIND; + $this->yybegin(self::INITIAL); + } + function yy_r5_6($yy_subpatterns) + { + + $this->token = self::NEGATIVELOOKBEHIND; + $this->yybegin(self::INITIAL); + } + function yy_r5_7($yy_subpatterns) + { + + $this->token = self::POSITIVELOOKAHEAD; + $this->yybegin(self::INITIAL); + } + function yy_r5_8($yy_subpatterns) + { + + $this->token = self::NEGATIVELOOKAHEAD; + $this->yybegin(self::INITIAL); + } + function yy_r5_9($yy_subpatterns) + { + + $this->token = self::ONCEONLY; + $this->yybegin(self::INITIAL); + } + function yy_r5_10($yy_subpatterns) + { + + $this->token = self::OPENASSERTION; + } + function yy_r5_11($yy_subpatterns) + { + + $this->token = self::COMMENT; + $this->yybegin(self::INITIAL); + } + function yy_r5_12($yy_subpatterns) + { + + $this->token = self::RECUR; + } + function yy_r5_13($yy_subpatterns) + { + + $this->yybegin(self::INITIAL); + return true; + } + +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Regex/Lexer.plex b/core/oql/build/PHP/LexerGenerator/Regex/Lexer.plex new file mode 100644 index 000000000..c5cad0fa6 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Regex/Lexer.plex @@ -0,0 +1,285 @@ +input = $data; + $this->N = 0; + } + + function reset($data, $line) + { + $this->input = $data; + $this->N = 0; + // passed in from parent parser + $this->line = $line; + $this->yybegin(self::INITIAL); + } + +/*!lex2php +%input {$this->input} +%counter {$this->N} +%token {$this->token} +%value {$this->value} +%line {$this->line} +NONESCAPE = /[^[\\^$.|()?*+{}]+/ +NONESCAPECHARCLASS = /[^\-\\]/ +ESCAPEDTHING = /\\[][{}*.^$|?()+]/ +ESCAPEDCHARCLASSTHING = /\\[]\.\-\^]/ +MULTIPLIER = /\*\?|\+\?|[*?+]|\{[0-9]+\}|\{[0-9]+,\}|\{[0-9]+,[0-9]+\}/ +STRINGCHAR = /\\[frnt]|\\x[0-9a-fA-F][0-9a-fA-F]?|\\[0-7][0-7][0-7]|\\x\{[0-9a-fA-F]+\}/ +CONTROLCHAR = /\\[abBGcedDsSwW0C]|\\c\\/ +COULDBEBACKREF = /\\[0-9][0-9]/ +CHARCLASSCONTROLCHAR = /\\[bacedDsSwW0C]|\\c\\|\\x\{[0-9a-fA-F]+\}|\\[0-7][0-7][0-7]|\\x[0-9a-fA-F][0-9a-fA-F]?/ +SUBJECTEND = /\\[zZ]/ +BACKREF = /\\[1-9]/ +UNICODESTUFF = /\\p\{\^?..?\}|\\P\{..?\}|\\X/ +PROPERTYCODES = /C[cfnos]?|L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|S[ckmo]?|Z[lps]?/ +SIMPLEPROPERTYCODES = /[CLMNPSZ]/ +INTERNALOPTIONS = /[imsxUX]+-[imsxUX]+|[imsxUX]+|-[imsxUX]+/ +ANYTHING = /./ +PATTERNNAME = /[^>]+/ +COMMENT = /#[^)]+/ +HYPHEN = /-(?!])/ +*/ +/*!lex2php +%statename INITIAL +"\\\\" { + $this->token = self::ESCAPEDBACKSLASH; +} +NONESCAPE { + $this->token = self::TEXT; +} +ESCAPEDTHING { + $this->token = self::CONTROLCHAR; +} +"[" { + $this->token = self::OPENCHARCLASS; + $this->yybegin(self::CHARACTERCLASSSTART); +} +"|" { + $this->token = self::BAR; +} +STRINGCHAR { + $this->token = self::TEXT; +} +COULDBEBACKREF { + $this->token = self::COULDBEBACKREF; +} +CONTROLCHAR { + $this->token = self::CONTROLCHAR; +} +"^" { + $this->token = self::MATCHSTART; +} +"\\A" { + $this->token = self::MATCHSTART; +} +")" { + $this->token = self::CLOSEPAREN; + $this->yybegin(self::INITIAL); +} +"$" { + $this->token = self::MATCHEND; +} +MULTIPLIER { + $this->token = self::MULTIPLIER; +} +SUBJECTEND { + $this->token = self::MATCHEND; +} +"(?" { + $this->token = self::OPENASSERTION; + $this->yybegin(self::ASSERTION); +} +"(" { + $this->token = self::OPENPAREN; +} +"." { + $this->token = self::FULLSTOP; +} +BACKREF { + $this->token = self::BACKREFERENCE; +} +UNICODESTUFF { + $this->token = self::CONTROLCHAR; +} +"\\p{" PROPERTYCODES "}" { + $this->token = self::CONTROLCHAR; +} +"\\p{^" PROPERTYCODES "}" { + $this->token = self::CONTROLCHAR; +} +"\\p" SIMPLEPROPERTYCODES { + $this->token = self::CONTROLCHAR; +} +"\\" { + return false; +} +*/ +/*!lex2php +%statename CHARACTERCLASSSTART +"^" { + $this->token = self::NEGATE; +} +"]" { + $this->yybegin(self::CHARACTERCLASS); + $this->token = self::TEXT; +} +ANYTHING { + $this->yybegin(self::CHARACTERCLASS); + return true; +} +*/ +/*!lex2php +%statename CHARACTERCLASS +"\\\\" { + $this->token = self::ESCAPEDBACKSLASH; +} +"]" { + $this->yybegin(self::INITIAL); + $this->token = self::CLOSECHARCLASS; +} +STRINGCHAR { + $this->token = self::TEXT; +} +CHARCLASSCONTROLCHAR { + $this->token = self::TEXT; +} +COULDBEBACKREF { + $this->token = self::COULDBEBACKREF; +} +BACKREF { + $this->token = self::BACKREFERENCE; +} +ESCAPEDCHARCLASSTHING { + $this->token = self::TEXT; +} +HYPHEN { + $this->token = self::HYPHEN; + $this->yybegin(self::RANGE); +} +NONESCAPECHARCLASS { + $this->token = self::TEXT; +} +"\\" { + return false; // ignore escaping of normal text +} +ANYTHING { + $this->token = self::TEXT; +} +*/ +/*!lex2php +%statename RANGE +"\\\\" { + $this->token = self::ESCAPEDBACKSLASH; +} +"\\]" { + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); +} +CHARCLASSCONTROLCHAR { + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); +} +COULDBEBACKREF { + $this->token = self::COULDBEBACKREF; +} +BACKREF { + $this->token = self::BACKREFERENCE; +} +NONESCAPECHARCLASS { + $this->token = self::TEXT; + $this->yybegin(self::CHARACTERCLASS); +} +"\\" { + return false; // ignore escaping of normal text +} +*/ +/*!lex2php +%statename ASSERTION +INTERNALOPTIONS { + $this->token = self::INTERNALOPTIONS; +} +":" { + $this->token = self::COLON; + $this->yybegin(self::INITIAL); +} +")" { + $this->token = self::CLOSEPAREN; + $this->yybegin(self::INITIAL); +} +"P<" PATTERNNAME ">" { + $this->token = self::PATTERNNAME; + $this->yybegin(self::INITIAL); +} +"<=" { + $this->token = self::POSITIVELOOKBEHIND; + $this->yybegin(self::INITIAL); +} +"token = self::NEGATIVELOOKBEHIND; + $this->yybegin(self::INITIAL); +} +"=" { + $this->token = self::POSITIVELOOKAHEAD; + $this->yybegin(self::INITIAL); +} +"!" { + $this->token = self::NEGATIVELOOKAHEAD; + $this->yybegin(self::INITIAL); +} +">" { + $this->token = self::ONCEONLY; + $this->yybegin(self::INITIAL); +} +"(?" { + $this->token = self::OPENASSERTION; +} +COMMENT { + $this->token = self::COMMENT; + $this->yybegin(self::INITIAL); +} +"R" { + $this->token = self::RECUR; +} +ANYTHING { + $this->yybegin(self::INITIAL); + return true; +} +*/ +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Regex/Parser.out b/core/oql/build/PHP/LexerGenerator/Regex/Parser.out new file mode 100644 index 000000000..752e2c3d6 --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Regex/Parser.out @@ -0,0 +1,2568 @@ +State 0: + start ::= * pattern + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + start accept + pattern shift 45 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 1: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= OPENASSERTION NEGATIVELOOKAHEAD * pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 37 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 2: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= OPENASSERTION COLON * pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + grouping ::= OPENASSERTION COLON * pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 30 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 3: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN * pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN * pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 33 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 4: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= OPENASSERTION NEGATIVELOOKBEHIND * pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 34 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 5: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= OPENASSERTION POSITIVELOOKAHEAD * pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 40 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 6: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + assertion ::= OPENASSERTION INTERNALOPTIONS COLON * pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 25 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 7: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= OPENASSERTION lookahead * pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION lookahead * pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 39 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 8: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= OPENASSERTION lookbehind * pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION lookbehind * pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 32 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 9: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= OPENPAREN * pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + subpattern ::= OPENPAREN * pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 28 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 10: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= OPENASSERTION PATTERNNAME * pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= OPENASSERTION PATTERNNAME * pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 35 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 11: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= OPENASSERTION POSITIVELOOKBEHIND * pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 38 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 12: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + pattern ::= pattern BAR * pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 92 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 13: + pattern ::= * MATCHSTART basic_pattern MATCHEND + pattern ::= * MATCHSTART basic_pattern + pattern ::= * basic_pattern MATCHEND + pattern ::= * basic_pattern + pattern ::= * pattern BAR pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + onceonly ::= OPENASSERTION ONCEONLY * pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHSTART shift 14 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + pattern shift 36 + basic_pattern shift 15 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 14: + pattern ::= MATCHSTART * basic_pattern MATCHEND + pattern ::= MATCHSTART * basic_pattern + basic_pattern ::= * basic_text + basic_pattern ::= * character_class + basic_pattern ::= * assertion + basic_pattern ::= * grouping + basic_pattern ::= * lookahead + basic_pattern ::= * lookbehind + basic_pattern ::= * subpattern + basic_pattern ::= * onceonly + basic_pattern ::= * comment + basic_pattern ::= * recur + basic_pattern ::= * conditional + basic_pattern ::= * basic_pattern basic_text + basic_pattern ::= * basic_pattern character_class + basic_pattern ::= * basic_pattern assertion + basic_pattern ::= * basic_pattern grouping + basic_pattern ::= * basic_pattern lookahead + basic_pattern ::= * basic_pattern lookbehind + basic_pattern ::= * basic_pattern subpattern + basic_pattern ::= * basic_pattern onceonly + basic_pattern ::= * basic_pattern comment + basic_pattern ::= * basic_pattern recur + basic_pattern ::= * basic_pattern conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + basic_pattern shift 16 + basic_text shift 23 + character_class shift 104 + assertion shift 106 + grouping shift 107 + lookahead shift 109 + lookbehind shift 108 + subpattern shift 118 + onceonly shift 119 + comment shift 129 + recur shift 128 + conditional shift 130 + +State 15: + pattern ::= basic_pattern * MATCHEND + (4) pattern ::= basic_pattern * + basic_pattern ::= basic_pattern * basic_text + basic_pattern ::= basic_pattern * character_class + basic_pattern ::= basic_pattern * assertion + basic_pattern ::= basic_pattern * grouping + basic_pattern ::= basic_pattern * lookahead + basic_pattern ::= basic_pattern * lookbehind + basic_pattern ::= basic_pattern * subpattern + basic_pattern ::= basic_pattern * onceonly + basic_pattern ::= basic_pattern * comment + basic_pattern ::= basic_pattern * recur + basic_pattern ::= basic_pattern * conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHEND shift 117 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + basic_text shift 22 + character_class shift 72 + assertion shift 76 + grouping shift 85 + lookahead shift 84 + lookbehind shift 82 + subpattern shift 81 + onceonly shift 80 + comment shift 97 + recur shift 134 + conditional shift 125 + {default} reduce 4 + +State 16: + pattern ::= MATCHSTART basic_pattern * MATCHEND + (2) pattern ::= MATCHSTART basic_pattern * + basic_pattern ::= basic_pattern * basic_text + basic_pattern ::= basic_pattern * character_class + basic_pattern ::= basic_pattern * assertion + basic_pattern ::= basic_pattern * grouping + basic_pattern ::= basic_pattern * lookahead + basic_pattern ::= basic_pattern * lookbehind + basic_pattern ::= basic_pattern * subpattern + basic_pattern ::= basic_pattern * onceonly + basic_pattern ::= basic_pattern * comment + basic_pattern ::= basic_pattern * recur + basic_pattern ::= basic_pattern * conditional + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS + character_class ::= * OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= * OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + basic_text ::= * TEXT + basic_text ::= * TEXT MULTIPLIER + basic_text ::= * FULLSTOP + basic_text ::= * FULLSTOP MULTIPLIER + basic_text ::= * CONTROLCHAR + basic_text ::= * CONTROLCHAR MULTIPLIER + basic_text ::= * ESCAPEDBACKSLASH + basic_text ::= * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * BACKREFERENCE + basic_text ::= * BACKREFERENCE MULTIPLIER + basic_text ::= * COULDBEBACKREF + basic_text ::= * COULDBEBACKREF MULTIPLIER + basic_text ::= * basic_text TEXT + basic_text ::= * basic_text TEXT MULTIPLIER + basic_text ::= * basic_text FULLSTOP + basic_text ::= * basic_text FULLSTOP MULTIPLIER + basic_text ::= * basic_text CONTROLCHAR + basic_text ::= * basic_text CONTROLCHAR MULTIPLIER + basic_text ::= * basic_text ESCAPEDBACKSLASH + basic_text ::= * basic_text ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= * basic_text BACKREFERENCE + basic_text ::= * basic_text BACKREFERENCE MULTIPLIER + basic_text ::= * basic_text COULDBEBACKREF + basic_text ::= * basic_text COULDBEBACKREF MULTIPLIER + assertion ::= * OPENASSERTION INTERNALOPTIONS CLOSEPAREN + assertion ::= * OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN + grouping ::= * OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN + conditional ::= * OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN + subpattern ::= * OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER + subpattern ::= * OPENPAREN pattern CLOSEPAREN + subpattern ::= * OPENPAREN pattern CLOSEPAREN MULTIPLIER + onceonly ::= * OPENASSERTION ONCEONLY pattern CLOSEPAREN + comment ::= * OPENASSERTION COMMENT CLOSEPAREN + recur ::= * OPENASSERTION RECUR CLOSEPAREN + + OPENPAREN shift 9 + OPENASSERTION shift 17 + MATCHEND shift 91 + OPENCHARCLASS shift 18 + TEXT shift 52 + ESCAPEDBACKSLASH shift 43 + BACKREFERENCE shift 44 + COULDBEBACKREF shift 57 + CONTROLCHAR shift 42 + FULLSTOP shift 41 + basic_text shift 22 + character_class shift 72 + assertion shift 76 + grouping shift 85 + lookahead shift 84 + lookbehind shift 82 + subpattern shift 81 + onceonly shift 80 + comment shift 97 + recur shift 134 + conditional shift 125 + {default} reduce 2 + +State 17: + assertion ::= OPENASSERTION * INTERNALOPTIONS CLOSEPAREN + assertion ::= OPENASSERTION * INTERNALOPTIONS COLON pattern CLOSEPAREN + grouping ::= OPENASSERTION * COLON pattern CLOSEPAREN + grouping ::= OPENASSERTION * COLON pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION * OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION * OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN + conditional ::= OPENASSERTION * lookahead pattern CLOSEPAREN + conditional ::= OPENASSERTION * lookahead pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION * lookbehind pattern CLOSEPAREN + conditional ::= OPENASSERTION * lookbehind pattern CLOSEPAREN MULTIPLIER + lookahead ::= * OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= OPENASSERTION * POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= * OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= OPENASSERTION * NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= OPENASSERTION * POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= * OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= OPENASSERTION * NEGATIVELOOKBEHIND pattern CLOSEPAREN + subpattern ::= OPENASSERTION * PATTERNNAME pattern CLOSEPAREN + subpattern ::= OPENASSERTION * PATTERNNAME pattern CLOSEPAREN MULTIPLIER + onceonly ::= OPENASSERTION * ONCEONLY pattern CLOSEPAREN + comment ::= OPENASSERTION * COMMENT CLOSEPAREN + recur ::= OPENASSERTION * RECUR CLOSEPAREN + + OPENPAREN shift 54 + OPENASSERTION shift 24 + INTERNALOPTIONS shift 26 + COLON shift 2 + POSITIVELOOKAHEAD shift 5 + NEGATIVELOOKAHEAD shift 1 + POSITIVELOOKBEHIND shift 11 + NEGATIVELOOKBEHIND shift 4 + PATTERNNAME shift 10 + ONCEONLY shift 13 + COMMENT shift 49 + RECUR shift 50 + lookahead shift 7 + lookbehind shift 8 + +State 18: + character_class ::= OPENCHARCLASS * character_class_contents CLOSECHARCLASS + character_class ::= OPENCHARCLASS * NEGATE character_class_contents CLOSECHARCLASS + character_class ::= OPENCHARCLASS * character_class_contents CLOSECHARCLASS MULTIPLIER + character_class ::= OPENCHARCLASS * NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER + character_class_contents ::= * TEXT + character_class_contents ::= * ESCAPEDBACKSLASH + character_class_contents ::= * ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= * TEXT HYPHEN TEXT + character_class_contents ::= * TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= * BACKREFERENCE + character_class_contents ::= * COULDBEBACKREF + character_class_contents ::= * character_class_contents CONTROLCHAR + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH + character_class_contents ::= * character_class_contents TEXT + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH HYPHEN CONTROLCHAR + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= * character_class_contents TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= * character_class_contents TEXT HYPHEN TEXT + character_class_contents ::= * character_class_contents BACKREFERENCE + character_class_contents ::= * character_class_contents COULDBEBACKREF + + NEGATE shift 19 + TEXT shift 67 + ESCAPEDBACKSLASH shift 69 + BACKREFERENCE shift 101 + COULDBEBACKREF shift 87 + character_class_contents shift 20 + +State 19: + character_class ::= OPENCHARCLASS NEGATE * character_class_contents CLOSECHARCLASS + character_class ::= OPENCHARCLASS NEGATE * character_class_contents CLOSECHARCLASS MULTIPLIER + character_class_contents ::= * TEXT + character_class_contents ::= * ESCAPEDBACKSLASH + character_class_contents ::= * ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= * TEXT HYPHEN TEXT + character_class_contents ::= * TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= * BACKREFERENCE + character_class_contents ::= * COULDBEBACKREF + character_class_contents ::= * character_class_contents CONTROLCHAR + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH + character_class_contents ::= * character_class_contents TEXT + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH HYPHEN CONTROLCHAR + character_class_contents ::= * character_class_contents ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= * character_class_contents TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= * character_class_contents TEXT HYPHEN TEXT + character_class_contents ::= * character_class_contents BACKREFERENCE + character_class_contents ::= * character_class_contents COULDBEBACKREF + + TEXT shift 67 + ESCAPEDBACKSLASH shift 69 + BACKREFERENCE shift 101 + COULDBEBACKREF shift 87 + character_class_contents shift 21 + +State 20: + character_class ::= OPENCHARCLASS character_class_contents * CLOSECHARCLASS + character_class ::= OPENCHARCLASS character_class_contents * CLOSECHARCLASS MULTIPLIER + character_class_contents ::= character_class_contents * CONTROLCHAR + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents * TEXT + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH HYPHEN CONTROLCHAR + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= character_class_contents * TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents * TEXT HYPHEN TEXT + character_class_contents ::= character_class_contents * BACKREFERENCE + character_class_contents ::= character_class_contents * COULDBEBACKREF + + CLOSECHARCLASS shift 59 + TEXT shift 60 + ESCAPEDBACKSLASH shift 68 + BACKREFERENCE shift 111 + COULDBEBACKREF shift 116 + CONTROLCHAR shift 122 + +State 21: + character_class ::= OPENCHARCLASS NEGATE character_class_contents * CLOSECHARCLASS + character_class ::= OPENCHARCLASS NEGATE character_class_contents * CLOSECHARCLASS MULTIPLIER + character_class_contents ::= character_class_contents * CONTROLCHAR + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents * TEXT + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH HYPHEN CONTROLCHAR + character_class_contents ::= character_class_contents * ESCAPEDBACKSLASH HYPHEN TEXT + character_class_contents ::= character_class_contents * TEXT HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents * TEXT HYPHEN TEXT + character_class_contents ::= character_class_contents * BACKREFERENCE + character_class_contents ::= character_class_contents * COULDBEBACKREF + + CLOSECHARCLASS shift 61 + TEXT shift 60 + ESCAPEDBACKSLASH shift 68 + BACKREFERENCE shift 111 + COULDBEBACKREF shift 116 + CONTROLCHAR shift 122 + +State 22: + (17) basic_pattern ::= basic_pattern basic_text * + basic_text ::= basic_text * TEXT + basic_text ::= basic_text * TEXT MULTIPLIER + basic_text ::= basic_text * FULLSTOP + basic_text ::= basic_text * FULLSTOP MULTIPLIER + basic_text ::= basic_text * CONTROLCHAR + basic_text ::= basic_text * CONTROLCHAR MULTIPLIER + basic_text ::= basic_text * ESCAPEDBACKSLASH + basic_text ::= basic_text * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= basic_text * BACKREFERENCE + basic_text ::= basic_text * BACKREFERENCE MULTIPLIER + basic_text ::= basic_text * COULDBEBACKREF + basic_text ::= basic_text * COULDBEBACKREF MULTIPLIER + + TEXT shift 64 + TEXT reduce 17 ** Parsing conflict ** + ESCAPEDBACKSLASH shift 63 + ESCAPEDBACKSLASH reduce 17 ** Parsing conflict ** + BACKREFERENCE shift 62 + BACKREFERENCE reduce 17 ** Parsing conflict ** + COULDBEBACKREF shift 58 + COULDBEBACKREF reduce 17 ** Parsing conflict ** + CONTROLCHAR shift 66 + CONTROLCHAR reduce 17 ** Parsing conflict ** + FULLSTOP shift 65 + FULLSTOP reduce 17 ** Parsing conflict ** + {default} reduce 17 + +State 23: + (6) basic_pattern ::= basic_text * + basic_text ::= basic_text * TEXT + basic_text ::= basic_text * TEXT MULTIPLIER + basic_text ::= basic_text * FULLSTOP + basic_text ::= basic_text * FULLSTOP MULTIPLIER + basic_text ::= basic_text * CONTROLCHAR + basic_text ::= basic_text * CONTROLCHAR MULTIPLIER + basic_text ::= basic_text * ESCAPEDBACKSLASH + basic_text ::= basic_text * ESCAPEDBACKSLASH MULTIPLIER + basic_text ::= basic_text * BACKREFERENCE + basic_text ::= basic_text * BACKREFERENCE MULTIPLIER + basic_text ::= basic_text * COULDBEBACKREF + basic_text ::= basic_text * COULDBEBACKREF MULTIPLIER + + TEXT shift 64 + TEXT reduce 6 ** Parsing conflict ** + ESCAPEDBACKSLASH shift 63 + ESCAPEDBACKSLASH reduce 6 ** Parsing conflict ** + BACKREFERENCE shift 62 + BACKREFERENCE reduce 6 ** Parsing conflict ** + COULDBEBACKREF shift 58 + COULDBEBACKREF reduce 6 ** Parsing conflict ** + CONTROLCHAR shift 66 + CONTROLCHAR reduce 6 ** Parsing conflict ** + FULLSTOP shift 65 + FULLSTOP reduce 6 ** Parsing conflict ** + {default} reduce 6 + +State 24: + lookahead ::= OPENASSERTION * POSITIVELOOKAHEAD pattern CLOSEPAREN + lookahead ::= OPENASSERTION * NEGATIVELOOKAHEAD pattern CLOSEPAREN + lookbehind ::= OPENASSERTION * POSITIVELOOKBEHIND pattern CLOSEPAREN + lookbehind ::= OPENASSERTION * NEGATIVELOOKBEHIND pattern CLOSEPAREN + + POSITIVELOOKAHEAD shift 5 + NEGATIVELOOKAHEAD shift 1 + POSITIVELOOKBEHIND shift 11 + NEGATIVELOOKBEHIND shift 4 + +State 25: + pattern ::= pattern * BAR pattern + assertion ::= OPENASSERTION INTERNALOPTIONS COLON pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 133 + +State 26: + assertion ::= OPENASSERTION INTERNALOPTIONS * CLOSEPAREN + assertion ::= OPENASSERTION INTERNALOPTIONS * COLON pattern CLOSEPAREN + + CLOSEPAREN shift 112 + COLON shift 6 + +State 27: + character_class_contents ::= character_class_contents TEXT HYPHEN * ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents TEXT HYPHEN * TEXT + + TEXT shift 105 + ESCAPEDBACKSLASH shift 131 + +State 28: + pattern ::= pattern * BAR pattern + subpattern ::= OPENPAREN pattern * CLOSEPAREN + subpattern ::= OPENPAREN pattern * CLOSEPAREN MULTIPLIER + + BAR shift 12 + CLOSEPAREN shift 56 + +State 29: + character_class_contents ::= TEXT HYPHEN * TEXT + character_class_contents ::= TEXT HYPHEN * ESCAPEDBACKSLASH + + TEXT shift 113 + ESCAPEDBACKSLASH shift 124 + +State 30: + pattern ::= pattern * BAR pattern + grouping ::= OPENASSERTION COLON pattern * CLOSEPAREN + grouping ::= OPENASSERTION COLON pattern * CLOSEPAREN MULTIPLIER + + BAR shift 12 + CLOSEPAREN shift 53 + +State 31: + character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN * CONTROLCHAR + character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN * TEXT + + TEXT shift 127 + CONTROLCHAR shift 126 + +State 32: + pattern ::= pattern * BAR pattern + conditional ::= OPENASSERTION lookbehind pattern * CLOSEPAREN + conditional ::= OPENASSERTION lookbehind pattern * CLOSEPAREN MULTIPLIER + + BAR shift 12 + CLOSEPAREN shift 47 + +State 33: + pattern ::= pattern * BAR pattern + conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern * CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 46 + +State 34: + pattern ::= pattern * BAR pattern + lookbehind ::= OPENASSERTION NEGATIVELOOKBEHIND pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 98 + +State 35: + pattern ::= pattern * BAR pattern + subpattern ::= OPENASSERTION PATTERNNAME pattern * CLOSEPAREN + subpattern ::= OPENASSERTION PATTERNNAME pattern * CLOSEPAREN MULTIPLIER + + BAR shift 12 + CLOSEPAREN shift 48 + +State 36: + pattern ::= pattern * BAR pattern + onceonly ::= OPENASSERTION ONCEONLY pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 88 + +State 37: + pattern ::= pattern * BAR pattern + lookahead ::= OPENASSERTION NEGATIVELOOKAHEAD pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 77 + +State 38: + pattern ::= pattern * BAR pattern + lookbehind ::= OPENASSERTION POSITIVELOOKBEHIND pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 102 + +State 39: + pattern ::= pattern * BAR pattern + conditional ::= OPENASSERTION lookahead pattern * CLOSEPAREN + conditional ::= OPENASSERTION lookahead pattern * CLOSEPAREN MULTIPLIER + + BAR shift 12 + CLOSEPAREN shift 51 + +State 40: + pattern ::= pattern * BAR pattern + lookahead ::= OPENASSERTION POSITIVELOOKAHEAD pattern * CLOSEPAREN + + BAR shift 12 + CLOSEPAREN shift 71 + +State 41: + (50) basic_text ::= FULLSTOP * + basic_text ::= FULLSTOP * MULTIPLIER + + MULTIPLIER shift 94 + {default} reduce 50 + +State 42: + (52) basic_text ::= CONTROLCHAR * + basic_text ::= CONTROLCHAR * MULTIPLIER + + MULTIPLIER shift 96 + {default} reduce 52 + +State 43: + (54) basic_text ::= ESCAPEDBACKSLASH * + basic_text ::= ESCAPEDBACKSLASH * MULTIPLIER + + MULTIPLIER shift 75 + {default} reduce 54 + +State 44: + (56) basic_text ::= BACKREFERENCE * + basic_text ::= BACKREFERENCE * MULTIPLIER + + MULTIPLIER shift 132 + {default} reduce 56 + +State 45: + (0) start ::= pattern * + pattern ::= pattern * BAR pattern + + BAR shift 12 + {default} reduce 0 + +State 46: + conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN * MULTIPLIER + (77) conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN * + + MULTIPLIER shift 103 + {default} reduce 77 + +State 47: + (80) conditional ::= OPENASSERTION lookbehind pattern CLOSEPAREN * + conditional ::= OPENASSERTION lookbehind pattern CLOSEPAREN * MULTIPLIER + + MULTIPLIER shift 78 + {default} reduce 80 + +State 48: + (86) subpattern ::= OPENASSERTION PATTERNNAME pattern CLOSEPAREN * + subpattern ::= OPENASSERTION PATTERNNAME pattern CLOSEPAREN * MULTIPLIER + + MULTIPLIER shift 95 + {default} reduce 86 + +State 49: + comment ::= OPENASSERTION COMMENT * CLOSEPAREN + + CLOSEPAREN shift 90 + +State 50: + recur ::= OPENASSERTION RECUR * CLOSEPAREN + + CLOSEPAREN shift 93 + +State 51: + (78) conditional ::= OPENASSERTION lookahead pattern CLOSEPAREN * + conditional ::= OPENASSERTION lookahead pattern CLOSEPAREN * MULTIPLIER + + MULTIPLIER shift 79 + {default} reduce 78 + +State 52: + (48) basic_text ::= TEXT * + basic_text ::= TEXT * MULTIPLIER + + MULTIPLIER shift 120 + {default} reduce 48 + +State 53: + (74) grouping ::= OPENASSERTION COLON pattern CLOSEPAREN * + grouping ::= OPENASSERTION COLON pattern CLOSEPAREN * MULTIPLIER + + MULTIPLIER shift 121 + {default} reduce 74 + +State 54: + conditional ::= OPENASSERTION OPENPAREN * TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION OPENPAREN * TEXT CLOSEPAREN pattern CLOSEPAREN + + TEXT shift 55 + +State 55: + conditional ::= OPENASSERTION OPENPAREN TEXT * CLOSEPAREN pattern CLOSEPAREN MULTIPLIER + conditional ::= OPENASSERTION OPENPAREN TEXT * CLOSEPAREN pattern CLOSEPAREN + + CLOSEPAREN shift 3 + +State 56: + (88) subpattern ::= OPENPAREN pattern CLOSEPAREN * + subpattern ::= OPENPAREN pattern CLOSEPAREN * MULTIPLIER + + MULTIPLIER shift 110 + {default} reduce 88 + +State 57: + (58) basic_text ::= COULDBEBACKREF * + basic_text ::= COULDBEBACKREF * MULTIPLIER + + MULTIPLIER shift 114 + {default} reduce 58 + +State 58: + (70) basic_text ::= basic_text COULDBEBACKREF * + basic_text ::= basic_text COULDBEBACKREF * MULTIPLIER + + MULTIPLIER shift 74 + {default} reduce 70 + +State 59: + (28) character_class ::= OPENCHARCLASS character_class_contents CLOSECHARCLASS * + character_class ::= OPENCHARCLASS character_class_contents CLOSECHARCLASS * MULTIPLIER + + MULTIPLIER shift 123 + {default} reduce 28 + +State 60: + (41) character_class_contents ::= character_class_contents TEXT * + character_class_contents ::= character_class_contents TEXT * HYPHEN ESCAPEDBACKSLASH + character_class_contents ::= character_class_contents TEXT * HYPHEN TEXT + + HYPHEN shift 27 + {default} reduce 41 + +State 61: + (29) character_class ::= OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS * + character_class ::= OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS * MULTIPLIER + + MULTIPLIER shift 115 + {default} reduce 29 + +State 62: + (68) basic_text ::= basic_text BACKREFERENCE * + basic_text ::= basic_text BACKREFERENCE * MULTIPLIER + + MULTIPLIER shift 73 + {default} reduce 68 + +State 63: + (66) basic_text ::= basic_text ESCAPEDBACKSLASH * + basic_text ::= basic_text ESCAPEDBACKSLASH * MULTIPLIER + + MULTIPLIER shift 86 + {default} reduce 66 + +State 64: + (60) basic_text ::= basic_text TEXT * + basic_text ::= basic_text TEXT * MULTIPLIER + + MULTIPLIER shift 89 + {default} reduce 60 + +State 65: + (62) basic_text ::= basic_text FULLSTOP * + basic_text ::= basic_text FULLSTOP * MULTIPLIER + + MULTIPLIER shift 100 + {default} reduce 62 + +State 66: + (64) basic_text ::= basic_text CONTROLCHAR * + basic_text ::= basic_text CONTROLCHAR * MULTIPLIER + + MULTIPLIER shift 99 + {default} reduce 64 + +State 67: + (32) character_class_contents ::= TEXT * + character_class_contents ::= TEXT * HYPHEN TEXT + character_class_contents ::= TEXT * HYPHEN ESCAPEDBACKSLASH + + HYPHEN shift 29 + {default} reduce 32 + +State 68: + (40) character_class_contents ::= character_class_contents ESCAPEDBACKSLASH * + character_class_contents ::= character_class_contents ESCAPEDBACKSLASH * HYPHEN CONTROLCHAR + character_class_contents ::= character_class_contents ESCAPEDBACKSLASH * HYPHEN TEXT + + HYPHEN shift 31 + {default} reduce 40 + +State 69: + (33) character_class_contents ::= ESCAPEDBACKSLASH * + character_class_contents ::= ESCAPEDBACKSLASH * HYPHEN TEXT + + HYPHEN shift 70 + {default} reduce 33 + +State 70: + character_class_contents ::= ESCAPEDBACKSLASH HYPHEN * TEXT + + TEXT shift 83 + +State 71: + (82) lookahead ::= OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN * + + {default} reduce 82 + +State 72: + (18) basic_pattern ::= basic_pattern character_class * + + {default} reduce 18 + +State 73: + (69) basic_text ::= basic_text BACKREFERENCE MULTIPLIER * + + {default} reduce 69 + +State 74: + (71) basic_text ::= basic_text COULDBEBACKREF MULTIPLIER * + + {default} reduce 71 + +State 75: + (55) basic_text ::= ESCAPEDBACKSLASH MULTIPLIER * + + {default} reduce 55 + +State 76: + (19) basic_pattern ::= basic_pattern assertion * + + {default} reduce 19 + +State 77: + (83) lookahead ::= OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN * + + {default} reduce 83 + +State 78: + (81) conditional ::= OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 81 + +State 79: + (79) conditional ::= OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 79 + +State 80: + (24) basic_pattern ::= basic_pattern onceonly * + + {default} reduce 24 + +State 81: + (23) basic_pattern ::= basic_pattern subpattern * + + {default} reduce 23 + +State 82: + (22) basic_pattern ::= basic_pattern lookbehind * + + {default} reduce 22 + +State 83: + (34) character_class_contents ::= ESCAPEDBACKSLASH HYPHEN TEXT * + + {default} reduce 34 + +State 84: + (21) basic_pattern ::= basic_pattern lookahead * + + {default} reduce 21 + +State 85: + (20) basic_pattern ::= basic_pattern grouping * + + {default} reduce 20 + +State 86: + (67) basic_text ::= basic_text ESCAPEDBACKSLASH MULTIPLIER * + + {default} reduce 67 + +State 87: + (38) character_class_contents ::= COULDBEBACKREF * + + {default} reduce 38 + +State 88: + (90) onceonly ::= OPENASSERTION ONCEONLY pattern CLOSEPAREN * + + {default} reduce 90 + +State 89: + (61) basic_text ::= basic_text TEXT MULTIPLIER * + + {default} reduce 61 + +State 90: + (91) comment ::= OPENASSERTION COMMENT CLOSEPAREN * + + {default} reduce 91 + +State 91: + (1) pattern ::= MATCHSTART basic_pattern MATCHEND * + + {default} reduce 1 + +State 92: + pattern ::= pattern * BAR pattern + (5) pattern ::= pattern BAR pattern * + + {default} reduce 5 + +State 93: + (92) recur ::= OPENASSERTION RECUR CLOSEPAREN * + + {default} reduce 92 + +State 94: + (51) basic_text ::= FULLSTOP MULTIPLIER * + + {default} reduce 51 + +State 95: + (87) subpattern ::= OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 87 + +State 96: + (53) basic_text ::= CONTROLCHAR MULTIPLIER * + + {default} reduce 53 + +State 97: + (25) basic_pattern ::= basic_pattern comment * + + {default} reduce 25 + +State 98: + (85) lookbehind ::= OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN * + + {default} reduce 85 + +State 99: + (65) basic_text ::= basic_text CONTROLCHAR MULTIPLIER * + + {default} reduce 65 + +State 100: + (63) basic_text ::= basic_text FULLSTOP MULTIPLIER * + + {default} reduce 63 + +State 101: + (37) character_class_contents ::= BACKREFERENCE * + + {default} reduce 37 + +State 102: + (84) lookbehind ::= OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN * + + {default} reduce 84 + +State 103: + (76) conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 76 + +State 104: + (7) basic_pattern ::= character_class * + + {default} reduce 7 + +State 105: + (45) character_class_contents ::= character_class_contents TEXT HYPHEN TEXT * + + {default} reduce 45 + +State 106: + (8) basic_pattern ::= assertion * + + {default} reduce 8 + +State 107: + (9) basic_pattern ::= grouping * + + {default} reduce 9 + +State 108: + (11) basic_pattern ::= lookbehind * + + {default} reduce 11 + +State 109: + (10) basic_pattern ::= lookahead * + + {default} reduce 10 + +State 110: + (89) subpattern ::= OPENPAREN pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 89 + +State 111: + (46) character_class_contents ::= character_class_contents BACKREFERENCE * + + {default} reduce 46 + +State 112: + (72) assertion ::= OPENASSERTION INTERNALOPTIONS CLOSEPAREN * + + {default} reduce 72 + +State 113: + (35) character_class_contents ::= TEXT HYPHEN TEXT * + + {default} reduce 35 + +State 114: + (59) basic_text ::= COULDBEBACKREF MULTIPLIER * + + {default} reduce 59 + +State 115: + (31) character_class ::= OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER * + + {default} reduce 31 + +State 116: + (47) character_class_contents ::= character_class_contents COULDBEBACKREF * + + {default} reduce 47 + +State 117: + (3) pattern ::= basic_pattern MATCHEND * + + {default} reduce 3 + +State 118: + (12) basic_pattern ::= subpattern * + + {default} reduce 12 + +State 119: + (13) basic_pattern ::= onceonly * + + {default} reduce 13 + +State 120: + (49) basic_text ::= TEXT MULTIPLIER * + + {default} reduce 49 + +State 121: + (75) grouping ::= OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER * + + {default} reduce 75 + +State 122: + (39) character_class_contents ::= character_class_contents CONTROLCHAR * + + {default} reduce 39 + +State 123: + (30) character_class ::= OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER * + + {default} reduce 30 + +State 124: + (36) character_class_contents ::= TEXT HYPHEN ESCAPEDBACKSLASH * + + {default} reduce 36 + +State 125: + (27) basic_pattern ::= basic_pattern conditional * + + {default} reduce 27 + +State 126: + (42) character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN CONTROLCHAR * + + {default} reduce 42 + +State 127: + (43) character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN TEXT * + + {default} reduce 43 + +State 128: + (15) basic_pattern ::= recur * + + {default} reduce 15 + +State 129: + (14) basic_pattern ::= comment * + + {default} reduce 14 + +State 130: + (16) basic_pattern ::= conditional * + + {default} reduce 16 + +State 131: + (44) character_class_contents ::= character_class_contents TEXT HYPHEN ESCAPEDBACKSLASH * + + {default} reduce 44 + +State 132: + (57) basic_text ::= BACKREFERENCE MULTIPLIER * + + {default} reduce 57 + +State 133: + (73) assertion ::= OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN * + + {default} reduce 73 + +State 134: + (26) basic_pattern ::= basic_pattern recur * + + {default} reduce 26 + diff --git a/core/oql/build/PHP/LexerGenerator/Regex/Parser.php b/core/oql/build/PHP/LexerGenerator/Regex/Parser.php new file mode 100644 index 000000000..4e1faf1fd --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Regex/Parser.php @@ -0,0 +1,1933 @@ +string = $s->string; + $this->metadata = $s->metadata; + } else { + $this->string = (string) $s; + if ($m instanceof PHP_LexerGenerator_Regex_yyToken) { + $this->metadata = $m->metadata; + } elseif (is_array($m)) { + $this->metadata = $m; + } + } + } + + function __toString() + { + return $this->_string; + } + + function offsetExists($offset) + { + return isset($this->metadata[$offset]); + } + + function offsetGet($offset) + { + return $this->metadata[$offset]; + } + + function offsetSet($offset, $value) + { + if ($offset === null) { + if (isset($value[0])) { + $x = ($value instanceof PHP_LexerGenerator_Regex_yyToken) ? + $value->metadata : $value; + $this->metadata = array_merge($this->metadata, $x); + return; + } + $offset = count($this->metadata); + } + if ($value === null) { + return; + } + if ($value instanceof PHP_LexerGenerator_Regex_yyToken) { + if ($value->metadata) { + $this->metadata[$offset] = $value->metadata; + } + } elseif ($value) { + $this->metadata[$offset] = $value; + } + } + + function offsetUnset($offset) + { + unset($this->metadata[$offset]); + } +} + +/** The following structure represents a single element of the + * parser's stack. Information stored includes: + * + * + The state number for the parser at this level of the stack. + * + * + The value of the token stored at this level of the stack. + * (In other words, the "major" token.) + * + * + The semantic value stored at this level of the stack. This is + * the information used by the action routines in the grammar. + * It is sometimes called the "minor" token. + */ +class PHP_LexerGenerator_Regex_yyStackEntry +{ + public $stateno; /* The state-number */ + public $major; /* The major token value. This is the code + ** number for the token at this stack level */ + public $minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; + +// code external to the class is included here +#line 2 "Parser.y" + +require_once 'PHP/LexerGenerator/Exception.php'; +#line 102 "Parser.php" + +// declare_class is output here +#line 5 "Parser.y" +class PHP_LexerGenerator_Regex_Parser#line 107 "Parser.php" +{ +/* First off, code is included which follows the "include_class" declaration +** in the input file. */ +#line 21 "Parser.y" + + private $_lex; + private $_subpatterns; + private $_updatePattern; + private $_patternIndex; + public $result; + function __construct($lex) + { + $this->result = new PHP_LexerGenerator_ParseryyToken(''); + $this->_lex = $lex; + $this->_subpatterns = 0; + $this->_patternIndex = 1; + } + + function reset($patternIndex, $updatePattern = false) + { + $this->_updatePattern = $updatePattern; + $this->_patternIndex = $patternIndex; + $this->_subpatterns = 0; + $this->result = new PHP_LexerGenerator_ParseryyToken(''); + } +#line 134 "Parser.php" + +/* Next is all token values, as class constants +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ + const OPENPAREN = 1; + const OPENASSERTION = 2; + const BAR = 3; + const MULTIPLIER = 4; + const MATCHSTART = 5; + const MATCHEND = 6; + const OPENCHARCLASS = 7; + const CLOSECHARCLASS = 8; + const NEGATE = 9; + const TEXT = 10; + const ESCAPEDBACKSLASH = 11; + const HYPHEN = 12; + const BACKREFERENCE = 13; + const COULDBEBACKREF = 14; + const CONTROLCHAR = 15; + const FULLSTOP = 16; + const INTERNALOPTIONS = 17; + const CLOSEPAREN = 18; + const COLON = 19; + const POSITIVELOOKAHEAD = 20; + const NEGATIVELOOKAHEAD = 21; + const POSITIVELOOKBEHIND = 22; + const NEGATIVELOOKBEHIND = 23; + const PATTERNNAME = 24; + const ONCEONLY = 25; + const COMMENT = 26; + const RECUR = 27; + const YY_NO_ACTION = 230; + const YY_ACCEPT_ACTION = 229; + const YY_ERROR_ACTION = 228; + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N < self::YYNSTATE Shift N. That is, +** push the lookahead +** token onto the stack +** and goto state N. +** +** self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE Reduce by rule N-YYNSTATE. +** +** N == self::YYNSTATE+self::YYNRULE A syntax error has occurred. +** +** N == self::YYNSTATE+self::YYNRULE+1 The parser accepts its +** input. (and concludes parsing) +** +** N == self::YYNSTATE+self::YYNRULE+2 No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large static array $yy_action. +** Given state S and lookahead X, the action is computed as +** +** self::$yy_action[self::$yy_shift_ofst[S] + X ] +** +** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value +** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if +** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that +** the action is not in the table and that self::$yy_default[S] should be used instead. +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the static $yy_reduce_ofst array is used in place of +** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of +** self::YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** self::$yy_action A single table containing all actions. +** self::$yy_lookahead A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** self::$yy_shift_ofst For each state, the offset into self::$yy_action for +** shifting terminals. +** self::$yy_reduce_ofst For each state, the offset into self::$yy_action for +** shifting non-terminals after a reduce. +** self::$yy_default Default action for each state. +*/ + const YY_SZ_ACTTAB = 354; +static public $yy_action = array( + /* 0 */ 229, 45, 15, 23, 104, 106, 107, 109, 108, 118, + /* 10 */ 119, 129, 128, 130, 36, 15, 23, 104, 106, 107, + /* 20 */ 109, 108, 118, 119, 129, 128, 130, 39, 15, 23, + /* 30 */ 104, 106, 107, 109, 108, 118, 119, 129, 128, 130, + /* 40 */ 25, 15, 23, 104, 106, 107, 109, 108, 118, 119, + /* 50 */ 129, 128, 130, 32, 15, 23, 104, 106, 107, 109, + /* 60 */ 108, 118, 119, 129, 128, 130, 28, 15, 23, 104, + /* 70 */ 106, 107, 109, 108, 118, 119, 129, 128, 130, 35, + /* 80 */ 15, 23, 104, 106, 107, 109, 108, 118, 119, 129, + /* 90 */ 128, 130, 92, 15, 23, 104, 106, 107, 109, 108, + /* 100 */ 118, 119, 129, 128, 130, 38, 15, 23, 104, 106, + /* 110 */ 107, 109, 108, 118, 119, 129, 128, 130, 40, 15, + /* 120 */ 23, 104, 106, 107, 109, 108, 118, 119, 129, 128, + /* 130 */ 130, 33, 15, 23, 104, 106, 107, 109, 108, 118, + /* 140 */ 119, 129, 128, 130, 30, 15, 23, 104, 106, 107, + /* 150 */ 109, 108, 118, 119, 129, 128, 130, 37, 15, 23, + /* 160 */ 104, 106, 107, 109, 108, 118, 119, 129, 128, 130, + /* 170 */ 34, 15, 23, 104, 106, 107, 109, 108, 118, 119, + /* 180 */ 129, 128, 130, 16, 23, 104, 106, 107, 109, 108, + /* 190 */ 118, 119, 129, 128, 130, 54, 24, 22, 72, 76, + /* 200 */ 85, 84, 82, 81, 80, 97, 134, 125, 93, 12, + /* 210 */ 12, 26, 83, 2, 5, 1, 11, 4, 10, 13, + /* 220 */ 49, 50, 9, 17, 46, 98, 14, 12, 18, 113, + /* 230 */ 124, 52, 43, 79, 44, 57, 42, 41, 9, 17, + /* 240 */ 127, 12, 53, 91, 18, 126, 12, 52, 43, 120, + /* 250 */ 44, 57, 42, 41, 9, 17, 47, 12, 31, 117, + /* 260 */ 18, 88, 99, 52, 43, 75, 44, 57, 42, 41, + /* 270 */ 9, 17, 51, 19, 67, 69, 18, 101, 87, 52, + /* 280 */ 43, 12, 44, 57, 42, 41, 132, 64, 63, 103, + /* 290 */ 62, 58, 66, 65, 59, 12, 60, 68, 90, 111, + /* 300 */ 116, 122, 61, 100, 60, 68, 12, 111, 116, 122, + /* 310 */ 71, 5, 1, 11, 4, 67, 69, 12, 101, 87, + /* 320 */ 12, 102, 12, 12, 112, 6, 105, 131, 78, 7, + /* 330 */ 8, 95, 77, 74, 70, 56, 123, 48, 133, 73, + /* 340 */ 27, 114, 86, 55, 115, 89, 110, 121, 3, 94, + /* 350 */ 21, 29, 96, 20, + ); + static public $yy_lookahead = array( + /* 0 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + /* 10 */ 39, 40, 41, 42, 30, 31, 32, 33, 34, 35, + /* 20 */ 36, 37, 38, 39, 40, 41, 42, 30, 31, 32, + /* 30 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + /* 40 */ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + /* 50 */ 40, 41, 42, 30, 31, 32, 33, 34, 35, 36, + /* 60 */ 37, 38, 39, 40, 41, 42, 30, 31, 32, 33, + /* 70 */ 34, 35, 36, 37, 38, 39, 40, 41, 42, 30, + /* 80 */ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + /* 90 */ 41, 42, 30, 31, 32, 33, 34, 35, 36, 37, + /* 100 */ 38, 39, 40, 41, 42, 30, 31, 32, 33, 34, + /* 110 */ 35, 36, 37, 38, 39, 40, 41, 42, 30, 31, + /* 120 */ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + /* 130 */ 42, 30, 31, 32, 33, 34, 35, 36, 37, 38, + /* 140 */ 39, 40, 41, 42, 30, 31, 32, 33, 34, 35, + /* 150 */ 36, 37, 38, 39, 40, 41, 42, 30, 31, 32, + /* 160 */ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + /* 170 */ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + /* 180 */ 40, 41, 42, 31, 32, 33, 34, 35, 36, 37, + /* 190 */ 38, 39, 40, 41, 42, 1, 2, 32, 33, 34, + /* 200 */ 35, 36, 37, 38, 39, 40, 41, 42, 18, 3, + /* 210 */ 3, 17, 10, 19, 20, 21, 22, 23, 24, 25, + /* 220 */ 26, 27, 1, 2, 18, 18, 5, 3, 7, 10, + /* 230 */ 11, 10, 11, 4, 13, 14, 15, 16, 1, 2, + /* 240 */ 10, 3, 18, 6, 7, 15, 3, 10, 11, 4, + /* 250 */ 13, 14, 15, 16, 1, 2, 18, 3, 12, 6, + /* 260 */ 7, 18, 4, 10, 11, 4, 13, 14, 15, 16, + /* 270 */ 1, 2, 18, 9, 10, 11, 7, 13, 14, 10, + /* 280 */ 11, 3, 13, 14, 15, 16, 4, 10, 11, 4, + /* 290 */ 13, 14, 15, 16, 8, 3, 10, 11, 18, 13, + /* 300 */ 14, 15, 8, 4, 10, 11, 3, 13, 14, 15, + /* 310 */ 18, 20, 21, 22, 23, 10, 11, 3, 13, 14, + /* 320 */ 3, 18, 3, 3, 18, 19, 10, 11, 4, 36, + /* 330 */ 37, 4, 18, 4, 12, 18, 4, 18, 18, 4, + /* 340 */ 12, 4, 4, 10, 4, 4, 4, 4, 18, 4, + /* 350 */ 43, 12, 4, 43, +); + const YY_SHIFT_USE_DFLT = -1; + const YY_SHIFT_MAX = 70; + static public $yy_shift_ofst = array( + /* 0 */ 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + /* 10 */ 221, 221, 221, 221, 269, 253, 237, 194, 264, 305, + /* 20 */ 286, 294, 277, 277, 291, 320, 306, 316, 317, 219, + /* 30 */ 224, 230, 238, 206, 207, 319, 243, 314, 303, 254, + /* 40 */ 292, 345, 348, 261, 282, 278, 285, 324, 327, 280, + /* 50 */ 190, 229, 245, 343, 333, 330, 342, 337, 329, 332, + /* 60 */ 328, 340, 335, 338, 341, 299, 258, 339, 246, 322, + /* 70 */ 202, +); + const YY_REDUCE_USE_DFLT = -30; + const YY_REDUCE_MAX = 19; + static public $yy_reduce_ofst = array( + /* 0 */ -29, 127, 114, 101, 140, 88, 10, -3, 23, 36, + /* 10 */ 49, 75, 62, -16, 152, 165, 165, 293, 310, 307, +); + static public $yyExpectedTokens = array( + /* 0 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 1 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 2 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 3 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 4 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 5 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 6 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 7 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 8 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 9 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 10 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 11 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 12 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 13 */ array(1, 2, 5, 7, 10, 11, 13, 14, 15, 16, ), + /* 14 */ array(1, 2, 7, 10, 11, 13, 14, 15, 16, ), + /* 15 */ array(1, 2, 6, 7, 10, 11, 13, 14, 15, 16, ), + /* 16 */ array(1, 2, 6, 7, 10, 11, 13, 14, 15, 16, ), + /* 17 */ array(1, 2, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, ), + /* 18 */ array(9, 10, 11, 13, 14, ), + /* 19 */ array(10, 11, 13, 14, ), + /* 20 */ array(8, 10, 11, 13, 14, 15, ), + /* 21 */ array(8, 10, 11, 13, 14, 15, ), + /* 22 */ array(10, 11, 13, 14, 15, 16, ), + /* 23 */ array(10, 11, 13, 14, 15, 16, ), + /* 24 */ array(20, 21, 22, 23, ), + /* 25 */ array(3, 18, ), + /* 26 */ array(18, 19, ), + /* 27 */ array(10, 11, ), + /* 28 */ array(3, 18, ), + /* 29 */ array(10, 11, ), + /* 30 */ array(3, 18, ), + /* 31 */ array(10, 15, ), + /* 32 */ array(3, 18, ), + /* 33 */ array(3, 18, ), + /* 34 */ array(3, 18, ), + /* 35 */ array(3, 18, ), + /* 36 */ array(3, 18, ), + /* 37 */ array(3, 18, ), + /* 38 */ array(3, 18, ), + /* 39 */ array(3, 18, ), + /* 40 */ array(3, 18, ), + /* 41 */ array(4, ), + /* 42 */ array(4, ), + /* 43 */ array(4, ), + /* 44 */ array(4, ), + /* 45 */ array(3, ), + /* 46 */ array(4, ), + /* 47 */ array(4, ), + /* 48 */ array(4, ), + /* 49 */ array(18, ), + /* 50 */ array(18, ), + /* 51 */ array(4, ), + /* 52 */ array(4, ), + /* 53 */ array(4, ), + /* 54 */ array(10, ), + /* 55 */ array(18, ), + /* 56 */ array(4, ), + /* 57 */ array(4, ), + /* 58 */ array(4, ), + /* 59 */ array(4, ), + /* 60 */ array(12, ), + /* 61 */ array(4, ), + /* 62 */ array(4, ), + /* 63 */ array(4, ), + /* 64 */ array(4, ), + /* 65 */ array(4, ), + /* 66 */ array(4, ), + /* 67 */ array(12, ), + /* 68 */ array(12, ), + /* 69 */ array(12, ), + /* 70 */ array(10, ), + /* 71 */ array(), + /* 72 */ array(), + /* 73 */ array(), + /* 74 */ array(), + /* 75 */ array(), + /* 76 */ array(), + /* 77 */ array(), + /* 78 */ array(), + /* 79 */ array(), + /* 80 */ array(), + /* 81 */ array(), + /* 82 */ array(), + /* 83 */ array(), + /* 84 */ array(), + /* 85 */ array(), + /* 86 */ array(), + /* 87 */ array(), + /* 88 */ array(), + /* 89 */ array(), + /* 90 */ array(), + /* 91 */ array(), + /* 92 */ array(), + /* 93 */ array(), + /* 94 */ array(), + /* 95 */ array(), + /* 96 */ array(), + /* 97 */ array(), + /* 98 */ array(), + /* 99 */ array(), + /* 100 */ array(), + /* 101 */ array(), + /* 102 */ array(), + /* 103 */ array(), + /* 104 */ array(), + /* 105 */ array(), + /* 106 */ array(), + /* 107 */ array(), + /* 108 */ array(), + /* 109 */ array(), + /* 110 */ array(), + /* 111 */ array(), + /* 112 */ array(), + /* 113 */ array(), + /* 114 */ array(), + /* 115 */ array(), + /* 116 */ array(), + /* 117 */ array(), + /* 118 */ array(), + /* 119 */ array(), + /* 120 */ array(), + /* 121 */ array(), + /* 122 */ array(), + /* 123 */ array(), + /* 124 */ array(), + /* 125 */ array(), + /* 126 */ array(), + /* 127 */ array(), + /* 128 */ array(), + /* 129 */ array(), + /* 130 */ array(), + /* 131 */ array(), + /* 132 */ array(), + /* 133 */ array(), + /* 134 */ array(), +); + static public $yy_default = array( + /* 0 */ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + /* 10 */ 228, 228, 228, 228, 228, 139, 137, 228, 228, 228, + /* 20 */ 228, 228, 152, 141, 228, 228, 228, 228, 228, 228, + /* 30 */ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + /* 40 */ 228, 185, 187, 189, 191, 135, 212, 215, 221, 228, + /* 50 */ 228, 213, 183, 209, 228, 228, 223, 193, 205, 163, + /* 60 */ 176, 164, 203, 201, 195, 197, 199, 167, 175, 168, + /* 70 */ 228, 217, 153, 204, 206, 190, 154, 218, 216, 214, + /* 80 */ 159, 158, 157, 169, 156, 155, 202, 173, 225, 196, + /* 90 */ 226, 136, 140, 227, 186, 222, 188, 160, 220, 200, + /* 100 */ 198, 172, 219, 211, 142, 180, 143, 144, 146, 145, + /* 110 */ 224, 181, 207, 170, 194, 166, 182, 138, 147, 148, + /* 120 */ 184, 210, 174, 165, 171, 162, 177, 178, 150, 149, + /* 130 */ 151, 179, 192, 208, 161, +); +/* The next thing included is series of defines which control +** various aspects of the generated parser. +** self::YYNOCODE is a number which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. +** self::YYFALLBACK If defined, this indicates that one or more tokens +** have fall-back values which should be used if the +** original value of the token will not parse. +** self::YYSTACKDEPTH is the maximum depth of the parser's stack. +** self::YYNSTATE the combined number of states. +** self::YYNRULE the number of rules in the grammar +** self::YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +*/ + const YYNOCODE = 45; + const YYSTACKDEPTH = 100; + const YYNSTATE = 135; + const YYNRULE = 93; + const YYERRORSYMBOL = 28; + const YYERRSYMDT = 'yy0'; + const YYFALLBACK = 0; + /** The next table maps tokens into fallback tokens. If a construct + * like the following: + * + * %fallback ID X Y Z. + * + * appears in the grammer, then ID becomes a fallback token for X, Y, + * and Z. Whenever one of the tokens X, Y, or Z is input to the parser + * but it does not parse, the type of the token is changed to ID and + * the parse is retried before an error is thrown. + */ + static public $yyFallback = array( + ); + /** + * Turn parser tracing on by giving a stream to which to write the trace + * and a prompt to preface each trace message. Tracing is turned off + * by making either argument NULL + * + * Inputs: + * + * - A stream resource to which trace output should be written. + * If NULL, then tracing is turned off. + * - A prefix string written at the beginning of every + * line of trace output. If NULL, then tracing is + * turned off. + * + * Outputs: + * + * - None. + * @param resource + * @param string + */ + static function Trace($TraceFILE, $zTracePrompt) + { + if (!$TraceFILE) { + $zTracePrompt = 0; + } elseif (!$zTracePrompt) { + $TraceFILE = 0; + } + self::$yyTraceFILE = $TraceFILE; + self::$yyTracePrompt = $zTracePrompt; + } + + /** + * Output debug information to output (php://output stream) + */ + static function PrintTrace() + { + self::$yyTraceFILE = fopen('php://output', 'w'); + self::$yyTracePrompt = ''; + } + + /** + * @var resource|0 + */ + static public $yyTraceFILE; + /** + * String to prepend to debug output + * @var string|0 + */ + static public $yyTracePrompt; + /** + * @var int + */ + public $yyidx; /* Index of top element in stack */ + /** + * @var int + */ + public $yyerrcnt; /* Shifts left before out of the error */ + /** + * @var array + */ + public $yystack = array(); /* The parser's stack */ + + /** + * For tracing shifts, the names of all terminals and nonterminals + * are required. The following table supplies these names + * @var array + */ + static public $yyTokenName = array( + '$', 'OPENPAREN', 'OPENASSERTION', 'BAR', + 'MULTIPLIER', 'MATCHSTART', 'MATCHEND', 'OPENCHARCLASS', + 'CLOSECHARCLASS', 'NEGATE', 'TEXT', 'ESCAPEDBACKSLASH', + 'HYPHEN', 'BACKREFERENCE', 'COULDBEBACKREF', 'CONTROLCHAR', + 'FULLSTOP', 'INTERNALOPTIONS', 'CLOSEPAREN', 'COLON', + 'POSITIVELOOKAHEAD', 'NEGATIVELOOKAHEAD', 'POSITIVELOOKBEHIND', 'NEGATIVELOOKBEHIND', + 'PATTERNNAME', 'ONCEONLY', 'COMMENT', 'RECUR', + 'error', 'start', 'pattern', 'basic_pattern', + 'basic_text', 'character_class', 'assertion', 'grouping', + 'lookahead', 'lookbehind', 'subpattern', 'onceonly', + 'comment', 'recur', 'conditional', 'character_class_contents', + ); + + /** + * For tracing reduce actions, the names of all rules are required. + * @var array + */ + static public $yyRuleName = array( + /* 0 */ "start ::= pattern", + /* 1 */ "pattern ::= MATCHSTART basic_pattern MATCHEND", + /* 2 */ "pattern ::= MATCHSTART basic_pattern", + /* 3 */ "pattern ::= basic_pattern MATCHEND", + /* 4 */ "pattern ::= basic_pattern", + /* 5 */ "pattern ::= pattern BAR pattern", + /* 6 */ "basic_pattern ::= basic_text", + /* 7 */ "basic_pattern ::= character_class", + /* 8 */ "basic_pattern ::= assertion", + /* 9 */ "basic_pattern ::= grouping", + /* 10 */ "basic_pattern ::= lookahead", + /* 11 */ "basic_pattern ::= lookbehind", + /* 12 */ "basic_pattern ::= subpattern", + /* 13 */ "basic_pattern ::= onceonly", + /* 14 */ "basic_pattern ::= comment", + /* 15 */ "basic_pattern ::= recur", + /* 16 */ "basic_pattern ::= conditional", + /* 17 */ "basic_pattern ::= basic_pattern basic_text", + /* 18 */ "basic_pattern ::= basic_pattern character_class", + /* 19 */ "basic_pattern ::= basic_pattern assertion", + /* 20 */ "basic_pattern ::= basic_pattern grouping", + /* 21 */ "basic_pattern ::= basic_pattern lookahead", + /* 22 */ "basic_pattern ::= basic_pattern lookbehind", + /* 23 */ "basic_pattern ::= basic_pattern subpattern", + /* 24 */ "basic_pattern ::= basic_pattern onceonly", + /* 25 */ "basic_pattern ::= basic_pattern comment", + /* 26 */ "basic_pattern ::= basic_pattern recur", + /* 27 */ "basic_pattern ::= basic_pattern conditional", + /* 28 */ "character_class ::= OPENCHARCLASS character_class_contents CLOSECHARCLASS", + /* 29 */ "character_class ::= OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS", + /* 30 */ "character_class ::= OPENCHARCLASS character_class_contents CLOSECHARCLASS MULTIPLIER", + /* 31 */ "character_class ::= OPENCHARCLASS NEGATE character_class_contents CLOSECHARCLASS MULTIPLIER", + /* 32 */ "character_class_contents ::= TEXT", + /* 33 */ "character_class_contents ::= ESCAPEDBACKSLASH", + /* 34 */ "character_class_contents ::= ESCAPEDBACKSLASH HYPHEN TEXT", + /* 35 */ "character_class_contents ::= TEXT HYPHEN TEXT", + /* 36 */ "character_class_contents ::= TEXT HYPHEN ESCAPEDBACKSLASH", + /* 37 */ "character_class_contents ::= BACKREFERENCE", + /* 38 */ "character_class_contents ::= COULDBEBACKREF", + /* 39 */ "character_class_contents ::= character_class_contents CONTROLCHAR", + /* 40 */ "character_class_contents ::= character_class_contents ESCAPEDBACKSLASH", + /* 41 */ "character_class_contents ::= character_class_contents TEXT", + /* 42 */ "character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN CONTROLCHAR", + /* 43 */ "character_class_contents ::= character_class_contents ESCAPEDBACKSLASH HYPHEN TEXT", + /* 44 */ "character_class_contents ::= character_class_contents TEXT HYPHEN ESCAPEDBACKSLASH", + /* 45 */ "character_class_contents ::= character_class_contents TEXT HYPHEN TEXT", + /* 46 */ "character_class_contents ::= character_class_contents BACKREFERENCE", + /* 47 */ "character_class_contents ::= character_class_contents COULDBEBACKREF", + /* 48 */ "basic_text ::= TEXT", + /* 49 */ "basic_text ::= TEXT MULTIPLIER", + /* 50 */ "basic_text ::= FULLSTOP", + /* 51 */ "basic_text ::= FULLSTOP MULTIPLIER", + /* 52 */ "basic_text ::= CONTROLCHAR", + /* 53 */ "basic_text ::= CONTROLCHAR MULTIPLIER", + /* 54 */ "basic_text ::= ESCAPEDBACKSLASH", + /* 55 */ "basic_text ::= ESCAPEDBACKSLASH MULTIPLIER", + /* 56 */ "basic_text ::= BACKREFERENCE", + /* 57 */ "basic_text ::= BACKREFERENCE MULTIPLIER", + /* 58 */ "basic_text ::= COULDBEBACKREF", + /* 59 */ "basic_text ::= COULDBEBACKREF MULTIPLIER", + /* 60 */ "basic_text ::= basic_text TEXT", + /* 61 */ "basic_text ::= basic_text TEXT MULTIPLIER", + /* 62 */ "basic_text ::= basic_text FULLSTOP", + /* 63 */ "basic_text ::= basic_text FULLSTOP MULTIPLIER", + /* 64 */ "basic_text ::= basic_text CONTROLCHAR", + /* 65 */ "basic_text ::= basic_text CONTROLCHAR MULTIPLIER", + /* 66 */ "basic_text ::= basic_text ESCAPEDBACKSLASH", + /* 67 */ "basic_text ::= basic_text ESCAPEDBACKSLASH MULTIPLIER", + /* 68 */ "basic_text ::= basic_text BACKREFERENCE", + /* 69 */ "basic_text ::= basic_text BACKREFERENCE MULTIPLIER", + /* 70 */ "basic_text ::= basic_text COULDBEBACKREF", + /* 71 */ "basic_text ::= basic_text COULDBEBACKREF MULTIPLIER", + /* 72 */ "assertion ::= OPENASSERTION INTERNALOPTIONS CLOSEPAREN", + /* 73 */ "assertion ::= OPENASSERTION INTERNALOPTIONS COLON pattern CLOSEPAREN", + /* 74 */ "grouping ::= OPENASSERTION COLON pattern CLOSEPAREN", + /* 75 */ "grouping ::= OPENASSERTION COLON pattern CLOSEPAREN MULTIPLIER", + /* 76 */ "conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN MULTIPLIER", + /* 77 */ "conditional ::= OPENASSERTION OPENPAREN TEXT CLOSEPAREN pattern CLOSEPAREN", + /* 78 */ "conditional ::= OPENASSERTION lookahead pattern CLOSEPAREN", + /* 79 */ "conditional ::= OPENASSERTION lookahead pattern CLOSEPAREN MULTIPLIER", + /* 80 */ "conditional ::= OPENASSERTION lookbehind pattern CLOSEPAREN", + /* 81 */ "conditional ::= OPENASSERTION lookbehind pattern CLOSEPAREN MULTIPLIER", + /* 82 */ "lookahead ::= OPENASSERTION POSITIVELOOKAHEAD pattern CLOSEPAREN", + /* 83 */ "lookahead ::= OPENASSERTION NEGATIVELOOKAHEAD pattern CLOSEPAREN", + /* 84 */ "lookbehind ::= OPENASSERTION POSITIVELOOKBEHIND pattern CLOSEPAREN", + /* 85 */ "lookbehind ::= OPENASSERTION NEGATIVELOOKBEHIND pattern CLOSEPAREN", + /* 86 */ "subpattern ::= OPENASSERTION PATTERNNAME pattern CLOSEPAREN", + /* 87 */ "subpattern ::= OPENASSERTION PATTERNNAME pattern CLOSEPAREN MULTIPLIER", + /* 88 */ "subpattern ::= OPENPAREN pattern CLOSEPAREN", + /* 89 */ "subpattern ::= OPENPAREN pattern CLOSEPAREN MULTIPLIER", + /* 90 */ "onceonly ::= OPENASSERTION ONCEONLY pattern CLOSEPAREN", + /* 91 */ "comment ::= OPENASSERTION COMMENT CLOSEPAREN", + /* 92 */ "recur ::= OPENASSERTION RECUR CLOSEPAREN", + ); + + /** + * This function returns the symbolic name associated with a token + * value. + * @param int + * @return string + */ + function tokenName($tokenType) + { + if ($tokenType === 0) { + return 'End of Input'; + } + if ($tokenType > 0 && $tokenType < count(self::$yyTokenName)) { + return self::$yyTokenName[$tokenType]; + } else { + return "Unknown"; + } + } + + /** + * The following function deletes the value associated with a + * symbol. The symbol can be either a terminal or nonterminal. + * @param int the symbol code + * @param mixed the symbol's value + */ + static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are not used + ** inside the C code. + */ + default: break; /* If no destructor action specified: do nothing */ + } + } + + /** + * Pop the parser's stack once. + * + * If there is a destructor routine associated with the token which + * is popped from the stack, then call it. + * + * Return the major token number for the symbol popped. + * @param PHP_LexerGenerator_Regex_yyParser + * @return int + */ + function yy_pop_parser_stack() + { + if (!count($this->yystack)) { + return; + } + $yytos = array_pop($this->yystack); + if (self::$yyTraceFILE && $this->yyidx >= 0) { + fwrite(self::$yyTraceFILE, + self::$yyTracePrompt . 'Popping ' . self::$yyTokenName[$yytos->major] . + "\n"); + } + $yymajor = $yytos->major; + self::yy_destructor($yymajor, $yytos->minor); + $this->yyidx--; + return $yymajor; + } + + /** + * Deallocate and destroy a parser. Destructors are all called for + * all stack elements before shutting the parser down. + */ + function __destruct() + { + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + if (is_resource(self::$yyTraceFILE)) { + fclose(self::$yyTraceFILE); + } + } + + /** + * Based on the current state and parser stack, get a list of all + * possible lookahead tokens + * @param int + * @return array + */ + function yy_get_expected_tokens($token) + { + $state = $this->yystack[$this->yyidx]->stateno; + $expected = self::$yyExpectedTokens[$state]; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return $expected; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return array_unique($expected); + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate])) { + $expected += self::$yyExpectedTokens[$nextstate]; + if (in_array($token, + self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new PHP_LexerGenerator_Regex_yyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return array_unique($expected); + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return $expected; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + return array_unique($expected); + } + + /** + * Based on the parser state and current parser stack, determine whether + * the lookahead token is possible. + * + * The parser will convert the token value to an error token if not. This + * catches some unusual edge cases where the parser would fail. + * @param int + * @return bool + */ + function yy_is_expected_token($token) + { + if ($token === 0) { + return true; // 0 is not part of this + } + $state = $this->yystack[$this->yyidx]->stateno; + if (in_array($token, self::$yyExpectedTokens[$state], true)) { + return true; + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return true; + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs']; + $nextstate = $this->yy_find_reduce_action( + $this->yystack[$this->yyidx]->stateno, + self::$yyRuleInfo[$yyruleno]['lhs']); + if (isset(self::$yyExpectedTokens[$nextstate]) && + in_array($token, self::$yyExpectedTokens[$nextstate], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new PHP_LexerGenerator_Regex_yyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[$yyruleno]['lhs']; + $this->yystack[$this->yyidx] = $x; + continue 2; + } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + if (!$token) { + // end of input: this is valid + return true; + } + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return false; + } elseif ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return true; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + + /** + * Find the appropriate action for a parser given the terminal + * look-ahead token iLookAhead. + * + * If the look-ahead token is YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return YY_NO_ACTION. + * @param int The look-ahead token + */ + function yy_find_shift_action($iLookAhead) + { + $stateno = $this->yystack[$this->yyidx]->stateno; + + /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ + if (!isset(self::$yy_shift_ofst[$stateno])) { + // no shift actions + return self::$yy_default[$stateno]; + } + $i = self::$yy_shift_ofst[$stateno]; + if ($i === self::YY_SHIFT_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) + && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) { + if (self::$yyTraceFILE) { + fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " . + self::$yyTokenName[$iLookAhead] . " => " . + self::$yyTokenName[$iFallback] . "\n"); + } + return $this->yy_find_shift_action($iFallback); + } + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Find the appropriate action for a parser given the non-terminal + * look-ahead token $iLookAhead. + * + * If the look-ahead token is self::YYNOCODE, then check to see if the action is + * independent of the look-ahead. If it is, return the action, otherwise + * return self::YY_NO_ACTION. + * @param int Current state number + * @param int The look-ahead token + */ + function yy_find_reduce_action($stateno, $iLookAhead) + { + /* $stateno = $this->yystack[$this->yyidx]->stateno; */ + + if (!isset(self::$yy_reduce_ofst[$stateno])) { + return self::$yy_default[$stateno]; + } + $i = self::$yy_reduce_ofst[$stateno]; + if ($i == self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[$stateno]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || + self::$yy_lookahead[$i] != $iLookAhead) { + return self::$yy_default[$stateno]; + } else { + return self::$yy_action[$i]; + } + } + + /** + * Perform a shift action. + * @param int The new state to shift in + * @param int The major token to shift in + * @param mixed the minor token to shift in + */ + function yy_shift($yyNewState, $yyMajor, $yypMinor) + { + $this->yyidx++; + if ($this->yyidx >= self::YYSTACKDEPTH) { + $this->yyidx--; + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will execute if the parser + ** stack ever overflows */ + return; + } + $yytos = new PHP_LexerGenerator_Regex_yyStackEntry; + $yytos->stateno = $yyNewState; + $yytos->major = $yyMajor; + $yytos->minor = $yypMinor; + array_push($this->yystack, $yytos); + if (self::$yyTraceFILE && $this->yyidx > 0) { + fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt, + $yyNewState); + fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt); + for($i = 1; $i <= $this->yyidx; $i++) { + fprintf(self::$yyTraceFILE, " %s", + self::$yyTokenName[$this->yystack[$i]->major]); + } + fwrite(self::$yyTraceFILE,"\n"); + } + } + + /** + * The following table contains information about every rule that + * is used during the reduce. + * + *
+     * array(
+     *  array(
+     *   int $lhs;         Symbol on the left-hand side of the rule
+     *   int $nrhs;     Number of right-hand side symbols in the rule
+     *  ),...
+     * );
+     * 
+ */ + static public $yyRuleInfo = array( + array( 'lhs' => 29, 'rhs' => 1 ), + array( 'lhs' => 30, 'rhs' => 3 ), + array( 'lhs' => 30, 'rhs' => 2 ), + array( 'lhs' => 30, 'rhs' => 2 ), + array( 'lhs' => 30, 'rhs' => 1 ), + array( 'lhs' => 30, 'rhs' => 3 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 1 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 31, 'rhs' => 2 ), + array( 'lhs' => 33, 'rhs' => 3 ), + array( 'lhs' => 33, 'rhs' => 4 ), + array( 'lhs' => 33, 'rhs' => 4 ), + array( 'lhs' => 33, 'rhs' => 5 ), + array( 'lhs' => 43, 'rhs' => 1 ), + array( 'lhs' => 43, 'rhs' => 1 ), + array( 'lhs' => 43, 'rhs' => 3 ), + array( 'lhs' => 43, 'rhs' => 3 ), + array( 'lhs' => 43, 'rhs' => 3 ), + array( 'lhs' => 43, 'rhs' => 1 ), + array( 'lhs' => 43, 'rhs' => 1 ), + array( 'lhs' => 43, 'rhs' => 2 ), + array( 'lhs' => 43, 'rhs' => 2 ), + array( 'lhs' => 43, 'rhs' => 2 ), + array( 'lhs' => 43, 'rhs' => 4 ), + array( 'lhs' => 43, 'rhs' => 4 ), + array( 'lhs' => 43, 'rhs' => 4 ), + array( 'lhs' => 43, 'rhs' => 4 ), + array( 'lhs' => 43, 'rhs' => 2 ), + array( 'lhs' => 43, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 1 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 32, 'rhs' => 2 ), + array( 'lhs' => 32, 'rhs' => 3 ), + array( 'lhs' => 34, 'rhs' => 3 ), + array( 'lhs' => 34, 'rhs' => 5 ), + array( 'lhs' => 35, 'rhs' => 4 ), + array( 'lhs' => 35, 'rhs' => 5 ), + array( 'lhs' => 42, 'rhs' => 7 ), + array( 'lhs' => 42, 'rhs' => 6 ), + array( 'lhs' => 42, 'rhs' => 4 ), + array( 'lhs' => 42, 'rhs' => 5 ), + array( 'lhs' => 42, 'rhs' => 4 ), + array( 'lhs' => 42, 'rhs' => 5 ), + array( 'lhs' => 36, 'rhs' => 4 ), + array( 'lhs' => 36, 'rhs' => 4 ), + array( 'lhs' => 37, 'rhs' => 4 ), + array( 'lhs' => 37, 'rhs' => 4 ), + array( 'lhs' => 38, 'rhs' => 4 ), + array( 'lhs' => 38, 'rhs' => 5 ), + array( 'lhs' => 38, 'rhs' => 3 ), + array( 'lhs' => 38, 'rhs' => 4 ), + array( 'lhs' => 39, 'rhs' => 4 ), + array( 'lhs' => 40, 'rhs' => 3 ), + array( 'lhs' => 41, 'rhs' => 3 ), + ); + + /** + * The following table contains a mapping of reduce action to method name + * that handles the reduction. + * + * If a rule is not set, it has no handler. + */ + static public $yyReduceMap = array( + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 6 => 4, + 7 => 4, + 9 => 4, + 10 => 4, + 12 => 4, + 13 => 4, + 14 => 4, + 15 => 4, + 16 => 4, + 5 => 5, + 17 => 17, + 18 => 17, + 20 => 17, + 21 => 17, + 23 => 17, + 24 => 17, + 25 => 17, + 26 => 17, + 27 => 17, + 28 => 28, + 29 => 29, + 30 => 30, + 31 => 31, + 32 => 32, + 48 => 32, + 50 => 32, + 33 => 33, + 54 => 33, + 34 => 34, + 35 => 35, + 36 => 36, + 37 => 37, + 56 => 37, + 38 => 38, + 58 => 38, + 39 => 39, + 64 => 39, + 40 => 40, + 66 => 40, + 41 => 41, + 60 => 41, + 62 => 41, + 42 => 42, + 43 => 43, + 44 => 44, + 45 => 45, + 46 => 46, + 68 => 46, + 47 => 47, + 70 => 47, + 49 => 49, + 51 => 49, + 52 => 52, + 53 => 53, + 55 => 55, + 57 => 57, + 59 => 59, + 61 => 61, + 63 => 61, + 65 => 65, + 67 => 67, + 69 => 69, + 71 => 71, + 72 => 72, + 73 => 73, + 74 => 74, + 75 => 75, + 76 => 76, + 77 => 77, + 78 => 78, + 79 => 79, + 80 => 80, + 84 => 80, + 81 => 81, + 82 => 82, + 83 => 83, + 85 => 85, + 86 => 86, + 87 => 87, + 88 => 88, + 89 => 89, + 90 => 90, + 91 => 91, + 92 => 92, + ); + /* Beginning here are the reduction cases. A typical example + ** follows: + ** #line + ** function yy_r0($yymsp){ ... } // User supplied code + ** #line + */ +#line 47 "Parser.y" + function yy_r0(){ + $this->yystack[$this->yyidx + 0]->minor->string = str_replace('"', '\\"', $this->yystack[$this->yyidx + 0]->minor->string); + $x = $this->yystack[$this->yyidx + 0]->minor->metadata; + $x['subpatterns'] = $this->_subpatterns; + $this->yystack[$this->yyidx + 0]->minor->metadata = $x; + $this->_subpatterns = 0; + $this->result = $this->yystack[$this->yyidx + 0]->minor; + } +#line 1259 "Parser.php" +#line 56 "Parser.y" + function yy_r1(){ + throw new PHP_LexerGenerator_Exception('Cannot include start match "' . + $this->yystack[$this->yyidx + -2]->minor . '" or end match "' . $this->yystack[$this->yyidx + 0]->minor . '"'); + } +#line 1265 "Parser.php" +#line 60 "Parser.y" + function yy_r2(){ + throw new PHP_LexerGenerator_Exception('Cannot include start match "' . + B . '"'); + } +#line 1271 "Parser.php" +#line 64 "Parser.y" + function yy_r3(){ + throw new PHP_LexerGenerator_Exception('Cannot include end match "' . $this->yystack[$this->yyidx + 0]->minor . '"'); + } +#line 1276 "Parser.php" +#line 67 "Parser.y" + function yy_r4(){$this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } +#line 1279 "Parser.php" +#line 68 "Parser.y" + function yy_r5(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . '|' . $this->yystack[$this->yyidx + 0]->minor->string, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . '|' . $this->yystack[$this->yyidx + 0]->minor['pattern'])); + } +#line 1285 "Parser.php" +#line 84 "Parser.y" + function yy_r17(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . $this->yystack[$this->yyidx + 0]->minor->string, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . $this->yystack[$this->yyidx + 0]->minor['pattern'])); + } +#line 1291 "Parser.php" +#line 123 "Parser.y" + function yy_r28(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('[' . $this->yystack[$this->yyidx + -1]->minor->string . ']', array( + 'pattern' => '[' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ']')); + } +#line 1297 "Parser.php" +#line 127 "Parser.y" + function yy_r29(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('[^' . $this->yystack[$this->yyidx + -1]->minor->string . ']', array( + 'pattern' => '[^' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ']')); + } +#line 1303 "Parser.php" +#line 131 "Parser.y" + function yy_r30(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('[' . $this->yystack[$this->yyidx + -2]->minor->string . ']' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '[' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ']' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1309 "Parser.php" +#line 135 "Parser.y" + function yy_r31(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('[^' . $this->yystack[$this->yyidx + -2]->minor->string . ']' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '[^' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ']' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1315 "Parser.php" +#line 140 "Parser.y" + function yy_r32(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1321 "Parser.php" +#line 144 "Parser.y" + function yy_r33(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1327 "Parser.php" +#line 148 "Parser.y" + function yy_r34(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1333 "Parser.php" +#line 152 "Parser.y" + function yy_r35(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1339 "Parser.php" +#line 156 "Parser.y" + function yy_r36(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor . '-\\\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1345 "Parser.php" +#line 160 "Parser.y" + function yy_r37(){ + if (((int) substr($this->yystack[$this->yyidx + 0]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr($this->yystack[$this->yyidx + 0]->minor, 1)); + } + $this->yystack[$this->yyidx + 0]->minor = substr($this->yystack[$this->yyidx + 0]->minor, 1); + // adjust back-reference for containing () + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + 0]->minor))); + } +#line 1357 "Parser.php" +#line 170 "Parser.y" + function yy_r38(){ + if (((int) substr($this->yystack[$this->yyidx + 0]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception($this->yystack[$this->yyidx + 0]->minor . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr($this->yystack[$this->yyidx + 0]->minor, 1) . ' for octal'); + } + $this->yystack[$this->yyidx + 0]->minor = substr($this->yystack[$this->yyidx + 0]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + 0]->minor))); + } +#line 1368 "Parser.php" +#line 179 "Parser.y" + function yy_r39(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . '\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1374 "Parser.php" +#line 183 "Parser.y" + function yy_r40(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . '\\\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1380 "Parser.php" +#line 187 "Parser.y" + function yy_r41(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1386 "Parser.php" +#line 191 "Parser.y" + function yy_r42(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -3]->minor->string . '\\\\' . $this->yystack[$this->yyidx + -2]->minor . '-\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -3]->minor['pattern'] . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1392 "Parser.php" +#line 195 "Parser.y" + function yy_r43(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -3]->minor->string . '\\\\' . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -3]->minor['pattern'] . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1398 "Parser.php" +#line 199 "Parser.y" + function yy_r44(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -3]->minor->string . $this->yystack[$this->yyidx + -2]->minor . '-\\\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -3]->minor['pattern'] . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1404 "Parser.php" +#line 203 "Parser.y" + function yy_r45(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -3]->minor->string . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -3]->minor['pattern'] . $this->yystack[$this->yyidx + -2]->minor . '-' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1410 "Parser.php" +#line 207 "Parser.y" + function yy_r46(){ + if (((int) substr($this->yystack[$this->yyidx + 0]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr($this->yystack[$this->yyidx + 0]->minor, 1)); + } + $this->yystack[$this->yyidx + 0]->minor = substr($this->yystack[$this->yyidx + 0]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . '\\\\' . ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex), array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + 0]->minor))); + } +#line 1421 "Parser.php" +#line 216 "Parser.y" + function yy_r47(){ + if (((int) substr($this->yystack[$this->yyidx + 0]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception($this->yystack[$this->yyidx + 0]->minor . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr($this->yystack[$this->yyidx + 0]->minor, 1) . ' for octal'); + } + $this->yystack[$this->yyidx + 0]->minor = substr($this->yystack[$this->yyidx + 0]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor->string . '\\\\' . ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex), array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor['pattern'] . '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + 0]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + 0]->minor))); + } +#line 1432 "Parser.php" +#line 230 "Parser.y" + function yy_r49(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1438 "Parser.php" +#line 242 "Parser.y" + function yy_r52(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1444 "Parser.php" +#line 246 "Parser.y" + function yy_r53(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\' . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1450 "Parser.php" +#line 254 "Parser.y" + function yy_r55(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1456 "Parser.php" +#line 268 "Parser.y" + function yy_r57(){ + if (((int) substr($this->yystack[$this->yyidx + -1]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr($this->yystack[$this->yyidx + -1]->minor, 1)); + } + $this->yystack[$this->yyidx + -1]->minor = substr($this->yystack[$this->yyidx + -1]->minor, 1); + // adjust back-reference for containing () + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1468 "Parser.php" +#line 287 "Parser.y" + function yy_r59(){ + if (((int) substr($this->yystack[$this->yyidx + -1]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception($this->yystack[$this->yyidx + -1]->minor . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr($this->yystack[$this->yyidx + -1]->minor, 1) . ' for octal'); + } + $this->yystack[$this->yyidx + -1]->minor = substr($this->yystack[$this->yyidx + -1]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('\\\\' . ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1479 "Parser.php" +#line 300 "Parser.y" + function yy_r61(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1485 "Parser.php" +#line 316 "Parser.y" + function yy_r65(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . '\\' . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1491 "Parser.php" +#line 324 "Parser.y" + function yy_r67(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . '\\\\' . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1497 "Parser.php" +#line 337 "Parser.y" + function yy_r69(){ + if (((int) substr($this->yystack[$this->yyidx + -1]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr($this->yystack[$this->yyidx + -1]->minor, 1)); + } + $this->yystack[$this->yyidx + -1]->minor = substr($this->yystack[$this->yyidx + -1]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . '\\\\' . ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1508 "Parser.php" +#line 355 "Parser.y" + function yy_r71(){ + if (((int) substr($this->yystack[$this->yyidx + -1]->minor, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception($this->yystack[$this->yyidx + -1]->minor . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr($this->yystack[$this->yyidx + -1]->minor, 1) . ' for octal'); + } + $this->yystack[$this->yyidx + -1]->minor = substr($this->yystack[$this->yyidx + -1]->minor, 1); + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken($this->yystack[$this->yyidx + -2]->minor->string . '\\\\' . ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => $this->yystack[$this->yyidx + -2]->minor['pattern'] . '\\' . ($this->_updatePattern ? ($this->yystack[$this->yyidx + -1]->minor + $this->_patternIndex) : $this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1519 "Parser.php" +#line 365 "Parser.y" + function yy_r72(){ + throw new PHP_LexerGenerator_Exception('Error: cannot set preg options directly with "' . + $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + 0]->minor . '"'); + } +#line 1525 "Parser.php" +#line 369 "Parser.y" + function yy_r73(){ + throw new PHP_LexerGenerator_Exception('Error: cannot set preg options directly with "' . + $this->yystack[$this->yyidx + -4]->minor . $this->yystack[$this->yyidx + -3]->minor . $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + -1]->minor['pattern'] . $this->yystack[$this->yyidx + 0]->minor . '"'); + } +#line 1531 "Parser.php" +#line 374 "Parser.y" + function yy_r74(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?:' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(?:' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1537 "Parser.php" +#line 378 "Parser.y" + function yy_r75(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?:' . $this->yystack[$this->yyidx + -2]->minor->string . ')' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '(?:' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1543 "Parser.php" +#line 383 "Parser.y" + function yy_r76(){ + if ($this->yystack[$this->yyidx + -4]->minor != 'R') { + if (!preg_match('/[1-9][0-9]*/', $this->yystack[$this->yyidx + -4]->minor)) { + throw new PHP_LexerGenerator_Exception('Invalid sub-pattern conditional: "(?(' . $this->yystack[$this->yyidx + -4]->minor . ')"'); + } + if ($this->yystack[$this->yyidx + -4]->minor > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('sub-pattern conditional . "' . $this->yystack[$this->yyidx + -4]->minor . '" refers to non-existent sub-pattern'); + } + } else { + throw new PHP_LexerGenerator_Exception('Recursive conditional (?(' . $this->yystack[$this->yyidx + -4]->minor . ')" cannot work in this lexer'); + } + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?(' . $this->yystack[$this->yyidx + -4]->minor . ')' . $this->yystack[$this->yyidx + -2]->minor->string . ')' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '(?(' . $this->yystack[$this->yyidx + -4]->minor . ')' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1559 "Parser.php" +#line 397 "Parser.y" + function yy_r77(){ + if ($this->yystack[$this->yyidx + -3]->minor != 'R') { + if (!preg_match('/[1-9][0-9]*/', $this->yystack[$this->yyidx + -3]->minor)) { + throw new PHP_LexerGenerator_Exception('Invalid sub-pattern conditional: "(?(' . $this->yystack[$this->yyidx + -3]->minor . ')"'); + } + if ($this->yystack[$this->yyidx + -3]->minor > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('sub-pattern conditional . "' . $this->yystack[$this->yyidx + -3]->minor . '" refers to non-existent sub-pattern'); + } + } else { + throw new PHP_LexerGenerator_Exception('Recursive conditional (?(' . $this->yystack[$this->yyidx + -3]->minor . ')" cannot work in this lexer'); + } + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?(' . $this->yystack[$this->yyidx + -3]->minor . ')' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(?(' . $this->yystack[$this->yyidx + -3]->minor . ')' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1575 "Parser.php" +#line 411 "Parser.y" + function yy_r78(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?' . $this->yystack[$this->yyidx + -2]->minor->string . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(?' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1581 "Parser.php" +#line 415 "Parser.y" + function yy_r79(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?' . $this->yystack[$this->yyidx + -3]->minor->string . $this->yystack[$this->yyidx + -2]->minor->string . ')' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '(?' . $this->yystack[$this->yyidx + -3]->minor['pattern'] . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1587 "Parser.php" +#line 419 "Parser.y" + function yy_r80(){ + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?<=' . + $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')'); + } +#line 1593 "Parser.php" +#line 423 "Parser.y" + function yy_r81(){ + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?<=' . + $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')'); + } +#line 1599 "Parser.php" +#line 428 "Parser.y" + function yy_r82(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?=' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern '=> '(?=' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1605 "Parser.php" +#line 432 "Parser.y" + function yy_r83(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?!' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(?!' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1611 "Parser.php" +#line 441 "Parser.y" + function yy_r85(){ + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?yystack[$this->yyidx + -1]->minor['pattern'] . ')'); + } +#line 1617 "Parser.php" +#line 446 "Parser.y" + function yy_r86(){ + throw new PHP_LexerGenerator_Exception('Cannot use named sub-patterns: "(' . + $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')'); + } +#line 1623 "Parser.php" +#line 450 "Parser.y" + function yy_r87(){ + throw new PHP_LexerGenerator_Exception('Cannot use named sub-patterns: "(' . + $this->yystack[$this->yyidx + -3]->minor['pattern'] . ')'); + } +#line 1629 "Parser.php" +#line 454 "Parser.y" + function yy_r88(){ + $this->_subpatterns++; + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1636 "Parser.php" +#line 459 "Parser.y" + function yy_r89(){ + $this->_subpatterns++; + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(' . $this->yystack[$this->yyidx + -2]->minor->string . ')' . $this->yystack[$this->yyidx + 0]->minor, array( + 'pattern' => '(' . $this->yystack[$this->yyidx + -2]->minor['pattern'] . ')' . $this->yystack[$this->yyidx + 0]->minor)); + } +#line 1643 "Parser.php" +#line 465 "Parser.y" + function yy_r90(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(?>' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(?>' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1649 "Parser.php" +#line 470 "Parser.y" + function yy_r91(){ + $this->_retvalue = new PHP_LexerGenerator_ParseryyToken('(' . $this->yystack[$this->yyidx + -1]->minor->string . ')', array( + 'pattern' => '(' . $this->yystack[$this->yyidx + -1]->minor['pattern'] . ')')); + } +#line 1655 "Parser.php" +#line 475 "Parser.y" + function yy_r92(){ + throw new Exception('(?R) cannot work in this lexer'); + } +#line 1660 "Parser.php" + + /** + * placeholder for the left hand side in a reduce operation. + * + * For a parser with a rule like this: + *
+     * rule(A) ::= B. { A = 1; }
+     * 
+ * + * The parser will translate to something like: + * + * + * function yy_r0(){$this->_retvalue = 1;} + * + */ + private $_retvalue; + + /** + * Perform a reduce action and the shift that must immediately + * follow the reduce. + * + * For a rule such as: + * + *
+     * A ::= B blah C. { dosomething(); }
+     * 
+ * + * This function will first call the action, if any, ("dosomething();" in our + * example), and then it will pop three states from the stack, + * one for each entry on the right-hand side of the expression + * (B, blah, and C in our example rule), and then push the result of the action + * back on to the stack with the resulting state reduced to (as described in the .out + * file) + * @param int Number of the rule by which to reduce + */ + function yy_reduce($yyruleno) + { + //int $yygoto; /* The next state */ + //int $yyact; /* The next action */ + //mixed $yygotominor; /* The LHS of the rule reduced */ + //PHP_LexerGenerator_Regex_yyStackEntry $yymsp; /* The top of the parser's stack */ + //int $yysize; /* Amount to pop the stack */ + $yymsp = $this->yystack[$this->yyidx]; + if (self::$yyTraceFILE && $yyruleno >= 0 + && $yyruleno < count(self::$yyRuleName)) { + fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n", + self::$yyTracePrompt, $yyruleno, + self::$yyRuleName[$yyruleno]); + } + + $this->_retvalue = $yy_lefthand_side = null; + if (array_key_exists($yyruleno, self::$yyReduceMap)) { + // call the action + $this->_retvalue = null; + $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}(); + $yy_lefthand_side = $this->_retvalue; + } + $yygoto = self::$yyRuleInfo[$yyruleno]['lhs']; + $yysize = self::$yyRuleInfo[$yyruleno]['rhs']; + $this->yyidx -= $yysize; + for($i = $yysize; $i; $i--) { + // pop all of the right-hand side parameters + array_pop($this->yystack); + } + $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto); + if ($yyact < self::YYNSTATE) { + /* If we are not debugging and the reduce action popped at least + ** one element off the stack, then we can push the new element back + ** onto the stack here, and skip the stack overflow test in yy_shift(). + ** That gives a significant speed improvement. */ + if (!self::$yyTraceFILE && $yysize) { + $this->yyidx++; + $x = new PHP_LexerGenerator_Regex_yyStackEntry; + $x->stateno = $yyact; + $x->major = $yygoto; + $x->minor = $yy_lefthand_side; + $this->yystack[$this->yyidx] = $x; + } else { + $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + } + } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) { + $this->yy_accept(); + } + } + + /** + * The following code executes when the parse fails + * + * Code from %parse_fail is inserted here + */ + function yy_parse_failed() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser fails */ + } + + /** + * The following code executes when a syntax error first occurs. + * + * %syntax_error code is inserted here + * @param int The major type of the error token + * @param mixed The minor type of the error token + */ + function yy_syntax_error($yymajor, $TOKEN) + { +#line 6 "Parser.y" + +/* ?>_lex->line . ": token '" . + $this->_lex->value . "' while parsing rule:"; + foreach ($this->yystack as $entry) { + echo $this->tokenName($entry->major) . ' '; + } + foreach ($this->yy_get_expected_tokens($yymajor) as $token) { + $expect[] = self::$yyTokenName[$token]; + } + throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN + . '), expected one of: ' . implode(',', $expect)); +#line 1788 "Parser.php" + } + + /** + * The following is executed when the parser accepts + * + * %parse_accept code is inserted here + */ + function yy_accept() + { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt); + } + while ($this->yyidx >= 0) { + $stack = $this->yy_pop_parser_stack(); + } + /* Here code is inserted which will be executed whenever the + ** parser accepts */ + } + + /** + * The main parser program. + * + * The first argument is the major token number. The second is + * the token value string as scanned from the input. + * + * @param int the token number + * @param mixed the token value + * @param mixed any extra arguments that should be passed to handlers + */ + function doParse($yymajor, $yytokenvalue) + { +// $yyact; /* The parser action. */ +// $yyendofinput; /* True if we are at the end of input */ + $yyerrorhit = 0; /* True if yymajor has invoked an error */ + + /* (re)initialize the parser, if necessary */ + if ($this->yyidx === null || $this->yyidx < 0) { + /* if ($yymajor == 0) return; // not sure why this was here... */ + $this->yyidx = 0; + $this->yyerrcnt = -1; + $x = new PHP_LexerGenerator_Regex_yyStackEntry; + $x->stateno = 0; + $x->major = 0; + $this->yystack = array(); + array_push($this->yystack, $x); + } + $yyendofinput = ($yymajor==0); + + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sInput %s\n", + self::$yyTracePrompt, self::$yyTokenName[$yymajor]); + } + + do { + $yyact = $this->yy_find_shift_action($yymajor); + if ($yymajor < self::YYERRORSYMBOL && + !$this->yy_is_expected_token($yymajor)) { + // force a syntax error + $yyact = self::YY_ERROR_ACTION; + } + if ($yyact < self::YYNSTATE) { + $this->yy_shift($yyact, $yymajor, $yytokenvalue); + $this->yyerrcnt--; + if ($yyendofinput && $this->yyidx >= 0) { + $yymajor = 0; + } else { + $yymajor = self::YYNOCODE; + } + } elseif ($yyact < self::YYNSTATE + self::YYNRULE) { + $this->yy_reduce($yyact - self::YYNSTATE); + } elseif ($yyact == self::YY_ERROR_ACTION) { + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sSyntax Error!\n", + self::$yyTracePrompt); + } + if (self::YYERRORSYMBOL) { + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if ($this->yyerrcnt < 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $yymx = $this->yystack[$this->yyidx]->major; + if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){ + if (self::$yyTraceFILE) { + fprintf(self::$yyTraceFILE, "%sDiscard input token %s\n", + self::$yyTracePrompt, self::$yyTokenName[$yymajor]); + } + $this->yy_destructor($yymajor, $yytokenvalue); + $yymajor = self::YYNOCODE; + } else { + while ($this->yyidx >= 0 && + $yymx != self::YYERRORSYMBOL && + ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE + ){ + $this->yy_pop_parser_stack(); + } + if ($this->yyidx < 0 || $yymajor==0) { + $this->yy_destructor($yymajor, $yytokenvalue); + $this->yy_parse_failed(); + $yymajor = self::YYNOCODE; + } elseif ($yymx != self::YYERRORSYMBOL) { + $u2 = 0; + $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); + } + } + $this->yyerrcnt = 3; + $yyerrorhit = 1; + } else { + /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if ($this->yyerrcnt <= 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $this->yyerrcnt = 3; + $this->yy_destructor($yymajor, $yytokenvalue); + if ($yyendofinput) { + $this->yy_parse_failed(); + } + $yymajor = self::YYNOCODE; + } + } else { + $this->yy_accept(); + $yymajor = self::YYNOCODE; + } + } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/Regex/Parser.y b/core/oql/build/PHP/LexerGenerator/Regex/Parser.y new file mode 100644 index 000000000..bb74738dd --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/Regex/Parser.y @@ -0,0 +1,477 @@ +%name PHP_LexerGenerator_Regex_ +%include { +require_once 'PHP/LexerGenerator/Exception.php'; +} +%declare_class {class PHP_LexerGenerator_Regex_Parser} +%syntax_error { +/* ?>_lex->line . ": token '" . + $this->_lex->value . "' while parsing rule:"; + foreach ($this->yystack as $entry) { + echo $this->tokenName($entry->major) . ' '; + } + foreach ($this->yy_get_expected_tokens($yymajor) as $token) { + $expect[] = self::$yyTokenName[$token]; + } + throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN + . '), expected one of: ' . implode(',', $expect)); +} +%include_class { + private $_lex; + private $_subpatterns; + private $_updatePattern; + private $_patternIndex; + public $result; + function __construct($lex) + { + $this->result = new PHP_LexerGenerator_ParseryyToken(''); + $this->_lex = $lex; + $this->_subpatterns = 0; + $this->_patternIndex = 1; + } + + function reset($patternIndex, $updatePattern = false) + { + $this->_updatePattern = $updatePattern; + $this->_patternIndex = $patternIndex; + $this->_subpatterns = 0; + $this->result = new PHP_LexerGenerator_ParseryyToken(''); + } +} + +%left OPENPAREN OPENASSERTION BAR. +%right MULTIPLIER. + +start ::= pattern(B). { + B->string = str_replace('"', '\\"', B->string); + $x = B->metadata; + $x['subpatterns'] = $this->_subpatterns; + B->metadata = $x; + $this->_subpatterns = 0; + $this->result = B; +} + +pattern ::= MATCHSTART(B) basic_pattern MATCHEND(C). { + throw new PHP_LexerGenerator_Exception('Cannot include start match "' . + B . '" or end match "' . C . '"'); +} +pattern ::= MATCHSTART basic_pattern. { + throw new PHP_LexerGenerator_Exception('Cannot include start match "' . + B . '"'); +} +pattern ::= basic_pattern MATCHEND(C). { + throw new PHP_LexerGenerator_Exception('Cannot include end match "' . C . '"'); +} +pattern(A) ::= basic_pattern(B). {A = B;} +pattern(A) ::= pattern(B) BAR pattern(C). { + A = new PHP_LexerGenerator_ParseryyToken(B->string . '|' . C->string, array( + 'pattern' => B['pattern'] . '|' . C['pattern'])); +} + +basic_pattern(A) ::= basic_text(B). {A = B;} +basic_pattern(A) ::= character_class(B). {A = B;} +basic_pattern ::= assertion. +basic_pattern(A) ::= grouping(B). {A = B;} +basic_pattern(A) ::= lookahead(B). {A = B;} +basic_pattern ::= lookbehind. +basic_pattern(A) ::= subpattern(B). {A = B;} +basic_pattern(A) ::= onceonly(B). {A = B;} +basic_pattern(A) ::= comment(B). {A = B;} +basic_pattern(A) ::= recur(B). {A = B;} +basic_pattern(A) ::= conditional(B). {A = B;} +basic_pattern(A) ::= basic_pattern(P) basic_text(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) character_class(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern ::= basic_pattern assertion. +basic_pattern(A) ::= basic_pattern(P) grouping(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) lookahead(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern ::= basic_pattern lookbehind. +basic_pattern(A) ::= basic_pattern(P) subpattern(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) onceonly(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) comment(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) recur(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} +basic_pattern(A) ::= basic_pattern(P) conditional(B). { + A = new PHP_LexerGenerator_ParseryyToken(P->string . B->string, array( + 'pattern' => P['pattern'] . B['pattern'])); +} + +character_class(A) ::= OPENCHARCLASS character_class_contents(B) CLOSECHARCLASS. { + A = new PHP_LexerGenerator_ParseryyToken('[' . B->string . ']', array( + 'pattern' => '[' . B['pattern'] . ']')); +} +character_class(A) ::= OPENCHARCLASS NEGATE character_class_contents(B) CLOSECHARCLASS. { + A = new PHP_LexerGenerator_ParseryyToken('[^' . B->string . ']', array( + 'pattern' => '[^' . B['pattern'] . ']')); +} +character_class(A) ::= OPENCHARCLASS character_class_contents(B) CLOSECHARCLASS MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('[' . B->string . ']' . M, array( + 'pattern' => '[' . B['pattern'] . ']' . M)); +} +character_class(A) ::= OPENCHARCLASS NEGATE character_class_contents(B) CLOSECHARCLASS MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('[^' . B->string . ']' . M, array( + 'pattern' => '[^' . B['pattern'] . ']' . M)); +} + +character_class_contents(A) ::= TEXT(B). { + A = new PHP_LexerGenerator_ParseryyToken(B, array( + 'pattern' => B)); +} +character_class_contents(A) ::= ESCAPEDBACKSLASH(B). { + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . B, array( + 'pattern' => B)); +} +character_class_contents(A) ::= ESCAPEDBACKSLASH(B) HYPHEN TEXT(C). { + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . B . '-' . C, array( + 'pattern' => B . '-' . C)); +} +character_class_contents(A) ::= TEXT(B) HYPHEN TEXT(C). { + A = new PHP_LexerGenerator_ParseryyToken(B . '-' . C, array( + 'pattern' => B . '-' . C)); +} +character_class_contents(A) ::= TEXT(B) HYPHEN ESCAPEDBACKSLASH(C). { + A = new PHP_LexerGenerator_ParseryyToken(B . '-\\\\' . C, array( + 'pattern' => B . '-' . C)); +} +character_class_contents(A) ::= BACKREFERENCE(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + // adjust back-reference for containing () + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +character_class_contents(A) ::= COULDBEBACKREF(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +character_class_contents(A) ::= character_class_contents(D) CONTROLCHAR(B). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . '\\' . B, array( + 'pattern' => D['pattern'] . B)); +} +character_class_contents(A) ::= character_class_contents(D) ESCAPEDBACKSLASH(B). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . '\\\\' . B, array( + 'pattern' => D['pattern'] . B)); +} +character_class_contents(A) ::= character_class_contents(D) TEXT(B). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . B, array( + 'pattern' => D['pattern'] . B)); +} +character_class_contents(A) ::= character_class_contents(D) ESCAPEDBACKSLASH(B) HYPHEN CONTROLCHAR(C). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . '\\\\' . B . '-\\' . C, array( + 'pattern' => D['pattern'] . B . '-' . C)); +} +character_class_contents(A) ::= character_class_contents(D) ESCAPEDBACKSLASH(B) HYPHEN TEXT(C). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . '\\\\' . B . '-' . C, array( + 'pattern' => D['pattern'] . B . '-' . C)); +} +character_class_contents(A) ::= character_class_contents(D) TEXT(B) HYPHEN ESCAPEDBACKSLASH(C). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . B . '-\\\\' . C, array( + 'pattern' => D['pattern'] . B . '-' . C)); +} +character_class_contents(A) ::= character_class_contents(D) TEXT(B) HYPHEN TEXT(C). { + A = new PHP_LexerGenerator_ParseryyToken(D->string . B . '-' . C, array( + 'pattern' => D['pattern'] . B . '-' . C)); +} +character_class_contents(A) ::= character_class_contents(P) BACKREFERENCE(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex), array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +character_class_contents(A) ::= character_class_contents(P) COULDBEBACKREF(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex), array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} + +basic_text(A) ::= TEXT(B). { + A = new PHP_LexerGenerator_ParseryyToken(B, array( + 'pattern' => B)); +} +basic_text(A) ::= TEXT(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(B . M, array( + 'pattern' => B . M)); +} +basic_text(A) ::= FULLSTOP(B). { + A = new PHP_LexerGenerator_ParseryyToken(B, array( + 'pattern' => B)); +} +basic_text(A) ::= FULLSTOP(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(B . M, array( + 'pattern' => B . M)); +} +basic_text(A) ::= CONTROLCHAR(B). { + A = new PHP_LexerGenerator_ParseryyToken('\\' . B, array( + 'pattern' => B)); +} +basic_text(A) ::= CONTROLCHAR(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('\\' . B . M, array( + 'pattern' => B . M)); +} +basic_text(A) ::= ESCAPEDBACKSLASH(B). { + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . B, array( + 'pattern' => B)); +} +basic_text(A) ::= ESCAPEDBACKSLASH(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . B . M, array( + 'pattern' => B . M)); +} +basic_text(A) ::= BACKREFERENCE(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + // adjust back-reference for containing () + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +basic_text(A) ::= BACKREFERENCE(B) MULTIPLIER(M). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + // adjust back-reference for containing () + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex) . M, array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B) . M)); +} +basic_text(A) ::= COULDBEBACKREF(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex), array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +basic_text(A) ::= COULDBEBACKREF(B) MULTIPLIER(M). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken('\\\\' . (B + $this->_patternIndex) . M, array( + 'pattern' => '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B) . M)); +} +basic_text(A) ::= basic_text(T) TEXT(B). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . B, array( + 'pattern' => T['pattern'] . B)); +} +basic_text(A) ::= basic_text(T) TEXT(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . B . M, array( + 'pattern' => T['pattern'] . B . M)); +} +basic_text(A) ::= basic_text(T) FULLSTOP(B). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . B, array( + 'pattern' => T['pattern'] . B)); +} +basic_text(A) ::= basic_text(T) FULLSTOP(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . B . M, array( + 'pattern' => T['pattern'] . B . M)); +} +basic_text(A) ::= basic_text(T) CONTROLCHAR(B). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . '\\' . B, array( + 'pattern' => T['pattern'] . B)); +} +basic_text(A) ::= basic_text(T) CONTROLCHAR(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . '\\' . B . M, array( + 'pattern' => T['pattern'] . B . M)); +} +basic_text(A) ::= basic_text(T) ESCAPEDBACKSLASH(B). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . '\\\\' . B, array( + 'pattern' => T['pattern'] . B)); +} +basic_text(A) ::= basic_text(T) ESCAPEDBACKSLASH(B) MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken(T->string . '\\\\' . B . M, array( + 'pattern' => T['pattern'] . B . M)); +} +basic_text(A) ::= basic_text(P) BACKREFERENCE(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex), array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +basic_text(A) ::= basic_text(P) BACKREFERENCE(B) MULTIPLIER(M). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('Back-reference refers to non-existent ' . + 'sub-pattern ' . substr(B, 1)); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex) . M, array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B) . M)); +} +basic_text(A) ::= basic_text(P) COULDBEBACKREF(B). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex), array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B))); +} +basic_text(A) ::= basic_text(P) COULDBEBACKREF(B) MULTIPLIER(M). { + if (((int) substr(B, 1)) > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception(B . ' will be interpreted as an invalid' . + ' back-reference, use "\\0' . substr(B, 1) . ' for octal'); + } + B = substr(B, 1); + A = new PHP_LexerGenerator_ParseryyToken(P->string . '\\\\' . (B + $this->_patternIndex) . M, array( + 'pattern' => P['pattern'] . '\\' . ($this->_updatePattern ? (B + $this->_patternIndex) : B) . M)); +} + +assertion ::= OPENASSERTION(B) INTERNALOPTIONS(C) CLOSEPAREN(D). { + throw new PHP_LexerGenerator_Exception('Error: cannot set preg options directly with "' . + B . C . D . '"'); +} +assertion ::= OPENASSERTION(B) INTERNALOPTIONS(C) COLON(D) pattern(E) CLOSEPAREN(F). { + throw new PHP_LexerGenerator_Exception('Error: cannot set preg options directly with "' . + B . C . D . E['pattern'] . F . '"'); +} + +grouping(A) ::= OPENASSERTION COLON pattern(B) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(?:' . B->string . ')', array( + 'pattern' => '(?:' . B['pattern'] . ')')); +} +grouping(A) ::= OPENASSERTION COLON pattern(B) CLOSEPAREN MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('(?:' . B->string . ')' . M, array( + 'pattern' => '(?:' . B['pattern'] . ')' . M)); +} + +conditional(A) ::= OPENASSERTION OPENPAREN TEXT(T) CLOSEPAREN pattern(B) CLOSEPAREN MULTIPLIER(M). { + if (T != 'R') { + if (!preg_match('/[1-9][0-9]*/', T)) { + throw new PHP_LexerGenerator_Exception('Invalid sub-pattern conditional: "(?(' . T . ')"'); + } + if (T > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('sub-pattern conditional . "' . T . '" refers to non-existent sub-pattern'); + } + } else { + throw new PHP_LexerGenerator_Exception('Recursive conditional (?(' . T . ')" cannot work in this lexer'); + } + A = new PHP_LexerGenerator_ParseryyToken('(?(' . T . ')' . B->string . ')' . M, array( + 'pattern' => '(?(' . T . ')' . B['pattern'] . ')' . M)); +} +conditional(A) ::= OPENASSERTION OPENPAREN TEXT(T) CLOSEPAREN pattern(B) CLOSEPAREN. { + if (T != 'R') { + if (!preg_match('/[1-9][0-9]*/', T)) { + throw new PHP_LexerGenerator_Exception('Invalid sub-pattern conditional: "(?(' . T . ')"'); + } + if (T > $this->_subpatterns) { + throw new PHP_LexerGenerator_Exception('sub-pattern conditional . "' . T . '" refers to non-existent sub-pattern'); + } + } else { + throw new PHP_LexerGenerator_Exception('Recursive conditional (?(' . T . ')" cannot work in this lexer'); + } + A = new PHP_LexerGenerator_ParseryyToken('(?(' . T . ')' . B->string . ')', array( + 'pattern' => '(?(' . T . ')' . B['pattern'] . ')')); +} +conditional(A) ::= OPENASSERTION lookahead(B) pattern(C) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(?' . B->string . C->string . ')', array( + 'pattern' => '(?' . B['pattern'] . C['pattern'] . ')')); +} +conditional(A) ::= OPENASSERTION lookahead(B) pattern(C) CLOSEPAREN MULTIPLIER(M). { + A = new PHP_LexerGenerator_ParseryyToken('(?' . B->string . C->string . ')' . M, array( + 'pattern' => '(?' . B['pattern'] . C['pattern'] . ')' . M)); +} +conditional ::= OPENASSERTION lookbehind pattern(B) CLOSEPAREN. { + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?<=' . + B['pattern'] . ')'); +} +conditional ::= OPENASSERTION lookbehind pattern(B) CLOSEPAREN MULTIPLIER. { + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?<=' . + B['pattern'] . ')'); +} + +lookahead(A) ::= OPENASSERTION POSITIVELOOKAHEAD pattern(B) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(?=' . B->string . ')', array( + 'pattern '=> '(?=' . B['pattern'] . ')')); +} +lookahead(A) ::= OPENASSERTION NEGATIVELOOKAHEAD pattern(B) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(?!' . B->string . ')', array( + 'pattern' => '(?!' . B['pattern'] . ')')); +} + +lookbehind ::= OPENASSERTION POSITIVELOOKBEHIND pattern(B) CLOSEPAREN. { + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?<=' . + B['pattern'] . ')'); +} +lookbehind ::= OPENASSERTION NEGATIVELOOKBEHIND pattern(B) CLOSEPAREN. { + throw new PHP_LexerGenerator_Exception('Look-behind assertions cannot be used: "(?_subpatterns++; + A = new PHP_LexerGenerator_ParseryyToken('(' . B->string . ')', array( + 'pattern' => '(' . B['pattern'] . ')')); +} +subpattern(A) ::= OPENPAREN pattern(B) CLOSEPAREN MULTIPLIER(M). { + $this->_subpatterns++; + A = new PHP_LexerGenerator_ParseryyToken('(' . B->string . ')' . M, array( + 'pattern' => '(' . B['pattern'] . ')' . M)); +} + +onceonly(A) ::= OPENASSERTION ONCEONLY pattern(B) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(?>' . B->string . ')', array( + 'pattern' => '(?>' . B['pattern'] . ')')); +} + +comment(A) ::= OPENASSERTION COMMENT(B) CLOSEPAREN. { + A = new PHP_LexerGenerator_ParseryyToken('(' . B->string . ')', array( + 'pattern' => '(' . B['pattern'] . ')')); +} + +recur ::= OPENASSERTION RECUR CLOSEPAREN. { + throw new Exception('(?R) cannot work in this lexer'); +} \ No newline at end of file diff --git a/core/oql/build/PHP/LexerGenerator/cli.php b/core/oql/build/PHP/LexerGenerator/cli.php new file mode 100644 index 000000000..82f73167f --- /dev/null +++ b/core/oql/build/PHP/LexerGenerator/cli.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/core/oql/build/PHP/ParserGenerator.php b/core/oql/build/PHP/ParserGenerator.php new file mode 100644 index 000000000..4a6fa08a4 --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator.php @@ -0,0 +1,806 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: ParserGenerator.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/**#@+ + * Basic components of the parser generator + */ +require_once 'PHP/ParserGenerator/Action.php'; +require_once 'PHP/ParserGenerator/ActionTable.php'; +require_once 'PHP/ParserGenerator/Config.php'; +require_once 'PHP/ParserGenerator/Data.php'; +require_once 'PHP/ParserGenerator/Symbol.php'; +require_once 'PHP/ParserGenerator/Rule.php'; +require_once 'PHP/ParserGenerator/Parser.php'; +require_once 'PHP/ParserGenerator/PropagationLink.php'; +require_once 'PHP/ParserGenerator/State.php'; +/**#@-*/ +/** + * The basic home class for the parser generator + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + * @example Lempar.php + * @example examples/Parser.y Sample parser file format (PHP_LexerGenerator's parser) + * @example examples/Parser.php Sample parser file format PHP code (PHP_LexerGenerator's parser) + */ +class PHP_ParserGenerator +{ + /** + * Set this to 1 to turn on debugging of Lemon's parsing of + * grammar files. + */ + const DEBUG = 0; + const MAXRHS = 1000; + const OPT_FLAG = 1, OPT_INT = 2, OPT_DBL = 3, OPT_STR = 4, + OPT_FFLAG = 5, OPT_FINT = 6, OPT_FDBL = 7, OPT_FSTR = 8; + public $azDefine = array(); + private static $_options = array( + 'b' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'basisflag', + 'message' => 'Print only the basis in report.' + ), + 'c' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'compress', + 'message' => 'Don\'t compress the action table.' + ), + 'D' => array( + 'type' => self::OPT_FSTR, + 'arg' => 'handleDOption', + 'message' => 'Define an %ifdef macro.' + ), + 'g' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'rpflag', + 'message' => 'Print grammar without actions.' + ), + 'm' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'mhflag', + 'message' => 'Output a makeheaders compatible file' + ), + 'q' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'quiet', + 'message' => '(Quiet) Don\'t print the report file.' + ), + 's' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'statistics', + 'message' => 'Print parser stats to standard output.' + ), + 'x' => array( + 'type' => self::OPT_FLAG, + 'arg' => 'version', + 'message' => 'Print the version number.' + ), + 'T' => array( + 'type' => self::OPT_STR, + 'arg' => 'parser_template', + 'message' => 'Use different parser template file.' + ) + ); + + private $_basisflag = 0; + private $_compress = 0; + private $_rpflag = 0; + private $_mhflag = 0; + private $_quiet = 0; + private $_statistics = 0; + private $_version = 0; + private $_size; + private $_parser_template = ""; + + /** + * Process a flag command line argument. + * + * @param int $i + * @param array $argv + * + * @return int + */ + function handleflags($i, $argv) + { + if (!isset($argv[1]) || !isset(self::$_options[$argv[$i][1]])) { + throw new Exception('Command line syntax error: undefined option "' . $argv[$i] . '"'); + } + $v = self::$_options[$argv[$i][1]] == '-'; + if (self::$_options[$argv[$i][1]]['type'] == self::OPT_FLAG) { + $this->{self::$_options[$argv[$i][1]]['arg']} = 1; + } elseif (self::$_options[$argv[$i][1]]['type'] == self::OPT_FFLAG) { + $this->{self::$_options[$argv[$i][1]]['arg']}($v); + } elseif (self::$_options[$argv[$i][1]]['type'] == self::OPT_FSTR) { + $this->{self::$_options[$argv[$i][1]]['arg']}(substr($v, 2)); + } else { + throw new Exception('Command line syntax error: missing argument on switch: "' . $argv[$i] . '"'); + } + return 0; + } + + /** + * Process a command line switch which has an argument. + * + * @param int $i + * @param array $argv + * + * @return int + */ + function handleswitch($i, $argv) + { + $lv = 0; + $dv = 0.0; + $sv = $end = $cp = ''; + $j; // int + $errcnt = 0; + $cp = strstr($argv[$i], '='); + if (!$cp) { + throw new Exception('INTERNAL ERROR: handleswitch passed bad argument, no "=" in arg'); + } + $argv[$i] = substr($argv[$i], 0, strlen($argv[$i]) - strlen($cp)); + if (!isset(self::$_options[$argv[$i]])) { + throw new Exception('Command line syntax error: undefined option "' . $argv[$i] . + $cp . '"'); + } + $cp = substr($cp, 1); + switch (self::$_options[$argv[$i]]['type']) { + case self::OPT_FLAG: + case self::OPT_FFLAG: + throw new Exception('Command line syntax error: option requires an argument "' . + $argv[$i] . '=' . $cp . '"'); + case self::OPT_DBL: + case self::OPT_FDBL: + $dv = (double) $cp; + break; + case self::OPT_INT: + case self::OPT_FINT: + $lv = (int) $cp; + break; + case self::OPT_STR: + case self::OPT_FSTR: + $sv = $cp; + break; + } + switch(self::$_options[$argv[$i]]['type']) { + case self::OPT_FLAG: + case self::OPT_FFLAG: + break; + case self::OPT_DBL: + $this->{self::$_options[$argv[$i]]['arg']} = $dv; + break; + case self::OPT_FDBL: + $this->{self::$_options[$argv[$i]]['arg']}($dv); + break; + case self::OPT_INT: + $this->{self::$_options[$argv[$i]]['arg']} = $lv; + break; + case self::OPT_FINT: + $this->{self::$_options[$argv[$i]]['arg']}($lv); + break; + case self::OPT_STR: + $this->{self::$_options[$argv[$i]]['arg']} = $sv; + break; + case self::OPT_FSTR: + $this->{self::$_options[$argv[$i]]['arg']}($sv); + break; + } + return 0; + } + + /** + * OptInit + * + * @param array $a Arguments + * + * @return int + */ + function OptInit($a) + { + $errcnt = 0; + $argv = $a; + try { + if (is_array($argv) && count($argv) && self::$_options) { + for ($i = 1; $i < count($argv); $i++) { + if ($argv[$i][0] == '+' || $argv[$i][0] == '-') { + $errcnt += $this->handleflags($i, $argv); + } elseif (strstr($argv[$i], '=')) { + $errcnt += $this->handleswitch($i, $argv); + } + } + } + } catch (Exception $e) { + $this->OptPrint(); + echo $e->getMessage()."\n"; + exit(1); + } + return 0; + } + + /** + * Return the index of the N-th non-switch argument. Return -1 + * if N is out of range. + * + * @param int $n + * @param int $a + * + * @return int + */ + private function _argindex($n, $a) + { + $dashdash = 0; + if (!is_array($a) || !count($a)) { + return -1; + } + for ($i=1; $i < count($a); $i++) { + if ($dashdash || !($a[$i][0] == '-' || $a[$i][0] == '+' || strchr($a[$i], '='))) { + if ($n == 0) { + return $i; + } + $n--; + } + if ($_SERVER['argv'][$i] == '--') { + $dashdash = 1; + } + } + return -1; + } + + /** + * Return the value of the non-option argument as indexed by $i + * + * @param int $i + * @param array $a the value of $argv + * + * @return 0|string + */ + private function _optArg($i, $a) + { + if (-1 == ($ind = $this->_argindex($i, $a))) { + return 0; + } + return $a[$ind]; + } + + /** + * @param array $a + * + * @return int number of arguments + */ + function OptNArgs($a) + { + $cnt = $dashdash = 0; + if (is_array($a) && count($a)) { + for ($i = 1; $i < count($a); $i++) { + if ($dashdash + || !($a[$i][0] == '-' || $a[$i][0] == '+' || strchr($a[$i], '=')) + ) { + $cnt++; + } + if ($a[$i] == "--") { + $dashdash = 1; + } + } + } + return $cnt; + } + + /** + * Print out command-line options + * + * @return void + */ + function OptPrint() + { + $max = 0; + foreach (self::$_options as $label => $info) { + $len = strlen($label) + 1; + switch ($info['type']) { + case self::OPT_FLAG: + case self::OPT_FFLAG: + break; + case self::OPT_INT: + case self::OPT_FINT: + $len += 9; /* length of "" */ + break; + case self::OPT_DBL: + case self::OPT_FDBL: + $len += 6; /* length of "" */ + break; + case self::OPT_STR: + case self::OPT_FSTR: + $len += 8; /* length of "" */ + break; + } + if ($len > $max) { + $max = $len; + } + } + foreach (self::$_options as $label => $info) { + switch ($info['type']) { + case self::OPT_FLAG: + case self::OPT_FFLAG: + echo " -$label"; + echo str_repeat(' ', $max - strlen($label)); + echo " $info[message]\n"; + break; + case self::OPT_INT: + case self::OPT_FINT: + echo " $label=" . str_repeat(' ', $max - strlen($label) - 9); + echo " $info[message]\n"; + break; + case self::OPT_DBL: + case self::OPT_FDBL: + echo " $label=" . str_repeat(' ', $max - strlen($label) - 6); + echo " $info[message]\n"; + break; + case self::OPT_STR: + case self::OPT_FSTR: + echo " $label=" . str_repeat(' ', $max - strlen($label) - 8); + echo " $info[message]\n"; + break; + } + } + } + + /** + * This routine is called with the argument to each -D command-line option. + * Add the macro defined to the azDefine array. + * + * @param string $z + * + * @return void + */ + private function _handleDOption($z) + { + if ($a = strstr($z, '=')) { + $z = substr($a, 1); // strip first = + } + $this->azDefine[] = $z; + } + + /**************** From the file "main.c" ************************************/ + /* + ** Main program file for the LEMON parser generator. + */ + + + /** + * The main program. Parse the command line and do it... + * + * @return int Number of error and conflicts + */ + function main() + { + $lem = new PHP_ParserGenerator_Data; + + $this->OptInit($_SERVER['argv']); + if ($this->_version) { + echo "Lemon version 1.0/PHP_ParserGenerator port version @package_version@\n"; + exit(0); + } + if ($this->OptNArgs($_SERVER['argv']) != 1) { + echo "Exactly one filename argument is required.\n"; + exit(1); + } + $lem->errorcnt = 0; + $lem->parser_template = $this->_parser_template; + + /* Initialize the machine */ + $lem->argv0 = $_SERVER['argv'][0]; + $lem->filename = $this->_optArg(0, $_SERVER['argv']); + $a = pathinfo($lem->filename); + if (isset($a['extension'])) { + $ext = '.' . $a['extension']; + $lem->filenosuffix = substr($lem->filename, 0, strlen($lem->filename) - strlen($ext)); + } else { + $lem->filenosuffix = $lem->filename; + } + $lem->basisflag = $this->_basisflag; + $lem->has_fallback = 0; + $lem->nconflict = 0; + $lem->name = $lem->include_code = $lem->include_classcode = $lem->arg = $lem->tokentype = $lem->start = 0; + $lem->vartype = 0; + $lem->stacksize = 0; + $lem->error = $lem->overflow = $lem->failure = $lem->accept = $lem->tokendest = $lem->tokenprefix = $lem->outname = $lem->extracode = 0; + $lem->vardest = 0; + $lem->tablesize = 0; + PHP_ParserGenerator_Symbol::Symbol_new("$"); + $lem->errsym = PHP_ParserGenerator_Symbol::Symbol_new("error"); + + /* Parse the input file */ + $parser = new PHP_ParserGenerator_Parser($this); + $parser->Parse($lem); + if ($lem->errorcnt) { + exit($lem->errorcnt); + } + if ($lem->rule === 0) { + printf("Empty grammar.\n"); + exit(1); + } + + /* Count and index the symbols of the grammar */ + $lem->nsymbol = PHP_ParserGenerator_Symbol::Symbol_count(); + PHP_ParserGenerator_Symbol::Symbol_new("{default}"); + $lem->symbols = PHP_ParserGenerator_Symbol::Symbol_arrayof(); + for ($i = 0; $i <= $lem->nsymbol; $i++) { + $lem->symbols[$i]->index = $i; + } + usort($lem->symbols, array('PHP_ParserGenerator_Symbol', 'sortSymbols')); + for ($i = 0; $i <= $lem->nsymbol; $i++) { + $lem->symbols[$i]->index = $i; + } + // find the first lower-case symbol + for ($i = 1; ord($lem->symbols[$i]->name[0]) <= ord('Z'); $i++); + $lem->nterminal = $i; + + /* Generate a reprint of the grammar, if requested on the command line */ + if ($this->_rpflag) { + $this->Reprint(); + } else { + /* Initialize the size for all follow and first sets */ + $this->SetSize($lem->nterminal); + + /* Find the precedence for every production rule (that has one) */ + $lem->FindRulePrecedences(); + + /* Compute the lambda-nonterminals and the first-sets for every + ** nonterminal */ + $lem->FindFirstSets(); + + /* Compute all LR(0) states. Also record follow-set propagation + ** links so that the follow-set can be computed later */ + $lem->nstate = 0; + $lem->FindStates(); + $lem->sorted = PHP_ParserGenerator_State::State_arrayof(); + + /* Tie up loose ends on the propagation links */ + $lem->FindLinks(); + + /* Compute the follow set of every reducible configuration */ + $lem->FindFollowSets(); + + /* Compute the action tables */ + $lem->FindActions(); + + /* Compress the action tables */ + if ($this->_compress===0) { + $lem->CompressTables(); + } + + /* Reorder and renumber the states so that states with fewer choices + ** occur at the end. */ + $lem->ResortStates(); + + /* Generate a report of the parser generated. (the "y.output" file) */ + if (!$this->_quiet) { + $lem->ReportOutput(); + } + + /* Generate the source code for the parser */ + $lem->ReportTable($this->_mhflag); + + /* Produce a header file for use by the scanner. (This step is + ** omitted if the "-m" option is used because makeheaders will + ** generate the file for us.) */ + //if (!$this->_mhflag) { + // $this->ReportHeader(); + //} + } + if ($this->_statistics) { + printf( + "Parser statistics: %d terminals, %d nonterminals, %d rules\n", + $lem->nterminal, + $lem->nsymbol - $lem->nterminal, + $lem->nrule + ); + printf( + " %d states, %d parser table entries, %d conflicts\n", + $lem->nstate, + $lem->tablesize, + $lem->nconflict + ); + } + if ($lem->nconflict) { + printf("%d parsing conflicts.\n", $lem->nconflict); + } + exit($lem->errorcnt + $lem->nconflict); + return ($lem->errorcnt + $lem->nconflict); + } + + /** + * SetSize + * + * @param int $n + * + * @access public + * @return void + */ + function SetSize($n) + { + $this->_size = $n + 1; + } + + /** + * Merge in a merge sort for a linked list + * + * Side effects: + * The "next" pointers for elements in the lists a and b are + * changed. + * + * @param mixed $a A sorted, null-terminated linked list. (May be null). + * @param mixed $b A sorted, null-terminated linked list. (May be null). + * @param function $cmp A pointer to the comparison function. + * @param integer $offset Offset in the structure to the "next" field. + * + * @return mixed A pointer to the head of a sorted list containing the + * elements of both a and b. + */ + static function merge($a, $b, $cmp, $offset) + { + if ($a === 0) { + $head = $b; + } elseif ($b === 0) { + $head = $a; + } else { + if (call_user_func($cmp, $a, $b) < 0) { + $ptr = $a; + $a = $a->$offset; + } else { + $ptr = $b; + $b = $b->$offset; + } + $head = $ptr; + while ($a && $b) { + if (call_user_func($cmp, $a, $b) < 0) { + $ptr->$offset = $a; + $ptr = $a; + $a = $a->$offset; + } else { + $ptr->$offset = $b; + $ptr = $b; + $b = $b->$offset; + } + } + if ($a !== 0) { + $ptr->$offset = $a; + } else { + $ptr->$offset = $b; + } + } + return $head; + } + + #define LISTSIZE 30 + /** + * Side effects: + * The "next" pointers for elements in list are changed. + * + * @param mixed $list Pointer to a singly-linked list of structures. + * @param mixed $next Pointer to pointer to the second element of the list. + * @param function $cmp A comparison function. + * + * @return mixed A pointer to the head of a sorted list containing the + * elements orginally in list. + */ + static function msort($list, $next, $cmp) + { + if ($list === 0) { + return $list; + } + if ($list->$next === 0) { + return $list; + } + $set = array_fill(0, 30, 0); + while ($list) { + $ep = $list; + $list = $list->$next; + $ep->$next = 0; + for ($i = 0; $i < 29 && $set[$i] !== 0; $i++) { + $ep = self::merge($ep, $set[$i], $cmp, $next); + $set[$i] = 0; + } + $set[$i] = $ep; + } + $ep = 0; + for ($i = 0; $i < 30; $i++) { + if ($set[$i] !== 0) { + $ep = self::merge($ep, $set[$i], $cmp, $next); + } + } + return $ep; + } + + /* Find a good place to break "msg" so that its length is at least "min" + ** but no more than "max". Make the point as close to max as possible. + */ + static function findbreak($msg, $min, $max) + { + if ($min >= strlen($msg)) { + return strlen($msg); + } + for ($i = $spot = $min; $i <= $max && $i < strlen($msg); $i++) { + $c = $msg[$i]; + if ($c == '-' && $i < $max - 1) { + $spot = $i + 1; + } + if ($c == ' ') { + $spot = $i; + } + } + return $spot; + } + + static function ErrorMsg($filename, $lineno, $format) + { + /* Prepare a prefix to be prepended to every output line */ + if ($lineno > 0) { + $prefix = sprintf("%20s:%d: ", $filename, $lineno); + } else { + $prefix = sprintf("%20s: ", $filename); + } + $prefixsize = strlen($prefix); + $availablewidth = 79 - $prefixsize; + + /* Generate the error message */ + $ap = func_get_args(); + array_shift($ap); // $filename + array_shift($ap); // $lineno + array_shift($ap); // $format + $errmsg = vsprintf($format, $ap); + $linewidth = strlen($errmsg); + /* Remove trailing "\n"s from the error message. */ + while ($linewidth > 0 + && in_array($errmsg[$linewidth-1], array("\n", "\r"), true) + ) { + --$linewidth; + $errmsg = substr($errmsg, 0, strlen($errmsg) - 1); + } + + /* Print the error message */ + $base = 0; + $errmsg = str_replace( + array("\r", "\n", "\t"), + array(' ', ' ', ' '), + $errmsg + ); + while (strlen($errmsg)) { + $end = $restart = self::findbreak($errmsg, 0, $availablewidth); + if (strlen($errmsg) <= 79 && $end < strlen($errmsg) && $end <= 79) { + $end = $restart = strlen($errmsg); + } + while (isset($errmsg[$restart]) && $errmsg[$restart] == ' ') { + $restart++; + } + printf("%s%.${end}s\n", $prefix, $errmsg); + $errmsg = substr($errmsg, $restart); + } + } + + /** + * Duplicate the input file without comments and without actions + * on rules + * + * @return void + */ + function Reprint() + { + printf("// Reprint of input file \"%s\".\n// Symbols:\n", $this->filename); + $maxlen = 10; + for ($i = 0; $i < $this->nsymbol; $i++) { + $sp = $this->symbols[$i]; + $len = strlen($sp->name); + if ($len > $maxlen ) { + $maxlen = $len; + } + } + $ncolumns = 76 / ($maxlen + 5); + if ($ncolumns < 1) { + $ncolumns = 1; + } + $skip = ($this->nsymbol + $ncolumns - 1) / $ncolumns; + for ($i = 0; $i < $skip; $i++) { + print "//"; + for ($j = $i; $j < $this->nsymbol; $j += $skip) { + $sp = $this->symbols[$j]; + //assert( sp->index==j ); + printf(" %3d %-${maxlen}.${maxlen}s", $j, $sp->name); + } + print "\n"; + } + for ($rp = $this->rule; $rp; $rp = $rp->next) { + printf("%s", $rp->lhs->name); + /*if ($rp->lhsalias) { + printf("(%s)", $rp->lhsalias); + }*/ + print " ::="; + for ($i = 0; $i < $rp->nrhs; $i++) { + $sp = $rp->rhs[$i]; + printf(" %s", $sp->name); + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for ($j = 1; $j < $sp->nsubsym; $j++) { + printf("|%s", $sp->subsym[$j]->name); + } + } + /*if ($rp->rhsalias[$i]) { + printf("(%s)", $rp->rhsalias[$i]); + }*/ + } + print "."; + if ($rp->precsym) { + printf(" [%s]", $rp->precsym->name); + } + /*if ($rp->code) { + print "\n " . $rp->code); + }*/ + print "\n"; + } + } +} diff --git a/core/oql/build/PHP/ParserGenerator/Action.php b/core/oql/build/PHP/ParserGenerator/Action.php new file mode 100644 index 000000000..e0108890e --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Action.php @@ -0,0 +1,257 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Action.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ + +/** + * Every shift or reduce operation is stored as one of the following objects. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_Action +{ + const SHIFT = 1, + ACCEPT = 2, + REDUCE = 3, + ERROR = 4, + /** + * Was a reduce, but part of a conflict + */ + CONFLICT = 5, + /** + * Was a shift. Precedence resolved conflict + */ + SH_RESOLVED = 6, + /** + * Was a reduce. Precedence resolved conflict + */ + RD_RESOLVED = 7, + /** + * Deleted by compression + * @see PHP_ParserGenerator::CompressTables() + */ + NOT_USED = 8; + /** + * The look-ahead symbol that triggers this action + * @var PHP_ParserGenerator_Symbol + */ + public $sp; /* The look-ahead symbol */ + /** + * This defines the kind of action, and must be one + * of the class constants. + * + * - {@link PHP_ParserGenerator_Action::SHIFT} + * - {@link PHP_ParserGenerator_Action::ACCEPT} + * - {@link PHP_ParserGenerator_Action::REDUCE} + * - {@link PHP_ParserGenerator_Action::ERROR} + * - {@link PHP_ParserGenerator_Action::CONFLICT} + * - {@link PHP_ParserGenerator_Action::SH_RESOLVED} + * - {@link PHP_ParserGenerator_Action:: RD_RESOLVED} + * - {@link PHP_ParserGenerator_Action::NOT_USED} + */ + public $type; + /** + * The new state, if this is a shift, + * the parser rule index, if this is a reduce. + * + * @var PHP_ParserGenerator_State|PHP_ParserGenerator_Rule + */ + public $x; + /** + * The next action for this state. + * @var PHP_ParserGenerator_Action + */ + public $next; + + /** + * Compare two actions + * + * This is used by {@link Action_sort()} to compare actions + */ + static function actioncmp(PHP_ParserGenerator_Action $ap1, PHP_ParserGenerator_Action $ap2) + { + $rc = $ap1->sp->index - $ap2->sp->index; + if ($rc === 0) { + $rc = $ap1->type - $ap2->type; + } + if ($rc === 0) { + if ($ap1->type == self::SHIFT) { + if ($ap1->x->statenum != $ap2->x->statenum) { + throw new Exception('Shift conflict: ' . $ap1->sp->name . + ' shifts both to state ' . $ap1->x->statenum . ' (rule ' . + $ap1->x->cfp->rp->lhs->name . ' on line ' . + $ap1->x->cfp->rp->ruleline . ') and to state ' . + $ap2->x->statenum . ' (rule ' . + $ap2->x->cfp->rp->lhs->name . ' on line ' . + $ap2->x->cfp->rp->ruleline . ')'); + } + } + if ($ap1->type != self::REDUCE + && $ap1->type != self::RD_RESOLVED + && $ap1->type != self::CONFLICT + ) { + throw new Exception('action has not been processed: ' . + $ap1->sp->name . ' on line ' . $ap1->x->cfp->rp->ruleline . + ', rule ' . $ap1->x->cfp->rp->lhs->name); + } + if ($ap2->type != self::REDUCE + && $ap2->type != self::RD_RESOLVED + && $ap2->type != self::CONFLICT + ) { + throw new Exception('action has not been processed: ' . + $ap2->sp->name . ' on line ' . $ap2->x->cfp->rp->ruleline . + ', rule ' . $ap2->x->cfp->rp->lhs->name); + } + $rc = $ap1->x->index - $ap2->x->index; + } + return $rc; + } + + function display($processed = false) + { + $map = array( + self::ACCEPT => 'ACCEPT', + self::CONFLICT => 'CONFLICT', + self::REDUCE => 'REDUCE', + self::SHIFT => 'SHIFT' + ); + echo $map[$this->type] . ' for ' . $this->sp->name; + if ($this->type == self::REDUCE) { + echo ' - rule ' . $this->x->lhs->name . "\n"; + } elseif ($this->type == self::SHIFT) { + echo ' - state ' . $this->x->statenum . ', basis ' . $this->x->cfp->rp->lhs->name . "\n"; + } else { + echo "\n"; + } + } + + /** + * create linked list of PHP_ParserGenerator_Actions + * + * @param PHP_ParserGenerator_Action|null $app + * @param int $type one of the class constants from PHP_ParserGenerator_Action + * @param PHP_ParserGenerator_Symbol $sp + * @param PHP_ParserGenerator_State|PHP_ParserGenerator_Rule $arg + */ + static function Action_add(&$app, $type, PHP_ParserGenerator_Symbol $sp, $arg) + { + $new = new PHP_ParserGenerator_Action; + $new->next = $app; + $app = $new; + $new->type = $type; + $new->sp = $sp; + $new->x = $arg; + echo ' Adding '; + $new->display(); + } + + /** + * Sort parser actions + * + * @param PHP_ParserGenerator_Action $ap a parser action + * + * @see PHP_ParserGenerator_Data::FindActions() + * + * @return PHP_ParserGenerator_Action + */ + static function Action_sort(PHP_ParserGenerator_Action $ap) + { + $ap = PHP_ParserGenerator::msort($ap, 'next', array('PHP_ParserGenerator_Action', 'actioncmp')); + return $ap; + } + + /** + * Print an action to the given file descriptor. Return FALSE if + * nothing was actually printed. + * + * @param resource $fp File descriptor to print on + * @param integer $indent Number of indents + * + * @see PHP_ParserGenerator_Data::ReportOutput() + * + * @return int|false + */ + function PrintAction($fp, $indent) + { + if (!$fp) { + $fp = STDOUT; + } + $result = 1; + switch ($this->type) + { + case self::SHIFT: + fprintf($fp, "%${indent}s shift %d", $this->sp->name, $this->x->statenum); + break; + case self::REDUCE: + fprintf($fp, "%${indent}s reduce %d", $this->sp->name, $this->x->index); + break; + case self::ACCEPT: + fprintf($fp, "%${indent}s accept", $this->sp->name); + break; + case self::ERROR: + fprintf($fp, "%${indent}s error", $this->sp->name); + break; + case self::CONFLICT: + fprintf($fp, "%${indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index); + break; + case self::SH_RESOLVED: + case self::RD_RESOLVED: + case self::NOT_USED: + $result = 0; + break; + } + return $result; + } +} +?> diff --git a/core/oql/build/PHP/ParserGenerator/ActionTable.php b/core/oql/build/PHP/ParserGenerator/ActionTable.php new file mode 100644 index 000000000..9e6c8ca3d --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/ActionTable.php @@ -0,0 +1,299 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: ActionTable.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** + * The state of the yy_action table under construction is an instance of + * the following structure + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_ActionTable +{ + /** + * Number of used slots in {@link $aAction} + * @var int + */ + public $nAction = 0; + /** + * The $yy_action table under construction. + * + * Each entry is of format: + * + * array( + * 'lookahead' => -1, // Value of the lookahead token (symbol index) + * 'action' => -1 // Action to take on the given lookahead (action index) + * ); + * + * @see PHP_ParserGenerator_Data::compute_action() + * @var array + */ + public $aAction = array( + array( + 'lookahead' => -1, + 'action' => -1 + ) + ); + /** + * A single new transaction set. + * + * @see $aAction format of the internal array is described here + * @var array + */ + public $aLookahead = array( + array( + 'lookahead' => 0, + 'action' => 0 + ) + ); + /** + * The smallest (minimum) value of any lookahead token in {@link $aLookahead} + * + * The lowest non-terminal is always introduced earlier in the parser file, + * and is therefore a more significant token. + * @var int + */ + public $mnLookahead = 0; + /** + * The action associated with the smallest lookahead token. + * @see $mnLookahead + * @var int + */ + public $mnAction = 0; + /** + * The largest (maximum) value of any lookahead token in {@link $aLookahead} + * @var int + */ + public $mxLookahead = 0; + /** + * The number of slots used in {@link $aLookahead}. + * + * This is the same as count($aLookahead), but there was no pressing reason + * to change this when porting from C. + * @see $mnLookahead + * @var int + */ + public $nLookahead = 0; + + /** + * Add a new action to the current transaction set + * + * @param int $lookahead + * @param int $action + * + * @return void + */ + function acttab_action($lookahead, $action) + { + if ($this->nLookahead === 0) { + $this->aLookahead = array(); + $this->mxLookahead = $lookahead; + $this->mnLookahead = $lookahead; + $this->mnAction = $action; + } else { + if ($this->mxLookahead < $lookahead) { + $this->mxLookahead = $lookahead; + } + if ($this->mnLookahead > $lookahead) { + $this->mnLookahead = $lookahead; + $this->mnAction = $action; + } + } + $this->aLookahead[$this->nLookahead] = array( + 'lookahead' => $lookahead, + 'action' => $action); + $this->nLookahead++; + } + + /** + * Add the transaction set built up with prior calls to acttab_action() + * into the current action table. Then reset the transaction set back + * to an empty set in preparation for a new round of acttab_action() calls. + * + * Return the offset into the action table of the new transaction. + * + * @return int Return the offset that should be added to the lookahead in + * order to get the index into $yy_action of the action. This will be used + * in generation of $yy_ofst tables (reduce and shift) + * @throws Exception + */ + function acttab_insert() + { + if ($this->nLookahead <= 0) { + throw new Exception('nLookahead is not set up?'); + } + + /* Scan the existing action table looking for an offset where we can + ** insert the current transaction set. Fall out of the loop when that + ** offset is found. In the worst case, we fall out of the loop when + ** i reaches $this->nAction, which means we append the new transaction set. + ** + ** i is the index in $this->aAction[] where $this->mnLookahead is inserted. + */ + for ($i = 0; $i < $this->nAction + $this->mnLookahead; $i++) { + if (!isset($this->aAction[$i])) { + $this->aAction[$i] = array( + 'lookahead' => -1, + 'action' => -1, + ); + } + if ($this->aAction[$i]['lookahead'] < 0) { + for ($j = 0; $j < $this->nLookahead; $j++) { + if (!isset($this->aLookahead[$j])) { + $this->aLookahead[$j] = array( + 'lookahead' => 0, + 'action' => 0, + ); + } + $k = $this->aLookahead[$j]['lookahead'] - + $this->mnLookahead + $i; + if ($k < 0) { + break; + } + if (!isset($this->aAction[$k])) { + $this->aAction[$k] = array( + 'lookahead' => -1, + 'action' => -1, + ); + } + if ($this->aAction[$k]['lookahead'] >= 0) { + break; + } + } + if ($j < $this->nLookahead ) { + continue; + } + for ($j = 0; $j < $this->nAction; $j++) { + if (!isset($this->aAction[$j])) { + $this->aAction[$j] = array( + 'lookahead' => -1, + 'action' => -1, + ); + } + if ($this->aAction[$j]['lookahead'] == $j + $this->mnLookahead - $i) { + break; + } + } + if ($j == $this->nAction) { + break; /* Fits in empty slots */ + } + } elseif ($this->aAction[$i]['lookahead'] == $this->mnLookahead) { + if ($this->aAction[$i]['action'] != $this->mnAction) { + continue; + } + for ($j = 0; $j < $this->nLookahead; $j++) { + $k = $this->aLookahead[$j]['lookahead'] - + $this->mnLookahead + $i; + if ($k < 0 || $k >= $this->nAction) { + break; + } + if (!isset($this->aAction[$k])) { + $this->aAction[$k] = array( + 'lookahead' => -1, + 'action' => -1, + ); + } + if ($this->aLookahead[$j]['lookahead'] != $this->aAction[$k]['lookahead']) { + break; + } + if ($this->aLookahead[$j]['action'] != $this->aAction[$k]['action']) { + break; + } + } + if ($j < $this->nLookahead) { + continue; + } + $n = 0; + for ($j = 0; $j < $this->nAction; $j++) { + if (!isset($this->aAction[$j])) { + $this->aAction[$j] = array( + 'lookahead' => -1, + 'action' => -1, + ); + } + if ($this->aAction[$j]['lookahead'] < 0) { + continue; + } + if ($this->aAction[$j]['lookahead'] == $j + $this->mnLookahead - $i) { + $n++; + } + } + if ($n == $this->nLookahead) { + break; /* Same as a prior transaction set */ + } + } + } + /* Insert transaction set at index i. */ + for ($j = 0; $j < $this->nLookahead; $j++) { + if (!isset($this->aLookahead[$j])) { + $this->aLookahead[$j] = array( + 'lookahead' => 0, + 'action' => 0, + ); + } + $k = $this->aLookahead[$j]['lookahead'] - $this->mnLookahead + $i; + $this->aAction[$k] = $this->aLookahead[$j]; + if ($k >= $this->nAction) { + $this->nAction = $k + 1; + } + } + $this->nLookahead = 0; + $this->aLookahead = array(); + + /* Return the offset that is added to the lookahead in order to get the + ** index into yy_action of the action */ + return $i - $this->mnLookahead; + } +} +?> diff --git a/core/oql/build/PHP/ParserGenerator/Config.php b/core/oql/build/PHP/ParserGenerator/Config.php new file mode 100644 index 000000000..591fb03bc --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Config.php @@ -0,0 +1,574 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Config.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** +/** A configuration is a production rule of the grammar together with + * a mark (dot) showing how much of that rule has been processed so far. + * + * Configurations also contain a follow-set which is a list of terminal + * symbols which are allowed to immediately follow the end of the rule. + * Every configuration is recorded as an instance of the following class. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_Config +{ + const COMPLETE = 1; + const INCOMPLETE = 2; + /** + * The parser rule upon with the configuration is based. + * + * A parser rule is something like: + *
+     * blah ::= FOO bar.
+     * 
+ * @var PHP_ParserGenerator_Rule + */ + public $rp; + /** + * The parse point. + * + * This is the index into the right-hand side of a rule that is + * represented by this configuration. In other words, possible + * dots for this rule: + * + *
+     * blah ::= FOO bar.
+     * 
+ * + * are (represented by "[here]"): + * + *
+     * blah ::= [here] FOO bar.
+     * blah ::= FOO [here] bar.
+     * blah ::= FOO bar [here].
+     * 
+ * @var int + */ + public $dot; + /** + * Follow-set for this configuration only + * + * This is the list of terminals and non-terminals that + * can follow this configuration. + * @var array + */ + public $fws; + /** + * Follow-set forward propagation links. + * @var PHP_ParserGenerator_PropagationLink + */ + public $fplp; + /** + * Follow-set backwards propagation links + * @var PHP_ParserGenerator_PropagationLink + */ + public $bplp; + /** + * State that contains this configuration + * @var PHP_ParserGenerator_State + */ + public $stp; + /* enum { + COMPLETE, /* The status is used during followset and + INCOMPLETE /* shift computations + } */ + /** + * Status during followset and shift computations. + * + * One of PHP_ParserGenerator_Config::COMPLETE or + * PHP_ParserGenerator_Config::INCOMPLETE. + * @var int + */ + public $status; + /** + * Next configuration in the state. + * + * Index of next PHP_ParserGenerator_Config object. + * @var int + */ + public $next; + /** + * Index of the next basis configuration PHP_ParserGenerator_Config object + * @var int + */ + public $bp; + + /** + * Top of the list of configurations for the current state. + * @var PHP_ParserGenerator_Config + */ + static public $current; + /** + * Last on the list of configurations for the current state. + * @var PHP_ParserGenerator_Config + */ + static public $currentend; + + /** + * Top of the list of basis configurations for the current state. + * @var PHP_ParserGenerator_Config + */ + static public $basis; + /** + * Last on the list of basis configurations for the current state. + * @var PHP_ParserGenerator_Config + */ + static public $basisend; + + /** + * Associative array representation of the linked list of configurations + * found in {@link $current} + * + * @var array + */ + static public $x4a = array(); + + /** + * Return a pointer to a new configuration + * @return PHP_ParserGenerator_Config + */ + private static function newconfig() + { + return new PHP_ParserGenerator_Config; + } + + /** + * Display the current configuration for the .out file + * + * @param PHP_ParserGenerator_Config $cfp + * @see PHP_ParserGenerator_Data::ReportOutput() + */ + static function Configshow(PHP_ParserGenerator_Config $cfp) + { + $fp = fopen('php://output', 'w'); + while ($cfp) { + if ($cfp->dot == $cfp->rp->nrhs) { + $buf = sprintf('(%d)', $cfp->rp->index); + fprintf($fp, ' %5s ', $buf); + } else { + fwrite($fp,' '); + } + $cfp->ConfigPrint($fp); + fwrite($fp, "\n"); + if (0) { + //SetPrint(fp,cfp->fws,$this); + //PlinkPrint(fp,cfp->fplp,"To "); + //PlinkPrint(fp,cfp->bplp,"From"); + } + $cfp = $cfp->next; + } + fwrite($fp, "\n"); + fclose($fp); + } + + /** + * Initialize the configuration list builder for a new state. + */ + static function Configlist_init() + { + self::$current = 0; + self::$currentend = &self::$current; + self::$basis = 0; + self::$basisend = &self::$basis; + self::$x4a = array(); + } + + /** + * Remove all data from the table. + * + * Pass each data to the function $f as it is removed if + * $f is a valid callback. + * @param callback|null + * @see Configtable_clear() + */ + static function Configtable_reset($f) + { + self::$current = 0; + self::$currentend = &self::$current; + self::$basis = 0; + self::$basisend = &self::$basis; + self::Configtable_clear(0); + } + + /** + * Remove all data from the associative array representation + * of configurations. + * + * Pass each data to the function $f as it is removed if + * $f is a valid callback. + * @param callback|null + */ + static function Configtable_clear($f) + { + if (!count(self::$x4a)) { + return; + } + if ($f) { + for ($i = 0; $i < count(self::$x4a); $i++) { + call_user_func($f, self::$x4a[$i]->data); + } + } + self::$x4a = array(); + } + + /** + * Reset the configuration list builder for a new state. + * @see Configtable_clear() + */ + static function Configlist_reset() + { + self::Configtable_clear(0); + } + + /** + * Add another configuration to the configuration list for this parser state. + * @param PHP_ParserGenerator_Rule the rule + * @param int Index into the right-hand side of the rule where the dot goes + * @return PHP_ParserGenerator_Config + */ + static function Configlist_add($rp, $dot) + { + $model = new PHP_ParserGenerator_Config; + $model->rp = $rp; + $model->dot = $dot; + $cfp = self::Configtable_find($model); + if ($cfp === 0) { + $cfp = self::newconfig(); + $cfp->rp = $rp; + $cfp->dot = $dot; + $cfp->fws = array(); + $cfp->stp = 0; + $cfp->fplp = $cfp->bplp = 0; + $cfp->next = 0; + $cfp->bp = 0; + self::$currentend = $cfp; + self::$currentend = &$cfp->next; + self::Configtable_insert($cfp); + } + return $cfp; + } + + /** + * Add a basis configuration to the configuration list for this parser state. + * + * Basis configurations are the root for a configuration. This method also + * inserts the configuration into the regular list of configurations for this + * reason. + * @param PHP_ParserGenerator_Rule the rule + * @param int Index into the right-hand side of the rule where the dot goes + * @return PHP_ParserGenerator_Config + */ + static function Configlist_addbasis($rp, $dot) + { + $model = new PHP_ParserGenerator_Config; + $model->rp = $rp; + $model->dot = $dot; + $cfp = self::Configtable_find($model); + if ($cfp === 0) { + $cfp = self::newconfig(); + $cfp->rp = $rp; + $cfp->dot = $dot; + $cfp->fws = array(); + $cfp->stp = 0; + $cfp->fplp = $cfp->bplp = 0; + $cfp->next = 0; + $cfp->bp = 0; + self::$currentend = $cfp; + self::$currentend = &$cfp->next; + self::$basisend = $cfp; + self::$basisend = &$cfp->bp; + self::Configtable_insert($cfp); + } + return $cfp; + } + + /** + * Compute the closure of the configuration list. + * + * This calculates all of the possible continuations of + * each configuration, ensuring that each state accounts + * for every configuration that could arrive at that state. + */ + static function Configlist_closure(PHP_ParserGenerator_Data $lemp) + { + for ($cfp = self::$current; $cfp; $cfp = $cfp->next) { + $rp = $cfp->rp; + $dot = $cfp->dot; + if ($dot >= $rp->nrhs) { + continue; + } + $sp = $rp->rhs[$dot]; + if ($sp->type == PHP_ParserGenerator_Symbol::NONTERMINAL) { + if ($sp->rule === 0 && $sp !== $lemp->errsym) { + PHP_ParserGenerator::ErrorMsg($lemp->filename, $rp->line, + "Nonterminal \"%s\" has no rules.", $sp->name); + $lemp->errorcnt++; + } + for ($newrp = $sp->rule; $newrp; $newrp = $newrp->nextlhs) { + $newcfp = self::Configlist_add($newrp, 0); + for ($i = $dot + 1; $i < $rp->nrhs; $i++) { + $xsp = $rp->rhs[$i]; + if ($xsp->type == PHP_ParserGenerator_Symbol::TERMINAL) { + $newcfp->fws[$xsp->index] = 1; + break; + } elseif ($xsp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for ($k = 0; $k < $xsp->nsubsym; $k++) { + $newcfp->fws[$xsp->subsym[$k]->index] = 1; + } + break; + } else { + $a = array_diff_key($xsp->firstset, $newcfp->fws); + $newcfp->fws += $a; + if ($xsp->lambda === false) { + break; + } + } + } + if ($i == $rp->nrhs) { + PHP_ParserGenerator_PropagationLink::Plink_add($cfp->fplp, $newcfp); + } + } + } + } + } + + /** + * Sort the configuration list + * @uses Configcmp() + */ + static function Configlist_sort() + { + $a = 0; + //self::Configshow(self::$current); + self::$current = PHP_ParserGenerator::msort(self::$current,'next', array('PHP_ParserGenerator_Config', 'Configcmp')); + //self::Configshow(self::$current); + self::$currentend = &$a; + self::$currentend = 0; + } + + /** + * Sort the configuration list + * @uses Configcmp + */ + static function Configlist_sortbasis() + { + $a = 0; + self::$basis = PHP_ParserGenerator::msort(self::$current,'bp', array('PHP_ParserGenerator_Config', 'Configcmp')); + self::$basisend = &$a; + self::$basisend = 0; + } + + /** + * Return a pointer to the head of the configuration list and + * reset the list + * @see $current + * @return PHP_ParserGenerator_Config + */ + static function Configlist_return() + { + $old = self::$current; + self::$current = 0; + self::$currentend = &self::$current; + return $old; + } + + /** + * Return a pointer to the head of the basis list and + * reset the list + * @see $basis + * @return PHP_ParserGenerator_Config + */ + static function Configlist_basis() + { + $old = self::$basis; + self::$basis = 0; + self::$basisend = &self::$basis; + return $old; + } + + /** + * Free all elements of the given configuration list + * @param PHP_ParserGenerator_Config + */ + static function Configlist_eat($cfp) + { + for (; $cfp; $cfp = $nextcfp) { + $nextcfp = $cfp->next; + if ($cfp->fplp !=0) { + throw new Exception('fplp of configuration non-zero?'); + } + if ($cfp->bplp !=0) { + throw new Exception('bplp of configuration non-zero?'); + } + if ($cfp->fws) { + $cfp->fws = array(); + } + } + } + + /** + * Compare two configurations for sorting purposes. + * + * Configurations based on higher precedence rules + * (those earlier in the file) are chosen first. Two + * configurations that are the same rule are sorted by + * dot (see {@link $dot}), and those configurations + * with a dot closer to the left-hand side are chosen first. + * @param unknown_type $a + * @param unknown_type $b + * @return unknown + */ + static function Configcmp($a, $b) + { + $x = $a->rp->index - $b->rp->index; + if (!$x) { + $x = $a->dot - $b->dot; + } + return $x; + } + + /** + * Print out information on this configuration. + * + * @param resource $fp + * @see PHP_ParserGenerator_Data::ReportOutput() + */ + function ConfigPrint($fp) + { + $rp = $this->rp; + fprintf($fp, "%s ::=", $rp->lhs->name); + for ($i = 0; $i <= $rp->nrhs; $i++) { + if ($i === $this->dot) { + fwrite($fp,' *'); + } + if ($i === $rp->nrhs) { + break; + } + $sp = $rp->rhs[$i]; + fprintf($fp,' %s', $sp->name); + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for ($j = 1; $j < $sp->nsubsym; $j++) { + fprintf($fp, '|%s', $sp->subsym[$j]->name); + } + } + } + } + + /** + * Hash a configuration for the associative array {@link $x4a} + */ + private static function confighash(PHP_ParserGenerator_Config $a) + { + $h = 0; + $h = $h * 571 + $a->rp->index * 37 + $a->dot; + return $h; + } + + /** + * Insert a new record into the array. Return TRUE if successful. + * Prior data with the same key is NOT overwritten + */ + static function Configtable_insert(PHP_ParserGenerator_Config $data) + { + $h = self::confighash($data); + if (isset(self::$x4a[$h])) { + $np = self::$x4a[$h]; + } else { + $np = 0; + } + while ($np) { + if (self::Configcmp($np->data, $data) == 0) { + /* An existing entry with the same key is found. */ + /* Fail because overwrite is not allows. */ + return 0; + } + $np = $np->next; + } + /* Insert the new data */ + $np = array('data' => $data, 'next' => 0, 'from' => 0); + $np = new PHP_ParserGenerator_StateNode; + $np->data = $data; + if (isset(self::$x4a[$h])) { + self::$x4a[$h]->from = $np->next; + $np->next = self::$x4a[$h]; + } + $np->from = $np; + self::$x4a[$h] = $np; + return 1; + } + + /** + * Return a pointer to data assigned to the given key. Return NULL + * if no such key. + * @return PHP_ParserGenerator_Config|0 + */ + static function Configtable_find(PHP_ParserGenerator_Config $key) + { + $h = self::confighash($key); + if (!isset(self::$x4a[$h])) { + return 0; + } + $np = self::$x4a[$h]; + while ($np) { + if (self::Configcmp($np->data, $key) == 0) { + break; + } + $np = $np->next; + } + return $np ? $np->data : 0; + } +} +?> diff --git a/core/oql/build/PHP/ParserGenerator/Data.php b/core/oql/build/PHP/ParserGenerator/Data.php new file mode 100644 index 000000000..39e62597c --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Data.php @@ -0,0 +1,1857 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category php + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Data.php 302209 2010-08-14 14:32:56Z jespino $ + * @since File available since Release 0.1.0 + */ +/** +/** + * The state vector for the entire parser generator is recorded in + * this class. + * + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version @package_version@ + * @since Class available since Release 0.1.0 + */ + +class PHP_ParserGenerator_Data +{ + /** + * Used for terminal and non-terminal offsets into the action table + * when their default should be used instead + */ + const NO_OFFSET = -2147483647; + /** + * Table of states sorted by state number + * @var array array of {@link PHP_ParserGenerator_State} objects + */ + public $sorted; + /** + * List of all rules + * @var PHP_ParserGenerator_Rule + */ + public $rule; + /** + * Number of states + * @var int + */ + public $nstate; + /** + * Number of rules + * @var int + */ + public $nrule; + /** + * Number of terminal and nonterminal symbols + * @var int + */ + public $nsymbol; + /** + * Number of terminal symbols (tokens) + * @var int + */ + public $nterminal; + /** + * Sorted array of pointers to symbols + * @var array array of {@link PHP_ParserGenerator_Symbol} objects + */ + public $symbols = array(); + /** + * Number of errors + * @var int + */ + public $errorcnt; + /** + * The error symbol + * @var PHP_ParserGenerator_Symbol + */ + public $errsym; + /** + * Name of the generated parser + * @var string + */ + public $name; + /** + * Unused relic from the C version + * + * Type of terminal symbols in the parser stack + * @var string + */ + public $tokentype; + /** + * Unused relic from the C version + * + * The default type of non-terminal symbols + * @var string + */ + public $vartype; + /** + * Name of the start symbol for the grammar + * @var string + */ + public $start; + /** + * Size of the parser stack + * + * This is 100 by default, but is set with the %stack_size directive + * @var int + */ + public $stacksize; + /** + * Code to put at the start of the parser file + * + * This is set by the %include directive + * @var string + */ + public $include_code; + /** + * Line number for start of include code + * @var int + */ + public $includeln; + /** + * Code to put in the parser class + * + * This is set by the %include_class directive + * @var string + */ + public $include_classcode; + /** + * Line number for start of include code + * @var int + */ + public $include_classln; + /** + * any extends/implements code + * + * This is set by the %declare_class directive + * @var string + */ + /** + * Line number for class declaration code + * @var int + */ + public $declare_classcode; + /** + * Line number for start of class declaration code + * @var int + */ + public $declare_classln; + /** + * Code to execute when a syntax error is seen + * + * This is set by the %syntax_error directive + * @var string + */ + public $error; + /** + * Line number for start of error code + * @var int + */ + public $errorln; + /** + * Code to execute on a stack overflow + * + * This is set by the %stack_overflow directive + */ + public $overflow; + /** + * Line number for start of overflow code + * @var int + */ + public $overflowln; + /** + * Code to execute on parser failure + * + * This is set by the %parse_failure directive + * @var string + */ + public $failure; + /** + * Line number for start of failure code + * @var int + */ + public $failureln; + /** + * Code to execute when the parser acccepts (completes parsing) + * + * This is set by the %parse_accept directive + * @var string + */ + public $accept; + /** + * Line number for the start of accept code + * @var int + */ + public $acceptln; + /** + * Code appended to the generated file + * + * This is set by the %code directive + * @var string + */ + public $extracode; + /** + * Line number for the start of the extra code + * @var int + */ + public $extracodeln; + /** + * Code to execute to destroy token data + * + * This is set by the %token_destructor directive + * @var string + */ + public $tokendest; + /** + * Line number for token destroyer code + * @var int + */ + public $tokendestln; + /** + * Code for the default non-terminal destructor + * + * This is set by the %default_destructor directive + * @var string + */ + public $vardest; + /** + * Line number for default non-terminal destructor code + * @var int + */ + public $vardestln; + /** + * Name of the input file + * @var string + */ + public $filename; + /** + * Name of the input file without its extension + * @var string + */ + public $filenosuffix; + /** + * Name of the current output file + * @var string + */ + public $outname; + /** + * A prefix added to token names + * @var string + */ + public $tokenprefix; + /** + * Number of parsing conflicts + * @var int + */ + public $nconflict; + /** + * Size of the parse tables + * @var int + */ + public $tablesize; + /** + * Public only basis configurations + */ + public $basisflag; + /** + * True if any %fallback is seen in the grammer + * @var boolean + */ + public $has_fallback; + /** + * Name of the program + * @var string + */ + public $argv0; + + /** + * Alternate parser template file + * @var string + */ + public $parser_template = ""; + + /* Find a precedence symbol of every rule in the grammar. + * + * Those rules which have a precedence symbol coded in the input + * grammar using the "[symbol]" construct will already have the + * $rp->precsym field filled. Other rules take as their precedence + * symbol the first RHS symbol with a defined precedence. If there + * are not RHS symbols with a defined precedence, the precedence + * symbol field is left blank. + */ + function FindRulePrecedences() + { + for ($rp = $this->rule; $rp; $rp = $rp->next) { + if ($rp->precsym === 0) { + for ($i = 0; $i < $rp->nrhs && $rp->precsym === 0; $i++) { + $sp = $rp->rhs[$i]; + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for ($j = 0; $j < $sp->nsubsym; $j++) { + if ($sp->subsym[$j]->prec >= 0) { + $rp->precsym = $sp->subsym[$j]; + break; + } + } + } elseif ($sp->prec >= 0) { + $rp->precsym = $rp->rhs[$i]; + } + } + } + } + } + + /** + * Find all nonterminals which will generate the empty string. + * Then go back and compute the first sets of every nonterminal. + * The first set is the set of all terminal symbols which can begin + * a string generated by that nonterminal. + */ + function FindFirstSets() + { + for ($i = 0; $i < $this->nsymbol; $i++) { + $this->symbols[$i]->lambda = false; + } + for($i = $this->nterminal; $i < $this->nsymbol; $i++) { + $this->symbols[$i]->firstset = array(); + } + + /* First compute all lambdas */ + do{ + $progress = 0; + for ($rp = $this->rule; $rp; $rp = $rp->next) { + if ($rp->lhs->lambda) { + continue; + } + for ($i = 0; $i < $rp->nrhs; $i++) { + $sp = $rp->rhs[$i]; + if ($sp->type != PHP_ParserGenerator_Symbol::TERMINAL || $sp->lambda === false) { + break; + } + } + if ($i === $rp->nrhs) { + $rp->lhs->lambda = true; + $progress = 1; + } + } + } while ($progress); + + /* Now compute all first sets */ + do { + $progress = 0; + for ($rp = $this->rule; $rp; $rp = $rp->next) { + $s1 = $rp->lhs; + for ($i = 0; $i < $rp->nrhs; $i++) { + $s2 = $rp->rhs[$i]; + if ($s2->type == PHP_ParserGenerator_Symbol::TERMINAL) { + //progress += SetAdd(s1->firstset,s2->index); + $progress += isset($s1->firstset[$s2->index]) ? 0 : 1; + $s1->firstset[$s2->index] = 1; + break; + } elseif ($s2->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for ($j = 0; $j < $s2->nsubsym; $j++) { + //progress += SetAdd(s1->firstset,s2->subsym[j]->index); + $progress += isset($s1->firstset[$s2->subsym[$j]->index]) ? 0 : 1; + $s1->firstset[$s2->subsym[$j]->index] = 1; + } + break; + } elseif ($s1 === $s2) { + if ($s1->lambda === false) { + break; + } + } else { + //progress += SetUnion(s1->firstset,s2->firstset); + $test = array_diff_key($s2->firstset, $s1->firstset); + if (count($test)) { + $progress++; + $s1->firstset += $test; + } + if ($s2->lambda === false) { + break; + } + } + } + } + } while ($progress); + } + + /** + * Compute all LR(0) states for the grammar. Links + * are added to between some states so that the LR(1) follow sets + * can be computed later. + */ + function FindStates() + { + PHP_ParserGenerator_Config::Configlist_init(); + + /* Find the start symbol */ + if ($this->start) { + $sp = PHP_ParserGenerator_Symbol::Symbol_find($this->start); + if ($sp == 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, 0, + "The specified start symbol \"%s\" is not " . + "in a nonterminal of the grammar. \"%s\" will be used as the start " . + "symbol instead.", $this->start, $this->rule->lhs->name); + $this->errorcnt++; + $sp = $this->rule->lhs; + } + } else { + $sp = $this->rule->lhs; + } + + /* Make sure the start symbol doesn't occur on the right-hand side of + ** any rule. Report an error if it does. (YACC would generate a new + ** start symbol in this case.) */ + for ($rp = $this->rule; $rp; $rp = $rp->next) { + for ($i = 0; $i < $rp->nrhs; $i++) { + if ($rp->rhs[$i]->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + foreach ($rp->rhs[$i]->subsym as $subsp) { + if ($subsp === $sp) { + PHP_ParserGenerator::ErrorMsg($this->filename, 0, + "The start symbol \"%s\" occurs on the " . + "right-hand side of a rule. This will result in a parser which " . + "does not work properly.", $sp->name); + $this->errorcnt++; + } + } + } elseif ($rp->rhs[$i] === $sp) { + PHP_ParserGenerator::ErrorMsg($this->filename, 0, + "The start symbol \"%s\" occurs on the " . + "right-hand side of a rule. This will result in a parser which " . + "does not work properly.", $sp->name); + $this->errorcnt++; + } + } + } + + /* The basis configuration set for the first state + ** is all rules which have the start symbol as their + ** left-hand side */ + for ($rp = $sp->rule; $rp; $rp = $rp->nextlhs) { + $newcfp = PHP_ParserGenerator_Config::Configlist_addbasis($rp, 0); + $newcfp->fws[0] = 1; + } + + /* Compute the first state. All other states will be + ** computed automatically during the computation of the first one. + ** The returned pointer to the first state is not used. */ + $newstp = array(); + $newstp = $this->getstate(); + if (is_array($newstp)) { + $this->buildshifts($newstp[0]); /* Recursively compute successor states */ + } + } + + /** + * @return PHP_ParserGenerator_State + */ + private function getstate() + { + /* Extract the sorted basis of the new state. The basis was constructed + ** by prior calls to "Configlist_addbasis()". */ + PHP_ParserGenerator_Config::Configlist_sortbasis(); + $bp = PHP_ParserGenerator_Config::Configlist_basis(); + + /* Get a state with the same basis */ + $stp = PHP_ParserGenerator_State::State_find($bp); + if ($stp) { + /* A state with the same basis already exists! Copy all the follow-set + ** propagation links from the state under construction into the + ** preexisting state, then return a pointer to the preexisting state */ + for($x = $bp, $y = $stp->bp; $x && $y; $x = $x->bp, $y = $y->bp) { + PHP_ParserGenerator_PropagationLink::Plink_copy($y->bplp, $x->bplp); + PHP_ParserGenerator_PropagationLink::Plink_delete($x->fplp); + $x->fplp = $x->bplp = 0; + } + $cfp = PHP_ParserGenerator_Config::Configlist_return(); + PHP_ParserGenerator_Config::Configlist_eat($cfp); + } else { + /* This really is a new state. Construct all the details */ + PHP_ParserGenerator_Config::Configlist_closure($this); /* Compute the configuration closure */ + PHP_ParserGenerator_Config::Configlist_sort(); /* Sort the configuration closure */ + $cfp = PHP_ParserGenerator_Config::Configlist_return(); /* Get a pointer to the config list */ + $stp = new PHP_ParserGenerator_State; /* A new state structure */ + $stp->bp = $bp; /* Remember the configuration basis */ + $stp->cfp = $cfp; /* Remember the configuration closure */ + $stp->statenum = $this->nstate++; /* Every state gets a sequence number */ + $stp->ap = 0; /* No actions, yet. */ + PHP_ParserGenerator_State::State_insert($stp, $stp->bp); /* Add to the state table */ + // this can't work, recursion is too deep, move it into FindStates() + //$this->buildshifts($stp); /* Recursively compute successor states */ + return array($stp); + } + return $stp; + } + + /** + * Construct all successor states to the given state. A "successor" + * state is any state which can be reached by a shift action. + * @param PHP_ParserGenerator_Data + * @param PHP_ParserGenerator_State The state from which successors are computed + */ + private function buildshifts(PHP_ParserGenerator_State $stp) + { +// struct config *cfp; /* For looping thru the config closure of "stp" */ +// struct config *bcfp; /* For the inner loop on config closure of "stp" */ +// struct config *new; /* */ +// struct symbol *sp; /* Symbol following the dot in configuration "cfp" */ +// struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */ +// struct state *newstp; /* A pointer to a successor state */ + + /* Each configuration becomes complete after it contibutes to a successor + ** state. Initially, all configurations are incomplete */ + $cfp = $stp->cfp; + for ($cfp = $stp->cfp; $cfp; $cfp = $cfp->next) { + $cfp->status = PHP_ParserGenerator_Config::INCOMPLETE; + } + + /* Loop through all configurations of the state "stp" */ + for ($cfp = $stp->cfp; $cfp; $cfp = $cfp->next) { + if ($cfp->status == PHP_ParserGenerator_Config::COMPLETE) { + continue; /* Already used by inner loop */ + } + if ($cfp->dot >= $cfp->rp->nrhs) { + continue; /* Can't shift this config */ + } + PHP_ParserGenerator_Config::Configlist_reset(); /* Reset the new config set */ + $sp = $cfp->rp->rhs[$cfp->dot]; /* Symbol after the dot */ + + /* For every configuration in the state "stp" which has the symbol "sp" + ** following its dot, add the same configuration to the basis set under + ** construction but with the dot shifted one symbol to the right. */ + $bcfp = $cfp; + for ($bcfp = $cfp; $bcfp; $bcfp = $bcfp->next) { + if ($bcfp->status == PHP_ParserGenerator_Config::COMPLETE) { + continue; /* Already used */ + } + if ($bcfp->dot >= $bcfp->rp->nrhs) { + continue; /* Can't shift this one */ + } + $bsp = $bcfp->rp->rhs[$bcfp->dot]; /* Get symbol after dot */ + if (!PHP_ParserGenerator_Symbol::same_symbol($bsp, $sp)) { + continue; /* Must be same as for "cfp" */ + } + $bcfp->status = PHP_ParserGenerator_Config::COMPLETE; /* Mark this config as used */ + $new = PHP_ParserGenerator_Config::Configlist_addbasis($bcfp->rp, $bcfp->dot + 1); + PHP_ParserGenerator_PropagationLink::Plink_add($new->bplp, $bcfp); + } + + /* Get a pointer to the state described by the basis configuration set + ** constructed in the preceding loop */ + $newstp = $this->getstate(); + if (is_array($newstp)) { + $this->buildshifts($newstp[0]); /* Recursively compute successor states */ + $newstp = $newstp[0]; + } + + /* The state "newstp" is reached from the state "stp" by a shift action + ** on the symbol "sp" */ + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for($i = 0; $i < $sp->nsubsym; $i++) { + PHP_ParserGenerator_Action::Action_add($stp->ap, PHP_ParserGenerator_Action::SHIFT, $sp->subsym[$i], + $newstp); + } + } else { + PHP_ParserGenerator_Action::Action_add($stp->ap, PHP_ParserGenerator_Action::SHIFT, $sp, $newstp); + } + } + } + + /** + * Construct the propagation links + */ + function FindLinks() + { + /* Housekeeping detail: + ** Add to every propagate link a pointer back to the state to + ** which the link is attached. */ + foreach ($this->sorted as $info) { + $info->key->stp = $info->data; + } + + /* Convert all backlinks into forward links. Only the forward + ** links are used in the follow-set computation. */ + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]; + for ($cfp = $stp->data->cfp; $cfp; $cfp = $cfp->next) { + for ($plp = $cfp->bplp; $plp; $plp = $plp->next) { + $other = $plp->cfp; + PHP_ParserGenerator_PropagationLink::Plink_add($other->fplp, $cfp); + } + } + } + } + + /** + * Compute the reduce actions, and resolve conflicts. + */ + function FindActions() + { + /* Add all of the reduce actions + ** A reduce action is added for each element of the followset of + ** a configuration which has its dot at the extreme right. + */ + for ($i = 0; $i < $this->nstate; $i++) { /* Loop over all states */ + $stp = $this->sorted[$i]->data; + for ($cfp = $stp->cfp; $cfp; $cfp = $cfp->next) { + /* Loop over all configurations */ + if ($cfp->rp->nrhs == $cfp->dot) { /* Is dot at extreme right? */ + for ($j = 0; $j < $this->nterminal; $j++) { + if (isset($cfp->fws[$j])) { + /* Add a reduce action to the state "stp" which will reduce by the + ** rule "cfp->rp" if the lookahead symbol is "$this->symbols[j]" */ + PHP_ParserGenerator_Action::Action_add($stp->ap, PHP_ParserGenerator_Action::REDUCE, + $this->symbols[$j], $cfp->rp); + } + } + } + } + } + + /* Add the accepting token */ + if ($this->start instanceof PHP_ParserGenerator_Symbol) { + $sp = PHP_ParserGenerator_Symbol::Symbol_find($this->start); + if ($sp === 0) { + $sp = $this->rule->lhs; + } + } else { + $sp = $this->rule->lhs; + } + /* Add to the first state (which is always the starting state of the + ** finite state machine) an action to ACCEPT if the lookahead is the + ** start nonterminal. */ + PHP_ParserGenerator_Action::Action_add($this->sorted[0]->data->ap, PHP_ParserGenerator_Action::ACCEPT, $sp, 0); + + /* Resolve conflicts */ + for ($i = 0; $i < $this->nstate; $i++) { + // struct action *ap, *nap; + // struct state *stp; + $stp = $this->sorted[$i]->data; + if (!$stp->ap) { + throw new Exception('state has no actions associated'); + } + echo 'processing state ' . $stp->statenum . " actions:\n"; + for ($ap = $stp->ap; $ap !== 0 && $ap->next !== 0; $ap = $ap->next) { + echo ' Action '; + $ap->display(true); + } + $stp->ap = PHP_ParserGenerator_Action::Action_sort($stp->ap); + for ($ap = $stp->ap; $ap !== 0 && $ap->next !== 0; $ap = $ap->next) { + for ($nap = $ap->next; $nap !== 0 && $nap->sp === $ap->sp ; $nap = $nap->next) { + /* The two actions "ap" and "nap" have the same lookahead. + ** Figure out which one should be used */ + $this->nconflict += $this->resolve_conflict($ap, $nap, $this->errsym); + } + } + } + + /* Report an error for each rule that can never be reduced. */ + for ($rp = $this->rule; $rp; $rp = $rp->next) { + $rp->canReduce = false; + } + for ($i = 0; $i < $this->nstate; $i++) { + for ($ap = $this->sorted[$i]->data->ap; $ap !== 0; $ap = $ap->next) { + if ($ap->type == PHP_ParserGenerator_Action::REDUCE) { + $ap->x->canReduce = true; + } + } + } + for ($rp = $this->rule; $rp !== 0; $rp = $rp->next) { + if ($rp->canReduce) { + continue; + } + PHP_ParserGenerator::ErrorMsg($this->filename, $rp->ruleline, "This rule can not be reduced (is not connected to the start symbol).\n"); + $this->errorcnt++; + } + } + + /** Resolve a conflict between the two given actions. If the + * conflict can't be resolve, return non-zero. + * + * NO LONGER TRUE: + * To resolve a conflict, first look to see if either action + * is on an error rule. In that case, take the action which + * is not associated with the error rule. If neither or both + * actions are associated with an error rule, then try to + * use precedence to resolve the conflict. + * + * If either action is a SHIFT, then it must be apx. This + * function won't work if apx->type==REDUCE and apy->type==SHIFT. + * @param PHP_ParserGenerator_Action + * @param PHP_ParserGenerator_Action + * @param PHP_ParserGenerator_Symbol|null The error symbol (if defined. NULL otherwise) + */ + function resolve_conflict($apx, $apy, $errsym) + { + $errcnt = 0; + if ($apx->sp !== $apy->sp) { + throw new Exception('no conflict but resolve_conflict called'); + } + if ($apx->type == PHP_ParserGenerator_Action::SHIFT && $apy->type == PHP_ParserGenerator_Action::REDUCE) { + $spx = $apx->sp; + $spy = $apy->x->precsym; + if ($spy === 0 || $spx->prec < 0 || $spy->prec < 0) { + /* Not enough precedence information. */ + $apy->type = PHP_ParserGenerator_Action::CONFLICT; + $errcnt++; + } elseif ($spx->prec > $spy->prec) { /* Lower precedence wins */ + $apy->type = PHP_ParserGenerator_Action::RD_RESOLVED; + } elseif ($spx->prec < $spy->prec) { + $apx->type = PHP_ParserGenerator_Action::SH_RESOLVED; + } elseif ($spx->prec === $spy->prec && $spx->assoc == PHP_ParserGenerator_Symbol::RIGHT) { + /* Use operator */ + $apy->type = PHP_ParserGenerator_Action::RD_RESOLVED; /* associativity */ + } elseif ($spx->prec === $spy->prec && $spx->assoc == PHP_ParserGenerator_Symbol::LEFT) { + /* to break tie */ + $apx->type = PHP_ParserGenerator_Action::SH_RESOLVED; + } else { + if ($spx->prec !== $spy->prec || $spx->assoc !== PHP_ParserGenerator_Symbol::NONE) { + throw new Exception('$spx->prec !== $spy->prec || $spx->assoc !== PHP_ParserGenerator_Symbol::NONE'); + } + $apy->type = PHP_ParserGenerator_Action::CONFLICT; + $errcnt++; + } + } elseif ($apx->type == PHP_ParserGenerator_Action::REDUCE && $apy->type == PHP_ParserGenerator_Action::REDUCE) { + $spx = $apx->x->precsym; + $spy = $apy->x->precsym; + if ($spx === 0 || $spy === 0 || $spx->prec < 0 || + $spy->prec < 0 || $spx->prec === $spy->prec) { + $apy->type = PHP_ParserGenerator_Action::CONFLICT; + $errcnt++; + } elseif ($spx->prec > $spy->prec) { + $apy->type = PHP_ParserGenerator_Action::RD_RESOLVED; + } elseif ($spx->prec < $spy->prec) { + $apx->type = PHP_ParserGenerator_Action::RD_RESOLVED; + } + } else { + if ($apx->type!== PHP_ParserGenerator_Action::SH_RESOLVED && + $apx->type!== PHP_ParserGenerator_Action::RD_RESOLVED && + $apx->type!== PHP_ParserGenerator_Action::CONFLICT && + $apy->type!== PHP_ParserGenerator_Action::SH_RESOLVED && + $apy->type!== PHP_ParserGenerator_Action::RD_RESOLVED && + $apy->type!== PHP_ParserGenerator_Action::CONFLICT) { + throw new Exception('$apx->type!== PHP_ParserGenerator_Action::SH_RESOLVED && + $apx->type!== PHP_ParserGenerator_Action::RD_RESOLVED && + $apx->type!== PHP_ParserGenerator_Action::CONFLICT && + $apy->type!== PHP_ParserGenerator_Action::SH_RESOLVED && + $apy->type!== PHP_ParserGenerator_Action::RD_RESOLVED && + $apy->type!== PHP_ParserGenerator_Action::CONFLICT'); + } + /* The REDUCE/SHIFT case cannot happen because SHIFTs come before + ** REDUCEs on the list. If we reach this point it must be because + ** the parser conflict had already been resolved. */ + } + return $errcnt; + } + + /** + * Reduce the size of the action tables, if possible, by making use + * of defaults. + * + * In this version, we take the most frequent REDUCE action and make + * it the default. + */ + function CompressTables() + { + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]->data; + $nbest = 0; + $rbest = 0; + + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->type != PHP_ParserGenerator_Action::REDUCE) { + continue; + } + $rp = $ap->x; + if ($rp === $rbest) { + continue; + } + $n = 1; + for ($ap2 = $ap->next; $ap2; $ap2 = $ap2->next) { + if ($ap2->type != PHP_ParserGenerator_Action::REDUCE) { + continue; + } + $rp2 = $ap2->x; + if ($rp2 === $rbest) { + continue; + } + if ($rp2 === $rp) { + $n++; + } + } + if ($n > $nbest) { + $nbest = $n; + $rbest = $rp; + } + } + + /* Do not make a default if the number of rules to default + ** is not at least 1 */ + if ($nbest < 1) { + continue; + } + + + /* Combine matching REDUCE actions into a single default */ + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->type == PHP_ParserGenerator_Action::REDUCE && $ap->x === $rbest) { + break; + } + } + if ($ap === 0) { + throw new Exception('$ap is not an object'); + } + $ap->sp = PHP_ParserGenerator_Symbol::Symbol_new("{default}"); + for ($ap = $ap->next; $ap; $ap = $ap->next) { + if ($ap->type == PHP_ParserGenerator_Action::REDUCE && $ap->x === $rbest) { + $ap->type = PHP_ParserGenerator_Action::NOT_USED; + } + } + $stp->ap = PHP_ParserGenerator_Action::Action_sort($stp->ap); + } + } + + /** + * Renumber and resort states so that states with fewer choices + * occur at the end. Except, keep state 0 as the first state. + */ + function ResortStates() + { + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]->data; + $stp->nTknAct = $stp->nNtAct = 0; + $stp->iDflt = $this->nstate + $this->nrule; + $stp->iTknOfst = PHP_ParserGenerator_Data::NO_OFFSET; + $stp->iNtOfst = PHP_ParserGenerator_Data::NO_OFFSET; + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($this->compute_action($ap) >= 0) { + if ($ap->sp->index < $this->nterminal) { + $stp->nTknAct++; + } elseif ($ap->sp->index < $this->nsymbol) { + $stp->nNtAct++; + } else { + $stp->iDflt = $this->compute_action($ap); + } + } + } + $this->sorted[$i] = $stp; + } + $save = $this->sorted[0]; + unset($this->sorted[0]); + usort($this->sorted, array('PHP_ParserGenerator_State', 'stateResortCompare')); + array_unshift($this->sorted, $save); + for($i = 0; $i < $this->nstate; $i++) { + $this->sorted[$i]->statenum = $i; + } + } + + /** + * Given an action, compute the integer value for that action + * which is to be put in the action table of the generated machine. + * Return negative if no action should be generated. + * @param PHP_ParserGenerator_Action + */ + function compute_action($ap) + { + switch ($ap->type) { + case PHP_ParserGenerator_Action::SHIFT: + $act = $ap->x->statenum; + break; + case PHP_ParserGenerator_Action::REDUCE: + $act = $ap->x->index + $this->nstate; + break; + case PHP_ParserGenerator_Action::ERROR: + $act = $this->nstate + $this->nrule; + break; + case PHP_ParserGenerator_Action::ACCEPT: + $act = $this->nstate + $this->nrule + 1; + break; + default: + $act = -1; + break; + } + return $act; + } + + /** + * Generate the "Parse.out" log file + */ + function ReportOutput() + { + $fp = fopen($this->filenosuffix . ".out", "wb"); + if (!$fp) { + return; + } + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]; + fprintf($fp, "State %d:\n", $stp->statenum); + if ($this->basisflag) { + $cfp = $stp->bp; + } else { + $cfp = $stp->cfp; + } + while ($cfp) { + if ($cfp->dot == $cfp->rp->nrhs) { + $buf = sprintf('(%d)', $cfp->rp->index); + fprintf($fp, ' %5s ', $buf); + } else { + fwrite($fp,' '); + } + $cfp->ConfigPrint($fp); + fwrite($fp, "\n"); + if (0) { + //SetPrint(fp,cfp->fws,$this); + //PlinkPrint(fp,cfp->fplp,"To "); + //PlinkPrint(fp,cfp->bplp,"From"); + } + if ($this->basisflag) { + $cfp = $cfp->bp; + } else { + $cfp = $cfp->next; + } + } + fwrite($fp, "\n"); + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->PrintAction($fp, 30)) { + fprintf($fp,"\n"); + } + } + fwrite($fp,"\n"); + } + fclose($fp); + } + + /** + * The next function finds the template file and opens it, returning + * a pointer to the opened file. + * @return resource + */ + private function tplt_open() + { + $templatename = $this->parser_template ? $this->parser_template : dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . "Lempar.php"; + + $buf = $this->filenosuffix . '.lt'; + if (file_exists($buf) && is_readable($buf)) { + $tpltname = $buf; + } elseif (file_exists($templatename) && is_readable($templatename)) { + $tpltname = $templatename; + } elseif ($fp = @fopen($templatename, 'rb', true)) { + return $fp; + } + if (!isset($tpltname)) { + echo "Can't find the parser driver template file \"%s\".\n", + $templatename; + $this->errorcnt++; + return 0; + } + $in = @fopen($tpltname,"rb"); + if (!$in) { + printf("Can't open the template file \"%s\".\n", $tpltname); + $this->errorcnt++; + return 0; + } + return $in; + } + +#define LINESIZE 1000 + /**#@+ + * The next cluster of routines are for reading the template file + * and writing the results to the generated parser + */ + /** + * The first function transfers data from "in" to "out" until + * a line is seen which begins with "%%". The line number is + * tracked. + * + * if name!=0, then any word that begin with "Parse" is changed to + * begin with *name instead. + */ + private function tplt_xfer($name, $in, $out, &$lineno) + { + while (($line = fgets($in, 1024)) && ($line[0] != '%' || $line[1] != '%')) { + $lineno++; + $iStart = 0; + if ($name) { + for ($i = 0; $i < strlen($line); $i++) { + if ($line[$i] == 'P' && substr($line, $i, 5) == "Parse" + && ($i === 0 || preg_match('/[^a-zA-Z]/', $line[$i - 1]))) { + if ($i > $iStart) { + fwrite($out, substr($line, $iStart, $i - $iStart)); + } + fwrite($out, $name); + $i += 4; + $iStart = $i + 1; + } + } + } + fwrite($out, substr($line, $iStart)); + } + } + + /** + * Print a #line directive line to the output file. + */ + private function tplt_linedir($out, $lineno, $filename) + { + fwrite($out, '#line ' . $lineno . ' "' . $filename . "\"\n"); + } + + /** + * Print a string to the file and keep the linenumber up to date + */ + private function tplt_print($out, $str, $strln, &$lineno) + { + if ($str == '') { + return; + } + $this->tplt_linedir($out, $strln, $this->filename); + $lineno++; + fwrite($out, $str); + $lineno += count(explode("\n", $str)) - 1; + $this->tplt_linedir($out, $lineno + 2, $this->outname); + $lineno += 2; + } + /**#@-*/ + + /** + * Compute all followsets. + * + * A followset is the set of all symbols which can come immediately + * after a configuration. + */ + function FindFollowSets() + { + for ($i = 0; $i < $this->nstate; $i++) { + for ($cfp = $this->sorted[$i]->data->cfp; $cfp; $cfp = $cfp->next) { + $cfp->status = PHP_ParserGenerator_Config::INCOMPLETE; + } + } + + do { + $progress = 0; + for ($i = 0; $i < $this->nstate; $i++) { + for ($cfp = $this->sorted[$i]->data->cfp; $cfp; $cfp = $cfp->next) { + if ($cfp->status == PHP_ParserGenerator_Config::COMPLETE) { + continue; + } + for ($plp = $cfp->fplp; $plp; $plp = $plp->next) { + $a = array_diff_key($cfp->fws, $plp->cfp->fws); + if (count($a)) { + $plp->cfp->fws += $a; + $plp->cfp->status = PHP_ParserGenerator_Config::INCOMPLETE; + $progress = 1; + } + } + $cfp->status = PHP_ParserGenerator_Config::COMPLETE; + } + } + } while ($progress); + } + + /** + * Generate C source code for the parser + * @param int Output in makeheaders format if true + */ + function ReportTable($mhflag) + { +// FILE *out, *in; +// char line[LINESIZE]; +// int lineno; +// struct state *stp; +// struct action *ap; +// struct rule *rp; +// struct acttab *pActtab; +// int i, j, n; +// char *name; +// int mnTknOfst, mxTknOfst; +// int mnNtOfst, mxNtOfst; +// struct axset *ax; + + $in = $this->tplt_open(); + if (!$in) { + return; + } + $out = fopen($this->filenosuffix . ".php", "wb"); + if (!$out) { + fclose($in); + return; + } + $this->outname = $this->filenosuffix . ".php"; + $lineno = 1; + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the include code, if any */ + $this->tplt_print($out, $this->include_code, $this->includeln, $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the class declaration code */ + $this->tplt_print($out, $this->declare_classcode, $this->declare_classln, + $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the internal parser class include code, if any */ + $this->tplt_print($out, $this->include_classcode, $this->include_classln, + $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate #defines for all tokens */ + //if ($mhflag) { + //fprintf($out, "#if INTERFACE\n"); + $lineno++; + if ($this->tokenprefix) { + $prefix = $this->tokenprefix; + } else { + $prefix = ''; + } + for ($i = 1; $i < $this->nterminal; $i++) { + fprintf($out, " const %s%-30s = %2d;\n", $prefix, $this->symbols[$i]->name, $i); + $lineno++; + } + //fwrite($out, "#endif\n"); + $lineno++; + //} + fwrite($out, " const YY_NO_ACTION = " . + ($this->nstate + $this->nrule + 2) . ";\n"); + $lineno++; + fwrite($out, " const YY_ACCEPT_ACTION = " . + ($this->nstate + $this->nrule + 1) . ";\n"); + $lineno++; + fwrite($out, " const YY_ERROR_ACTION = " . + ($this->nstate + $this->nrule) . ";\n"); + $lineno++; + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the action table and its associates: + ** + ** yy_action[] A single table containing all actions. + ** yy_lookahead[] A table containing the lookahead for each entry in + ** yy_action. Used to detect hash collisions. + ** yy_shift_ofst[] For each state, the offset into yy_action for + ** shifting terminals. + ** yy_reduce_ofst[] For each state, the offset into yy_action for + ** shifting non-terminals after a reduce. + ** yy_default[] Default action for each state. + */ + + /* Compute the actions on all states and count them up */ + + $ax = array(); + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]; + $ax[$i * 2] = array(); + $ax[$i * 2]['stp'] = $stp; + $ax[$i * 2]['isTkn'] = 1; + $ax[$i * 2]['nAction'] = $stp->nTknAct; + $ax[$i * 2 + 1] = array(); + $ax[$i * 2 + 1]['stp'] = $stp; + $ax[$i * 2 + 1]['isTkn'] = 0; + $ax[$i * 2 + 1]['nAction'] = $stp->nNtAct; + } + $mxTknOfst = $mnTknOfst = 0; + $mxNtOfst = $mnNtOfst = 0; + + /* Compute the action table. In order to try to keep the size of the + ** action table to a minimum, the heuristic of placing the largest action + ** sets first is used. + */ + + usort($ax, array('PHP_ParserGenerator_Data', 'axset_compare')); + $pActtab = new PHP_ParserGenerator_ActionTable; + for ($i = 0; $i < $this->nstate * 2 && $ax[$i]['nAction'] > 0; $i++) { + $stp = $ax[$i]['stp']; + if ($ax[$i]['isTkn']) { + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->sp->index >= $this->nterminal) { + continue; + } + $action = $this->compute_action($ap); + if ($action < 0) { + continue; + } + $pActtab->acttab_action($ap->sp->index, $action); + } + $stp->iTknOfst = $pActtab->acttab_insert(); + if ($stp->iTknOfst < $mnTknOfst) { + $mnTknOfst = $stp->iTknOfst; + } + if ($stp->iTknOfst > $mxTknOfst) { + $mxTknOfst = $stp->iTknOfst; + } + } else { + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->sp->index < $this->nterminal) { + continue; + } + if ($ap->sp->index == $this->nsymbol) { + continue; + } + $action = $this->compute_action($ap); + if ($action < 0) { + continue; + } + $pActtab->acttab_action($ap->sp->index, $action); + } + $stp->iNtOfst = $pActtab->acttab_insert(); + if ($stp->iNtOfst < $mnNtOfst) { + $mnNtOfst = $stp->iNtOfst; + } + if ($stp->iNtOfst > $mxNtOfst) { + $mxNtOfst = $stp->iNtOfst; + } + } + } + /* Output the yy_action table */ + + fprintf($out, " const YY_SZ_ACTTAB = %d;\n", $pActtab->nAction); + $lineno++; + fwrite($out, "static public \$yy_action = array(\n"); + $lineno++; + $n = $pActtab->nAction; + for($i = $j = 0; $i < $n; $i++) { + $action = $pActtab->aAction[$i]['action']; + if ($action < 0) { + $action = $this->nsymbol + $this->nrule + 2; + } + // change next line + if ($j === 0) { + fprintf($out, " /* %5d */ ", $i); + } + fprintf($out, " %4d,", $action); + if ($j == 9 || $i == $n - 1) { + fwrite($out, "\n"); + $lineno++; + $j = 0; + } else { + $j++; + } + } + fwrite($out, " );\n"); $lineno++; + + /* Output the yy_lookahead table */ + + fwrite($out, " static public \$yy_lookahead = array(\n"); + $lineno++; + for ($i = $j = 0; $i < $n; $i++) { + $la = $pActtab->aAction[$i]['lookahead']; + if ($la < 0) { + $la = $this->nsymbol; + } + // change next line + if ($j === 0) { + fprintf($out, " /* %5d */ ", $i); + } + fprintf($out, " %4d,", $la); + if ($j == 9 || $i == $n - 1) { + fwrite($out, "\n"); + $lineno++; + $j = 0; + } else { + $j++; + } + } + fwrite($out, ");\n"); + $lineno++; + + /* Output the yy_shift_ofst[] table */ + fprintf($out, " const YY_SHIFT_USE_DFLT = %d;\n", $mnTknOfst - 1); + $lineno++; + $n = $this->nstate; + while ($n > 0 && $this->sorted[$n - 1]->iTknOfst == PHP_ParserGenerator_Data::NO_OFFSET) { + $n--; + } + fprintf($out, " const YY_SHIFT_MAX = %d;\n", $n - 1); + $lineno++; + fwrite($out, " static public \$yy_shift_ofst = array(\n"); + $lineno++; + for ($i = $j = 0; $i < $n; $i++) { + $stp = $this->sorted[$i]; + $ofst = $stp->iTknOfst; + if ($ofst === PHP_ParserGenerator_Data::NO_OFFSET) { + $ofst = $mnTknOfst - 1; + } + // change next line + if ($j === 0) { + fprintf($out, " /* %5d */ ", $i); + } + fprintf($out, " %4d,", $ofst); + if ($j == 9 || $i == $n - 1) { + fwrite($out, "\n"); + $lineno++; + $j = 0; + } else { + $j++; + } + } + fwrite($out, ");\n"); + $lineno++; + + + /* Output the yy_reduce_ofst[] table */ + + fprintf($out, " const YY_REDUCE_USE_DFLT = %d;\n", $mnNtOfst - 1); + $lineno++; + $n = $this->nstate; + while ($n > 0 && $this->sorted[$n - 1]->iNtOfst == PHP_ParserGenerator_Data::NO_OFFSET) { + $n--; + } + fprintf($out, " const YY_REDUCE_MAX = %d;\n", $n - 1); + $lineno++; + fwrite($out, " static public \$yy_reduce_ofst = array(\n"); + $lineno++; + for ($i = $j = 0; $i < $n; $i++) { + $stp = $this->sorted[$i]; + $ofst = $stp->iNtOfst; + if ($ofst == PHP_ParserGenerator_Data::NO_OFFSET) { + $ofst = $mnNtOfst - 1; + } + // change next line + if ($j == 0) { + fprintf($out, " /* %5d */ ", $i); + } + fprintf($out, " %4d,", $ofst); + if ($j == 9 || $i == $n - 1) { + fwrite($out, "\n"); + $lineno++; + $j = 0; + } else { + $j++; + } + } + fwrite($out, ");\n"); + $lineno++; + + /* Output the expected tokens table */ + + fwrite($out, " static public \$yyExpectedTokens = array(\n"); + $lineno++; + for ($i = 0; $i < $this->nstate; $i++) { + $stp = $this->sorted[$i]; + fwrite($out, " /* $i */ array("); + for ($ap = $stp->ap; $ap; $ap = $ap->next) { + if ($ap->sp->index < $this->nterminal) { + if ($ap->type == PHP_ParserGenerator_Action::SHIFT || + $ap->type == PHP_ParserGenerator_Action::REDUCE) { + fwrite($out, $ap->sp->index . ', '); + } + } + } + fwrite($out, "),\n"); + $lineno++; + } + fwrite($out, ");\n"); + $lineno++; + + /* Output the default action table */ + + fwrite($out, " static public \$yy_default = array(\n"); + $lineno++; + $n = $this->nstate; + for ($i = $j = 0; $i < $n; $i++) { + $stp = $this->sorted[$i]; + // change next line + if ($j == 0) { + fprintf($out, " /* %5d */ ", $i); + } + fprintf($out, " %4d,", $stp->iDflt); + if ($j == 9 || $i == $n - 1) { + fprintf($out, "\n"); $lineno++; + $j = 0; + } else { + $j++; + } + } + fwrite($out, ");\n"); + $lineno++; + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the defines */ + fprintf($out, " const YYNOCODE = %d;\n", $this->nsymbol + 1); + $lineno++; + if ($this->stacksize) { + if($this->stacksize <= 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, 0, + "Illegal stack size: [%s]. The stack size should be an integer constant.", + $this->stacksize); + $this->errorcnt++; + $this->stacksize = "100"; + } + fprintf($out, " const YYSTACKDEPTH = %s;\n", $this->stacksize); + $lineno++; + } else { + fwrite($out," const YYSTACKDEPTH = 100;\n"); + $lineno++; + } + fprintf($out, " const YYNSTATE = %d;\n", $this->nstate); + $lineno++; + fprintf($out, " const YYNRULE = %d;\n", $this->nrule); + $lineno++; + fprintf($out, " const YYERRORSYMBOL = %d;\n", $this->errsym->index); + $lineno++; + fprintf($out, " const YYERRSYMDT = 'yy%d';\n", $this->errsym->dtnum); + $lineno++; + if ($this->has_fallback) { + fwrite($out, " const YYFALLBACK = 1;\n"); + } else { + fwrite($out, " const YYFALLBACK = 0;\n"); + } + $lineno++; + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the table of fallback tokens. + */ + + if ($this->has_fallback) { + for ($i = 0; $i < $this->nterminal; $i++) { + $p = $this->symbols[$i]; + if ($p->fallback === 0) { + // change next line + fprintf($out, " 0, /* %10s => nothing */\n", $p->name); + } else { + // change next line + fprintf($out, " %3d, /* %10s => %s */\n", + $p->fallback->index, $p->name, $p->fallback->name); + } + $lineno++; + } + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + + /* Generate a table containing the symbolic name of every symbol + ($yyTokenName) + */ + + for ($i = 0; $i < $this->nsymbol; $i++) { + fprintf($out," %-15s", "'" . $this->symbols[$i]->name . "',"); + if (($i & 3) == 3) { + fwrite($out,"\n"); + $lineno++; + } + } + if (($i & 3) != 0) { + fwrite($out, "\n"); + $lineno++; + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate a table containing a text string that describes every + ** rule in the rule set of the grammer. This information is used + ** when tracing REDUCE actions. + */ + + for ($i = 0, $rp = $this->rule; $rp; $rp = $rp->next, $i++) { + if ($rp->index !== $i) { + throw new Exception('rp->index != i and should be'); + } + // change next line + fprintf($out, " /* %3d */ \"%s ::=", $i, $rp->lhs->name); + for ($j = 0; $j < $rp->nrhs; $j++) { + $sp = $rp->rhs[$j]; + fwrite($out,' ' . $sp->name); + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + for($k = 1; $k < $sp->nsubsym; $k++) { + fwrite($out, '|' . $sp->subsym[$k]->name); + } + } + } + fwrite($out, "\",\n"); + $lineno++; + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate code which executes every time a symbol is popped from + ** the stack while processing errors or while destroying the parser. + ** (In other words, generate the %destructor actions) + */ + + if ($this->tokendest) { + for ($i = 0; $i < $this->nsymbol; $i++) { + $sp = $this->symbols[$i]; + if ($sp === 0 || $sp->type != PHP_ParserGenerator_Symbol::TERMINAL) { + continue; + } + fprintf($out, " case %d:\n", $sp->index); + $lineno++; + } + for ($i = 0; $i < $this->nsymbol && + $this->symbols[$i]->type != PHP_ParserGenerator_Symbol::TERMINAL; $i++); + if ($i < $this->nsymbol) { + $this->emit_destructor_code($out, $this->symbols[$i], $lineno); + fprintf($out, " break;\n"); + $lineno++; + } + } + if ($this->vardest) { + $dflt_sp = 0; + for ($i = 0; $i < $this->nsymbol; $i++) { + $sp = $this->symbols[$i]; + if ($sp === 0 || $sp->type == PHP_ParserGenerator_Symbol::TERMINAL || + $sp->index <= 0 || $sp->destructor != 0) { + continue; + } + fprintf($out, " case %d:\n", $sp->index); + $lineno++; + $dflt_sp = $sp; + } + if ($dflt_sp != 0) { + $this->emit_destructor_code($out, $dflt_sp, $lineno); + fwrite($out, " break;\n"); + $lineno++; + } + } + for ($i = 0; $i < $this->nsymbol; $i++) { + $sp = $this->symbols[$i]; + if ($sp === 0 || $sp->type == PHP_ParserGenerator_Symbol::TERMINAL || + $sp->destructor === 0) { + continue; + } + fprintf($out, " case %d:\n", $sp->index); + $lineno++; + + /* Combine duplicate destructors into a single case */ + + for ($j = $i + 1; $j < $this->nsymbol; $j++) { + $sp2 = $this->symbols[$j]; + if ($sp2 && $sp2->type != PHP_ParserGenerator_Symbol::TERMINAL && $sp2->destructor + && $sp2->dtnum == $sp->dtnum + && $sp->destructor == $sp2->destructor) { + fprintf($out, " case %d:\n", $sp2->index); + $lineno++; + $sp2->destructor = 0; + } + } + + $this->emit_destructor_code($out, $this->symbols[$i], $lineno); + fprintf($out, " break;\n"); + $lineno++; + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate code which executes whenever the parser stack overflows */ + + $this->tplt_print($out, $this->overflow, $this->overflowln, $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate the table of rule information + ** + ** Note: This code depends on the fact that rules are number + ** sequentually beginning with 0. + */ + + for ($rp = $this->rule; $rp; $rp = $rp->next) { + fprintf($out, " array( 'lhs' => %d, 'rhs' => %d ),\n", + $rp->lhs->index, $rp->nrhs); + $lineno++; + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + + /* Generate code which executes during each REDUCE action */ + + for ($rp = $this->rule; $rp; $rp = $rp->next) { + if ($rp->code) { + $this->translate_code($rp); + } + } + + /* Generate the method map for each REDUCE action */ + + for ($rp = $this->rule; $rp; $rp = $rp->next) { + if ($rp->code === 0) { + continue; + } + fwrite($out, ' ' . $rp->index . ' => ' . $rp->index . ",\n"); + $lineno++; + for ($rp2 = $rp->next; $rp2; $rp2 = $rp2->next) { + if ($rp2->code === $rp->code) { + fwrite($out, ' ' . $rp2->index . ' => ' . + $rp->index . ",\n"); + $lineno++; + $rp2->code = 0; + } + } + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + for ($rp = $this->rule; $rp; $rp = $rp->next) { + if ($rp->code === 0) { + continue; + } + $this->emit_code($out, $rp, $lineno); + } + $this->tplt_xfer($this->name, $in, $out, $lineno); + + + /* Generate code which executes if a parse fails */ + + $this->tplt_print($out, $this->failure, $this->failureln, $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate code which executes when a syntax error occurs */ + + $this->tplt_print($out, $this->error, $this->errorln, $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Generate code which executes when the parser accepts its input */ + + $this->tplt_print($out, $this->accept, $this->acceptln, $lineno); + $this->tplt_xfer($this->name, $in, $out, $lineno); + + /* Append any addition code the user desires */ + + $this->tplt_print($out, $this->extracode, $this->extracodeln, $lineno); + + fclose($in); + fclose($out); + } + + /** + * Generate code which executes when the rule "rp" is reduced. Write + * the code to "out". Make sure lineno stays up-to-date. + */ + function emit_code($out, PHP_ParserGenerator_Rule $rp, &$lineno) + { + $linecnt = 0; + + /* Generate code to do the reduce action */ + if ($rp->code) { + $this->tplt_linedir($out, $rp->line, $this->filename); + fwrite($out, " function yy_r$rp->index(){" . $rp->code); + $linecnt += count(explode("\n", $rp->code)) - 1; + $lineno += 3 + $linecnt; + fwrite($out, " }\n"); + $this->tplt_linedir($out, $lineno, $this->outname); + } /* End if( rp->code ) */ + } + + /** + * Append text to a dynamically allocated string. If zText is 0 then + * reset the string to be empty again. Always return the complete text + * of the string (which is overwritten with each call). + * + * n bytes of zText are stored. If n==0 then all of zText is stored. + * + * If n==-1, then the previous character is overwritten. + * @param string + * @param int + */ + function append_str($zText, $n) + { + static $z = ''; + $zInt = ''; + + if ($zText === '') { + $ret = $z; + $z = ''; + return $ret; + } + if ($n <= 0) { + if ($n < 0) { + if (!strlen($z)) { + throw new Exception('z is zero-length'); + } + $z = substr($z, 0, strlen($z) - 1); + if (!$z) { + $z = ''; + } + } + $n = strlen($zText); + } + $i = 0; + $z .= substr($zText, 0, $n); + return $z; + } + + /** + * zCode is a string that is the action associated with a rule. Expand + * the symbols in this string so that the refer to elements of the parser + * stack. + */ + function translate_code(PHP_ParserGenerator_Rule $rp) + { + $lhsused = 0; /* True if the LHS element has been used */ + $used = array(); /* True for each RHS element which is used */ + + $this->append_str('', 0); + for ($i = 0; $i < strlen($rp->code); $i++) { + $cp = $rp->code[$i]; + if (preg_match('/[A-Za-z]/', $cp) && + ($i === 0 || (!preg_match('/[A-Za-z0-9_]/', $rp->code[$i - 1])))) { + //*xp = 0; + // previous line is in essence a temporary substr, so + // we will simulate it + $test = substr($rp->code, $i); + preg_match('/[A-Za-z0-9_]+/', $test, $matches); + $tempcp = $matches[0]; + $j = strlen($tempcp) + $i; + if ($rp->lhsalias && $tempcp == $rp->lhsalias) { + $this->append_str("\$this->_retvalue", 0); + $cp = $rp->code[$j]; + $i = $j; + $lhsused = 1; + } else { + for ($ii = 0; $ii < $rp->nrhs; $ii++) { + if ($rp->rhsalias[$ii] && $tempcp == $rp->rhsalias[$ii]) { + if ($rp->code[0] == '@') { + /* If the argument is of the form @X then substitute + ** the token number of X, not the value of X */ + $this->append_str("\$this->yystack[\$this->yyidx + " . + ($ii - $rp->nrhs + 1) . "]->major", -1); + } else { + $sp = $rp->rhs[$ii]; + if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + $dtnum = $sp->subsym[0]->dtnum; + } else { + $dtnum = $sp->dtnum; + } + $this->append_str("\$this->yystack[\$this->yyidx + " . + ($ii - $rp->nrhs + 1) . "]->minor", 0); + } + $cp = $rp->code[$j]; + $i = $j; + $used[$ii] = 1; + break; + } + } + } + } + $this->append_str($cp, 1); + } /* End loop */ + + /* Check to make sure the LHS has been used */ + if ($rp->lhsalias && !$lhsused) { + PHP_ParserGenerator::ErrorMsg($this->filename, $rp->ruleline, + "Label \"%s\" for \"%s(%s)\" is never used.", + $rp->lhsalias, $rp->lhs->name, $rp->lhsalias); + $this->errorcnt++; + } + + /* Generate destructor code for RHS symbols which are not used in the + ** reduce code */ + for($i = 0; $i < $rp->nrhs; $i++) { + if ($rp->rhsalias[$i] && !isset($used[$i])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $rp->ruleline, + "Label %s for \"%s(%s)\" is never used.", + $rp->rhsalias[$i], $rp->rhs[$i]->name, $rp->rhsalias[$i]); + $this->errorcnt++; + } elseif ($rp->rhsalias[$i] == 0) { + if ($rp->rhs[$i]->type == PHP_ParserGenerator_Symbol::TERMINAL) { + $hasdestructor = $this->tokendest != 0; + }else{ + $hasdestructor = $this->vardest !== 0 || $rp->rhs[$i]->destructor !== 0; + } + if ($hasdestructor) { + $this->append_str(" \$this->yy_destructor(" . + ($rp->rhs[$i]->index) . ", \$this->yystack[\$this->yyidx + " . + ($i - $rp->nrhs + 1) . "]->minor);\n", 0); + } else { + /* No destructor defined for this term */ + } + } + } + $cp = $this->append_str('', 0); + $rp->code = $cp; + } + + /** + * The following routine emits code for the destructor for the + * symbol sp + */ + function emit_destructor_code($out, PHP_ParserGenerator_Symbol $sp, &$lineno) +// FILE *out; +// struct symbol *sp; +// struct lemon *lemp; +// int *lineno; + { + $cp = 0; + + $linecnt = 0; + if ($sp->type == PHP_ParserGenerator_Symbol::TERMINAL) { + $cp = $this->tokendest; + if ($cp === 0) { + return; + } + $this->tplt_linedir($out, $this->tokendestln, $this->filename); + fwrite($out, "{"); + } elseif ($sp->destructor) { + $cp = $sp->destructor; + $this->tplt_linedir($out, $sp->destructorln, $this->filename); + fwrite($out, "{"); + } elseif ($this->vardest) { + $cp = $this->vardest; + if ($cp === 0) { + return; + } + $this->tplt_linedir($out, $this->vardestln, $this->filename); + fwrite($out, "{"); + } else { + throw new Exception('emit_destructor'); /* Cannot happen */ + } + for ($i = 0; $i < strlen($cp); $i++) { + if ($cp[$i]=='$' && $cp[$i + 1]=='$' ) { + fprintf($out, "(yypminor->yy%d)", $sp->dtnum); + $i++; + continue; + } + if ($cp[$i] == "\n") { + $linecnt++; + } + fwrite($out, $cp[$i]); + } + $lineno += 3 + $linecnt; + fwrite($out, "}\n"); + $this->tplt_linedir($out, $lineno, $this->outname); + } + + /** + * Compare to axset structures for sorting purposes + */ + static function axset_compare($a, $b) + { + return $b['nAction'] - $a['nAction']; + } +} diff --git a/core/oql/build/PHP/ParserGenerator/Parser.php b/core/oql/build/PHP/ParserGenerator/Parser.php new file mode 100644 index 000000000..c777aad88 --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Parser.php @@ -0,0 +1,851 @@ + + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Parser.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** + * The grammar parser for lemon grammar files. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_Parser +{ + const INITIALIZE = 1; + const WAITING_FOR_DECL_OR_RULE = 2; + const WAITING_FOR_DECL_KEYWORD = 3; + const WAITING_FOR_DECL_ARG = 4; + const WAITING_FOR_PRECEDENCE_SYMBOL = 5; + const WAITING_FOR_ARROW = 6; + const IN_RHS = 7; + const LHS_ALIAS_1 = 8; + const LHS_ALIAS_2 = 9; + const LHS_ALIAS_3 = 10; + const RHS_ALIAS_1 = 11; + const RHS_ALIAS_2 = 12; + const PRECEDENCE_MARK_1 = 13; + const PRECEDENCE_MARK_2 = 14; + const RESYNC_AFTER_RULE_ERROR = 15; + const RESYNC_AFTER_DECL_ERROR = 16; + const WAITING_FOR_DESTRUCTOR_SYMBOL = 17; + const WAITING_FOR_DATATYPE_SYMBOL = 18; + const WAITING_FOR_FALLBACK_ID = 19; + + /** + * Name of the input file + * + * @var string + */ + public $filename; + /** + * Linenumber at which current token starts + * @var int + */ + public $tokenlineno; + /** + * Number of parsing errors so far + * @var int + */ + public $errorcnt; + /** + * Index of current token within the input string + * @var int + */ + public $tokenstart; + /** + * Global state vector + * @var PHP_ParserGenerator_Data + */ + public $gp; + /** + * Parser state (one of the class constants for this class) + * + * - PHP_ParserGenerator_Parser::INITIALIZE, + * - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_OR_RULE, + * - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_KEYWORD, + * - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_ARG, + * - PHP_ParserGenerator_Parser::WAITING_FOR_PRECEDENCE_SYMBOL, + * - PHP_ParserGenerator_Parser::WAITING_FOR_ARROW, + * - PHP_ParserGenerator_Parser::IN_RHS, + * - PHP_ParserGenerator_Parser::LHS_ALIAS_1, + * - PHP_ParserGenerator_Parser::LHS_ALIAS_2, + * - PHP_ParserGenerator_Parser::LHS_ALIAS_3, + * - PHP_ParserGenerator_Parser::RHS_ALIAS_1, + * - PHP_ParserGenerator_Parser::RHS_ALIAS_2, + * - PHP_ParserGenerator_Parser::PRECEDENCE_MARK_1, + * - PHP_ParserGenerator_Parser::PRECEDENCE_MARK_2, + * - PHP_ParserGenerator_Parser::RESYNC_AFTER_RULE_ERROR, + * - PHP_ParserGenerator_Parser::RESYNC_AFTER_DECL_ERROR, + * - PHP_ParserGenerator_Parser::WAITING_FOR_DESTRUCTOR_SYMBOL, + * - PHP_ParserGenerator_Parser::WAITING_FOR_DATATYPE_SYMBOL, + * - PHP_ParserGenerator_Parser::WAITING_FOR_FALLBACK_ID + * @var int + */ + public $state; + /** + * The fallback token + * @var PHP_ParserGenerator_Symbol + */ + public $fallback; + /** + * Left-hand side of the current rule + * @var PHP_ParserGenerator_Symbol + */ + public $lhs; + /** + * Alias for the LHS + * @var string + */ + public $lhsalias; + /** + * Number of right-hand side symbols seen + * @var int + */ + public $nrhs; + /** + * Right-hand side symbols + * @var array array of {@link PHP_ParserGenerator_Symbol} objects + */ + public $rhs = array(); + /** + * Aliases for each RHS symbol name (or NULL) + * @var array array of strings + */ + public $alias = array(); + /** + * Previous rule parsed + * @var PHP_ParserGenerator_Rule + */ + public $prevrule; + /** + * Keyword of a declaration + * + * This is one of the %keyword keywords in the grammar file + * @var string + */ + public $declkeyword; + /** + * Where the declaration argument should be put + * + * This is assigned as a reference to an internal variable + * @var mixed + */ + public $declargslot = array(); + /** + * Where the declaration linenumber is put + * + * This is assigned as a reference to an internal variable + * @var mixed + */ + public $decllnslot; + /*enum e_assoc*/ + public $declassoc; /* Assign this association to decl arguments */ + public $preccounter; /* Assign this precedence to decl arguments */ + /** + * @var PHP_ParserGenerator_Rule + */ + public $firstrule; /* Pointer to first rule in the grammar */ + /** + * @var PHP_ParserGenerator_Rule + */ + public $lastrule; /* Pointer to the most recently parsed rule */ + + /** + * @var PHP_ParserGenerator + */ + private $lemon; + + function __construct(PHP_ParserGenerator $lem) + { + $this->lemon = $lem; + } + + /** + * Run the preprocessor over the input file text. The Lemon variable + * $azDefine contains the names of all defined + * macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and + * comments them out. Text in between is also commented out as appropriate. + * @param string + */ + private function preprocess_input(&$z) + { + $lineno = $exclude = 0; + for ($i=0; $i < strlen($z); $i++) { + if ($z[$i] == "\n") { + $lineno++; + } + if ($z[$i] != '%' || ($i > 0 && $z[$i-1] != "\n")) { + continue; + } + if (substr($z, $i, 6) === "%endif" && trim($z[$i+6]) === '') { + if ($exclude) { + $exclude--; + if ($exclude === 0) { + for ($j = $start; $j < $i; $j++) { + if ($z[$j] != "\n") $z[$j] = ' '; + } + } + } + for ($j = $i; $j < strlen($z) && $z[$j] != "\n"; $j++) { + $z[$j] = ' '; + } + } elseif (substr($z, $i, 6) === "%ifdef" && trim($z[$i+6]) === '' || + substr($z, $i, 7) === "%ifndef" && trim($z[$i+7]) === '') { + if ($exclude) { + $exclude++; + } else { + $j = $i; + $n = strtok(substr($z, $j), " \t"); + $exclude = 1; + if (isset($this->lemon->azDefine[$n])) { + $exclude = 0; + } + if ($z[$i + 3]=='n') { + // this is a rather obtuse way of checking whether this is %ifndef + $exclude = !$exclude; + } + if ($exclude) { + $start = $i; + $start_lineno = $lineno; + } + } + //for ($j = $i; $j < strlen($z) && $z[$j] != "\n"; $j++) $z[$j] = ' '; + $j = strpos(substr($z, $i), "\n"); + if ($j === false) { + $z = substr($z, 0, $i); // remove instead of adding ' ' + } else { + $z = substr($z, 0, $i) . substr($z, $i + $j); // remove instead of adding ' ' + } + } + } + if ($exclude) { + throw new Exception("unterminated %ifdef starting on line $start_lineno\n"); + } + } + + /** + * In spite of its name, this function is really a scanner. + * + * It reads in the entire input file (all at once) then tokenizes it. + * Each token is passed to the function "parseonetoken" which builds all + * the appropriate data structures in the global state vector "gp". + * @param PHP_ParserGenerator_Data + */ + function Parse(PHP_ParserGenerator_Data $gp) + { + $startline = 0; + + $this->gp = $gp; + $this->filename = $gp->filename; + $this->errorcnt = 0; + $this->state = self::INITIALIZE; + + /* Begin by reading the input file */ + $filebuf = file_get_contents($this->filename); + if (!$filebuf) { + PHP_ParserGenerator::ErrorMsg($this->filename, 0, "Can't open this file for reading."); + $gp->errorcnt++; + return; + } + if (filesize($this->filename) != strlen($filebuf)) { + ErrorMsg($this->filename, 0, "Can't read in all %d bytes of this file.", + filesize($this->filename)); + $gp->errorcnt++; + return; + } + + /* Make an initial pass through the file to handle %ifdef and %ifndef */ + $this->preprocess_input($filebuf); + + /* Now scan the text of the input file */ + $lineno = 1; + for ($cp = 0, $c = $filebuf[0]; $cp < strlen($filebuf); $cp++) { + $c = $filebuf[$cp]; + if ($c == "\n") $lineno++; /* Keep track of the line number */ + if (trim($c) === '') { + continue; + } /* Skip all white space */ + if ($filebuf[$cp] == '/' && ($cp + 1 < strlen($filebuf)) && $filebuf[$cp + 1] == '/') { + /* Skip C++ style comments */ + $cp += 2; + $z = strpos(substr($filebuf, $cp), "\n"); + if ($z === false) { + $cp = strlen($filebuf); + break; + } + $lineno++; + $cp += $z; + continue; + } + if ($filebuf[$cp] == '/' && ($cp + 1 < strlen($filebuf)) && $filebuf[$cp + 1] == '*') { + /* Skip C style comments */ + $cp += 2; + $z = strpos(substr($filebuf, $cp), '*/'); + if ($z !== false) { + $lineno += count(explode("\n", substr($filebuf, $cp, $z))) - 1; + } + $cp += $z + 1; + continue; + } + $this->tokenstart = $cp; /* Mark the beginning of the token */ + $this->tokenlineno = $lineno; /* Linenumber on which token begins */ + if ($filebuf[$cp] == '"') { /* String literals */ + $cp++; + $oldcp = $cp; + $test = strpos(substr($filebuf, $cp), '"'); + if ($test === false) { + PHP_ParserGenerator::ErrorMsg($this->filename, $startline, + "String starting on this line is not terminated before the end of the file."); + $this->errorcnt++; + $nextcp = $cp = strlen($filebuf); + } else { + $cp += $test; + $nextcp = $cp + 1; + } + $lineno += count(explode("\n", substr($filebuf, $oldcp, $cp - $oldcp))) - 1; + } elseif ($filebuf[$cp] == '{') { /* A block of C code */ + $cp++; + if ($filebuf[$cp]=="}") { + $filebuf = substr($filebuf, 0, $cp)." ".substr($filebuf, $cp); + } + + for ($level = 1; $cp < strlen($filebuf) && ($level > 1 || $filebuf[$cp] != '}'); $cp++) { + if ($filebuf[$cp] == "\n") { + $lineno++; + } elseif ($filebuf[$cp] == '{') { + $level++; + } elseif ($filebuf[$cp] == '}') { + $level--; + } elseif ($filebuf[$cp] == '/' && $filebuf[$cp + 1] == '*') { + /* Skip comments */ + $cp += 2; + $z = strpos(substr($filebuf, $cp), '*/'); + if ($z !== false) { + $lineno += count(explode("\n", substr($filebuf, $cp, $z))) - 1; + } + $cp += $z + 2; + } elseif ($filebuf[$cp] == '/' && $filebuf[$cp + 1] == '/') { + /* Skip C++ style comments too */ + $cp += 2; + $z = strpos(substr($filebuf, $cp), "\n"); + if ($z === false) { + $cp = strlen($filebuf); + break; + } else { + $lineno++; + } + $cp += $z; + } elseif ($filebuf[$cp] == "'" || $filebuf[$cp] == '"') { + /* String a character literals */ + $startchar = $filebuf[$cp]; + $prevc = 0; + for ($cp++; $cp < strlen($filebuf) && ($filebuf[$cp] != $startchar || $prevc === '\\'); $cp++) { + if ($filebuf[$cp] == "\n") { + $lineno++; + } + if ($prevc === '\\') { + $prevc = 0; + } else { + $prevc = $filebuf[$cp]; + } + } + } + } + if ($cp >= strlen($filebuf)) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "PHP code starting on this line is not terminated before the end of the file."); + $this->errorcnt++; + $nextcp = $cp; + } else { + $nextcp = $cp + 1; + } + } elseif (preg_match('/[a-zA-Z0-9]/', $filebuf[$cp])) { + /* Identifiers */ + preg_match('/[a-zA-Z0-9_]+/', substr($filebuf, $cp), $preg_results); + $cp += strlen($preg_results[0]); + $nextcp = $cp; + } elseif ($filebuf[$cp] == ':' && $filebuf[$cp + 1] == ':' && + $filebuf[$cp + 2] == '=') { + /* The operator "::=" */ + $cp += 3; + $nextcp = $cp; + } elseif (($filebuf[$cp] == '/' || $filebuf[$cp] == '|') && + preg_match('/[a-zA-Z]/', $filebuf[$cp + 1])) { + $cp += 2; + preg_match('/[a-zA-Z0-9_]+/', substr($filebuf, $cp), $preg_results); + $cp += strlen($preg_results[0]); + $nextcp = $cp; + } else { + /* All other (one character) operators */ + $cp ++; + $nextcp = $cp; + } + $this->parseonetoken(substr($filebuf, $this->tokenstart, + $cp - $this->tokenstart)); /* Parse the token */ + $cp = $nextcp - 1; + } + $gp->rule = $this->firstrule; + $gp->errorcnt = $this->errorcnt; + } + + /** + * Parse a single token + * @param string token + */ + function parseonetoken($token) + { + $x = $token; + $this->a = 0; // for referencing in WAITING_FOR_DECL_KEYWORD + if (PHP_ParserGenerator::DEBUG) { + printf("%s:%d: Token=[%s] state=%d\n", + $this->filename, $this->tokenlineno, $token, $this->state); + } + switch ($this->state) { + case self::INITIALIZE: + $this->prevrule = 0; + $this->preccounter = 0; + $this->firstrule = $this->lastrule = 0; + $this->gp->nrule = 0; + /* Fall thru to next case */ + case self::WAITING_FOR_DECL_OR_RULE: + if ($x[0] == '%') { + $this->state = self::WAITING_FOR_DECL_KEYWORD; + } elseif (preg_match('/[a-z]/', $x[0])) { + $this->lhs = PHP_ParserGenerator_Symbol::Symbol_new($x); + $this->nrhs = 0; + $this->lhsalias = 0; + $this->state = self::WAITING_FOR_ARROW; + } elseif ($x[0] == '{') { + if ($this->prevrule === 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "There is no prior rule opon which to attach the code + fragment which begins on this line."); + $this->errorcnt++; + } elseif ($this->prevrule->code != 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Code fragment beginning on this line is not the first \ + to follow the previous rule."); + $this->errorcnt++; + } else { + $this->prevrule->line = $this->tokenlineno; + $this->prevrule->code = substr($x, 1); + } + } elseif ($x[0] == '[') { + $this->state = self::PRECEDENCE_MARK_1; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Token \"%s\" should be either \"%%\" or a nonterminal name.", + $x); + $this->errorcnt++; + } + break; + case self::PRECEDENCE_MARK_1: + if (!preg_match('/[A-Z]/', $x[0])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "The precedence symbol must be a terminal."); + $this->errorcnt++; + } elseif ($this->prevrule === 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "There is no prior rule to assign precedence \"[%s]\".", $x); + $this->errorcnt++; + } elseif ($this->prevrule->precsym != 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Precedence mark on this line is not the first to follow the previous rule."); + $this->errorcnt++; + } else { + $this->prevrule->precsym = PHP_ParserGenerator_Symbol::Symbol_new($x); + } + $this->state = self::PRECEDENCE_MARK_2; + break; + case self::PRECEDENCE_MARK_2: + if ($x[0] != ']') { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Missing \"]\" on precedence mark."); + $this->errorcnt++; + } + $this->state = self::WAITING_FOR_DECL_OR_RULE; + break; + case self::WAITING_FOR_ARROW: + if ($x[0] == ':' && $x[1] == ':' && $x[2] == '=') { + $this->state = self::IN_RHS; + } elseif ($x[0] == '(') { + $this->state = self::LHS_ALIAS_1; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Expected to see a \":\" following the LHS symbol \"%s\".", + $this->lhs->name); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::LHS_ALIAS_1: + if (preg_match('/[A-Za-z]/', $x[0])) { + $this->lhsalias = $x; + $this->state = self::LHS_ALIAS_2; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "\"%s\" is not a valid alias for the LHS \"%s\"\n", + $x, $this->lhs->name); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::LHS_ALIAS_2: + if ($x[0] == ')') { + $this->state = self::LHS_ALIAS_3; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Missing \")\" following LHS alias name \"%s\".",$this->lhsalias); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::LHS_ALIAS_3: + if ($x == '::=') { + $this->state = self::IN_RHS; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Missing \"->\" following: \"%s(%s)\".", + $this->lhs->name, $this->lhsalias); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::IN_RHS: + if ($x[0] == '.') { + $rp = new PHP_ParserGenerator_Rule; + $rp->ruleline = $this->tokenlineno; + for ($i = 0; $i < $this->nrhs; $i++) { + $rp->rhs[$i] = $this->rhs[$i]; + $rp->rhsalias[$i] = $this->alias[$i]; + } + if (count(array_unique($rp->rhsalias)) != count($rp->rhsalias)) { + $used = array(); + foreach ($rp->rhsalias as $i => $symbol) { + if (!is_string($symbol)) { + continue; + } + if (isset($used[$symbol])) { + PHP_ParserGenerator::ErrorMsg($this->filename, + $this->tokenlineno, + "RHS symbol \"%s\" used multiple times.", + $symbol); + $this->errorcnt++; + } else { + $used[$symbol] = $i; + } + } + } + $rp->lhs = $this->lhs; + $rp->lhsalias = $this->lhsalias; + $rp->nrhs = $this->nrhs; + $rp->code = 0; + $rp->precsym = 0; + $rp->index = $this->gp->nrule++; + $rp->nextlhs = $rp->lhs->rule; + $rp->lhs->rule = $rp; + $rp->next = 0; + if ($this->firstrule === 0) { + $this->firstrule = $this->lastrule = $rp; + } else { + $this->lastrule->next = $rp; + $this->lastrule = $rp; + } + $this->prevrule = $rp; + $this->state = self::WAITING_FOR_DECL_OR_RULE; + } elseif (preg_match('/[a-zA-Z]/', $x[0])) { + if ($this->nrhs >= PHP_ParserGenerator::MAXRHS) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Too many symbols on RHS or rule beginning at \"%s\".", + $x); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } else { + if (isset($this->rhs[$this->nrhs - 1])) { + $msp = $this->rhs[$this->nrhs - 1]; + if ($msp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { + $inf = array_reduce($msp->subsym, + array($this, '_printmulti'), ''); + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + 'WARNING: symbol ' . $x . ' will not' . + ' be part of previous multiterminal %s', + substr($inf, 0, strlen($inf) - 1) + ); + } + } + $this->rhs[$this->nrhs] = PHP_ParserGenerator_Symbol::Symbol_new($x); + $this->alias[$this->nrhs] = 0; + $this->nrhs++; + } + } elseif (($x[0] == '|' || $x[0] == '/') && $this->nrhs > 0) { + $msp = $this->rhs[$this->nrhs - 1]; + if ($msp->type != PHP_ParserGenerator_Symbol::MULTITERMINAL) { + $origsp = $msp; + $msp = new PHP_ParserGenerator_Symbol; + $msp->type = PHP_ParserGenerator_Symbol::MULTITERMINAL; + $msp->nsubsym = 1; + $msp->subsym = array($origsp); + $msp->name = $origsp->name; + $this->rhs[$this->nrhs - 1] = $msp; + } + $msp->nsubsym++; + $msp->subsym[$msp->nsubsym - 1] = PHP_ParserGenerator_Symbol::Symbol_new(substr($x, 1)); + if (preg_match('/[a-z]/', $x[1]) || + preg_match('/[a-z]/', $msp->subsym[0]->name[0])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Cannot form a compound containing a non-terminal"); + $this->errorcnt++; + } + } elseif ($x[0] == '(' && $this->nrhs > 0) { + $this->state = self::RHS_ALIAS_1; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Illegal character on RHS of rule: \"%s\".", $x); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::RHS_ALIAS_1: + if (preg_match('/[A-Za-z]/', $x[0])) { + $this->alias[$this->nrhs - 1] = $x; + $this->state = self::RHS_ALIAS_2; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", + $x, $this->rhs[$this->nrhs - 1]->name); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::RHS_ALIAS_2: + if ($x[0] == ')') { + $this->state = self::IN_RHS; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Missing \")\" following LHS alias name \"%s\".", $this->lhsalias); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_RULE_ERROR; + } + break; + case self::WAITING_FOR_DECL_KEYWORD: + if(preg_match('/[A-Za-z]/', $x[0])) { + $this->declkeyword = $x; + $this->declargslot = &$this->a; + $this->decllnslot = &$this->a; + $this->state = self::WAITING_FOR_DECL_ARG; + if ('name' == $x) { + $this->declargslot = &$this->gp->name; + } elseif ('include' == $x) { + $this->declargslot = &$this->gp->include_code; + $this->decllnslot = &$this->gp->includeln; + } elseif ('include_class' == $x) { + $this->declargslot = &$this->gp->include_classcode; + $this->decllnslot = &$this->gp->include_classln; + } elseif ('declare_class' == $x) { + $this->declargslot = &$this->gp->declare_classcode; + $this->decllnslot = &$this->gp->declare_classln; + } elseif ('code' == $x) { + $this->declargslot = &$this->gp->extracode; + $this->decllnslot = &$this->gp->extracodeln; + } elseif ('token_destructor' == $x) { + $this->declargslot = &$this->gp->tokendest; + $this->decllnslot = &$this->gp->tokendestln; + } elseif ('default_destructor' == $x) { + $this->declargslot = &$this->gp->vardest; + $this->decllnslot = &$this->gp->vardestln; + } elseif ('token_prefix' == $x) { + $this->declargslot = &$this->gp->tokenprefix; + } elseif ('syntax_error' == $x) { + $this->declargslot = &$this->gp->error; + $this->decllnslot = &$this->gp->errorln; + } elseif ('parse_accept' == $x) { + $this->declargslot = &$this->gp->accept; + $this->decllnslot = &$this->gp->acceptln; + } elseif ('parse_failure' == $x) { + $this->declargslot = &$this->gp->failure; + $this->decllnslot = &$this->gp->failureln; + } elseif ('stack_overflow' == $x) { + $this->declargslot = &$this->gp->overflow; + $this->decllnslot = &$this->gp->overflowln; + } elseif ('token_type' == $x) { + $this->declargslot = &$this->gp->tokentype; + } elseif ('default_type' == $x) { + $this->declargslot = &$this->gp->vartype; + } elseif ('stack_size' == $x) { + $this->declargslot = &$this->gp->stacksize; + } elseif ('start_symbol' == $x) { + $this->declargslot = &$this->gp->start; + } elseif ('left' == $x) { + $this->preccounter++; + $this->declassoc = PHP_ParserGenerator_Symbol::LEFT; + $this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL; + } elseif ('right' == $x) { + $this->preccounter++; + $this->declassoc = PHP_ParserGenerator_Symbol::RIGHT; + $this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL; + } elseif ('nonassoc' == $x) { + $this->preccounter++; + $this->declassoc = PHP_ParserGenerator_Symbol::NONE; + $this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL; + } elseif ('destructor' == $x) { + $this->state = self::WAITING_FOR_DESTRUCTOR_SYMBOL; + } elseif ('type' == $x) { + $this->state = self::WAITING_FOR_DATATYPE_SYMBOL; + } elseif ('fallback' == $x) { + $this->fallback = 0; + $this->state = self::WAITING_FOR_FALLBACK_ID; + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Unknown declaration keyword: \"%%%s\".", $x); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Illegal declaration keyword: \"%s\".", $x); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } + break; + case self::WAITING_FOR_DESTRUCTOR_SYMBOL: + if (!preg_match('/[A-Za-z]/', $x[0])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Symbol name missing after %destructor keyword"); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } else { + $sp = PHP_ParserGenerator_Symbol::Symbol_new($x); + $this->declargslot = &$sp->destructor; + $this->decllnslot = &$sp->destructorln; + $this->state = self::WAITING_FOR_DECL_ARG; + } + break; + case self::WAITING_FOR_DATATYPE_SYMBOL: + if (!preg_match('/[A-Za-z]/', $x[0])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Symbol name missing after %destructor keyword"); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } else { + $sp = PHP_ParserGenerator_Symbol::Symbol_new($x); + $this->declargslot = &$sp->datatype; + $this->state = self::WAITING_FOR_DECL_ARG; + } + break; + case self::WAITING_FOR_PRECEDENCE_SYMBOL: + if ($x[0] == '.') { + $this->state = self::WAITING_FOR_DECL_OR_RULE; + } elseif (preg_match('/[A-Z]/', $x[0])) { + $sp = PHP_ParserGenerator_Symbol::Symbol_new($x); + if ($sp->prec >= 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Symbol \"%s\" has already been given a precedence.", $x); + $this->errorcnt++; + } else { + $sp->prec = $this->preccounter; + $sp->assoc = $this->declassoc; + } + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Can't assign a precedence to \"%s\".", $x); + $this->errorcnt++; + } + break; + case self::WAITING_FOR_DECL_ARG: + if (preg_match('/[A-Za-z0-9{"]/', $x[0])) { + if ($this->declargslot != 0) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "The argument \"%s\" to declaration \"%%%s\" is not the first.", + $x[0] == '"' ? substr($x, 1) : $x, $this->declkeyword); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } else { + $this->declargslot = ($x[0] == '"' || $x[0] == '{') ? substr($x, 1) : $x; + $this->a = 1; + if (!$this->decllnslot) { + $this->decllnslot = $this->tokenlineno; + } + $this->state = self::WAITING_FOR_DECL_OR_RULE; + } + } else { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "Illegal argument to %%%s: %s",$this->declkeyword, $x); + $this->errorcnt++; + $this->state = self::RESYNC_AFTER_DECL_ERROR; + } + break; + case self::WAITING_FOR_FALLBACK_ID: + if ($x[0] == '.') { + $this->state = self::WAITING_FOR_DECL_OR_RULE; + } elseif (!preg_match('/[A-Z]/', $x[0])) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "%%fallback argument \"%s\" should be a token", $x); + $this->errorcnt++; + } else { + $sp = PHP_ParserGenerator_Symbol::Symbol_new($x); + if ($this->fallback === 0) { + $this->fallback = $sp; + } elseif (is_object($sp->fallback)) { + PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno, + "More than one fallback assigned to token %s", $x); + $this->errorcnt++; + } else { + $sp->fallback = $this->fallback; + $this->gp->has_fallback = 1; + } + } + break; + case self::RESYNC_AFTER_RULE_ERROR: + /* if ($x[0] == '.') $this->state = self::WAITING_FOR_DECL_OR_RULE; + ** break; */ + case self::RESYNC_AFTER_DECL_ERROR: + if ($x[0] == '.') { + $this->state = self::WAITING_FOR_DECL_OR_RULE; + } + if ($x[0] == '%') { + $this->state = self::WAITING_FOR_DECL_KEYWORD; + } + break; + } + } + + /** + * return a descriptive string for a multi-terminal token. + * + * @param string $a + * @param string $b + * @return string + */ + private function _printmulti($a, $b) + { + if (!$a) { + $a = ''; + } + $a .= $b->name . '|'; + return $a; + } +} diff --git a/core/oql/build/PHP/ParserGenerator/PropagationLink.php b/core/oql/build/PHP/ParserGenerator/PropagationLink.php new file mode 100644 index 000000000..d8802e0f9 --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/PropagationLink.php @@ -0,0 +1,126 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: PropagationLink.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** + * A followset propagation link indicates that the contents of one + * configuration followset should be propagated to another whenever + * the first changes. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ + +class PHP_ParserGenerator_PropagationLink +{ + /** + * The configuration that defines this propagation link + * + * @var PHP_ParserGenerator_Config + */ + public $cfp; + /** + * The next propagation link + * + * @var PHP_ParserGenerator_PropagationLink|0 + */ + public $next = 0; + + /** + * Add a propagation link to the current list + * + * This prepends the configuration passed in to the first parameter + * which is either 0 or a PHP_ParserGenerator_PropagationLink defining + * an existing list. + * + * @param PHP_ParserGenerator_PropagationLink|null + * @param PHP_ParserGenerator_Config + */ + static function Plink_add(&$plpp, PHP_ParserGenerator_Config $cfp) + { + $new = new PHP_ParserGenerator_PropagationLink; + $new->next = $plpp; + $plpp = $new; + $new->cfp = $cfp; + } + + /** + * Transfer every propagation link on the list "from" to the list "to" + */ + static function Plink_copy(PHP_ParserGenerator_PropagationLink &$to, PHP_ParserGenerator_PropagationLink $from) + { + while ($from) { + $nextpl = $from->next; + $from->next = $to; + $to = $from; + $from = $nextpl; + } + } + + /** + * Delete every propagation link on the list + * + * @param PHP_ParserGenerator_PropagationLink|0 + * + * @return void + */ + static function Plink_delete($plp) + { + while ($plp) { + $nextpl = $plp->next; + $plp->next = 0; + $plp = $nextpl; + } + } +} + diff --git a/core/oql/build/PHP/ParserGenerator/Rule.php b/core/oql/build/PHP/ParserGenerator/Rule.php new file mode 100644 index 000000000..a3523008e --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Rule.php @@ -0,0 +1,144 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Rule.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** + * Each production rule in the grammar is stored in this class + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_Rule +{ + /** + * Left-hand side of the rule + * @var array an array of {@link PHP_ParserGenerator_Symbol} objects + */ + public $lhs; + /** + * Alias for the LHS (NULL if none) + * + * @var array + */ + public $lhsalias = array(); + /** + * Line number for the rule + * @var int + */ + public $ruleline; + /** + * Number of right-hand side symbols + */ + public $nrhs; + /** + * The right-hand side symbols + * @var array an array of {@link PHP_ParserGenerator_Symbol} objects + */ + public $rhs; + /** + * Aliases for each right-hand side symbol, or null if no alis. + * + * In this rule: + *
+     * foo ::= BAR(A) baz(B).
+     * 
+ * + * The right-hand side aliases are A for BAR, and B for baz. + * @var array aliases are indexed by the right-hand side symbol index. + */ + public $rhsalias = array(); + /** + * Line number at which code begins + * @var int + */ + public $line; + /** + * The code executed when this rule is reduced + * + *
+     * foo(R) ::= BAR(A) baz(B). {R = A + B;}
+     * 
+ * + * In the rule above, the code is "R = A + B;" + * @var string|0 + */ + public $code; + /** + * Precedence symbol for this rule + * @var PHP_ParserGenerator_Symbol + */ + public $precsym; + /** + * An index number for this rule + * + * Used in both naming of reduce functions and determining which rule code + * to use for reduce actions + * @var int + */ + public $index; + /** + * True if this rule is ever reduced + * @var boolean + */ + public $canReduce; + /** + * Next rule with the same left-hand side + * @var PHP_ParserGenerator_Rule|0 + */ + public $nextlhs; + /** + * Next rule in the global list + * @var PHP_ParserGenerator_Rule|0 + */ + public $next; +} diff --git a/core/oql/build/PHP/ParserGenerator/State.php b/core/oql/build/PHP/ParserGenerator/State.php new file mode 100644 index 000000000..e48c9f589 --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/State.php @@ -0,0 +1,283 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: State.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ + +/** + * The structure used to represent a state in the associative array + * for a PHP_ParserGenerator_Config. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_StateNode +{ + public $key; + public $data; + public $from = 0; + public $next = 0; +} + +/** + * Each state of the generated parser's finite state machine + * is encoded as an instance of this class + * + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_State +{ + /** + * The basis configurations for this state + * @var PHP_ParserGenerator_Config + */ + public $bp; + /** + * All configurations in this state + * @var PHP_ParserGenerator_Config + */ + public $cfp; + /** + * Sequential number for this state + * + * @var int + */ + public $statenum; + /** + * Linked list of actions for this state. + * @var PHP_ParserGenerator_Action + */ + public $ap; + /** + * Number of terminal (token) actions + * + * @var int + */ + public $nTknAct, + /** + * Number of non-terminal actions + * + * @var int + */ + $nNtAct; + /** + * The offset into the $yy_action table for terminal tokens. + * + * @var int + */ + public $iTknOfst, + /** + * The offset into the $yy_action table for non-terminals. + * + * @var int + */ + $iNtOfst; + /** + * Default action + * + * @var int + */ + public $iDflt; + /** + * Associative array of PHP_ParserGenerator_State objects + * + * @var array + */ + public static $x3a = array(); + /** + * Array of PHP_ParserGenerator_State objects + * + * @var array + */ + public static $states = array(); + + /** + * Compare two states for sorting purposes. The smaller state is the + * one with the most non-terminal actions. If they have the same number + * of non-terminal actions, then the smaller is the one with the most + * token actions. + */ + static function stateResortCompare($a, $b) + { + $n = $b->nNtAct - $a->nNtAct; + if ($n === 0) { + $n = $b->nTknAct - $a->nTknAct; + } + return $n; + } + + /** + * Compare two states based on their configurations + * + * @param PHP_ParserGenerator_Config|0 $a + * @param PHP_ParserGenerator_Config|0 $b + * @return int + */ + static function statecmp($a, $b) + { + for ($rc = 0; $rc == 0 && $a && $b; $a = $a->bp, $b = $b->bp) { + $rc = $a->rp->index - $b->rp->index; + if ($rc === 0) { + $rc = $a->dot - $b->dot; + } + } + if ($rc == 0) { + if ($a) { + $rc = 1; + } + if ($b) { + $rc = -1; + } + } + return $rc; + } + + /** + * Hash a state based on its configuration + * + * @return int + */ + private static function statehash(PHP_ParserGenerator_Config $a) + { + $h = 0; + while ($a) { + $h = $h * 571 + $a->rp->index * 37 + $a->dot; + $a = $a->bp; + } + return (int) $h; + } + + /** + * Return a pointer to data assigned to the given key. Return NULL + * if no such key. + * @param PHP_ParserGenerator_Config + * @return null|PHP_ParserGenerator_State + */ + static function State_find(PHP_ParserGenerator_Config $key) + { + if (!count(self::$x3a)) { + return 0; + } + $h = self::statehash($key); + if (!isset(self::$x3a[$h])) { + return 0; + } + $np = self::$x3a[$h]; + while ($np) { + if (self::statecmp($np->key, $key) == 0) { + break; + } + $np = $np->next; + } + return $np ? $np->data : 0; + } + + /** + * Insert a new record into the array. Return TRUE if successful. + * Prior data with the same key is NOT overwritten + * + * @param PHP_ParserGenerator_State $state + * @param PHP_ParserGenerator_Config $key + * @return unknown + */ + static function State_insert(PHP_ParserGenerator_State $state, PHP_ParserGenerator_Config $key) + { + $h = self::statehash($key); + if (isset(self::$x3a[$h])) { + $np = self::$x3a[$h]; + } else { + $np = 0; + } + while ($np) { + if (self::statecmp($np->key, $key) == 0) { + /* An existing entry with the same key is found. */ + /* Fail because overwrite is not allows. */ + return 0; + } + $np = $np->next; + } + /* Insert the new data */ + $np = new PHP_ParserGenerator_StateNode; + $np->key = $key; + $np->data = $state; + self::$states[] = $np; + // the original lemon code sets the from link always to itself + // setting up a faulty double-linked list + // however, the from links are never used, so I suspect a copy/paste + // error from a standard algorithm that was never caught + if (isset(self::$x3a[$h])) { + self::$x3a[$h]->from = $np; // lemon has $np->next here + } else { + self::$x3a[$h] = 0; // dummy to avoid notice + } + $np->next = self::$x3a[$h]; + self::$x3a[$h] = $np; + $np->from = self::$x3a[$h]; + return 1; + } + + /** + * Get an array indexed by state number + * + * @return array + */ + static function State_arrayof() + { + return self::$states; + } +} diff --git a/core/oql/build/PHP/ParserGenerator/Symbol.php b/core/oql/build/PHP/ParserGenerator/Symbol.php new file mode 100644 index 000000000..d24a86fb4 --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/Symbol.php @@ -0,0 +1,288 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_ParserGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Symbol.php 302382 2010-08-17 06:08:09Z jespino $ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since File available since Release 0.1.0 + */ +/** + * Symbols (terminals and nonterminals) of the grammar are stored in this class + * + * @category PHP + * @package PHP_ParserGenerator + * @author Gregory Beaver + * @copyright 2006 Gregory Beaver + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/PHP_ParserGenerator + * @since Class available since Release 0.1.0 + */ +class PHP_ParserGenerator_Symbol +{ + /** + * Symbols that start with a capital letter like FOO. + * + * These are tokens directly from the lexer + */ + const TERMINAL = 1; + /** + * Symbols that start with a lower-case letter like foo. + * + * These are grammar rules like "foo ::= BLAH." + */ + const NONTERMINAL = 2; + /** + * Multiple terminal symbols. + * + * These are a grammar rule that consists of several terminals like + * FOO|BAR|BAZ. Note that non-terminals cannot be in a multi-terminal, + * and a multi-terminal acts like a single terminal. + * + * "FOO|BAR FOO|BAZ" is actually two multi-terminals, FOO|BAR and FOO|BAZ. + */ + const MULTITERMINAL = 3; + + const LEFT = 1; + const RIGHT = 2; + const NONE = 3; + const UNK = 4; + /** + * Name of the symbol + * + * @var string + */ + public $name; + /** + * Index of this symbol. + * + * This will ultimately end up representing the symbol in the generated + * parser + * @var int + */ + public $index; + /** + * Symbol type + * + * One of PHP_ParserGenerator_Symbol::TERMINAL, + * PHP_ParserGenerator_Symbol::NONTERMINAL or + * PHP_ParserGenerator_Symbol::MULTITERMINAL + * @var int + */ + public $type; + /** + * Linked list of rules that use this symbol, if it is a non-terminal. + * @var PHP_ParserGenerator_Rule + */ + public $rule; + /** + * Fallback token in case this token doesn't parse + * @var PHP_ParserGenerator_Symbol + */ + public $fallback; + /** + * Precendence, if defined. + * + * -1 if no unusual precedence + * @var int + */ + public $prec = -1; + /** + * Associativity if precedence is defined. + * + * One of PHP_ParserGenerator_Symbol::LEFT, + * PHP_ParserGenerator_Symbol::RIGHT, PHP_ParserGenerator_Symbol::NONE + * or PHP_ParserGenerator_Symbol::UNK + * @var unknown_type + */ + public $assoc; + /** + * First-set for all rules of this symbol + * + * @var array + */ + public $firstset; + /** + * True if this symbol is a non-terminal and can generate an empty + * result. + * + * For instance "foo ::= ." + * @var boolean + */ + public $lambda; + /** + * Code that executes whenever this symbol is popped from the stack during + * error processing. + * + * @var string|0 + */ + public $destructor = 0; + /** + * Line number of destructor code + * @var int + */ + public $destructorln; + /** + * Unused relic of the C version of Lemon. + * + * The data type of information held by this object. Only used + * if this is a non-terminal + * @var string + */ + public $datatype; + /** + * Unused relic of the C version of Lemon. + * + * The data type number. In the parser, the value + * stack is a union. The .yy%d element of this + * union is the correct data type for this object + * @var string + */ + public $dtnum; + /**#@+ + * The following fields are used by MULTITERMINALs only + */ + /** + * Number of terminal symbols in the MULTITERMINAL + * + * This is of course the same as count($this->subsym) + * @var int + */ + public $nsubsym; + /** + * Array of terminal symbols in the MULTITERMINAL + * @var array an array of {@link PHP_ParserGenerator_Symbol} objects + */ + public $subsym = array(); + /**#@-*/ + /** + * Singleton storage of symbols + * + * @var array an array of PHP_ParserGenerator_Symbol objects + */ + private static $_symbol_table = array(); + /** + * Return a pointer to the (terminal or nonterminal) symbol "x". + * Create a new symbol if this is the first time "x" has been seen. + * (this is a singleton) + * @param string + * @return PHP_ParserGenerator_Symbol + */ + public static function Symbol_new($x) + { + if (isset(self::$_symbol_table[$x])) { + return self::$_symbol_table[$x]; + } + $sp = new PHP_ParserGenerator_Symbol; + $sp->name = $x; + $sp->type = preg_match('/[A-Z]/', $x[0]) ? self::TERMINAL : self::NONTERMINAL; + $sp->rule = 0; + $sp->fallback = 0; + $sp->prec = -1; + $sp->assoc = self::UNK; + $sp->firstset = array(); + $sp->lambda = false; + $sp->destructor = 0; + $sp->datatype = 0; + self::$_symbol_table[$sp->name] = $sp; + return $sp; + } + + /** + * Return the number of unique symbols + * + * @return int + */ + public static function Symbol_count() + { + return count(self::$_symbol_table); + } + + public static function Symbol_arrayof() + { + return array_values(self::$_symbol_table); + } + + public static function Symbol_find($x) + { + if (isset(self::$_symbol_table[$x])) { + return self::$_symbol_table[$x]; + } + return 0; + } + + /** + * Sort function helper for symbols + * + * Symbols that begin with upper case letters (terminals or tokens) + * must sort before symbols that begin with lower case letters + * (non-terminals). Other than that, the order does not matter. + * + * We find experimentally that leaving the symbols in their original + * order (the order they appeared in the grammar file) gives the + * smallest parser tables in SQLite. + * @param PHP_ParserGenerator_Symbol + * @param PHP_ParserGenerator_Symbol + */ + public static function sortSymbols($a, $b) + { + $i1 = $a->index + 10000000*(ord($a->name[0]) > ord('Z')); + $i2 = $b->index + 10000000*(ord($b->name[0]) > ord('Z')); + return $i1 - $i2; + } + + /** + * Return true if two symbols are the same. + */ + public static function same_symbol(PHP_ParserGenerator_Symbol $a, PHP_ParserGenerator_Symbol $b) + { + if ($a === $b) return 1; + if ($a->type != self::MULTITERMINAL) return 0; + if ($b->type != self::MULTITERMINAL) return 0; + if ($a->nsubsym != $b->nsubsym) return 0; + for ($i = 0; $i < $a->nsubsym; $i++) { + if ($a->subsym[$i] != $b->subsym[$i]) return 0; + } + return 1; + } +} diff --git a/core/oql/build/PHP/ParserGenerator/cli.php b/core/oql/build/PHP/ParserGenerator/cli.php new file mode 100644 index 000000000..bb1113afb --- /dev/null +++ b/core/oql/build/PHP/ParserGenerator/cli.php @@ -0,0 +1,5 @@ +main(); +?> \ No newline at end of file diff --git a/core/oql/build/build.bash b/core/oql/build/build.bash new file mode 100644 index 000000000..eb3c1f6ab --- /dev/null +++ b/core/oql/build/build.bash @@ -0,0 +1,4 @@ +#!/bin/bash +php PHP/LexerGenerator/cli.php oql-lexer.plex +php PHP/ParserGenerator/cli.php oql-parser.y + diff --git a/core/oql/build/build.cmd b/core/oql/build/build.cmd new file mode 100644 index 000000000..df34ce8d6 --- /dev/null +++ b/core/oql/build/build.cmd @@ -0,0 +1,5 @@ +rem must be run with current directory = the directory of the batch +rem PEAR is required to build +php -d include_path=".;C:\iTop\PHP\PEAR" ".\PHP\LexerGenerator\cli.php" ..\oql-lexer.plex +php ".\PHP\ParserGenerator\cli.php" ..\oql-parser.y +pause \ No newline at end of file diff --git a/core/oql/exclude.txt b/core/oql/exclude.txt index 126cbeac5..d0ed5567c 100644 --- a/core/oql/exclude.txt +++ b/core/oql/exclude.txt @@ -2,7 +2,6 @@ # The following source files are not re-distributed with the "build" of the application # since they are used solely for constructing other files during the build process # -build.cmd -build.bash +build oql-lexer.plex -oql-parser.y +oql-parser.y \ No newline at end of file diff --git a/core/oql/oql-parser.php b/core/oql/oql-parser.php index 5b67cd205..f5587048e 100644 --- a/core/oql/oql-parser.php +++ b/core/oql/oql-parser.php @@ -96,8 +96,8 @@ class OQLParser_yyStackEntry // code external to the class is included here // declare_class is output here -#line 24 "oql-parser.y" -class OQLParserRaw#line 102 "oql-parser.php" +#line 24 "..\oql-parser.y" +class OQLParserRaw#line 102 "..\oql-parser.php" { /* First off, code is included which follows the "include_class" declaration ** in the input file. */ @@ -1422,139 +1422,139 @@ static public $yy_action = array( ** function yy_r0($yymsp){ ... } // User supplied code ** #line */ -#line 29 "oql-parser.y" +#line 29 "..\oql-parser.y" function yy_r0(){ $this->my_result = $this->yystack[$this->yyidx + 0]->minor; } -#line 1431 "oql-parser.php" -#line 32 "oql-parser.y" +#line 1431 "..\oql-parser.php" +#line 32 "..\oql-parser.y" function yy_r2(){ $this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, array($this->yystack[$this->yyidx + -2]->minor)); } -#line 1436 "oql-parser.php" -#line 35 "oql-parser.y" +#line 1436 "..\oql-parser.php" +#line 35 "..\oql-parser.y" function yy_r3(){ $this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, array($this->yystack[$this->yyidx + -2]->minor)); } -#line 1441 "oql-parser.php" -#line 39 "oql-parser.y" +#line 1441 "..\oql-parser.php" +#line 39 "..\oql-parser.y" function yy_r4(){ $this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + -4]->minor); } -#line 1446 "oql-parser.php" -#line 42 "oql-parser.y" +#line 1446 "..\oql-parser.php" +#line 42 "..\oql-parser.y" function yy_r5(){ $this->_retvalue = new OqlObjectQuery($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + -6]->minor); } -#line 1451 "oql-parser.php" -#line 47 "oql-parser.y" +#line 1451 "..\oql-parser.php" +#line 47 "..\oql-parser.y" function yy_r6(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor); } -#line 1456 "oql-parser.php" -#line 50 "oql-parser.y" +#line 1456 "..\oql-parser.php" +#line 50 "..\oql-parser.y" function yy_r7(){ array_push($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor); $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor; } -#line 1462 "oql-parser.php" -#line 55 "oql-parser.y" +#line 1462 "..\oql-parser.php" +#line 55 "..\oql-parser.y" function yy_r8(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 1465 "oql-parser.php" -#line 56 "oql-parser.y" +#line 1465 "..\oql-parser.php" +#line 56 "..\oql-parser.y" function yy_r9(){ $this->_retvalue = null; } -#line 1468 "oql-parser.php" -#line 58 "oql-parser.y" +#line 1468 "..\oql-parser.php" +#line 58 "..\oql-parser.y" function yy_r10(){ // insert the join statement on top of the existing list array_unshift($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor); // and return the updated array $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 1476 "oql-parser.php" -#line 64 "oql-parser.y" +#line 1476 "..\oql-parser.php" +#line 64 "..\oql-parser.y" function yy_r11(){ $this->_retvalue = Array($this->yystack[$this->yyidx + 0]->minor); } -#line 1481 "oql-parser.php" -#line 70 "oql-parser.y" +#line 1481 "..\oql-parser.php" +#line 70 "..\oql-parser.y" function yy_r13(){ // create an array with one single item $this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor); } -#line 1487 "oql-parser.php" -#line 75 "oql-parser.y" +#line 1487 "..\oql-parser.php" +#line 75 "..\oql-parser.y" function yy_r14(){ // create an array with one single item $this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor); } -#line 1493 "oql-parser.php" -#line 80 "oql-parser.y" +#line 1493 "..\oql-parser.php" +#line 80 "..\oql-parser.y" function yy_r15(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, '=', $this->yystack[$this->yyidx + 0]->minor); } -#line 1496 "oql-parser.php" -#line 81 "oql-parser.y" +#line 1496 "..\oql-parser.php" +#line 81 "..\oql-parser.y" function yy_r16(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'BELOW', $this->yystack[$this->yyidx + 0]->minor); } -#line 1499 "oql-parser.php" -#line 82 "oql-parser.y" +#line 1499 "..\oql-parser.php" +#line 82 "..\oql-parser.y" function yy_r17(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'BELOW_STRICT', $this->yystack[$this->yyidx + 0]->minor); } -#line 1502 "oql-parser.php" -#line 83 "oql-parser.y" +#line 1502 "..\oql-parser.php" +#line 83 "..\oql-parser.y" function yy_r18(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_BELOW', $this->yystack[$this->yyidx + 0]->minor); } -#line 1505 "oql-parser.php" -#line 84 "oql-parser.y" +#line 1505 "..\oql-parser.php" +#line 84 "..\oql-parser.y" function yy_r19(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_BELOW_STRICT', $this->yystack[$this->yyidx + 0]->minor); } -#line 1508 "oql-parser.php" -#line 85 "oql-parser.y" +#line 1508 "..\oql-parser.php" +#line 85 "..\oql-parser.y" function yy_r20(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'ABOVE', $this->yystack[$this->yyidx + 0]->minor); } -#line 1511 "oql-parser.php" -#line 86 "oql-parser.y" +#line 1511 "..\oql-parser.php" +#line 86 "..\oql-parser.y" function yy_r21(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'ABOVE_STRICT', $this->yystack[$this->yyidx + 0]->minor); } -#line 1514 "oql-parser.php" -#line 87 "oql-parser.y" +#line 1514 "..\oql-parser.php" +#line 87 "..\oql-parser.y" function yy_r22(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_ABOVE', $this->yystack[$this->yyidx + 0]->minor); } -#line 1517 "oql-parser.php" -#line 88 "oql-parser.y" +#line 1517 "..\oql-parser.php" +#line 88 "..\oql-parser.y" function yy_r23(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, 'NOT_ABOVE_STRICT', $this->yystack[$this->yyidx + 0]->minor); } -#line 1520 "oql-parser.php" -#line 90 "oql-parser.y" +#line 1520 "..\oql-parser.php" +#line 90 "..\oql-parser.y" function yy_r24(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; } -#line 1523 "oql-parser.php" -#line 95 "oql-parser.y" +#line 1523 "..\oql-parser.php" +#line 95 "..\oql-parser.y" function yy_r28(){ $this->_retvalue = new FunctionOqlExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor); } -#line 1526 "oql-parser.php" -#line 96 "oql-parser.y" +#line 1526 "..\oql-parser.php" +#line 96 "..\oql-parser.y" function yy_r29(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; } -#line 1529 "oql-parser.php" -#line 97 "oql-parser.y" +#line 1529 "..\oql-parser.php" +#line 97 "..\oql-parser.y" function yy_r30(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); } -#line 1532 "oql-parser.php" -#line 112 "oql-parser.y" +#line 1532 "..\oql-parser.php" +#line 112 "..\oql-parser.y" function yy_r39(){ $this->_retvalue = new ListOqlExpression($this->yystack[$this->yyidx + -1]->minor); } -#line 1537 "oql-parser.php" -#line 123 "oql-parser.y" +#line 1537 "..\oql-parser.php" +#line 123 "..\oql-parser.y" function yy_r42(){ $this->_retvalue = array(); } -#line 1542 "oql-parser.php" -#line 134 "oql-parser.y" +#line 1542 "..\oql-parser.php" +#line 134 "..\oql-parser.y" function yy_r46(){ $this->_retvalue = new IntervalOqlExpression($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); } -#line 1545 "oql-parser.php" -#line 146 "oql-parser.y" +#line 1545 "..\oql-parser.php" +#line 146 "..\oql-parser.y" function yy_r55(){ $this->_retvalue = new ScalarOqlExpression($this->yystack[$this->yyidx + 0]->minor); } -#line 1548 "oql-parser.php" -#line 149 "oql-parser.y" +#line 1548 "..\oql-parser.php" +#line 149 "..\oql-parser.y" function yy_r57(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor); } -#line 1551 "oql-parser.php" -#line 150 "oql-parser.y" +#line 1551 "..\oql-parser.php" +#line 150 "..\oql-parser.y" function yy_r58(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -2]->minor); } -#line 1554 "oql-parser.php" -#line 151 "oql-parser.y" +#line 1554 "..\oql-parser.php" +#line 151 "..\oql-parser.y" function yy_r59(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } -#line 1557 "oql-parser.php" -#line 154 "oql-parser.y" +#line 1557 "..\oql-parser.php" +#line 154 "..\oql-parser.y" function yy_r60(){ $this->_retvalue = new VariableOqlExpression(substr($this->yystack[$this->yyidx + 0]->minor, 1)); } -#line 1560 "oql-parser.php" -#line 156 "oql-parser.y" +#line 1560 "..\oql-parser.php" +#line 156 "..\oql-parser.y" function yy_r61(){ if ($this->yystack[$this->yyidx + 0]->minor[0] == '`') { @@ -1566,22 +1566,22 @@ static public $yy_action = array( } $this->_retvalue = new OqlName($name, $this->m_iColPrev); } -#line 1573 "oql-parser.php" -#line 167 "oql-parser.y" +#line 1573 "..\oql-parser.php" +#line 167 "..\oql-parser.y" function yy_r62(){$this->_retvalue=(int)$this->yystack[$this->yyidx + 0]->minor; } -#line 1576 "oql-parser.php" -#line 168 "oql-parser.y" +#line 1576 "..\oql-parser.php" +#line 168 "..\oql-parser.y" function yy_r63(){$this->_retvalue=(int)-$this->yystack[$this->yyidx + 0]->minor; } -#line 1579 "oql-parser.php" -#line 169 "oql-parser.y" +#line 1579 "..\oql-parser.php" +#line 169 "..\oql-parser.y" function yy_r64(){$this->_retvalue=new OqlHexValue($this->yystack[$this->yyidx + 0]->minor); } -#line 1582 "oql-parser.php" -#line 170 "oql-parser.y" +#line 1582 "..\oql-parser.php" +#line 170 "..\oql-parser.y" function yy_r65(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); } -#line 1585 "oql-parser.php" -#line 173 "oql-parser.y" +#line 1585 "..\oql-parser.php" +#line 173 "..\oql-parser.y" function yy_r66(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } -#line 1588 "oql-parser.php" +#line 1588 "..\oql-parser.php" /** * placeholder for the left hand side in a reduce operation. @@ -1693,10 +1693,10 @@ static public $yy_action = array( */ function yy_syntax_error($yymajor, $TOKEN) { -#line 25 "oql-parser.y" +#line 25 "..\oql-parser.y" throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN); -#line 1704 "oql-parser.php" +#line 1704 "..\oql-parser.php" } /** @@ -1863,7 +1863,7 @@ throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCo } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); } } -#line 231 "oql-parser.y" +#line 231 "..\oql-parser.y" class OQLParserException extends OQLException @@ -1928,4 +1928,4 @@ class OQLParser extends OQLParserRaw } } -#line 1937 "oql-parser.php" +#line 1937 "..\oql-parser.php"