Skip to content

Instantly share code, notes, and snippets.

@Mouq
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mouq/9452638 to your computer and use it in GitHub Desktop.
Save Mouq/9452638 to your computer and use it in GitHub Desktop.
Potential Grammar::Precedence test
use Test;
use Grammar::Precedence;
grammar Arithmetic does Grammar::Precedence {
token TOP { <EXPR> }
# self.push-prec($str) makes $str a new
# precedence level and the loosest level.
# self.unshift-prec($str) would therefor
# make $str a new precedence level and
# the tightest level.
# (maybe these should be renamed, though,
# since self.pop-prec and self.shift-prec
# don't make sense)
$.push-prec('sign', :assoc<unary>); #?
$.push-prec('mantissa', :assoc<unary>); #?
$.push-prec('exponential', :assoc<right>);
$.push-prec('multiplicative', :assoc<left>);
$.push-prec('additive', :assoc<left>);
# <EXPR> operates as:
# [ <prefixish>* <termish> <postfixish>* ] +% <infixish>
# --> Or should this be editable?
# (in this case »… <termish> <postfixish>? ] …«)
rule termish { <digit> | \( ~ \) <EXPR> }
token digit { \d+ [\. \d+]? }
token infixish { <infix> }
proto token infix {*}
token infix:sym<^> { <sym> <O('exponential')> }
token infix:sym<*> { <sym> <O('multiplicative')> }
token infix:sym</> { <sym> <O('multiplicative')> }
token infix:sym<+> { <sym> <O('additive')> }
token infix:sym<-> { <sym> <O('additive')> }
token prefixish { <prefix> }
proto token prefix {*}
token prefix:sym<+> { <sym> <O('sign')> }
token prefix:sym<-> { <sym> <O('sign')> }
token postfixish { <[eE]> <EXPR('sign')> <O('mantissa')> }
}
class ArithActions {
method TOP ($/) { make $<EXPR>.ast }
method termish ($/) {
make $<digit>
?? +$<digit>.Str
!! $<EXPR>.ast
}
method infixish ($/) { make $<infix>.ast }
method infix:sym<^> ($/) { make {$^a ** $^b} }
method infix:sym<*> ($/) { make {$^a * $^b} }
method infix:sym</> ($/) { make {$^a / $^b} }
method infix:sym<+> ($/) { make {$^a + $^b} }
method infix:sym<-> ($/) { make {$^a - $^b} }
method prefixish ($/) { make $<prefix>.ast }
method prefix:sym<+> ($/) { make { $^a } }
method prefix:sym<-> ($/) { make { 0 - $^a } }
method postfixish ($/) { make { $^a * 10 ** $<EXPR>.ast } }
# Already defined as such (though over-writable)
# method EXPR ($/) {
# my &reduce = $<OPER>.ast();
# make reduce |$/.list».ast;
# }
}
my &arith = { Arithmetic.parse(:actions(ArithActions), $^str).ast };
is arith('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3'), 3 + 4 * 2 / (1 - 5) ** 2 ** 3;
is arith('3e5'), 300000;
is arith('+3.1E-7'), 3.1e-7;
# vim: ft=perl6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment