public
Created

  • Download Gist
lex-easy.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
package Math::Parser;
use strict;
use warnings;
use Method::Signatures::Simple;
use Marpa::R2 2.026;
use MarpaX::Lex::Easy;
 
my $grammar = Marpa::R2::Grammar->new({
actions => 'Math::Parser::Actions',
start => 'Expression',
rules => q{
Expression ::= NUMBER action => number
| (LPAREN) Expression (RPAREN) action => parens assoc => group
|| Expression (ASTERISK) Expression action => multiply
| Expression (SLASH) Expression action => divide
|| Expression (PLUS) Expression action => add
| Expression (MINUS) Expression action => subtract
},
});
$grammar->precompute;
print $grammar->show_rules;
 
my %tokens = (
'LPAREN' => [ qr/\G[(]/ ],
'RPAREN' => [ qr/\G[)]/ ],
'ASTERISK' => [ qr/\G[*]/ ],
'SLASH' => [ qr/\G[\/]/ ],
'PLUS' => [ qr/\G[+]/ ],
'MINUS' => [ qr/\G[-]/ ],
'NUMBER' => [ qr/\G([-+]?[0-9.]+(?:e[+-]?[0-9]+)?)/, sub { 0 + $1 } ],
);
 
method parse_line ($line) {
my $rec = Marpa::R2::Recognizer->new({
grammar => $grammar,
ranking_method => 'rule',
trace_terminals => 1,
trace_actions => 1,
trace_values => 1,
});
 
my $lex = MarpaX::Lex::Easy->new(
tokens => \%tokens,
recognizer => $rec,
automatic_whitespace => 1,
whitespace_pattern => qr/\G\s+/,
);
 
return $lex->read_and_parse($line);
 
}
 
package Math::Parser::Actions;
 
sub parens {
return $_[1];
}
 
sub multiply {
return $_[1] * $_[2];
}
 
sub divide {
return $_[1] / $_[2];
}
 
sub add {
return $_[1] + $_[2];
}
 
sub subtract {
return $_[1] - $_[2];
}
 
sub number {
return $_[1];
}
 
package main;
while (<>) {
chomp;
print Math::Parser->parse_line($_), "\n";
}
scanless.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
package Math::Parser;
use strict;
use warnings;
use Method::Signatures::Simple;
use Marpa::R2 2.026;
 
my $grammar = Marpa::R2::Scanless::G->new({
action_object => 'Math::Parser::Actions',
source => \q{
:start ::= Expression
 
Expression ::= NUMBER action => number
| ('(') Expression (')') action => parens assoc => group
|| Expression ('*') Expression action => multiply
| Expression ('/') Expression action => divide
|| Expression ('+') Expression action => add
| Expression ('-') Expression action => subtract
 
NUMBER ~ SIGN FLOATING EXPONENT
SIGN ~ [-+]
SIGN ~
FLOATING ~ [0-9.]+
EXPONENT ~ 'e' SIGN DIGITS
EXPONENT ~
DIGITS ~ [0-9]+
 
:discard ~ WS
WS ~ [\s]+
},
});
print $grammar->show_rules;
 
method parse_line ($line) {
my $rec = Marpa::R2::Scanless::R->new({
grammar => $grammar,
trace_terminals => 1,
trace_values => 1,
});
 
$rec->read(\$line);
my $value = $rec->value;
if (defined $value) {
return $$value;
} else {
die "Parse error";
}
}
 
package Math::Parser::Actions;
 
# I really just wanted actions, not action_object ;)
sub new {
return bless {};
}
 
sub parens {
return $_[1];
}
 
sub multiply {
return $_[1] * $_[2];
}
 
sub divide {
return $_[1] / $_[2];
}
 
sub add {
return $_[1] + $_[2];
}
 
sub subtract {
return $_[1] - $_[2];
}
 
sub number {
return $_[1];
}
 
package main;
while (<>) {
chomp;
print Math::Parser->parse_line($_), "\n";
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.