mirror of https://github.com/vitalif/lime
Added support for inline %prec definitions
parent
175b67c614
commit
6c257fc45b
|
@ -1,335 +1,315 @@
|
|||
<?php
|
||||
|
||||
|
||||
/*
|
||||
*** DON'T EDIT THIS FILE! ***
|
||||
*
|
||||
* This file was automatically generated by the Lime parser generator.
|
||||
* The real source code you should be looking at is in one or more
|
||||
* grammar files in the Lime format.
|
||||
*
|
||||
* THE ONLY REASON TO LOOK AT THIS FILE is to see where in the grammar
|
||||
* file that your error happened, because there are enough comments to
|
||||
* help you debug your grammar.
|
||||
|
||||
DON'T EDIT THIS FILE!
|
||||
|
||||
This file was automatically generated by the Lime parser generator.
|
||||
The real source code you should be looking at is in one or more
|
||||
grammar files in the Lime format.
|
||||
|
||||
THE ONLY REASON TO LOOK AT THIS FILE is to see where in the grammar
|
||||
file that your error happened, because there are enough comments to
|
||||
help you debug your grammar.
|
||||
|
||||
If you ignore this warning, you're shooting yourself in the brain,
|
||||
not the foot.
|
||||
|
||||
*/
|
||||
|
||||
* If you ignore this warning, you're shooting yourself in the brain,
|
||||
* not the foot.
|
||||
*/
|
||||
class calc extends lime_parser {
|
||||
var $qi = 0;
|
||||
var $i = array (
|
||||
0 =>
|
||||
array (
|
||||
'exp' => 's 1',
|
||||
'var' => 's 15',
|
||||
'num' => 's 3',
|
||||
'\'(\'' => 's 12',
|
||||
'stmt' => 's 18',
|
||||
'\'start\'' => 'a \'start\'',
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'\'+\'' => 's 2',
|
||||
'\'-\'' => 's 6',
|
||||
'\'*\'' => 's 8',
|
||||
'\'/\'' => 's 10',
|
||||
'#' => 'r 0',
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 5',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
'\'+\'' => 'r 2',
|
||||
'\'-\'' => 'r 2',
|
||||
'\'*\'' => 'r 2',
|
||||
'\'/\'' => 'r 2',
|
||||
'\')\'' => 'r 2',
|
||||
'#' => 'r 2',
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
'\'+\'' => 'r 3',
|
||||
'\'-\'' => 'r 3',
|
||||
'\'*\'' => 'r 3',
|
||||
'\'/\'' => 'r 3',
|
||||
'\')\'' => 'r 3',
|
||||
'#' => 'r 3',
|
||||
),
|
||||
5 =>
|
||||
array (
|
||||
'\'+\'' => 'r 4',
|
||||
'\'-\'' => 'r 4',
|
||||
'\'*\'' => 's 8',
|
||||
'\'/\'' => 's 10',
|
||||
'\')\'' => 'r 4',
|
||||
'#' => 'r 4',
|
||||
),
|
||||
6 =>
|
||||
array (
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 7',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
7 =>
|
||||
array (
|
||||
'\'+\'' => 'r 5',
|
||||
'\'-\'' => 'r 5',
|
||||
'\'*\'' => 's 8',
|
||||
'\'/\'' => 's 10',
|
||||
'\')\'' => 'r 5',
|
||||
'#' => 'r 5',
|
||||
),
|
||||
8 =>
|
||||
array (
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 9',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
9 =>
|
||||
array (
|
||||
'\'+\'' => 'r 6',
|
||||
'\'-\'' => 'r 6',
|
||||
'\'*\'' => 'r 6',
|
||||
'\'/\'' => 'r 6',
|
||||
'\')\'' => 'r 6',
|
||||
'#' => 'r 6',
|
||||
),
|
||||
10 =>
|
||||
array (
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 11',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
'\'+\'' => 'r 7',
|
||||
'\'-\'' => 'r 7',
|
||||
'\'*\'' => 'r 7',
|
||||
'\'/\'' => 'r 7',
|
||||
'\')\'' => 'r 7',
|
||||
'#' => 'r 7',
|
||||
),
|
||||
12 =>
|
||||
array (
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 13',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
13 =>
|
||||
array (
|
||||
'\'+\'' => 's 2',
|
||||
'\'-\'' => 's 6',
|
||||
'\'*\'' => 's 8',
|
||||
'\'/\'' => 's 10',
|
||||
'\')\'' => 's 14',
|
||||
),
|
||||
14 =>
|
||||
array (
|
||||
'\'/\'' => 'r 8',
|
||||
'\'*\'' => 'r 8',
|
||||
'\'-\'' => 'r 8',
|
||||
'\'+\'' => 'r 8',
|
||||
'\')\'' => 'r 8',
|
||||
'#' => 'r 8',
|
||||
),
|
||||
15 =>
|
||||
array (
|
||||
'\'=\'' => 's 16',
|
||||
'\'+\'' => 'r 3',
|
||||
'\'-\'' => 'r 3',
|
||||
'\'*\'' => 'r 3',
|
||||
'\'/\'' => 'r 3',
|
||||
'#' => 'r 3',
|
||||
),
|
||||
16 =>
|
||||
array (
|
||||
'exp' => 's 17',
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'\'(\'' => 's 12',
|
||||
),
|
||||
17 =>
|
||||
array (
|
||||
'\'+\'' => 's 2',
|
||||
'\'-\'' => 's 6',
|
||||
'\'*\'' => 's 8',
|
||||
'\'/\'' => 's 10',
|
||||
'#' => 'r 1',
|
||||
),
|
||||
18 =>
|
||||
array (
|
||||
'#' => 'r 9',
|
||||
),
|
||||
);
|
||||
function reduce_0_stmt_1($tokens, &$result) {
|
||||
#
|
||||
# (0) stmt := exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
echo " -> "; echo $tokens[0]; echo "\n";
|
||||
}
|
||||
|
||||
function reduce_1_stmt_2($tokens, &$result) {
|
||||
#
|
||||
# (1) stmt := var '=' exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$v =& $tokens[0];
|
||||
$e =& $tokens[2];
|
||||
|
||||
echo "$v = $e\n";
|
||||
set_variable($v, $e);
|
||||
|
||||
}
|
||||
|
||||
function reduce_2_exp_1($tokens, &$result) {
|
||||
#
|
||||
# (2) exp := num
|
||||
#
|
||||
$result = reset($tokens);
|
||||
|
||||
}
|
||||
|
||||
function reduce_3_exp_2($tokens, &$result) {
|
||||
#
|
||||
# (3) exp := var
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$result = get_variable($tokens[0]);
|
||||
}
|
||||
|
||||
function reduce_4_exp_3($tokens, &$result) {
|
||||
#
|
||||
# (4) exp := exp '+' exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] + $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_5_exp_4($tokens, &$result) {
|
||||
#
|
||||
# (5) exp := exp '-' exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] - $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_6_exp_5($tokens, &$result) {
|
||||
#
|
||||
# (6) exp := exp '*' exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] * $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_7_exp_6($tokens, &$result) {
|
||||
#
|
||||
# (7) exp := exp '/' exp
|
||||
#
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] / $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_8_exp_7($tokens, &$result) {
|
||||
#
|
||||
# (8) exp := '(' exp ')'
|
||||
#
|
||||
$result = $tokens[1];
|
||||
|
||||
}
|
||||
|
||||
function reduce_9_start_1($tokens, &$result) {
|
||||
#
|
||||
# (9) 'start' := stmt
|
||||
#
|
||||
$result = reset($tokens);
|
||||
|
||||
}
|
||||
|
||||
var $method = array (
|
||||
0 => 'reduce_0_stmt_1',
|
||||
1 => 'reduce_1_stmt_2',
|
||||
2 => 'reduce_2_exp_1',
|
||||
3 => 'reduce_3_exp_2',
|
||||
4 => 'reduce_4_exp_3',
|
||||
5 => 'reduce_5_exp_4',
|
||||
6 => 'reduce_6_exp_5',
|
||||
7 => 'reduce_7_exp_6',
|
||||
8 => 'reduce_8_exp_7',
|
||||
9 => 'reduce_9_start_1',
|
||||
);
|
||||
var $a = array (
|
||||
0 =>
|
||||
array (
|
||||
'symbol' => 'stmt',
|
||||
'len' => 1,
|
||||
'replace' => true,
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'symbol' => 'stmt',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 1,
|
||||
'replace' => true,
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 1,
|
||||
'replace' => true,
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
5 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
6 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
7 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
8 =>
|
||||
array (
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true,
|
||||
),
|
||||
9 =>
|
||||
array (
|
||||
'symbol' => '\'start\'',
|
||||
'len' => 1,
|
||||
'replace' => true,
|
||||
),
|
||||
);
|
||||
public $qi = 0;
|
||||
public $i = array(
|
||||
array(
|
||||
'exp' => 's 1',
|
||||
'var' => 's 17',
|
||||
'num' => 's 3',
|
||||
"'('" => 's 14',
|
||||
'stmt' => 's 20',
|
||||
"'start'" => "a 'start'"
|
||||
),
|
||||
array(
|
||||
"'+'" => 's 2',
|
||||
"'-'" => 's 6',
|
||||
"'*'" => 's 8',
|
||||
"'/'" => 's 10',
|
||||
"'^'" => 's 12',
|
||||
'#' => 'r 0'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 5',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 2',
|
||||
"'-'" => 'r 2',
|
||||
"'*'" => 'r 2',
|
||||
"'/'" => 'r 2',
|
||||
"'^'" => 'r 2',
|
||||
"')'" => 'r 2',
|
||||
'#' => 'r 2'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 3',
|
||||
"'-'" => 'r 3',
|
||||
"'*'" => 'r 3',
|
||||
"'/'" => 'r 3',
|
||||
"'^'" => 'r 3',
|
||||
"')'" => 'r 3',
|
||||
'#' => 'r 3'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 4',
|
||||
"'-'" => 'r 4',
|
||||
"'*'" => 's 8',
|
||||
"'/'" => 's 10',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 'r 4',
|
||||
'#' => 'r 4'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 7',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 5',
|
||||
"'-'" => 'r 5',
|
||||
"'*'" => 's 8',
|
||||
"'/'" => 's 10',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 'r 5',
|
||||
'#' => 'r 5'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 9',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 6',
|
||||
"'-'" => 'r 6',
|
||||
"'*'" => 'r 6',
|
||||
"'/'" => 'r 6',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 'r 6',
|
||||
'#' => 'r 6'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 11',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 7',
|
||||
"'-'" => 'r 7',
|
||||
"'*'" => 'r 7',
|
||||
"'/'" => 'r 7',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 'r 7',
|
||||
'#' => 'r 7'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 13',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 'r 8',
|
||||
"'-'" => 'r 8',
|
||||
"'*'" => 'r 8',
|
||||
"'/'" => 'r 8',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 'r 8',
|
||||
'#' => 'r 8'
|
||||
),
|
||||
array(
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
'exp' => 's 15',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 's 2',
|
||||
"'-'" => 's 6',
|
||||
"'*'" => 's 8',
|
||||
"'/'" => 's 10',
|
||||
"'^'" => 's 12',
|
||||
"')'" => 's 16'
|
||||
),
|
||||
array(
|
||||
"'^'" => 'r 9',
|
||||
"'/'" => 'r 9',
|
||||
"'*'" => 'r 9',
|
||||
"'-'" => 'r 9',
|
||||
"'+'" => 'r 9',
|
||||
"')'" => 'r 9',
|
||||
'#' => 'r 9'
|
||||
),
|
||||
array(
|
||||
"'='" => 's 18',
|
||||
"'+'" => 'r 3',
|
||||
"'-'" => 'r 3',
|
||||
"'*'" => 'r 3',
|
||||
"'/'" => 'r 3',
|
||||
"'^'" => 'r 3',
|
||||
'#' => 'r 3'
|
||||
),
|
||||
array(
|
||||
'exp' => 's 19',
|
||||
'num' => 's 3',
|
||||
'var' => 's 4',
|
||||
"'('" => 's 14'
|
||||
),
|
||||
array(
|
||||
"'+'" => 's 2',
|
||||
"'-'" => 's 6',
|
||||
"'*'" => 's 8',
|
||||
"'/'" => 's 10',
|
||||
"'^'" => 's 12',
|
||||
'#' => 'r 1'
|
||||
),
|
||||
array(
|
||||
'#' => 'r 10'
|
||||
)
|
||||
);
|
||||
function reduce_0_stmt_1($tokens, &$result) {
|
||||
// (0) stmt := exp
|
||||
$result = reset($tokens);
|
||||
echo " -> "; echo $tokens[0]; echo "\n";
|
||||
}
|
||||
|
||||
function reduce_1_stmt_2($tokens, &$result) {
|
||||
// (1) stmt := var '=' exp
|
||||
$result = reset($tokens);
|
||||
$v = &$tokens[0];
|
||||
$e = &$tokens[2];
|
||||
|
||||
echo "$v = $e\n";
|
||||
set_variable($v, $e);
|
||||
}
|
||||
|
||||
function reduce_2_exp_1($tokens, &$result) {
|
||||
// (2) exp := num
|
||||
$result = reset($tokens);
|
||||
}
|
||||
|
||||
function reduce_3_exp_2($tokens, &$result) {
|
||||
// (3) exp := var
|
||||
$result = reset($tokens);
|
||||
$result = get_variable($tokens[0]);
|
||||
}
|
||||
|
||||
function reduce_4_exp_3($tokens, &$result) {
|
||||
// (4) exp := exp '+' exp
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] + $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_5_exp_4($tokens, &$result) {
|
||||
// (5) exp := exp '-' exp
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] - $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_6_exp_5($tokens, &$result) {
|
||||
// (6) exp := exp '*' exp
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] * $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_7_exp_6($tokens, &$result) {
|
||||
// (7) exp := exp '/' exp
|
||||
$result = reset($tokens);
|
||||
$result = $tokens[0] / $tokens[2];
|
||||
}
|
||||
|
||||
function reduce_8_exp_7($tokens, &$result) {
|
||||
// (8) exp := exp '^' exp
|
||||
$result = reset($tokens);
|
||||
$result = pow($tokens[0], $tokens[2]);
|
||||
}
|
||||
|
||||
function reduce_9_exp_8($tokens, &$result) {
|
||||
// (9) exp := '(' exp ')'
|
||||
$result = $tokens[1];
|
||||
}
|
||||
|
||||
function reduce_10_start_1($tokens, &$result) {
|
||||
// (10) 'start' := stmt
|
||||
$result = reset($tokens);
|
||||
}
|
||||
|
||||
public $method = array(
|
||||
'reduce_0_stmt_1',
|
||||
'reduce_1_stmt_2',
|
||||
'reduce_2_exp_1',
|
||||
'reduce_3_exp_2',
|
||||
'reduce_4_exp_3',
|
||||
'reduce_5_exp_4',
|
||||
'reduce_6_exp_5',
|
||||
'reduce_7_exp_6',
|
||||
'reduce_8_exp_7',
|
||||
'reduce_9_exp_8',
|
||||
'reduce_10_start_1'
|
||||
);
|
||||
public $a = array(
|
||||
array(
|
||||
'symbol' => 'stmt',
|
||||
'len' => 1,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'stmt',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 1,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 1,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => 'exp',
|
||||
'len' => 3,
|
||||
'replace' => true
|
||||
),
|
||||
array(
|
||||
'symbol' => "'start'",
|
||||
'len' => 1,
|
||||
'replace' => true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
%left '+' '-'
|
||||
%left '*' '/'
|
||||
%right '^'
|
||||
|
||||
stmt = exp { echo " -> "; echo $1; echo "\n"; }
|
||||
| var/v '=' exp/e {
|
||||
|
@ -18,6 +19,7 @@ exp = num
|
|||
| exp '-' exp { $$ = $1 - $3; }
|
||||
| exp '*' exp { $$ = $1 * $3; }
|
||||
| exp '/' exp { $$ = $1 / $3; }
|
||||
| exp '^' exp { $$ = pow($1, $3); }
|
||||
| '(' exp/$ ')'
|
||||
.
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ lit : $$ = new lime_glyph($1, NULL);
|
|||
to slot
|
||||
: $$ = new lime_rhs();
|
||||
rhs slot : $$->add($2);
|
||||
rhs prec tok : $$->set_prec_glyph($3);
|
||||
to rhs
|
||||
'{' code '}' : $$ = $2;
|
||||
to action
|
||||
|
@ -29,3 +30,6 @@ to action
|
|||
code php : $$.=$2;
|
||||
code '{' code '}' : $$.='{'.$3.'}';
|
||||
to code
|
||||
sym :
|
||||
lit :
|
||||
to tok
|
||||
|
|
48
lime.php
48
lime.php
|
@ -160,11 +160,13 @@ class error extends step {
|
|||
|
||||
class shift extends step {
|
||||
public $q;
|
||||
public $rule;
|
||||
|
||||
public function __construct(sym $sym, $q) {
|
||||
public function __construct(sym $sym, $q, rule $rule) {
|
||||
parent::__construct($sym);
|
||||
|
||||
$this->q = $q;
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
public function instruction() {
|
||||
|
@ -178,7 +180,7 @@ class shift extends step {
|
|||
bug_unless($that instanceof reduce);
|
||||
|
||||
// That being said, the resolution is a matter of precedence.
|
||||
$shift_prec = $this->sym->right_prec;
|
||||
$shift_prec = $this->rule->right_prec;
|
||||
$reduce_prec = $that->rule->prec;
|
||||
|
||||
// If we don't have defined precedence levels for both options,
|
||||
|
@ -274,8 +276,8 @@ class state {
|
|||
}
|
||||
}
|
||||
|
||||
public function add_shift(sym $sym, $state) {
|
||||
$this->add_instruction(new shift($sym, $state->id));
|
||||
public function add_shift(sym $sym, $state, $rule) {
|
||||
$this->add_instruction(new shift($sym, $state->id, $rule));
|
||||
}
|
||||
|
||||
public function add_reduce(sym $sym, $rule) {
|
||||
|
@ -375,7 +377,7 @@ class sym {
|
|||
}
|
||||
|
||||
class rule {
|
||||
public function __construct($id, $sym, $rhs, $code, $look, $replace) {
|
||||
public function __construct($id, $sym, $rhs, $code, $look, $replace, $prec_sym) {
|
||||
bug_unless(is_int($look));
|
||||
|
||||
$this->id = $id;
|
||||
|
@ -384,8 +386,9 @@ class rule {
|
|||
$this->code = $code;
|
||||
$this->look = $look;
|
||||
$this->replace = $replace;
|
||||
//$this->prec_sym = $prec_sym;
|
||||
$this->prec_sym = $prec_sym;
|
||||
$this->prec = 0;
|
||||
$this->right_prec = 0;
|
||||
$this->first = array();
|
||||
$this->epsilon = count($rhs);
|
||||
}
|
||||
|
@ -401,15 +404,17 @@ class rule {
|
|||
// is a reasonable alternative behaviour, but I don't see the big
|
||||
// deal just now.
|
||||
|
||||
//$prec_sym = $this->prec_sym;
|
||||
//if (!$prec_sym)
|
||||
$prec_sym = $this->rightmost_terminal();
|
||||
$prec_sym = $this->prec_sym;
|
||||
if (!$prec_sym) {
|
||||
$prec_sym = $this->rightmost_terminal();
|
||||
}
|
||||
|
||||
if (!$prec_sym) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->prec = $prec_sym->left_prec;
|
||||
$this->right_prec = $prec_sym->right_prec;
|
||||
}
|
||||
|
||||
private function rightmost_terminal() {
|
||||
|
@ -664,7 +669,7 @@ class lime {
|
|||
return "'{$real}'" . count($this->rule);
|
||||
}
|
||||
|
||||
function add_raw_rule($lhs, $rhs, $code, $look, $replace) {
|
||||
function add_raw_rule($lhs, $rhs, $code, $look, $replace, $prec_sym) {
|
||||
$sym = $this->sym($lhs);
|
||||
$sym->term = false;
|
||||
|
||||
|
@ -679,7 +684,7 @@ class lime {
|
|||
}
|
||||
|
||||
$rid = count($this->rule);
|
||||
$r = new rule($rid, $sym, $rs, $code, $look, $replace);
|
||||
$r = new rule($rid, $sym, $rs, $code, $look, $replace, $prec_sym);
|
||||
$this->rule[$rid] = $r;
|
||||
$sym->rule[] = $r;
|
||||
}
|
||||
|
@ -754,7 +759,7 @@ class lime {
|
|||
$candidate = current($this->start_symbol_set);
|
||||
|
||||
// Did the person try to set a start symbol at all?
|
||||
if (!$candidate) {
|
||||
if (!is_object($candidate)) {
|
||||
return $this->first_rule_lhs();
|
||||
}
|
||||
|
||||
|
@ -862,7 +867,7 @@ class lime {
|
|||
}
|
||||
|
||||
$dest = $this->get_state($basis);
|
||||
$state->add_shift($this->sym($glyph), $dest);
|
||||
$state->add_shift($this->sym($glyph), $dest, $segment[0]->rule);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1074,6 +1079,8 @@ class lime_language_php extends lime_language {
|
|||
}
|
||||
|
||||
class lime_rhs {
|
||||
public $prec_glyph;
|
||||
|
||||
function __construct() {
|
||||
// Construct and add glyphs and actions in whatever order.
|
||||
// Then, add this to a lime_rewrite.
|
||||
|
@ -1083,10 +1090,14 @@ class lime_rhs {
|
|||
$this->rhs = array();
|
||||
}
|
||||
|
||||
function add(lime_slot $slot) {
|
||||
public function add(lime_slot $slot) {
|
||||
$this->rhs[] = $slot;
|
||||
}
|
||||
|
||||
public function set_prec_glyph($glyph) {
|
||||
$this->prec_glyph = $glyph;
|
||||
}
|
||||
|
||||
function install_rule(lime $lime, $lhs) {
|
||||
// This is the part that has to break the rule into subrules if necessary.
|
||||
$rhs = $this->rhs;
|
||||
|
@ -1095,6 +1106,11 @@ class lime_rhs {
|
|||
$rhs[] = new lime_action('', null);
|
||||
}
|
||||
|
||||
$prec_sym = null;
|
||||
if ($this->prec_glyph) {
|
||||
$prec_sym = $lime->sym($this->prec_glyph);
|
||||
}
|
||||
|
||||
// Now, split it into chunks based on the actions.
|
||||
|
||||
$lang = $lime->language();
|
||||
|
@ -1118,12 +1134,12 @@ class lime_rhs {
|
|||
// no.
|
||||
$subsymbol = $lime->trump_up_bogus_lhs($lhs);
|
||||
$action = $lang->default_result() . $preamble . $code;
|
||||
$lime->add_raw_rule($subsymbol, $subrule, $action, $look, false);
|
||||
$lime->add_raw_rule($subsymbol, $subrule, $action, $look, false, $prec_sym);
|
||||
$subrule = array($subsymbol);
|
||||
} else {
|
||||
// yes.
|
||||
$action = $result_code . $preamble . $code;
|
||||
$lime->add_raw_rule($lhs, $subrule, $action, $look, true);
|
||||
$lime->add_raw_rule($lhs, $subrule, $action, $look, true, $prec_sym);
|
||||
}
|
||||
} else {
|
||||
impossible();
|
||||
|
|
BIN
lime_scan_tokens
BIN
lime_scan_tokens
Binary file not shown.
|
@ -63,6 +63,9 @@ BLOCKCMT "/*"({CC}|{CX})*{CT}
|
|||
{BLOCKCMT} {}
|
||||
"/"{WORD}+ |
|
||||
"/$" out("lambda", yytext+1);
|
||||
"%prec" {
|
||||
tok("prec");
|
||||
}
|
||||
"%"{WORD}+ {
|
||||
out("pragma", yytext+1);
|
||||
yy_push_state(pragma);
|
||||
|
|
|
@ -260,6 +260,18 @@ class parse_engine {
|
|||
return explode(' ', $row[$type]);
|
||||
}
|
||||
|
||||
private function get_steps() {
|
||||
$out = array();
|
||||
foreach($this->current_row() as $type => $row) {
|
||||
list($opcode) = explode(' ', $row, 2);
|
||||
if ($opcode != 'e') {
|
||||
$out[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function has_step_for($type) {
|
||||
$row = $this->current_row();
|
||||
return isset($row[$type]);
|
||||
|
@ -300,6 +312,9 @@ class parse_engine {
|
|||
// flutter while the parse engine waits for an edible token.
|
||||
// if ($this->debug) echo "($type) causes a problem.\n";
|
||||
|
||||
// get these before doing anything
|
||||
$expected = $this->get_steps();
|
||||
|
||||
if ($this->enter_error_tolerant_state()) {
|
||||
$this->eat('error', null);
|
||||
if ($this->has_step_for($type)) {
|
||||
|
@ -307,7 +322,7 @@ class parse_engine {
|
|||
}
|
||||
} else {
|
||||
// If that didn't work, give up:
|
||||
throw new parse_error("Parse Error: ({$type})({$semantic}) not expected");
|
||||
throw new parse_error("Parse Error: ({$type})({$semantic}) not expected, expected {" . implode(', ', $expected) . '}');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue