Help language development. Donate to The Perl Foundation
Raku Module LR1 supports LR(1) syntax analysis.
Artistic-2.0
Import
dummy
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.
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;