I have this thing I want to try, but it requires a bit of runtime smarts, since I don't know ahead of time what some of the inputs are. So I figured I would try to write a grammar capable of learning or...being dynamic.
However I've run into a bit of a snag.
Code:
use v6.c;
use Grammar::Tracer;
class UnitParser {
has @.defUnits;
has $.parser;
grammar UnitParserGrammar {
regex TOP { <num> [ '/' <den> ]? }
regex num { ( <expr> \s* )+ }
regex den { <expr> }
token expr {
<mag> <unit> [ '^' (\d+) ]?
}
token mag {
T || G || M || k || h || da || d || c || m || u || µ || n || dn || p || f
}
proto token unit { * }
token unit:sym<xxx> { <sym> }
}
submethod BUILD {
$!parser = UnitParserGrammar.new;
}
method addUnit(Str $unit) {
# @.defUnits.push: $unit;
$.parser.HOW.^add_method("unit:sym<$unit>", token { <sym> });
$.parser.HOW.^compose;
}
# method refresh {
# @!defUnits = Units.enum.keys, %formulas.keys;
# }
method parse($s) {
#self.refresh;
$.parser.parse($s);
say $.parser.^methods».name;
}
}
sub MAIN {
my $up = UnitParser.new;
$up.addUnit('ft');
$up.addUnit('s');
say $up.parse('ft/s');
say $up.parse('Mft/ks');
}
Output:
$ perl6 scripts/testGrammar.pl6
===SORRY!===
Substring length (-5) cannot be negative
So what is rakudo telling me I'm doing wrong?
Thanks!