Directives: defer
{my %variables}
start: statement <commit> eof {$variables {'.'} = $item [1]}
| <error?> <reject>
eof: /^\Z/
statement: variable '=' <commit> statement
{$return = $item [4]}
<defer: $variables {$item [1]} = $item [4]>
| expression
expression: <leftop: term ('+' | '-') term>
{my $s = shift @{$item [1]};
while (@{$item [1]}) {
my ($op, $exp) = splice @{$item [1]}, 0, 2;
if ($op eq '+') {$s += $exp}
else {$s -= $exp}
}
$s
}
term: <leftop: factor m{([*/])} factor>
{my $p = shift @{$item [1]};
while (@{$item [1]}) {
my ($op, $term) = splice @{$item [1]}, 0, 2;
if ($op eq '*') {$p *= $term}
else {$p /= $term}
}
$p
}
factor: number
| variable {$variables {$item [1]} ||=
Math::BigInt -> new (0)}
| '+' <commit> factor {$item [3]}
| '-' <commit> factor {$item [3] * -1}
| '(' <commit> statement ')'
{$item [3]}
| <error>
number: /\d+/ {Math::BigInt -> new ($item [1])}
variable: /[a-z]+/i
| "."
In [1] := x = 3
Out [1] = +3
In [2] := x = 5 (6)
ERROR (line 1): Invalid start: Was expecting eof but found "(6)"
instead
Out [2] = <<UNDEF>>
In [3] := x
Out [3] = +3
In [4] :=
- A <defer> directive is like a
block of code, except that it is only executed when the
current production was used in the final match.
- The action will be queued, and will be removed from the queue
if the parser backtracks and rejects the current production.
- This can be used to make the parsing be done more efficiently,
by only executing those actions that are part of the final
parse tree.
- The code in a <defer> directive
is turned into a closure, and only the
<defer> directives from productions
contributing to the match will be run.
- <defer> always succeeds, returning
the number of queued deferred actions so far.
[Prev]
[Next]
[Index]