crazyinsomniac has asked for the wisdom of the Perl Monks concerning the following question:
It is not working as I think it should, as illustrated by the program below, and its output (provided in readmore tags).
Any insight would be appreciated.
PS- I am writing a parser for !SCALASCRIPT, which is a pretty damn well structured , but and I'm making progress, but this is one thing tripping me up, and until I pass this hurdle, I cannot go on to muck with !SCALASCRIPT.
#!/usr/bin/perl -w use strict; use Parse::RecDescent; use Data::Dumper; use vars qw(%VARIABLE); # Enable warnings within the Parse::RecDescent module. $::RD_ERRORS = 1; # Make sure the parser dies when it encounters an er +ror $::RD_WARN = 1; # Enable warnings. This will warn on unused rules &c +. $::RD_HINT = 1; # Give out hints to help fix problems. my $grammar = <<'_EOGRAMMAR_'; # Terminals (macros that can't expand further) # OP : m([-+*/%]) # Mathematical operators INTEGER : /[-+]?\d+/ # Signed integers VARIABLE : /\w[a-z0-9_]*/i # Variable expression : INTEGER OP expression { return &::expression(@item) } | VARIABLE OP expression { return &::expression(@item) } | INTEGER | VARIABLE { return $::VARIABLE{$item{VARIABLE}} }
print_instruction : /print/i expression { use Data::Dumper; print Dumper \%item; print $item{expression}."\n" } assign_instruction : VARIABLE "=" expression { $::VARIABLE{$item{VARIABLE}} = $item{expression +} } myprint_instruction: 'print(' expression ')' # I want print(1+1) t +o work { print $item{expression}."\n" } range: '(' INTEGER '..' INTEGER ')' { print "Gosh darn, $item{INTEGER}\n"; } instruction : myprint_instruction | assign_instruction | print_instruction startrule: instruction(s /;/) # multiple instructions, separated by +; _EOGRAMMAR_ sub expression { shift; my ($lhs,$op,$rhs) = @_; $lhs = $VARIABLE{$lhs} if $lhs=~/[^-+0-9]/; return eval "$lhs $op $rhs"; } my $parser = Parse::RecDescent->new($grammar); print "a=2\n"; $parser->startrule("a=2"); print "a=1+3\n"; $parser->startrule("a=1+3"); print "print 5*7\n"; $parser->startrule("print 5*7"); print "print 2/4\n"; $parser->startrule("print 2/4"); print "print 2+2/4\n"; $parser->startrule("print 2+2/4"); print "print 2+-2/4\n"; $parser->startrule("print 2+-2/4"); print "a = 5 ; print a\n"; $parser->startrule("a = 5 ; print a"); print "a = 69 ; print(a)\n"; $parser->startrule("a = 69 ; print(a)"); +# WTF??? print "a = 69 ; print a ; print(a)\n"; $parser->startrule("a = 69 ; pr +int a ; print(a)"); # WTF??? print "print( 6 + 9 )\n"; $parser->myprint_instruction("print( 6 + 9 ) +"); # WTF?? print "print(69)\n"; $parser->myprint_instruction("print(69)"); # ok print "print(69)\n"; $parser->startrule("print(69)"); # ok print "(4..9)\n"; $parser->range("(4..4)"); # ok print Dumper $parser; __END__ a=2 a=1+3 print 5*7 $VAR1 = { 'expression' => 35, '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 35 print 2/4 $VAR1 = { 'expression' => '0.5', '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 0.5 print 2+2/4 $VAR1 = { 'expression' => '2.5', '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 2.5 print 2+-2/4 $VAR1 = { 'expression' => '1.5', '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 1.5 a = 5 ; print a $VAR1 = { 'expression' => '5', '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 5 a = 69 ; print(a) a = 69 ; print a ; print(a) $VAR1 = { 'expression' => '69', '__PATTERN1__' => 'print', '__RULE__' => 'print_instruction' }; 69 print( 6 + 9 ) print(69) 69 print(69) 69 (4..9) God damn, 4
(Editor note Masem - breaking the output here to make the first part pretty-printed -- the D::D of the parser is not complete)
$VAR1 = bless( { '_AUTOTREE' => undef, 'rules' => { 'assign_instruction' => bless( { 'impcou +nt' => 0, 'line' +=> '24', 'prods' + => [ + bless( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 1, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'line' => '24', + 'subrule' => 'VARIABLE', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'description' => '\'=\'', + 'line' => '24', + 'pattern' => '=', + 'hashname' => '__STRING1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::InterpLit' +), + bless( { + 'line' => '24', + 'subrule' => 'expression', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '25', + 'code' => '{ $::VARIABLE{$item{V +ARIABLE}} = $item{expression} }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ) + ], 'calls' + => [ + 'VARIABLE', + 'expression' + ], 'opcoun +t' => 0, 'change +d' => 0, 'vars' +=> '', 'name' +=> 'assign_instruction' }, 'Parse +::RecDescent::Rule' ), 'instruction' => bless( { 'impcount' => +0, 'line' => '36' +, 'prods' => [ b +less( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'line' => '36', + 'subrule' => 'myprint_instruction', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ), b +less( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 1, + 'error' => undef, + 'line' => '37', + 'items' => [ + bless( { + 'line' => '37', + 'subrule' => 'assign_instruction', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ), b +less( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 2, + 'error' => undef, + 'line' => '38', + 'items' => [ + bless( { + 'line' => '38', + 'subrule' => 'print_instruction', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ) ], 'calls' => [ ' +myprint_instruction', ' +assign_instruction', ' +print_instruction' ], 'opcount' => 0 +, 'changed' => 0 +, 'vars' => '', 'name' => 'ins +truction' }, 'Parse::RecDe +scent::Rule' ), 'OP' => bless( { 'impcount' => 0, 'line' => '3', 'prods' => [ bless( { ' +dircount' => 0, ' +uncommit' => undef, ' +patcount' => 1, ' +strcount' => 0, ' +number' => 0, ' +error' => undef, ' +line' => undef, ' +items' => [ + bless( { + 'description' => 'm([-+*/%])', + 'pattern' => '[-+*/%]', + 'mod' => '', + 'hashname' => '__PATTERN1__', + 'lookahead' => 0, + 'ldelim' => '(', + 'line' => '5', + 'rdelim' => ')' + }, 'Parse::RecDescent::Token' ) + ], ' +actcount' => 0 }, +'Parse::RecDescent::Production' ) ], 'calls' => [], 'opcount' => 0, 'changed' => 0, 'vars' => '', 'name' => 'OP' }, 'Parse::RecDescent::Ru +le' ), 'startrule' => bless( { 'impcount' => 0, 'line' => '40', 'prods' => [ ble +ss( { + 'dircount' => 1, + 'uncommit' => undef, + 'op' => [], + 'patcount' => 1, + 'strcount' => 0, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'expected' => '<leftop: instruction /;/ i +nstruction>', + 'rightarg' => bless( { + 'line' => '40', + 'subrule' => 'inst +ruction', + 'argcode' => undef +, + 'implicit' => unde +f, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescen +t::Subrule' ), + 'min' => 1, + 'max' => 100000000, + 'op' => bless( { + 'description' => '/;/', + 'pattern' => ';', + 'mod' => '', + 'hashname' => '__PATTERN +1__', + 'lookahead' => 0, + 'ldelim' => '/', + 'line' => '40', + 'rdelim' => '/' + }, 'Parse::RecDescent::Tok +en' ), + 'hashname' => '__DIRECTIVE1__', + 'leftarg' => bless( { + 'line' => '40', + 'subrule' => 'instr +uction', + 'argcode' => undef, + 'implicit' => undef +, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent +::Subrule' ), + 'type' => 'leftop' + }, 'Parse::RecDescent::Operator' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ) ], 'calls' => [ 'in +struction' ], 'opcount' => 0, 'changed' => 0, 'vars' => '', 'name' => 'start +rule' }, 'Parse::RecDesc +ent::Rule' ), 'VARIABLE' => bless( { 'impcount' => 0, 'line' => '6', 'prods' => [ bles +s( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 1, + 'strcount' => 0, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'description' => '/\\\\w[a-z0-9_]*/i', + 'pattern' => '\\w[a-z0-9_]*', + 'mod' => 'i', + 'hashname' => '__PATTERN1__', + 'lookahead' => 0, + 'ldelim' => '/', + 'line' => '7', + 'rdelim' => '/' + }, 'Parse::RecDescent::Token' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ) ], 'calls' => [], 'opcount' => 0, 'changed' => 0, 'vars' => '', 'name' => 'VARIAB +LE' }, 'Parse::RecDesce +nt::Rule' ), 'print_instruction' => bless( { 'impcoun +t' => 0, 'line' = +> '17', 'prods' +=> [ + bless( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 1, + 'strcount' => 0, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'description' => '/print/i', + 'pattern' => 'print', + 'mod' => 'i', + 'hashname' => '__PATTERN1__', + 'lookahead' => 0, + 'ldelim' => '/', + 'line' => '17', + 'rdelim' => '/' + }, 'Parse::RecDescent::Token' ), + bless( { + 'line' => '17', + 'subrule' => 'expression', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '18', + 'code' => '{ use Data::Dumper; print Dumper \\%item; print $item{expression}."\\n" }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ) + ], 'calls' +=> [ + 'expression' + ], 'opcount +' => 0, 'changed +' => 0, 'vars' = +> '', 'name' = +> 'print_instruction' }, 'Parse: +:RecDescent::Rule' ), 'myprint_instruction' => bless( { 'impco +unt' => 0, 'line' + => '26', 'prods +' => [ + bless( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 2, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'description' => '\'print(\'', + 'line' => '26', + 'pattern' => 'print(', + 'hashname' => '__STRING1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Literal' ) +, + bless( { + 'line' => '26', + 'subrule' => 'expression', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ) +, + bless( { + 'description' => '\')\'', + 'line' => '26', + 'pattern' => ')', + 'hashname' => '__STRING2__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Literal' ) +, + bless( { + 'line' => '26', + 'code' => '{ print $item{expression}."\\n" }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ) + ], 'calls +' => [ + 'expression' + ], 'opcou +nt' => 0, 'chang +ed' => 0, 'vars' + => '', 'name' + => 'myprint_instruction' }, 'Pars +e::RecDescent::Rule' ), 'expression' => bless( { 'impcount' => 0 +, 'line' => '7', 'prods' => [ bl +ess( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'line' => '9', + 'subrule' => 'INTEGER', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '9', + 'subrule' => 'OP', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '9', + 'subrule' => 'expression', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '10', + 'code' => '{ return &::expression(@item) + }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ), bl +ess( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 1, + 'error' => undef, + 'line' => '11', + 'items' => [ + bless( { + 'line' => '11', + 'subrule' => 'VARIABLE', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '11', + 'subrule' => 'OP', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '11', + 'subrule' => 'expression', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '12', + 'code' => '{ return &::expression(@item) + }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ), bl +ess( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 2, + 'error' => undef, + 'line' => '13', + 'items' => [ + bless( { + 'line' => '13', + 'subrule' => 'INTEGER', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ) + ], + 'actcount' => 0 + }, 'Parse::RecDescent::Production' ), bl +ess( { + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 0, + 'number' => 3, + 'error' => undef, + 'line' => '14', + 'items' => [ + bless( { + 'line' => '14', + 'subrule' => 'VARIABLE', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'line' => '15', + 'code' => '{ return $::VARIABLE{$item{VA +RIABLE}} }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 + }, 'Parse::RecDescent::Production' ) ], 'calls' => [ 'I +NTEGER', 'O +P', 'e +xpression', 'V +ARIABLE' ], 'opcount' => 0, 'changed' => 0, 'vars' => '', 'name' => 'expr +ession' }, 'Parse::RecDes +cent::Rule' ), 'range' => bless( { 'impcount' => 0, 'line' => '31', 'prods' => [ bless( +{ + 'dircount' => 0, + 'uncommit' => undef, + 'patcount' => 0, + 'strcount' => 3, + 'number' => 0, + 'error' => undef, + 'line' => undef, + 'items' => [ + bless( { + 'description' => '\'(\'', + 'line' => '31', + 'pattern' => '(', + 'hashname' => '__STRING1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Literal' ), + bless( { + 'line' => '31', + 'subrule' => 'INTEGER', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'description' => '\'..\'', + 'line' => '31', + 'pattern' => '..', + 'hashname' => '__STRING2__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Literal' ), + bless( { + 'line' => '31', + 'subrule' => 'INTEGER', + 'argcode' => undef, + 'implicit' => undef, + 'matchrule' => 0, + 'lookahead' => 0 + }, 'Parse::RecDescent::Subrule' ), + bless( { + 'description' => '\')\'', + 'line' => '31', + 'pattern' => ')', + 'hashname' => '__STRING3__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Literal' ), + bless( { + 'line' => '32', + 'code' => '{ print "God damn, $item{INTEGER}\\n"; }', + 'hashname' => '__ACTION1__', + 'lookahead' => 0 + }, 'Parse::RecDescent::Action' ) + ], + 'actcount' => 1 +}, 'Parse::RecDescent::Production' ) ], 'calls' => [ 'INTEGE +R' ], 'opcount' => 0, 'changed' => 0, 'vars' => '', 'name' => 'range' }, 'Parse::RecDescent: +:Rule' ), 'INTEGER' => bless( { 'impcount' => 0, 'line' => '5', 'prods' => [ bless +( { + 'dircount' => 0,
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Parse::RecDescent grammar and Parenthesis
by maverick (Curate) on Dec 17, 2001 at 13:29 UTC | |
by crazyinsomniac (Prior) on Dec 17, 2001 at 13:54 UTC | |
|
Re: Parse::RecDescent grammar and Parenthesis
by Masem (Monsignor) on Dec 17, 2001 at 19:32 UTC | |
|
Re: Parse::RecDescent grammar and Parenthesis
by ariels (Curate) on Dec 17, 2001 at 19:54 UTC | |
|
Re: Parse::RecDescent grammar and Parenthesis
by TheDamian (Vicar) on Dec 18, 2001 at 06:09 UTC | |
by Masem (Monsignor) on Dec 18, 2001 at 07:26 UTC | |
|
Re: Parse::RecDescent grammar and Parenthesis
by japhy (Canon) on Dec 17, 2001 at 19:56 UTC | |
|
(crazyinsomniac: thank you) Re: Parse::RecDescent grammar and Parenthesis
by crazyinsomniac (Prior) on Dec 18, 2001 at 07:23 UTC |