Raku Land

LR1

zef:codechurch

Overview

Raku Module LR1 supports LR(1) syntax analysis.

License

Artistic-2.0

Usage

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;