Lempar.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. <?php
  2. /* Driver template for the PHP_ParserGenerator parser generator. (PHP port of LEMON)
  3. */
  4. /**
  5. * This can be used to store both the string representation of
  6. * a token, and any useful meta-data associated with the token.
  7. *
  8. * meta-data should be stored as an array
  9. */
  10. class ParseyyToken implements ArrayAccess
  11. {
  12. public $string = '';
  13. public $metadata = array();
  14. function __construct($s, $m = array())
  15. {
  16. if ($s instanceof ParseyyToken) {
  17. $this->string = $s->string;
  18. $this->metadata = $s->metadata;
  19. } else {
  20. $this->string = (string) $s;
  21. if ($m instanceof ParseyyToken) {
  22. $this->metadata = $m->metadata;
  23. } elseif (is_array($m)) {
  24. $this->metadata = $m;
  25. }
  26. }
  27. }
  28. function __toString()
  29. {
  30. return $this->string;
  31. }
  32. function offsetExists($offset)
  33. {
  34. return isset($this->metadata[$offset]);
  35. }
  36. function offsetGet($offset)
  37. {
  38. return $this->metadata[$offset];
  39. }
  40. function offsetSet($offset, $value)
  41. {
  42. if ($offset === null) {
  43. if (isset($value[0])) {
  44. $x = ($value instanceof ParseyyToken) ?
  45. $value->metadata : $value;
  46. $this->metadata = array_merge($this->metadata, $x);
  47. return;
  48. }
  49. $offset = count($this->metadata);
  50. }
  51. if ($value === null) {
  52. return;
  53. }
  54. if ($value instanceof ParseyyToken) {
  55. if ($value->metadata) {
  56. $this->metadata[$offset] = $value->metadata;
  57. }
  58. } elseif ($value) {
  59. $this->metadata[$offset] = $value;
  60. }
  61. }
  62. function offsetUnset($offset)
  63. {
  64. unset($this->metadata[$offset]);
  65. }
  66. }
  67. /** The following structure represents a single element of the
  68. * parser's stack. Information stored includes:
  69. *
  70. * + The state number for the parser at this level of the stack.
  71. *
  72. * + The value of the token stored at this level of the stack.
  73. * (In other words, the "major" token.)
  74. *
  75. * + The semantic value stored at this level of the stack. This is
  76. * the information used by the action routines in the grammar.
  77. * It is sometimes called the "minor" token.
  78. */
  79. class ParseyyStackEntry
  80. {
  81. public $stateno; /* The state-number */
  82. public $major; /* The major token value. This is the code
  83. ** number for the token at this stack level */
  84. public $minor; /* The user-supplied minor token value. This
  85. ** is the value of the token */
  86. };
  87. // code external to the class is included here
  88. %%
  89. // declare_class is output here
  90. %%
  91. {
  92. /* First off, code is included which follows the "include_class" declaration
  93. ** in the input file. */
  94. %%
  95. /* Next is all token values, as class constants
  96. */
  97. /*
  98. ** These constants (all generated automatically by the parser generator)
  99. ** specify the various kinds of tokens (terminals) that the parser
  100. ** understands.
  101. **
  102. ** Each symbol here is a terminal symbol in the grammar.
  103. */
  104. %%
  105. /* Next are that tables used to determine what action to take based on the
  106. ** current state and lookahead token. These tables are used to implement
  107. ** functions that take a state number and lookahead value and return an
  108. ** action integer.
  109. **
  110. ** Suppose the action integer is N. Then the action is determined as
  111. ** follows
  112. **
  113. ** 0 <= N < self::YYNSTATE Shift N. That is,
  114. ** push the lookahead
  115. ** token onto the stack
  116. ** and goto state N.
  117. **
  118. ** self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE Reduce by rule N-YYNSTATE.
  119. **
  120. ** N == self::YYNSTATE+self::YYNRULE A syntax error has occurred.
  121. **
  122. ** N == self::YYNSTATE+self::YYNRULE+1 The parser accepts its
  123. ** input. (and concludes parsing)
  124. **
  125. ** N == self::YYNSTATE+self::YYNRULE+2 No such action. Denotes unused
  126. ** slots in the yy_action[] table.
  127. **
  128. ** The action table is constructed as a single large static array $yy_action.
  129. ** Given state S and lookahead X, the action is computed as
  130. **
  131. ** self::$yy_action[self::$yy_shift_ofst[S] + X ]
  132. **
  133. ** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value
  134. ** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if
  135. ** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that
  136. ** the action is not in the table and that self::$yy_default[S] should be used instead.
  137. **
  138. ** The formula above is for computing the action when the lookahead is
  139. ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
  140. ** a reduce action) then the static $yy_reduce_ofst array is used in place of
  141. ** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of
  142. ** self::YY_SHIFT_USE_DFLT.
  143. **
  144. ** The following are the tables generated in this section:
  145. **
  146. ** self::$yy_action A single table containing all actions.
  147. ** self::$yy_lookahead A table containing the lookahead for each entry in
  148. ** yy_action. Used to detect hash collisions.
  149. ** self::$yy_shift_ofst For each state, the offset into self::$yy_action for
  150. ** shifting terminals.
  151. ** self::$yy_reduce_ofst For each state, the offset into self::$yy_action for
  152. ** shifting non-terminals after a reduce.
  153. ** self::$yy_default Default action for each state.
  154. */
  155. %%
  156. /* The next thing included is series of defines which control
  157. ** various aspects of the generated parser.
  158. ** self::YYNOCODE is a number which corresponds
  159. ** to no legal terminal or nonterminal number. This
  160. ** number is used to fill in empty slots of the hash
  161. ** table.
  162. ** self::YYFALLBACK If defined, this indicates that one or more tokens
  163. ** have fall-back values which should be used if the
  164. ** original value of the token will not parse.
  165. ** self::YYSTACKDEPTH is the maximum depth of the parser's stack.
  166. ** self::YYNSTATE the combined number of states.
  167. ** self::YYNRULE the number of rules in the grammar
  168. ** self::YYERRORSYMBOL is the code number of the error symbol. If not
  169. ** defined, then do no error processing.
  170. */
  171. %%
  172. /** The next table maps tokens into fallback tokens. If a construct
  173. * like the following:
  174. *
  175. * %fallback ID X Y Z.
  176. *
  177. * appears in the grammer, then ID becomes a fallback token for X, Y,
  178. * and Z. Whenever one of the tokens X, Y, or Z is input to the parser
  179. * but it does not parse, the type of the token is changed to ID and
  180. * the parse is retried before an error is thrown.
  181. */
  182. static public $yyFallback = array(
  183. %%
  184. );
  185. /**
  186. * Turn parser tracing on by giving a stream to which to write the trace
  187. * and a prompt to preface each trace message. Tracing is turned off
  188. * by making either argument NULL
  189. *
  190. * Inputs:
  191. *
  192. * - A stream resource to which trace output should be written.
  193. * If NULL, then tracing is turned off.
  194. * - A prefix string written at the beginning of every
  195. * line of trace output. If NULL, then tracing is
  196. * turned off.
  197. *
  198. * Outputs:
  199. *
  200. * - None.
  201. * @param resource
  202. * @param string
  203. */
  204. static function Trace($TraceFILE, $zTracePrompt)
  205. {
  206. if (!$TraceFILE) {
  207. $zTracePrompt = 0;
  208. } elseif (!$zTracePrompt) {
  209. $TraceFILE = 0;
  210. }
  211. self::$yyTraceFILE = $TraceFILE;
  212. self::$yyTracePrompt = $zTracePrompt;
  213. }
  214. /**
  215. * Output debug information to output (php://output stream)
  216. */
  217. static function PrintTrace()
  218. {
  219. self::$yyTraceFILE = fopen('php://output', 'w');
  220. self::$yyTracePrompt = '';
  221. }
  222. /**
  223. * @var resource|0
  224. */
  225. static public $yyTraceFILE;
  226. /**
  227. * String to prepend to debug output
  228. * @var string|0
  229. */
  230. static public $yyTracePrompt;
  231. /**
  232. * @var int
  233. */
  234. public $yyidx = -1; /* Index of top element in stack */
  235. /**
  236. * @var int
  237. */
  238. public $yyerrcnt; /* Shifts left before out of the error */
  239. /**
  240. * @var array
  241. */
  242. public $yystack = array(); /* The parser's stack */
  243. /**
  244. * For tracing shifts, the names of all terminals and nonterminals
  245. * are required. The following table supplies these names
  246. * @var array
  247. */
  248. static public $yyTokenName = array(
  249. %%
  250. );
  251. /**
  252. * For tracing reduce actions, the names of all rules are required.
  253. * @var array
  254. */
  255. static public $yyRuleName = array(
  256. %%
  257. );
  258. /**
  259. * This function returns the symbolic name associated with a token
  260. * value.
  261. * @param int
  262. * @return string
  263. */
  264. function tokenName($tokenType)
  265. {
  266. if ($tokenType === 0) {
  267. return 'End of Input';
  268. }
  269. if ($tokenType > 0 && $tokenType < count(self::$yyTokenName)) {
  270. return self::$yyTokenName[$tokenType];
  271. } else {
  272. return "Unknown";
  273. }
  274. }
  275. /**
  276. * The following function deletes the value associated with a
  277. * symbol. The symbol can be either a terminal or nonterminal.
  278. * @param int the symbol code
  279. * @param mixed the symbol's value
  280. */
  281. static function yy_destructor($yymajor, $yypminor)
  282. {
  283. switch ($yymajor) {
  284. /* Here is inserted the actions which take place when a
  285. ** terminal or non-terminal is destroyed. This can happen
  286. ** when the symbol is popped from the stack during a
  287. ** reduce or during error processing or when a parser is
  288. ** being destroyed before it is finished parsing.
  289. **
  290. ** Note: during a reduce, the only symbols destroyed are those
  291. ** which appear on the RHS of the rule, but which are not used
  292. ** inside the C code.
  293. */
  294. %%
  295. default: break; /* If no destructor action specified: do nothing */
  296. }
  297. }
  298. /**
  299. * Pop the parser's stack once.
  300. *
  301. * If there is a destructor routine associated with the token which
  302. * is popped from the stack, then call it.
  303. *
  304. * Return the major token number for the symbol popped.
  305. * @param ParseyyParser
  306. * @return int
  307. */
  308. function yy_pop_parser_stack()
  309. {
  310. if (!count($this->yystack)) {
  311. return;
  312. }
  313. $yytos = array_pop($this->yystack);
  314. if (self::$yyTraceFILE && $this->yyidx >= 0) {
  315. fwrite(self::$yyTraceFILE,
  316. self::$yyTracePrompt . 'Popping ' . self::$yyTokenName[$yytos->major] .
  317. "\n");
  318. }
  319. $yymajor = $yytos->major;
  320. self::yy_destructor($yymajor, $yytos->minor);
  321. $this->yyidx--;
  322. return $yymajor;
  323. }
  324. /**
  325. * Deallocate and destroy a parser. Destructors are all called for
  326. * all stack elements before shutting the parser down.
  327. */
  328. function __destruct()
  329. {
  330. while ($this->yyidx >= 0) {
  331. $this->yy_pop_parser_stack();
  332. }
  333. if (is_resource(self::$yyTraceFILE)) {
  334. fclose(self::$yyTraceFILE);
  335. }
  336. }
  337. /**
  338. * Based on the current state and parser stack, get a list of all
  339. * possible lookahead tokens
  340. * @param int
  341. * @return array
  342. */
  343. function yy_get_expected_tokens($token)
  344. {
  345. $state = $this->yystack[$this->yyidx]->stateno;
  346. $expected = self::$yyExpectedTokens[$state];
  347. if (in_array($token, self::$yyExpectedTokens[$state], true)) {
  348. return $expected;
  349. }
  350. $stack = $this->yystack;
  351. $yyidx = $this->yyidx;
  352. do {
  353. $yyact = $this->yy_find_shift_action($token);
  354. if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
  355. // reduce action
  356. $done = 0;
  357. do {
  358. if ($done++ == 100) {
  359. $this->yyidx = $yyidx;
  360. $this->yystack = $stack;
  361. // too much recursion prevents proper detection
  362. // so give up
  363. return array_unique($expected);
  364. }
  365. $yyruleno = $yyact - self::YYNSTATE;
  366. $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  367. $nextstate = $this->yy_find_reduce_action(
  368. $this->yystack[$this->yyidx]->stateno,
  369. self::$yyRuleInfo[$yyruleno]['lhs']);
  370. if (isset(self::$yyExpectedTokens[$nextstate])) {
  371. $expected += self::$yyExpectedTokens[$nextstate];
  372. if (in_array($token,
  373. self::$yyExpectedTokens[$nextstate], true)) {
  374. $this->yyidx = $yyidx;
  375. $this->yystack = $stack;
  376. return array_unique($expected);
  377. }
  378. }
  379. if ($nextstate < self::YYNSTATE) {
  380. // we need to shift a non-terminal
  381. $this->yyidx++;
  382. $x = new ParseyyStackEntry;
  383. $x->stateno = $nextstate;
  384. $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  385. $this->yystack[$this->yyidx] = $x;
  386. continue 2;
  387. } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) {
  388. $this->yyidx = $yyidx;
  389. $this->yystack = $stack;
  390. // the last token was just ignored, we can't accept
  391. // by ignoring input, this is in essence ignoring a
  392. // syntax error!
  393. return array_unique($expected);
  394. } elseif ($nextstate === self::YY_NO_ACTION) {
  395. $this->yyidx = $yyidx;
  396. $this->yystack = $stack;
  397. // input accepted, but not shifted (I guess)
  398. return $expected;
  399. } else {
  400. $yyact = $nextstate;
  401. }
  402. } while (true);
  403. }
  404. break;
  405. } while (true);
  406. return array_unique($expected);
  407. }
  408. /**
  409. * Based on the parser state and current parser stack, determine whether
  410. * the lookahead token is possible.
  411. *
  412. * The parser will convert the token value to an error token if not. This
  413. * catches some unusual edge cases where the parser would fail.
  414. * @param int
  415. * @return bool
  416. */
  417. function yy_is_expected_token($token)
  418. {
  419. if ($token === 0) {
  420. return true; // 0 is not part of this
  421. }
  422. $state = $this->yystack[$this->yyidx]->stateno;
  423. if (in_array($token, self::$yyExpectedTokens[$state], true)) {
  424. return true;
  425. }
  426. $stack = $this->yystack;
  427. $yyidx = $this->yyidx;
  428. do {
  429. $yyact = $this->yy_find_shift_action($token);
  430. if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
  431. // reduce action
  432. $done = 0;
  433. do {
  434. if ($done++ == 100) {
  435. $this->yyidx = $yyidx;
  436. $this->yystack = $stack;
  437. // too much recursion prevents proper detection
  438. // so give up
  439. return true;
  440. }
  441. $yyruleno = $yyact - self::YYNSTATE;
  442. $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  443. $nextstate = $this->yy_find_reduce_action(
  444. $this->yystack[$this->yyidx]->stateno,
  445. self::$yyRuleInfo[$yyruleno]['lhs']);
  446. if (isset(self::$yyExpectedTokens[$nextstate]) &&
  447. in_array($token, self::$yyExpectedTokens[$nextstate], true)) {
  448. $this->yyidx = $yyidx;
  449. $this->yystack = $stack;
  450. return true;
  451. }
  452. if ($nextstate < self::YYNSTATE) {
  453. // we need to shift a non-terminal
  454. $this->yyidx++;
  455. $x = new ParseyyStackEntry;
  456. $x->stateno = $nextstate;
  457. $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  458. $this->yystack[$this->yyidx] = $x;
  459. continue 2;
  460. } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) {
  461. $this->yyidx = $yyidx;
  462. $this->yystack = $stack;
  463. if (!$token) {
  464. // end of input: this is valid
  465. return true;
  466. }
  467. // the last token was just ignored, we can't accept
  468. // by ignoring input, this is in essence ignoring a
  469. // syntax error!
  470. return false;
  471. } elseif ($nextstate === self::YY_NO_ACTION) {
  472. $this->yyidx = $yyidx;
  473. $this->yystack = $stack;
  474. // input accepted, but not shifted (I guess)
  475. return true;
  476. } else {
  477. $yyact = $nextstate;
  478. }
  479. } while (true);
  480. }
  481. break;
  482. } while (true);
  483. $this->yyidx = $yyidx;
  484. $this->yystack = $stack;
  485. return true;
  486. }
  487. /**
  488. * Find the appropriate action for a parser given the terminal
  489. * look-ahead token iLookAhead.
  490. *
  491. * If the look-ahead token is YYNOCODE, then check to see if the action is
  492. * independent of the look-ahead. If it is, return the action, otherwise
  493. * return YY_NO_ACTION.
  494. * @param int The look-ahead token
  495. */
  496. function yy_find_shift_action($iLookAhead)
  497. {
  498. $stateno = $this->yystack[$this->yyidx]->stateno;
  499. /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */
  500. if (!isset(self::$yy_shift_ofst[$stateno])) {
  501. // no shift actions
  502. return self::$yy_default[$stateno];
  503. }
  504. $i = self::$yy_shift_ofst[$stateno];
  505. if ($i === self::YY_SHIFT_USE_DFLT) {
  506. return self::$yy_default[$stateno];
  507. }
  508. if ($iLookAhead == self::YYNOCODE) {
  509. return self::YY_NO_ACTION;
  510. }
  511. $i += $iLookAhead;
  512. if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  513. self::$yy_lookahead[$i] != $iLookAhead) {
  514. if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback)
  515. && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) {
  516. if (self::$yyTraceFILE) {
  517. fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " .
  518. self::$yyTokenName[$iLookAhead] . " => " .
  519. self::$yyTokenName[$iFallback] . "\n");
  520. }
  521. return $this->yy_find_shift_action($iFallback);
  522. }
  523. return self::$yy_default[$stateno];
  524. } else {
  525. return self::$yy_action[$i];
  526. }
  527. }
  528. /**
  529. * Find the appropriate action for a parser given the non-terminal
  530. * look-ahead token $iLookAhead.
  531. *
  532. * If the look-ahead token is self::YYNOCODE, then check to see if the action is
  533. * independent of the look-ahead. If it is, return the action, otherwise
  534. * return self::YY_NO_ACTION.
  535. * @param int Current state number
  536. * @param int The look-ahead token
  537. */
  538. function yy_find_reduce_action($stateno, $iLookAhead)
  539. {
  540. /* $stateno = $this->yystack[$this->yyidx]->stateno; */
  541. if (!isset(self::$yy_reduce_ofst[$stateno])) {
  542. return self::$yy_default[$stateno];
  543. }
  544. $i = self::$yy_reduce_ofst[$stateno];
  545. if ($i == self::YY_REDUCE_USE_DFLT) {
  546. return self::$yy_default[$stateno];
  547. }
  548. if ($iLookAhead == self::YYNOCODE) {
  549. return self::YY_NO_ACTION;
  550. }
  551. $i += $iLookAhead;
  552. if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  553. self::$yy_lookahead[$i] != $iLookAhead) {
  554. return self::$yy_default[$stateno];
  555. } else {
  556. return self::$yy_action[$i];
  557. }
  558. }
  559. /**
  560. * Perform a shift action.
  561. * @param int The new state to shift in
  562. * @param int The major token to shift in
  563. * @param mixed the minor token to shift in
  564. */
  565. function yy_shift($yyNewState, $yyMajor, $yypMinor)
  566. {
  567. $this->yyidx++;
  568. if ($this->yyidx >= self::YYSTACKDEPTH) {
  569. $this->yyidx--;
  570. if (self::$yyTraceFILE) {
  571. fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt);
  572. }
  573. while ($this->yyidx >= 0) {
  574. $this->yy_pop_parser_stack();
  575. }
  576. /* Here code is inserted which will execute if the parser
  577. ** stack ever overflows */
  578. %%
  579. return;
  580. }
  581. $yytos = new ParseyyStackEntry;
  582. $yytos->stateno = $yyNewState;
  583. $yytos->major = $yyMajor;
  584. $yytos->minor = $yypMinor;
  585. array_push($this->yystack, $yytos);
  586. if (self::$yyTraceFILE && $this->yyidx > 0) {
  587. fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt,
  588. $yyNewState);
  589. fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt);
  590. for ($i = 1; $i <= $this->yyidx; $i++) {
  591. fprintf(self::$yyTraceFILE, " %s",
  592. self::$yyTokenName[$this->yystack[$i]->major]);
  593. }
  594. fwrite(self::$yyTraceFILE,"\n");
  595. }
  596. }
  597. /**
  598. * The following table contains information about every rule that
  599. * is used during the reduce.
  600. *
  601. * <pre>
  602. * array(
  603. * array(
  604. * int $lhs; Symbol on the left-hand side of the rule
  605. * int $nrhs; Number of right-hand side symbols in the rule
  606. * ),...
  607. * );
  608. * </pre>
  609. */
  610. static public $yyRuleInfo = array(
  611. %%
  612. );
  613. /**
  614. * The following table contains a mapping of reduce action to method name
  615. * that handles the reduction.
  616. *
  617. * If a rule is not set, it has no handler.
  618. */
  619. static public $yyReduceMap = array(
  620. %%
  621. );
  622. /* Beginning here are the reduction cases. A typical example
  623. ** follows:
  624. ** #line <lineno> <grammarfile>
  625. ** function yy_r0($yymsp){ ... } // User supplied code
  626. ** #line <lineno> <thisfile>
  627. */
  628. %%
  629. /**
  630. * placeholder for the left hand side in a reduce operation.
  631. *
  632. * For a parser with a rule like this:
  633. * <pre>
  634. * rule(A) ::= B. { A = 1; }
  635. * </pre>
  636. *
  637. * The parser will translate to something like:
  638. *
  639. * <code>
  640. * function yy_r0(){$this->_retvalue = 1;}
  641. * </code>
  642. */
  643. private $_retvalue;
  644. /**
  645. * Perform a reduce action and the shift that must immediately
  646. * follow the reduce.
  647. *
  648. * For a rule such as:
  649. *
  650. * <pre>
  651. * A ::= B blah C. { dosomething(); }
  652. * </pre>
  653. *
  654. * This function will first call the action, if any, ("dosomething();" in our
  655. * example), and then it will pop three states from the stack,
  656. * one for each entry on the right-hand side of the expression
  657. * (B, blah, and C in our example rule), and then push the result of the action
  658. * back on to the stack with the resulting state reduced to (as described in the .out
  659. * file)
  660. * @param int Number of the rule by which to reduce
  661. */
  662. function yy_reduce($yyruleno)
  663. {
  664. //int $yygoto; /* The next state */
  665. //int $yyact; /* The next action */
  666. //mixed $yygotominor; /* The LHS of the rule reduced */
  667. //ParseyyStackEntry $yymsp; /* The top of the parser's stack */
  668. //int $yysize; /* Amount to pop the stack */
  669. $yymsp = $this->yystack[$this->yyidx];
  670. if (self::$yyTraceFILE && $yyruleno >= 0
  671. && $yyruleno < count(self::$yyRuleName)) {
  672. fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n",
  673. self::$yyTracePrompt, $yyruleno,
  674. self::$yyRuleName[$yyruleno]);
  675. }
  676. $this->_retvalue = $yy_lefthand_side = null;
  677. if (array_key_exists($yyruleno, self::$yyReduceMap)) {
  678. // call the action
  679. $this->_retvalue = null;
  680. $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
  681. $yy_lefthand_side = $this->_retvalue;
  682. }
  683. $yygoto = self::$yyRuleInfo[$yyruleno]['lhs'];
  684. $yysize = self::$yyRuleInfo[$yyruleno]['rhs'];
  685. $this->yyidx -= $yysize;
  686. for ($i = $yysize; $i; $i--) {
  687. // pop all of the right-hand side parameters
  688. array_pop($this->yystack);
  689. }
  690. $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto);
  691. if ($yyact < self::YYNSTATE) {
  692. /* If we are not debugging and the reduce action popped at least
  693. ** one element off the stack, then we can push the new element back
  694. ** onto the stack here, and skip the stack overflow test in yy_shift().
  695. ** That gives a significant speed improvement. */
  696. if (!self::$yyTraceFILE && $yysize) {
  697. $this->yyidx++;
  698. $x = new ParseyyStackEntry;
  699. $x->stateno = $yyact;
  700. $x->major = $yygoto;
  701. $x->minor = $yy_lefthand_side;
  702. $this->yystack[$this->yyidx] = $x;
  703. } else {
  704. $this->yy_shift($yyact, $yygoto, $yy_lefthand_side);
  705. }
  706. } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) {
  707. $this->yy_accept();
  708. }
  709. }
  710. /**
  711. * The following code executes when the parse fails
  712. *
  713. * Code from %parse_fail is inserted here
  714. */
  715. function yy_parse_failed()
  716. {
  717. if (self::$yyTraceFILE) {
  718. fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt);
  719. }
  720. while ($this->yyidx >= 0) {
  721. $this->yy_pop_parser_stack();
  722. }
  723. /* Here code is inserted which will be executed whenever the
  724. ** parser fails */
  725. %%
  726. }
  727. /**
  728. * The following code executes when a syntax error first occurs.
  729. *
  730. * %syntax_error code is inserted here
  731. * @param int The major type of the error token
  732. * @param mixed The minor type of the error token
  733. */
  734. function yy_syntax_error($yymajor, $TOKEN)
  735. {
  736. %%
  737. }
  738. /**
  739. * The following is executed when the parser accepts
  740. *
  741. * %parse_accept code is inserted here
  742. */
  743. function yy_accept()
  744. {
  745. if (self::$yyTraceFILE) {
  746. fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt);
  747. }
  748. while ($this->yyidx >= 0) {
  749. $stack = $this->yy_pop_parser_stack();
  750. }
  751. /* Here code is inserted which will be executed whenever the
  752. ** parser accepts */
  753. %%
  754. }
  755. /**
  756. * The main parser program.
  757. *
  758. * The first argument is the major token number. The second is
  759. * the token value string as scanned from the input.
  760. *
  761. * @param int $yymajor the token number
  762. * @param mixed $yytokenvalue the token value
  763. * @param mixed ... any extra arguments that should be passed to handlers
  764. *
  765. * @return void
  766. */
  767. function doParse($yymajor, $yytokenvalue)
  768. {
  769. // $yyact; /* The parser action. */
  770. // $yyendofinput; /* True if we are at the end of input */
  771. $yyerrorhit = 0; /* True if yymajor has invoked an error */
  772. /* (re)initialize the parser, if necessary */
  773. if ($this->yyidx === null || $this->yyidx < 0) {
  774. /* if ($yymajor == 0) return; // not sure why this was here... */
  775. $this->yyidx = 0;
  776. $this->yyerrcnt = -1;
  777. $x = new ParseyyStackEntry;
  778. $x->stateno = 0;
  779. $x->major = 0;
  780. $this->yystack = array();
  781. array_push($this->yystack, $x);
  782. }
  783. $yyendofinput = ($yymajor==0);
  784. if (self::$yyTraceFILE) {
  785. fprintf(
  786. self::$yyTraceFILE,
  787. "%sInput %s\n",
  788. self::$yyTracePrompt,
  789. self::$yyTokenName[$yymajor]
  790. );
  791. }
  792. do {
  793. $yyact = $this->yy_find_shift_action($yymajor);
  794. if ($yymajor < self::YYERRORSYMBOL
  795. && !$this->yy_is_expected_token($yymajor)
  796. ) {
  797. // force a syntax error
  798. $yyact = self::YY_ERROR_ACTION;
  799. }
  800. if ($yyact < self::YYNSTATE) {
  801. $this->yy_shift($yyact, $yymajor, $yytokenvalue);
  802. $this->yyerrcnt--;
  803. if ($yyendofinput && $this->yyidx >= 0) {
  804. $yymajor = 0;
  805. } else {
  806. $yymajor = self::YYNOCODE;
  807. }
  808. } elseif ($yyact < self::YYNSTATE + self::YYNRULE) {
  809. $this->yy_reduce($yyact - self::YYNSTATE);
  810. } elseif ($yyact == self::YY_ERROR_ACTION) {
  811. if (self::$yyTraceFILE) {
  812. fprintf(
  813. self::$yyTraceFILE,
  814. "%sSyntax Error!\n",
  815. self::$yyTracePrompt
  816. );
  817. }
  818. if (self::YYERRORSYMBOL) {
  819. /* A syntax error has occurred.
  820. ** The response to an error depends upon whether or not the
  821. ** grammar defines an error token "ERROR".
  822. **
  823. ** This is what we do if the grammar does define ERROR:
  824. **
  825. ** * Call the %syntax_error function.
  826. **
  827. ** * Begin popping the stack until we enter a state where
  828. ** it is legal to shift the error symbol, then shift
  829. ** the error symbol.
  830. **
  831. ** * Set the error count to three.
  832. **
  833. ** * Begin accepting and shifting new tokens. No new error
  834. ** processing will occur until three tokens have been
  835. ** shifted successfully.
  836. **
  837. */
  838. if ($this->yyerrcnt < 0) {
  839. $this->yy_syntax_error($yymajor, $yytokenvalue);
  840. }
  841. $yymx = $this->yystack[$this->yyidx]->major;
  842. if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ) {
  843. if (self::$yyTraceFILE) {
  844. fprintf(
  845. self::$yyTraceFILE,
  846. "%sDiscard input token %s\n",
  847. self::$yyTracePrompt,
  848. self::$yyTokenName[$yymajor]
  849. );
  850. }
  851. $this->yy_destructor($yymajor, $yytokenvalue);
  852. $yymajor = self::YYNOCODE;
  853. } else {
  854. while ($this->yyidx >= 0
  855. && $yymx != self::YYERRORSYMBOL
  856. && ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
  857. ) {
  858. $this->yy_pop_parser_stack();
  859. }
  860. if ($this->yyidx < 0 || $yymajor==0) {
  861. $this->yy_destructor($yymajor, $yytokenvalue);
  862. $this->yy_parse_failed();
  863. $yymajor = self::YYNOCODE;
  864. } elseif ($yymx != self::YYERRORSYMBOL) {
  865. $u2 = 0;
  866. $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2);
  867. }
  868. }
  869. $this->yyerrcnt = 3;
  870. $yyerrorhit = 1;
  871. } else {
  872. /* YYERRORSYMBOL is not defined */
  873. /* This is what we do if the grammar does not define ERROR:
  874. **
  875. ** * Report an error message, and throw away the input token.
  876. **
  877. ** * If the input token is $, then fail the parse.
  878. **
  879. ** As before, subsequent error messages are suppressed until
  880. ** three input tokens have been successfully shifted.
  881. */
  882. if ($this->yyerrcnt <= 0) {
  883. $this->yy_syntax_error($yymajor, $yytokenvalue);
  884. }
  885. $this->yyerrcnt = 3;
  886. $this->yy_destructor($yymajor, $yytokenvalue);
  887. if ($yyendofinput) {
  888. $this->yy_parse_failed();
  889. }
  890. $yymajor = self::YYNOCODE;
  891. }
  892. } else {
  893. $this->yy_accept();
  894. $yymajor = self::YYNOCODE;
  895. }
  896. } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
  897. }
  898. }