diff --git a/README b/README index e8c9ed94..b3359ee5 100644 --- a/README +++ b/README @@ -5,23 +5,20 @@ This project is work in progress, but it basically works and was tested on a lar Usage: $parser = new Parser(); - $parser->yyparse( + $stmts = $parser->yyparse( new Lexer('yyparse will either be false (which + // signifies that an error occured) or an array of statements (Nodes) + if (false !== $stmts) { + // dump the AST + foreach ($stmts as $stmt) { + echo $stmt, "\n"; + } + } \ No newline at end of file diff --git a/grammar/kmyacc.class.php.parser b/grammar/kmyacc.class.php.parser index 375e3eff..c1ba2078 100644 --- a/grammar/kmyacc.class.php.parser +++ b/grammar/kmyacc.class.php.parser @@ -114,65 +114,51 @@ class YYParser ); } - protected function accept() { - $acceptCallback = $this->acceptCallback; - $acceptCallback($this->yyval); - } - - protected function yyaccept() { - $this->yyaccept = 1; - } - - protected function yyabort() { - $this->yyaccept = 2; - } - @if -t /* Traditional Debug Mode */ private function YYTRACE_NEWSTATE($state, $sym) { if ($this->yydebug) { - $this->yyprintln("% State " . $state . ", Lookahead " - . ($sym < 0 ? "--none--" : self::$yyterminals[$sym])); + $this->yyprintln('% State ' . $state . ', Lookahead ' + . ($sym < 0 ? '--none--' : self::$yyterminals[$sym])); } } private function YYTRACE_READ($sym) { if ($this->yydebug) - $this->yyprintln("% Reading " . self::$yyterminals[$sym]); + $this->yyprintln('% Reading ' . self::$yyterminals[$sym]); } private function YYTRACE_SHIFT($sym) { if ($this->yydebug) - $this->yyprintln("% Shift " . self::$yyterminals[$sym]); + $this->yyprintln('% Shift ' . self::$yyterminals[$sym]); } private function YYTRACE_ACCEPT() { if ($this->yydebug) - $this->yyprintln("% Accepted."); + $this->yyprintln('% Accepted.'); } private function YYTRACE_REDUCE($n) { if ($this->yydebug) - $this->yyprintln("% Reduce by (" . $n . ") " . self::$yyproduction[$n]); + $this->yyprintln('% Reduce by (' . $n . ') ' . self::$yyproduction[$n]); } private function YYTRACE_POP($state) { if ($this->yydebug) - $this->yyprintln("% Recovering, uncovers state " . $state); + $this->yyprintln('% Recovering, uncovers state ' . $state); } private function YYTRACE_DISCARD($sym) { if ($this->yydebug) - $this->yyprintln("% Discard " . self::$yyterminals[$sym]); + $this->yyprintln('% Discard ' . self::$yyterminals[$sym]); } @endif /** * Parser entry point */ - public function yyparse($lex, $acceptCallback, $errorCallback) { + public function yyparse($lex, $errorCallback) { $this->lex = $lex; - $this->acceptCallback = $acceptCallback; $this->errorCallback = $errorCallback; $this->yyastk = array(); @@ -222,14 +208,14 @@ class YYParser @if -t $this->YYTRACE_SHIFT($yychar); @endif - $this->yysp++; + ++$this->yysp; $yysstk[$this->yysp] = $yystate = $yyn; $this->yyastk[$this->yysp] = $yylval; $yychar = -1; if ($yyerrflag > 0) - $yyerrflag--; + --$yyerrflag; if ($yyn < self::YYNLSTATES) continue; @@ -250,36 +236,29 @@ class YYParser @if -t $this->YYTRACE_ACCEPT(); @endif - $this->accept(); - return $this->yyaccept - 1; + return $this->yyval; } elseif ($yyn != self::YYUNEXPECTED) { /* reduce */ - $yyl = self::$yylen[$yyn]; - $n = $this->yysp-$yyl+1; - $yyval = isset($this->yyastk[$n]) ? $this->yyastk[$n] : null; @if -t $this->YYTRACE_REDUCE($yyn); @endif $this->{'yyn' . $yyn}(); - if ($this->yyaccept) { - $yyn = self::YYNLSTATES; + + /* Goto - shift nonterminal */ + $this->yysp -= self::$yylen[$yyn]; + $yyn = self::$yylhs[$yyn]; + if (($yyp = self::$yygbase[$yyn] + $yysstk[$this->yysp]) >= 0 + && $yyp < self::YYGLAST + && self::$yygcheck[$yyp] == $yyn) { + $yystate = self::$yygoto[$yyp]; } else { - /* Goto - shift nonterminal */ - $this->yysp -= $yyl; - $yyn = self::$yylhs[$yyn]; - if (($yyp = self::$yygbase[$yyn] + $yysstk[$this->yysp]) >= 0 - && $yyp < self::YYGLAST - && self::$yygcheck[$yyp] == $yyn) { - $yystate = self::$yygoto[$yyp]; - } else { - $yystate = self::$yygdefault[$yyn]; - } - - $this->yysp++; - - $yysstk[$this->yysp] = $yystate; - $this->yyastk[$this->yysp] = $this->yyval; + $yystate = self::$yygdefault[$yyn]; } + + ++$this->yysp; + + $yysstk[$this->yysp] = $yystate; + $this->yyastk[$this->yysp] = $this->yyval; } else { /* error */ switch ($yyerrflag) { @@ -297,7 +276,7 @@ class YYParser && $yyn < self::YYLAST && self::$yycheck[$yyn] == self::YYINTERRTOK))) { if ($this->yysp <= 0) { - return 1; + return false; } $yystate = $yysstk[--$this->yysp]; @if -t @@ -316,7 +295,7 @@ class YYParser $this->YYTRACE_DISCARD($yychar); @endif if ($yychar == 0) { - return 1; + return false; } $yychar = -1; break; @@ -336,7 +315,10 @@ class YYParser %b } @noact - private function yyn%n() {} + + private function yyn%n() { + $this->yyval = $this->yyastk[$this->yysp]; + } @endreduce } @tailcode; diff --git a/lib/Parser.php b/lib/Parser.php index b826ad2f..41bceb69 100644 --- a/lib/Parser.php +++ b/lib/Parser.php @@ -145,7 +145,6 @@ class Parser protected $yyval; protected $yyastk; protected $yysp; - protected $yyaccept; /** Debug mode flag **/ public $yydebug = true; @@ -1254,63 +1253,49 @@ class Parser ); } - protected function accept() { - $acceptCallback = $this->acceptCallback; - $acceptCallback($this->yyval); - } - - protected function yyaccept() { - $this->yyaccept = 1; - } - - protected function yyabort() { - $this->yyaccept = 2; - } - /* Traditional Debug Mode */ private function YYTRACE_NEWSTATE($state, $sym) { if ($this->yydebug) { - $this->yyprintln("% State " . $state . ", Lookahead " - . ($sym < 0 ? "--none--" : self::$yyterminals[$sym])); + $this->yyprintln('% State ' . $state . ', Lookahead ' + . ($sym < 0 ? '--none--' : self::$yyterminals[$sym])); } } private function YYTRACE_READ($sym) { if ($this->yydebug) - $this->yyprintln("% Reading " . self::$yyterminals[$sym]); + $this->yyprintln('% Reading ' . self::$yyterminals[$sym]); } private function YYTRACE_SHIFT($sym) { if ($this->yydebug) - $this->yyprintln("% Shift " . self::$yyterminals[$sym]); + $this->yyprintln('% Shift ' . self::$yyterminals[$sym]); } private function YYTRACE_ACCEPT() { if ($this->yydebug) - $this->yyprintln("% Accepted."); + $this->yyprintln('% Accepted.'); } private function YYTRACE_REDUCE($n) { if ($this->yydebug) - $this->yyprintln("% Reduce by (" . $n . ") " . self::$yyproduction[$n]); + $this->yyprintln('% Reduce by (' . $n . ') ' . self::$yyproduction[$n]); } private function YYTRACE_POP($state) { if ($this->yydebug) - $this->yyprintln("% Recovering, uncovers state " . $state); + $this->yyprintln('% Recovering, uncovers state ' . $state); } private function YYTRACE_DISCARD($sym) { if ($this->yydebug) - $this->yyprintln("% Discard " . self::$yyterminals[$sym]); + $this->yyprintln('% Discard ' . self::$yyterminals[$sym]); } /** * Parser entry point */ - public function yyparse($lex, $acceptCallback, $errorCallback) { + public function yyparse($lex, $errorCallback) { $this->lex = $lex; - $this->acceptCallback = $acceptCallback; $this->errorCallback = $errorCallback; $this->yyastk = array(); @@ -1354,14 +1339,14 @@ class Parser if ($yyn > 0) { /* shift */ $this->YYTRACE_SHIFT($yychar); - $this->yysp++; + ++$this->yysp; $yysstk[$this->yysp] = $yystate = $yyn; $this->yyastk[$this->yysp] = $yylval; $yychar = -1; if ($yyerrflag > 0) - $yyerrflag--; + --$yyerrflag; if ($yyn < self::YYNLSTATES) continue; @@ -1376,38 +1361,30 @@ class Parser } for (;;) { - /* reduce/error */ if ($yyn == 0) { /* accept */ $this->YYTRACE_ACCEPT(); - $this->accept(); - return $this->yyaccept - 1; + return $this->yyval; } elseif ($yyn != self::YYUNEXPECTED) { /* reduce */ - $yyl = self::$yylen[$yyn]; - $n = $this->yysp-$yyl+1; - $yyval = isset($this->yyastk[$n]) ? $this->yyastk[$n] : null; $this->YYTRACE_REDUCE($yyn); $this->{'yyn' . $yyn}(); - if ($this->yyaccept) { - $yyn = self::YYNLSTATES; + + /* Goto - shift nonterminal */ + $this->yysp -= self::$yylen[$yyn]; + $yyn = self::$yylhs[$yyn]; + if (($yyp = self::$yygbase[$yyn] + $yysstk[$this->yysp]) >= 0 + && $yyp < self::YYGLAST + && self::$yygcheck[$yyp] == $yyn) { + $yystate = self::$yygoto[$yyp]; } else { - /* Goto - shift nonterminal */ - $this->yysp -= $yyl; - $yyn = self::$yylhs[$yyn]; - if (($yyp = self::$yygbase[$yyn] + $yysstk[$this->yysp]) >= 0 - && $yyp < self::YYGLAST - && self::$yygcheck[$yyp] == $yyn) { - $yystate = self::$yygoto[$yyp]; - } else { - $yystate = self::$yygdefault[$yyn]; - } - - $this->yysp++; - - $yysstk[$this->yysp] = $yystate; - $this->yyastk[$this->yysp] = $this->yyval; + $yystate = self::$yygdefault[$yyn]; } + + ++$this->yysp; + + $yysstk[$this->yysp] = $yystate; + $this->yyastk[$this->yysp] = $this->yyval; } else { /* error */ switch ($yyerrflag) { @@ -1425,7 +1402,7 @@ class Parser && $yyn < self::YYLAST && self::$yycheck[$yyn] == self::YYINTERRTOK))) { if ($this->yysp <= 0) { - return 1; + return false; } $yystate = $yysstk[--$this->yysp]; $this->YYTRACE_POP($yystate); @@ -1438,7 +1415,7 @@ class Parser case 3: $this->YYTRACE_DISCARD($yychar); if ($yychar == 0) { - return 1; + return false; } $yychar = -1; break; @@ -1452,7 +1429,10 @@ class Parser } } } - private function yyn0() {} + + private function yyn0() { + $this->yyval = $this->yyastk[$this->yysp]; + } private function yyn1() { $this->yyval = $this->yyastk[$this->yysp-(1-1)]; diff --git a/test.php b/test.php index 0cb89e76..b4311328 100644 --- a/test.php +++ b/test.php @@ -10,25 +10,26 @@ $parser = new Parser(); $parser->yydebug = false; // Output Demo -$parser->yyparse(new Lexer( +$stmts = $parser->yyparse(new Lexer( 'yyparse( + $stmts = $parser->yyparse( new Lexer(file_get_contents($file)), - function($stmts) { }, function($msg) { echo $msg, "\n"; } ); $endTime = microtime(true); - echo str_pad($file . ': ', 120, ' '), ($result == -1 ? 'successful' : 'ERROR'), ' (', $endTime - $startTime, ')', "\n"; + echo str_pad($file . ': ', 120, ' '), (false !== $stmts ? 'successful' : 'ERROR'), ' (', $endTime - $startTime, ')', "\n"; flush(); -} \ No newline at end of file +} +echo microtime(true) - $GST; \ No newline at end of file