diff --git a/examples/calc.class b/examples/calc.class index 8845277..1a86bdc 100644 --- a/examples/calc.class +++ b/examples/calc.class @@ -257,6 +257,10 @@ class calc extends lime_parser { '#' => 'r 13' ) ); + public $d = array( + "'+'" => 'plus sign (+)', + "'/'" => 'division (/)' + ); function reduce_0_stmt_1($tokens, &$result) { // (0) stmt := exp $result = reset($tokens); diff --git a/examples/calc.lime b/examples/calc.lime index abf0403..4b75dc5 100644 --- a/examples/calc.lime +++ b/examples/calc.lime @@ -1,6 +1,9 @@ %class calc %start stmt +%token '+' "plus sign (+)" +%token '/' "division (/)" + %left '+' '-' %left '*' '/' '%' %right '^' diff --git a/lime.php b/lime.php index 9d3d434..51d202d 100755 --- a/lime.php +++ b/lime.php @@ -17,7 +17,7 @@ */ define('LIME_DIR', __DIR__); -define('INDENT', ' '); + function emit($str) { fputs(STDERR, $str . PHP_EOL); @@ -607,6 +607,8 @@ class config { class lime { public $parser_class = 'parser'; + public $descr = array(); + public function __construct() { $this->p_next = 1; $this->sym = array(); @@ -652,8 +654,9 @@ class lime { $i = $this->resolve_conflicts(); $a = $this->rule_table(); $qi = $initial->id; + $d = $this->descr; - return $this->lang->ptab_to_class($this->parser_class, compact('a', 'qi', 'i')); + return $this->lang->ptab_to_class($this->parser_class, compact('a', 'qi', 'i', 'd')); } function rule_table() { @@ -697,6 +700,10 @@ class lime { function sym($str, $description = null) { if (!isset($this->sym[$str])) { $this->sym[$str] = new sym($str, count($this->sym), $description); + + if ($description) { + $this->descr[$str] = $description; + } } return $this->sym[$str]; @@ -1060,7 +1067,8 @@ class lime_language_php extends lime_language { public function ptab_to_class($parser_class, $ptab) { $code = ''; $code .= 'public $qi = ' . lime_export($ptab['qi'], true) . ';' . PHP_EOL; - $code .= 'public $i = '.lime_export($ptab['i'], true).';' . PHP_EOL; + $code .= 'public $i = ' . lime_export($ptab['i'], true) . ';' . PHP_EOL; + $code .= 'public $d = ' . lime_export($ptab['d'], true) . ';' . PHP_EOL; $rc = array(); $method = array(); @@ -1322,6 +1330,26 @@ function parse_lime_grammar($path) { if ($_SERVER['argv']) { $code = ''; + + if (!defined('INDENT')) { + foreach($_SERVER['argv'] as $i => $opt) { + if ($opt === '--indent') { + $val = @$_SERVER['argv'][$i + 1]; + if (!$val) { + define('INDENT', ' '); + } else { + define('INDENT', $val == 1 ? "\t" : str_repeat(' ', $val)); + } + unset($_SERVER['argv'][$i], $_SERVER['argv'][$i + 1]); + break; + } + } + + if (!defined('INDENT')) { + define('INDENT', ' '); + } + } + array_shift($_SERVER['argv']); // Strip out the program name. foreach ($_SERVER['argv'] as $path) { $code .= parse_lime_grammar($path); diff --git a/parse_engine.php b/parse_engine.php index c3615b0..17c79d2 100644 --- a/parse_engine.php +++ b/parse_engine.php @@ -106,6 +106,7 @@ class parse_engine { public $qi; public $rule; public $step; + public $descr; /** * @var boolean */ @@ -120,6 +121,7 @@ class parse_engine { $this->qi = $parser->qi; $this->rule = $parser->a; $this->step = $parser->i; + $this->descr = $parser->d; $this->reset(); } @@ -324,7 +326,7 @@ class parse_engine { } } else { // If that didn't work, give up: - throw new parse_error("Parse Error: {$type} ({$semantic}) not expected, expected {" . implode(', ', $expected) . '}'); + throw new parse_error('Parse Error: ' . $this->descr($type, $semantic) . ' not expected, expected {' . implode(', ', $expected) . '}'); } break; default: @@ -332,6 +334,14 @@ class parse_engine { } } + private function descr($type, $semantic) { + if (isset($this->descr[$type])) { + return $this->descr[$type]; + } else { + return $type . ' (' . $semantic . ')'; + } + } + private function reduce($rule_id) { $rule = $this->rule[$rule_id]; $len = $rule['len'];