Skip to content

Instantly share code, notes, and snippets.

@yusukebe
Last active January 26, 2020 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yusukebe/e51dfcc3d876bab011c7dc70a3226d15 to your computer and use it in GitHub Desktop.
Save yusukebe/e51dfcc3d876bab011c7dc70a3226d15 to your computer and use it in GitHub Desktop.
# (ほぼ)mattnさんのコードまんまです
# https://mattn.kaoriya.net/software/lang/perl6/20151019183138.htm
grammar Shoboi::Grammar {
token num { <[0..9]> + }
token ident { <[a..z]> + }
token op { '+' || '-' || '*' || '/' }
token exp { <ident> || <num> }
token expr { <exp> | <exp> \s* <op> \s* <exp> }
token let { <ident> \s* '=' \s* <expr> }
token call { <ident> '(' \s* <expr> \s* ')' }
token stmt { <call> || <let> }
rule TOP { ^ ( <stmt> || ";" ) * $ }
}
class Shoboi::Action {
my Hash $func = {
print => sub ($arg) {
say $arg;
}
}
my Hash $vars;
method num($/) { make $/.Str }
method ident($/) {
make $vars{$/.Str}
}
method call($/) {
make $func{$<ident>.Str}(self.expr($<expr>));
}
method let($/) {
my $v = self.expr($<expr>);
$vars{$<ident>.Str} = $v;
make $v;
}
method expr($/) {
given $<op> {
when '+' { make [+]($<exp>>>.made) }
when '-' { make [-]($<exp>>>.made) }
when '*' { make [*]($<exp>>>.made) }
when '/' { make [/]($<exp>>>.made) }
default { make $<exp>>>.made[0] }
}
}
method exp($/) {
make $/.values[0].made;
}
method TOP($/) {
make $<exp>.made;
}
}
my $src = "a = 1; a = a+2; print(a)";
Shoboi::Grammar.parse($src, actions => Shoboi::Action.new);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment