##
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) to 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 ; print 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
####
$VAR1 = bless( {
'_AUTOTREE' => undef,
'rules' => {
'assign_instruction' => bless( {
'impcount' => 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{VARIABLE}} = $item{expression} }',
'hashname' => '__ACTION1__',
'lookahead' => 0
}, 'Parse::RecDescent::Action' )
],
'actcount' => 1
}, 'Parse::RecDescent::Production' )
],
'calls' => [
'VARIABLE',
'expression'
],
'opcount' => 0,
'changed' => 0,
'vars' => '',
'name' => 'assign_instruction'
}, 'Parse::RecDescent::Rule' ),
'instruction' => bless( {
'impcount' => 0,
'line' => '36',
'prods' => [
bless( {
'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' ),
bless( {
'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' ),
bless( {
'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' => 'instruction'
}, 'Parse::RecDescent::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::Rule' ),
'startrule' => bless( {
'impcount' => 0,
'line' => '40',
'prods' => [
bless( {
'dircount' => 1,
'uncommit' => undef,
'op' => [],
'patcount' => 1,
'strcount' => 0,
'number' => 0,
'error' => undef,
'line' => undef,
'items' => [
bless( {
'expected' => '',
'rightarg' => bless( {
'line' => '40',
'subrule' => 'instruction',
'argcode' => undef,
'implicit' => undef,
'matchrule' => 0,
'lookahead' => 0
}, 'Parse::RecDescent::Subrule' ),
'min' => 1,
'max' => 100000000,
'op' => bless( {
'description' => '/;/',
'pattern' => ';',
'mod' => '',
'hashname' => '__PATTERN1__',
'lookahead' => 0,
'ldelim' => '/',
'line' => '40',
'rdelim' => '/'
}, 'Parse::RecDescent::Token' ),
'hashname' => '__DIRECTIVE1__',
'leftarg' => bless( {
'line' => '40',
'subrule' => 'instruction',
'argcode' => undef,
'implicit' => undef,
'matchrule' => 0,
'lookahead' => 0
}, 'Parse::RecDescent::Subrule' ),
'type' => 'leftop'
}, 'Parse::RecDescent::Operator' )
],
'actcount' => 0
}, 'Parse::RecDescent::Production' )
],
'calls' => [
'instruction'
],
'opcount' => 0,
'changed' => 0,
'vars' => '',
'name' => 'startrule'
}, 'Parse::RecDescent::Rule' ),
'VARIABLE' => bless( {
'impcount' => 0,
'line' => '6',
'prods' => [
bless( {
'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' => 'VARIABLE'
}, 'Parse::RecDescent::Rule' ),
'print_instruction' => bless( {
'impcount' => 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( {
'impcount' => 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'
],
'opcount' => 0,
'changed' => 0,
'vars' => '',
'name' => 'myprint_instruction'
}, 'Parse::RecDescent::Rule' ),
'expression' => bless( {
'impcount' => 0,
'line' => '7',
'prods' => [
bless( {
'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' ),
bless( {
'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' ),
bless( {
'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' ),
bless( {
'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{VARIABLE}} }',
'hashname' => '__ACTION1__',
'lookahead' => 0
}, 'Parse::RecDescent::Action' )
],
'actcount' => 1
}, 'Parse::RecDescent::Production' )
],
'calls' => [
'INTEGER',
'OP',
'expression',
'VARIABLE'
],
'opcount' => 0,
'changed' => 0,
'vars' => '',
'name' => 'expression'
}, 'Parse::RecDescent::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' => [
'INTEGER'
],
'opcount' => 0,
'changed' => 0,
'vars' => '',
'name' => 'range'
}, 'Parse::RecDescent::Rule' ),
'INTEGER' => bless( {
'impcount' => 0,
'line' => '5',
'prods' => [
bless( {
'dircount' => 0,