数据样例
x = 40 + 2;
print x;
y = x - (5/2);
print y;
z = 1 + y * x;
print z;
print 14 - 16/3 + x;
目录结构如下:
.
├── Lang
│ ├── Actions.pm6
│ └── Grammar.pm6
├── data
│ ├── calc.lang
Grammar
Grammar.pm6 的内容如下:
unit grammar Lang::Grammar;
rule TOP {
^ <statements> $
}
rule statements {
<statement>+ %% ';'
}
rule statement {
| <assignment>
| <printout>
}
rule assignment {
<identifier> '=' <expression>
}
rule printout {
'print' <expression>
}
rule expression {
| <term>+ %% $<op>=(['+'|'-'])
| <group>
}
rule term {
<factor>+ %% $<op>=(['*'|'/'])
}
rule factor {
| <identifier>
| <value>
| <group>
}
rule group {
'(' <expression> ')'
}
token identifier {
(<:alpha>+)
}
token value {
(
| \d+['.' \d+]?
| '.' \d+
)
}
Action
Actions.pm6 的内容如下:
unit class Lang::Actions;
has %.var;
method assignment($/) {
%!var{$<identifier>} = $<expression>.ast;
}
method printout($/) {
say $<expression>.ast;
}
method expression($/) {
if $<group> {
$/.make: $<group>.ast
}
else {
my $result = $<term>[0].ast;
if $<op> {
my @ops = $<op>.map(~*);
my @vals = $<term>[1..*].map(*.ast);
for 0..@ops.elems - 1 -> $c {
if @ops[$c] eq '+' {
$result += @vals[$c];
}
else {
$result -= @vals[$c];
}
}
}
$/.make: $result;
}
}
method term($/) {
my $result = $<factor>[0].ast;
if $<op> {
my @ops = $<op>.map(~*);
my @vals = $<factor>[1..*].map(*.ast);
for 0..@ops.elems - 1 -> $c {
if @ops[$c] eq '*' {
$result *= @vals[$c];
}
else {
$result /= @vals[$c];
}
}
}
$/.make: $result;
}
method factor($/) {
if $<identifier> {
$/.make: %!var{~$<identifier>} // 0
}
elsif $<value> {
$/.make: $<value>.ast
}
elsif $<group> {
$/.make: $<group>.ast
}
}
method group($/) {
$/.make: $<expression>.ast
}
method identifier($/) {
$/.make: ~$0
}
method value($/) {
$/.make: +$0
}
解析
use lib '.';
use Lang::Grammar;
use Lang::Actions;
my $parsed = Lang::Grammar.parsefile(@*ARGS[0] // 'data/calc.lang', :actions(Lang::Actions.new()));
say $parsed;