Skip to content

Instantly share code, notes, and snippets.

@pstuifzand
Created March 14, 2012 21:34
Show Gist options
  • Save pstuifzand/2039694 to your computer and use it in GitHub Desktop.
Save pstuifzand/2039694 to your computer and use it in GitHub Desktop.
Parser built with Marpa::XS
use 5.10.1;
use strict;
use Marpa::XS;
my $grammar = Marpa::XS::Grammar->new({
actions => 'Action',
start => 'Parser',
rules => [
{ lhs => 'Parser', rhs => [ qw/Expression/ ], action => 'Parser' },
{ lhs => 'Expression', rhs => [qw/Term Plus Term/], action => 'Expression' },
{ lhs => 'Expression', rhs => [qw/Term/], action => 'Expression' },
{ lhs => 'Term', rhs => [qw/Factor Star Factor/], action => 'Term' },
{ lhs => 'Term', rhs => [qw/Factor/], action => 'Term' },
{ lhs => 'Factor', rhs => [qw/Number/], action => 'Number' },
],
terminals => [qw/Number Plus Star/],
});
sub Action::Parser {
my (undef, $expr) = @_;
return $expr;
}
sub Action::Expression {
my (undef, $left, undef, $right) = @_;
if ($right) {
return $left + $right;
}
return $left;
}
sub Action::Term {
my (undef, $left, undef, $right) = @_;
if ($right) {
return $left * $right;
}
return $left;
}
sub Action::Number {
my (undef, $number) = @_;
return $number;
}
$grammar->precompute;
my %tokens = (
Number => qr/^\d+/,
Plus => qr/^\+/,
Star => qr/^\*/,
);
my $line = <>;
my $r = Marpa::XS::Recognizer->new({
grammar => $grammar,
});
while (length($line)) {
$line =~ s/^\s+//;
for my $token_name (@{$r->terminals_expected}) {
my $re = $tokens{$token_name};
my (@res) = ($line=~m/^($re)/);
if (@res) {
defined $r->alternative($token_name, $res[0], 1)
or next;
$line = substr $line, length($res[0]);
my $ok = eval {
$r->earleme_complete;
1;
};
if (!$ok) {
die "Error";
}
}
}
}
$r->end_input;
say ${$r->value};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment