Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 354
  • Last Modified:

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






#!/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"]);

Open in new window

0
anne2011
Asked:
anne2011
  • 6
  • 5
3 Solutions
 
ozoCommented:
I don't see how x or "on" can be part of an expression

It also looks like an if_statement must contain EOL

0
 
anne2011Author Commented:
Dear Savant,

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


my $g=<<'EndG';

<autoaction: {[@item]}>
#<autoaction: { bless \%item, $item{__RULE__} }>

template_file : stat(s) EOF 

stat : 'set' scalar_variable '=' scalar_variable ';' EOL
        | EOL
        |<error>

scalar_variable : IDENTIFIER

IDENTIFIER : /[a-zA-Z_][a-zA-Z0-9_]*/

EOL : /\n/
EOF : /^\Z/

EndG

Open in new window

0
 
anne2011Author Commented:
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.

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ozoCommented:
the default
$Parse::RecDescent::skip
would skip \n
0
 
anne2011Author Commented:
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 :
"\"" ;


0
 
ozoCommented:
/"(\\.|[^"\n])*"/
0
 
anne2011Author Commented:

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

Open in new window

0
 
ozoCommented:
expr :  command_argument
        | '(' expression ')'
0
 
ozoCommented:
expr :  command_argument
        | '(' expression ')'
        | function_name '(' command_argument_list ')'
0
 
anne2011Author Commented:
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]


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

Open in new window

0
 
anne2011Author Commented:
Dear,
Thank you for solving my question.
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now