Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Breaking The Rules II

by Rhandom (Curate)
on Jul 02, 2007 at 15:36 UTC ( #624487=note: print w/ replies, xml ) Need Help??


in reply to Breaking The Rules II

There are a few other options to place under existing wheels. Each of the mini-language based templating languages have expression parsing. Unfortunately most of the expression parsing isn't abstracted. There is at least one though, Template::Alloy (formerly known as CGI::Ex::Template) that does abstract the parsing of expressions, functions and operators. It does allow adding variables, functions, and custom operators.

It seems that the point of your node was to show various attempts to get a working grammar going - more as an exercise. In that case, Template::Alloy is sort of besides the point. But if you were just wanting to find an existing parser that would work for your use case, then maybe it would help.

I'm looking forward to Perl 6 and being able to use the existing grammar to parse expressions. I'll be interested to see how easy it will be to translate the parse tree into an easier to use AST.

#!/usr/bin/perl use Template::Alloy; my $ta = Template::Alloy->new; $ta->_vars->{'func'} = sub { local $" = ', '; "You passed me (@_)" }; $ta->_vars->{'a'} = 3; $ta->_vars->{'b'} = 4; $ta->define_operator({ type => 'left', # actually associativiy precedence => 85, # same as '+' in $Template::Alloy::OPERATOR +S table symbols => ['+++'], play_sub => sub { int($_[0]) + int($_[1]) }, }); for my $expr ( '1 + 2', '1 + 2 * 3', '(1 + 2) * 3', '2.7e+10 * 3.0e-9', # scientific 'a + b', # variables 'func(1 + 2, 3)', # functions '1.2 +++ 3.4 * 2', # custom ops '1 ? 2 : 3', 'a + (b', '3 + 4 foobar', ) { my $copy = $expr; print "--------------------\n"; print "- expr: $expr\n"; print "- outp: ".eval{ $ta->play_expr($ta->parse_expr(\$copy)) }." +\n"; if ($@) { print "- err : $@\n"; } else { print "- err : Failed to consume entire string\n" if pos $copy + != length $expr; print "- tree: ".Template::Alloy->dump_parse_expr(\$expr)."\n" +; } }

Prints:
-------------------- - expr: 1 + 2 - outp: 3 - tree: [[undef, '+', 1, 2], 0] -------------------- - expr: 1 + 2 * 3 - outp: 7 - tree: [[undef, '+', 1, [[undef, '*', 2, 3], 0]], 0] -------------------- - expr: (1 + 2) * 3 - outp: 9 - tree: [[undef, '*', [[undef, '+', 1, 2], 0], 3], 0] -------------------- - expr: 2.7e+10 * 3.0e-9 - outp: 81 - tree: [[undef, '*', 27000000000, '3e-09'], 0] -------------------- - expr: a + b - outp: 7 - tree: [[undef, '+', ['a', 0], ['b', 0]], 0] -------------------- - expr: func(1 + 2, 3) - outp: You passed me (3, 3) - tree: ['func', [[[undef, '+', 1, 2], 0], 3]] -------------------- - expr: 1.2 +++ 3.4 * 2 - outp: 7 - tree: [[undef, '+++', '1.2', [[undef, '*', '3.4', 2], 0]], 0] -------------------- - expr: 1 ? 2 : 3 - outp: 2 - tree: [[undef, '?', 1, 2, 3], 0] -------------------- - expr: a + (b - outp: - err : parse.missing.paren error - Missing close ) in group (At char +6) -------------------- - expr: 3 + 4 foobar - outp: 7 - err : Failed to consume entire string - tree: [[undef, '+', 3, 4], 0]


my @a=qw(random brilliant braindead); print $a[rand(@a)];


Comment on Re: Breaking The Rules II
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://624487]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2014-08-23 17:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (175 votes), past polls