anne2011
asked on
Please help a RecDescent grammer if statement problem!
If my code is correct, I should be able to see %tree be dumped.
But it is not working and I have no idea where is wrong.
I am not sure if the 'expression' and 'if_statement' is in correct grammar.
Please help!
============== input file (only 1 line as below) ===============
if ( x == "on" ) endif
But it is not working and I have no idea where is wrong.
I am not sure if the 'expression' and 'if_statement' is in correct grammar.
Please help!
============== input file (only 1 line as below) ===============
if ( x == "on" ) endif
#!/usr/local/bin/perl
#
if ($#ARGV < 0) {
print "Usage: $0 file\n";
exit 0;
}
use lib ".../Parse-RecDescent-1.965001/lib";
use Data::Dumper;
use strict;
use warnings;
use Parse::RecDescent;
my $file=$ARGV[0];
# $::RD_HINT=0;
if(defined $ARGV[1]) {
$::RD_TRACE=$ARGV[1];
}
my $g=<<'EndG';
<autoaction: {[@item]}>
template_file : statement(s?) EOF
{ print "MATCH!\n";
%::tree = %item;
}
expr : '!' expr
| '(' expr ')'
expression : expr unary_operator expression
| expr
statement : if_statement
| EOL
set_statement : 'set' scalar_variable '=' expression ';' EOL
if_statement : 'if' <commit> '(' expression ')' <commit> statement(s) else_statement(s)
# else_statement : 'elsif' '(' expression ')' statement(s) else_statement
# | 'else' statement(s) 'endif'
# | 'endif'
else_statement : 'endif'
unary_operator: '==' | '!=' | '<=' | '=' | '<' | '>'
scalar_variable : IDENTIFIER
command_argument_list : command_argument ',' command_argument_list
| command_argument
command_argument : INTEGER
| QUOTED_STRING | IDENTIFIER
INTEGER : /[-]?[0-9]+/
IDENTIFIER : /[a-zA-Z_][a-zA-Z0-9_]*/
QUOTED_STRING : /["][^"\n]+["]/
EOL : '\n'
EOF : /\s*\Z/
empty : ""
EndG
my %tree = ();
my $parse = new Parse::RecDescent $g or die "invalid grammar";
undef $/;
open(FILE, "<$file") || die $!;
my $lines=<FILE>;
close FILE;
$parse->template_file($lines);
print Data::Dumper->Dump([\%::tree], ["*tree"]);
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Dear,
I think something I did not figure out with $/ and \n
If I use :
#undef $/;
my $lines=join("___EOL___", <FILE>);
with:
EOL : /___EOL___/
It will work.
But if I use :
my $lines=join("", <FILE>);
with:
EOL : /\n/
It is not working. Why? I think '\n' is still there inside $lines.
I think something I did not figure out with $/ and \n
If I use :
#undef $/;
my $lines=join("___EOL___", <FILE>);
with:
EOL : /___EOL___/
It will work.
But if I use :
my $lines=join("", <FILE>);
with:
EOL : /\n/
It is not working. Why? I think '\n' is still there inside $lines.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Dear,
I got it! Thank you!
Now I think I am stuck at the QUOTED_STRING rule
my $g=<<'EndG';
template_file : <skip: qr/[ \t]*/> statement(s?) EOF
statement : QUOTED_STRING ';' EOL
| EOL
QUOTED_STRING : /["][^"\n]+["]/
EOL : /\n/
EOF : /^\Z/
EndG
But it could not match if a \" is there :
"\"" ;
I got it! Thank you!
Now I think I am stuck at the QUOTED_STRING rule
my $g=<<'EndG';
template_file : <skip: qr/[ \t]*/> statement(s?) EOF
statement : QUOTED_STRING ';' EOL
| EOL
QUOTED_STRING : /["][^"\n]+["]/
EOL : /\n/
EOF : /^\Z/
EndG
But it could not match if a \" is there :
"\"" ;
/"(\\.|[^"\n])*"/
ASKER
Dear,
Thanks! The QUOTE_STRING now is working!!!
Back to the if_statement, now simple expression could be matched, but not all expressions.
Since the original BNF will have left-recursive problem, I do not know how to rewrite it without left-recursive.
With my trial, if_statement will work only when there are no parentheses inside:
Working:
if ( getstr(A) )
endif
if (C == 1 & A==3)
endif
Not working:
if ( getstr(A) == "hello" )
endif
if ((C == 1) & A==3)
endif
my $g=<<'EndG';
<autoaction: { bless \%item, $item{__RULE__} }>
template_file : <skip: qr/[ \t]*/> statement(s?) EOF
statement : if_statement
| EOL
| <error>
#I tried to solve left recursive error...
expr : command_argument
expression : expr '+' expression
| expr '-' expression
| expr '*' expression
| expr '/' expression
| expr '%' expression
| expr '&' expression
| expr '|' expression
| expr '^' expression
| '!' expression
| expr '==' expression
| expr '!=' expression
| expr '<=' expression
| expr '>=' expression
| expr '<' expression
| expr '>' expression
| function_name '(' command_argument_list ')'
| '(' expression ')'
| expr
function_name : 'getstr'
command_argument_list : command_argument ',' command_argument_list
| command_argument
if_statement : 'if' <commit> '(' expression ')' <commit> statement(s?) else_statement
else_statement : 'elsif' '(' expression ')' statement(s?) else_statement
| 'else' statement(s?) 'endif'
| 'endif'
command_argument : INTEGER | QUOTED_STRING | IDENTIFIER
IDENTIFIER : /[a-zA-Z_][a-zA-Z0-9_]*/
INTEGER : /[-]?[0-9]+/
QUOTED_STRING : /"(\\"|[^"\n]*)"/
EOL : /\n/
EOF : /^\Z/
EndG
expr : command_argument
| '(' expression ')'
| '(' expression ')'
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Dear my idol,
one_variable : scalar_variable | declare_array_variable
scalar is ok. But b and c with array_dimension could not be matched.
Is something still incorrect with the expression?
a
b[2]
c[1][2]
one_variable : scalar_variable | declare_array_variable
scalar is ok. But b and c with array_dimension could not be matched.
Is something still incorrect with the expression?
a
b[2]
c[1][2]
my $g=<<'EndG';
<autoaction: { bless \%item, $item{__RULE__} }>
template_file : <skip: qr/[ \t]*/> statement(s?) EOF
| <error>
statement : one_variable EOL
| EOL
expression : expr '+' expression
| expr '-' expression
| expr '*' expression
| expr '/' expression
| expr '%' expression
| expr '&' expression
| expr '|' expression
| expr '^' expression
| '!' expression
| expr '==' expression
| expr '!=' expression
| expr '<=' expression
| expr '>=' expression
| expr '<' expression
| expr '>' expression
| function_name '(' command_argument_list ')'
| '(' expression ')'
| command_argument
| expr
| <error>
expr : function_name '(' command_argument_list ')'
| '(' expression ')'
| command_argument
function_name : 'getArrayNoOfDimensions'
| 'getArraySize'
| 'getI'
command_argument : INTEGER
| FLOATING_POINT
| QUOTED_STRING | IDENTIFIER | set_array_variable
command_argument_list : command_argument ',' command_argument_list
| command_argument
one_variable : scalar_variable
| declare_array_variable
scalar_variable : IDENTIFIER
declare_array_variable : IDENTIFIER declare_array_dimension(s)
declare_array_dimension : '[' expression ']'
| '[' ']'
set_array_variable : IDENTIFIER set_array_dimension(s)
set_array_dimension : '[' expression ']'
IDENTIFIER : /[a-zA-Z_][a-zA-Z0-9_]*/
INTEGER : /[-]?[0-9]+/
FLOAT_SIMPLE : /[\+]?[0-9]*.[0-9]+/
FLOAT_SCIENTIFIC : /[\+]?[0-9]+(.[0-9]+)?[eE][\+]?[0-9]+/
FLOATING_POINT : FLOAT_SIMPLE|FLOAT_SCIENTIFIC
QUOTED_STRING : '"' quoted_char(s?) '"'
quoted_char: /[^(?:\\(?="))]+/
| /\\n/ { "\n" }
| /\\"/ { "\"" }
EOL : /\n/
EOF : /^\Z/
EndG
ASKER
Dear,
Thank you for solving my question.
Thank you for solving my question.
ASKER
Thanks a lot. I have corrected x and "on" problem.
For the EOL problem, please help to see below grammar.
I think something wrong with the 'EOL'
file content:
--------------------
set a = c;
set b = a;
---------------------
The error message is :
Invalid stat: Was expecting EOL but found "set b = a;" instead
Open in new window