Help language development. Donate to The Perl Foundation

LR1 zef:codechurch last updated on 2022-02-23

1cdbead4a6cadcdbeecd5fcfbd5d09ff17b8bd2d/

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;