Overview
Raku Module LR1 supports LR(1) syntax analysis.
License
Artistic-2.0
Usage
Import
use LR1;
Input grammars
LR1Yacc.set-grammar ( @lines )
@lines: yacc code lines.
Return LR1Yacc:D
LR(1) Analysis:
class LR1Yacc: method analysis()
Get Yacc Result:
class LR1Yacc: method get-actions-data() return Hash:D
Compile:
LR1Compiling.syntax-analysis($table, $src, $rank)
$table: The Yacc result
$src : Seq of tokens
$rank : rank action, callable
Make rank actions:
LR1Compiling.make-rank-actions
To make a callable from a actions dictionary.
Example
The example implements a simple calculator.
#!/usr/bin/env perl6
use v6;
use LR1;
use JSON::Fast;
my $p = LR1Yacc.set-grammar: q:to/EOF/.lines;
%levels = add mul
add = + -
mul = * /
expr -> expr + expr
%% This is a payload for 'expr -> expr + expr'
| expr - expr
| expr * expr
| expr / expr
| ( expr )
| n
| id
stmt -> print expr
| id "=" expr
stmts -> stmt
| stmts stmt
top -> stmts
EOF
$p.analysis;
my $data = $p.get-actions-data;
# to-json($data).say;
my $txt = q:to/END/;
a = 2 * (4+5)
c = 10 + 2*a
print c
END
grammar TXT {
rule TOP { <.ws> [ <tok> <.ws> ]* }
token tok { [<n> | <id> | <op> | <pr> ] }
token n { <digit>+ }
token id { <alpha> }
token pr { 'print' }
token op { ['+' | '-' | '*' | '/' | '(' | ')' | '='] }
}
class TXTAction {
has @.tokens;
method push($t, $s) {
@.tokens.push: lr1token($s.Str, :cata($t))
}
method n ($/) { self.push: 'n', $/ }
method id($/) { self.push: 'id', $/ }
method op($/) { self.push: $/.Str, $/ }
method pr($/) { self.push: $/.Str, $/ }
}
my $pp = TXTAction.new;
TXT.parse: $txt, actions => $pp;
class My_Actions {
has %.vars;
has $.rank is rw;
has @.values;
method make () {
my $act = %(
' ' => {
},
'expr -> expr + expr' => {
.payload.say;
@.values.push: @.values.pop + @.values.pop
},
'expr -> expr - expr' => {
my $a = @.values.pop;
@.values.push: @.values.pop - $a
},
'expr -> expr * expr' => {
my $a = @.values.pop;
@.values.push: @.values.pop * $a
},
'expr -> expr / expr' => {
my $a = @.values.pop;
@.values.push: @.values.pop / $a
},
'expr -> id' => {
my $var = %.vars{.syms[0]};
say "$var is not exist" if !$var;
@.values.push: $var
},
'expr -> n' => {
my $n = .syms[0];
@.values.push: $n.Int
},
'stmt -> print expr' => {
my $a = @.values.pop;
put "$a"
},
'stmt -> id = expr' => {
my $a = @.values.pop;
%.vars{.syms[0]} = $a;
put "set {.syms[0]} <= $a"
}
);
$.rank = LR1Compiling.make-rank-actions: $act;
$.rank
}
}
LR1Compiling.syntax-analysis: $data, $pp.tokens.iterator, My_Actions.new.make;