I am writing a parser with flex and bison and so far have these tokens for flex:
[ \t\n] ;
(x[0-9]+) {
yylval.var = strdup(yytext);
return VARIABLE;
}
~(x[0-9]+) {
yylval.var = strdup(yytext);
return NEG_VARIABLE;
}
[a-zA-Z0-9]+ {
yylval.name = strdup(yytext);
return NAME;
}
~[a-zA-Z0-9]+ {
yylval.name = strdup(yytext);
return NEG_NAME;
}
[\{\},\(\)] { return yytext[0];}
. ;
and these parse rules for bison are:
fol:
clauses {cout << "Done with file"<<endl;}
;
clauses:
clauses clause
| clause
;
clause:
startc terms endc
;
startc:
'{' {cout << "Bison found start of clause" << endl;}
;
endc:
'}' {cout << "Bison found end of clause" << endl;}
;
function:
NAME startfun endfun {cout << "Bison found a function " << $1 << endl;}
|NEG_NAME startfun endfun {cout << "Bison found a negative function " << $1 << endl;}
;
startfun:
'(' {cout << "Bison found start of params" << endl;}
;
endfun:
terms ')' {cout << "Bison found a function end" << endl;}
;
terms:
terms ',' term
| term
;
term:
VARIABLE {cout << "Bison found a variable "<< $1 << endl;}
| NEG_VARIABLE {cout << "Bison found a negative variable " << $1 << endl;}
| NAME {cout << "Bison found a constant " << $1 << endl;}
|function
;
Now it all works great except that when it parses a function it first parses the parameters
and parens and then gives me the function name at the end. I can work around this, but it makes my life harder since I am storing functions as disjoint sets and I would need to keep a list of the parameters until I can get the name of the function to create the root and then union them in instead of creating it directly.
Can anyone show me how to get Bison to give me the function name before the parameters? I have been trying for over an hour with no luck.
What do you mean by "give me the function name before the parameters"? Currently you don't print the function name until after you see the endfun and reduce the function rule, which is after the various parameter rules. The usual technique is to have the terms rules produce a list of things that can then be used in the function rule:
terms: terms ',' term { $$ = append_list($1, $3); }
| term { $$ = create_singleton_list($1); }
;
term: VARIABLE { $$ = new VariableTerm($1); }
...
Alternately, if you just want to print things out, you can have a rule that is reduced as soon as you see a function name:
function: funcname startfun endfun {cout << "Bison ending a function " << $1 << endl;}
;
funcname: NAME { cout << "Starting a function " << ($$ = $1) << endl; }
| NEGNAME { cout << "Starting a negative function " << ($$ = $1) << endl; }
;
Related
I am trying to build a parser that takes a list of strings in the following format and performs either an addition or multiplication of all of its elements :
prod 5-6_
sum _
sum 5_
sum 5-6-7_
$
Should print the following to the screen :
prod = 30
sum = 0
sum = 5
sum = 18
What I am actually getting as output is this :
prod = 0
sum = 0
sum = 5
sum = 5
My lex file looks like this :
%{
#include <iostream>
#include "y.tab.h"
using namespace std;
extern "C" int yylex();
%}
%option yylineno
digit [0-9]
integer {digit}+
operator "sum"|"prod"
%%
{integer} { return number; }
{operator} { return oper; }
"-" { return '-'; }
"_" { return '_'; }
"$" { return '$'; }
\n { ; }
[\t ]+ { ; }
. { cout << "unknown char" << endl; }
%%
and my yacc file looks like this :
%token oper
%token number
%token '-'
%token '_'
%token '$'
%start valid
%{
#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define YYSTYPE int
extern FILE *yyin;
extern char yytext[];
extern "C" int yylex();
int yyparse();
extern int yyerror(char *);
char op;
%}
%%
valid : expr_seq endfile {}
| {}
;
expr_seq : expr {}
| expr_seq expr {}
;
expr : op sequence nl {if (op == '+') cout << "sum = " ; else cout << "prod = ";}
| op nl {if (op == '+') cout << "sum = 0"; else cout <<"prod = 1";}
;
op : oper { if (yytext[0] == 's') op = '+'; else op = '*';}
;
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + $3; else $$ = $1 * $3;}
;
nl : '_' { cout << endl;}
;
endfile : '$' {}
;
%%
int main(int argc, char *argv[])
{
++argv, --argc;
if(argc > 0) yyin = fopen(argv[0], "r");
else yyin = stdin;
yyparse();
return 0;
}
int yyerror(char * msg)
{
extern int yylineno;
cerr << msg << "on line # " << yylineno << endl;
return 0;
}
My reasoning for the yacc logic is as follows :
a file is valid only if it contains a sequence of expressions followed by the endfile symbol.
a sequence of expressions is a single expression or several expressions.
an expression is either an operator followed by a new line, OR an operator, followed by a list of numbers, followed by a new line symbol.
an operator is either 'sum' or 'prod'
a list of numbers is either a number or several numbers separated by the '-' symbol.
From my perspective this should work, but for some reason it doesn't interpret the sequence of numbers properly after the first element. Any tips would be helpful.
Thanks
You must not use yytext in your yacc actions. yytext is only valid during a scanner action, and the parser often reads ahead to the next token. (In fact, yacc always reads the next token. Bison sometimes doesn't, but it's not always easily predictable.)
You can associate a semantic value with every token (and non-terminal), and you can reference these semantic values using $1, $2, etc. in your yacc actions. You can even associate semantic values of different types to different grammar symbols. And if you use bison -- and you probably are using bison -- you can give grammar symbols names to make it easier to refer to their semantic values.
This is all explained in depth, with examples, in the bison manual.
The solution that worked was simply to change the following lines :
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + $3; else $$ = $1 * $3;}
;
to this :
sequence : number { $$ = atoi(yytext);}
| sequence '-' number { if (op == '+') $$ = $1 + atoi(yytext); else $$ = $1 * atoi(yytext);}
;
I'm writing an application for an assignment that uses Flex and Bison to determine if a statement is valid or not. After detecting an error in a statement, I want to print an error message and move onto the next line to look at the next statement, but everything I'm trying doesn't work.
Researching online, Bison has a built in error token that can be used for error handling. By using error '\n' {yyerrok;}, I should be able to achieve what I want, but it isn't working.
My Flex code:
%{
#include <cstdio>
#include <iostream>
using namespace std;
#include "exp.tab.h" // to get the token types from Bison
%}
%%
--.* ;
[a-zA-Z][a-zA-Z0-9]* {yylval.print = strdup(yytext); return ID;}
;\s* {return EOL;}
[-+*/%] {yylval.print = strdup(yytext); return OP;}
= {return EQU;}
\( {return OPEN;}
\) {return CLOSE;}
[0-9] ;
\n ;
\r ;
. ;
%%
My Bison tokens and rules:
%union{
char *print;
}
%token EQU
%token <print> ID
%token EOL
%token <print> OP
%token OPEN
%token CLOSE
%%
lines: line
| lines line
;
line: ass {cout << " VALID" << endl;}
| exp {cout << " VALID" << endl;}
| error '\n' {yyerrok;}
;
ass: id EQU {cout << " ="; } exp EOL {cout << ";";}
;
exp: term
| exp op term
;
term: id
| OPEN {cout << "(";} exp op term CLOSE {cout << ")";}
;
id: ID {cout << $1; }
op: OP {cout << $1; }
%%
My yyerror() just prints "Error ".
My input for parsing:
-- Good (valid) statements:
first = one1 + two2 - three3 / four4 ;
second = one1 * (two2 * three3) ;
one1 * i8766e98e + bignum
second = (one1 * two2) * three3 ;
third = ONE + twenty - three3 ;
third = old * thirty2 / b567 ;
-- Bad (invalid) statements:
first = = one1 + two2 - three3 / four4 ;
first = one1 + - two2 - three3 / four4 ;
first = one1 + two2 - three3 / four4
first = one1 + two2 ? three3 / four4 ;
second = 4 + ( one1 * two2 ) * ( three3 + four4 ;
third = one1 + 24 - three3 ;
one1 +- delta
sixty6 / min = fourth ;
I'd expect the output to print an error then move to the next line
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error
first = one1 + Error
first = one1 + two2 - three3 / four4 Error
first = one1 + two2 Error
.
.
.
But when I run it, it just stops at the first Error printing
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error
Any help would be appreciated, but mostly I want to know why the error '\n' rule isn't working and what I can do to fix it.
Since your lexer ignores \n, telling the parser to skip tokens until it sees a newline will cause it to skip the rest of the file.
However, you can (almost) make this work by getting the lexer to recognise newline characters, but only during error recovery. (Check in the action for \n and either ignore it or send it.)
But that will occasionally produce odd results, because the token which produces the error might be on the next line, in which case the newline will already have been ignored before the error was detected. For example, here the problem is a missing semicolon:
a = 1
while (a > 0) {
…
But that error will only be detected after while has been read. (If the next token were, say, +, the parse should continue.) So skipping to the end of the line means continuing the parse at the third line, thus introducing an unbalanced brace.
Even so, it could be an interesting start.
Using '\n' isn't working because your lexer never returns '\n', so there will never be any '\n' tokens in the token stream. Basically if the lexer ignores certain characters, you can't use them in the parser in any way, including for error recovery.
So your two options would be to stop ignoring line breaks (probably a bad idea because then you'd have to mention them everywhere in the grammar where you want to allow line breaks) or to use some other token for error recovery. Skipping everything until the next semicolon would probably be a good alternative (though that still won't produce your expected output since not all of your lines end with semicolons).
I'm trying to compile the following with bisonc++:
%baseclass-preinclude <iostream>
%lsp-needed
%token NUMBER COMMENT KEYWORD VARIABLE LOGICAND LOGICOR LOGICEQUALS DOUBLELESSER
%token DOUBLEGREATER MOD LESSER GREATER OPEN CLOSE NEGATE CURLYOPEN CURLYCLOSE SEMICOLON
%left EQUALS
%left PLUS MINUS
%left TIMES
%left DIVISION
%%
start:
expressions
{
std::cout << "start -> expressions" << std::endl;
}
;
expressions:
// empty
{
std::cout << "expressions -> epsylon" << std::endl;
}
|
exp expressions
{
std::cout << "expressions -> exp expressions" << std::endl;
}
;
exp:
NUMBER
{
std::cout << "exp -> NUMBER" << std::endl;
}
|
COMMENT
{
std::cout << "exp -> COMMENT" << std::endl;
}
|
exp LOGICAND exp
{
std::cout << "exp -> exp LOGICAND exp" << std::endl;
}
|
exp LOGICOR exp
{
std::cout << "exp -> exp LOGICOR exp" << std::endl;
}
|
exp LOGICEQUALS exp
{
std::cout << "exp -> exp LOGICEQUALS exp" << std::endl;
}
|
exp DOUBLELESSER exp
{
std::cout << "exp -> exp DOUBLELESSER exp" << std::endl;
}
|
exp DOUBLEGREATER exp
{
std::cout << "exp -> exp DOUBLEGREATER exp" << std::endl;
}
|
exp PLUS exp
{
std::cout << "exp -> exp PLUS exp" << std::endl;
}
|
exp MINUS exp
{
std::cout << "exp -> exp MINUS exp" << std::endl;
}
|
exp TIMES exp
{
std::cout << "exp -> exp EQUAL exp" << std::endl;
}
|
exp EQUAL exp
{
std::cout << "exp -> exp EQUAL exp" << std::endl;
}
|
exp DIVISION exp
{
std::cout << "exp -> exp DIVISION exp" << std::endl;
}
|
exp MOD exp
{
std::cout << "exp -> exp MOD exp" << std::endl;
}
|
exp LESSER exp
{
std::cout << "exp -> exp LESSER exp" << std::endl;
}
|
exp GREATER exp
{
std::cout << "exp -> exp GREATER exp" << std::endl;
}
|
OPEN exp CLOSE
{
std::cout << "exp -> OPEN exp CLOSE" << std::endl;
}
|
NEGATE exp
{
std::cout << "exp -> NEGATE exp" << std::endl;
}
|
CURLYOPEN exp CURLYCLOSE
{
std::cout << "exp -> CURLYOPEN exp CURLYCLOSE" << std::endl;
}
|
exp SEMICOLON
{
std::cout << "exp -> SEMICOLON" << std::endl;
}
|
KEYWORD VARIABLE SEMICOLON
{
std::cout << "exp -> KEYWORD VARIABLE SEMICOLON" << std::endl;
}
;
However, it keeps returning with the error
') encountered.1] Line 1: unrecognized input (`
': identifier or character-constant expected.
[bead.y: fatal] Line 23: No production rules
134950080
I obviously have some production rules and have no idea what I'm doing wrong. I've copied most of the code from another working example and modified it to my liking. What is wrong?
Your files are not UNIX conform (calculate.l and calculate.y)
If you're operating on Windows and you use Nodepad++, just do the following:
Edit/EOL conversion/UNIX format
Encoding/Convert your files to UTF-8 without BOM
Save and recompile with flex and bisonc++
Hope this helps
I had the same problem, and my teacher showed me, that some of the windows editors create invisible trash in your file, so edit your file with the terminal.
pico yourfile.y
Hit an Enter before the first line, than erase it.
Save
Thats it!
I am parsing the following file:
BEGIN BLOCK BLK_ROWDEC
NAME cell_rowdec
SIZE UNI_rowdecSize
ITERATE itr_rows
DIRECTION lgDir_rowdec
STRAP STRD1,STRD3,STRD2
WRAP WRD1
VIA VIAB,VIAC,VIAD
ENDS BLK_ROWDEC
My flex and bison file are as follows:
lexa.l
%{
#include <iostream>
#include <stdio.h>
const char s[2] = " ";
#include "yacc.tab.h"
char *token;
#define YY_DECL extern "C" int yylex()
int line_num = 1;
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT "<"
ANGLE_RIGHT ">"
AT "#"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>?#\[\]^_`{|}~]
%%
[ \t] ;
^BEGIN(.*)\r?\n+\s*BEGIN(.*) { printf("\nError : two continous BEGIN is not allowed : "); }
^ENDS(.*)\r?\n+\s*ENDS(.*) { printf("\nError : two continous END is not allowed : \n"); }
NAME { yylval.sval = strdup(yytext);
return TOK_NAME; }
SIZE { yylval.sval = strdup(yytext);
return TOK_SIZE; }
ITERATE { yylval.sval = strdup(yytext);
return TOK_ITERATE; }
DIRECTION { yylval.sval = strdup(yytext);
return TOK_DIRECTION; }
STRAP { yylval.sval = strdup(yytext);
return TOK_STRAP; }
WRAP { yylval.sval = strdup(yytext);
return TOK_WRAP; }
VIA { yylval.sval = strdup(yytext);
return TOK_VIA; }
ENDS { yylval.sval = strdup(yytext);
return TOK_END; }
BEGIN { yylval.sval = strdup(yytext);
return TOK_BEGIN; }
BLOCK { yylval.sval = strdup(yytext);
return TOK_BLOCK; }
[a-zA-Z0-9_,]+ { yylval.sval = strdup(yytext);
return TOK_STRING; }
{SPACE}* { return TOK_SPACE; }
^ENDS(.*)$ {}
^{CRLF} { return TOK_EMPTY_LINE; }
{CRLF} {}
. {}/* ignore unknown chars */
\n { ++line_num; return ENDL; }
yacca.y
%{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdio.h>
#define YYDEBUG 1
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
extern int line_num;
void yyerror(const char* s);
%}
// Symbols.
%union
{
char* sval;
};
%token <sval> TOK_NAME
%token <sval> TOK_SIZE
%token <sval> TOK_STRING
%token <sval> TOK_ITERATE
%token <sval> TOK_DIRECTION
%token <sval> TOK_STRAP
%token <sval> TOK_WRAP
%token <sval> TOK_VIA
%token <sval> TOK_EMPTY_LINE
%token <sval> TOK_BLOCK
%token <sval> TOK_LINE
%token <sval> TOK_BEGIN
%token <sval> TOK_END
%token TOK_SPACE
%token END ENDL
%%
language : program ;
program : block
| program block
;
block : TOK_BEGIN TOK_BLOCK TOK_SPACE TOK_STRING blockcontents TOK_END TOK_SPACE TOK_STRING
{
cout << endl << "SHAILAVI" << $4 << " ";
}
;
blockcontents : item
| blockcontents item
;
item : TOK_SPACE TOK_NAME TOK_SPACE TOK_STRING
{
cout << endl << "Value:" << $2 << "->" << $4 << " ";
}
| TOK_SPACE TOK_SIZE TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_ITERATE TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_DIRECTION TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " " << endl; }
| TOK_SPACE TOK_STRAP TOK_SPACE TOK_STRING { cout << "ref:" << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_WRAP TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " "; }
| TOK_SPACE TOK_VIA TOK_SPACE TOK_STRING { cout << $2 << "->" << $4 << " " << endl; }
;
%%
int main(void) {
FILE * pt = fopen("file", "r" );
if(!pt)
{
cout << "Bad Input.Noexistant file" << endl;
return -1;
}
yyin = pt;
do
{
yydebug = 1;
yyparse();
}while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "parse error on line " << line_num << "! Message: " << s << endl;
exit(-1);
}
#include "lex.yy.c"
Compilation steps:
flex lexa.l
bison -d yacca.y
g++ yacca.tab.c -lfl -o scanner.exe
At the time of execution it gives syntax error near blockcontents
Please help me to identify the mistake I have done.
Thank You so much.
It took me a while, but I've found the flaw.
In your lexer, you skip all sequences of tabs and blanks (first rule).
But your parser expects white space every now and then. Hence the syntax error.
Since you don't do anything with the white space, simply eat them within the lexer (as you already do now actually, but it is better to eliminate the {SPACE}* rule too) and eliminate the TOK_SPACE in the parser.
---- edit to give some hints ----
What I did to track down the bug is:
make the lexer verbose
I added (hash signs omitted; it confuses the renderer for some reason)
#ifdef DEBUG
#define RETURN(x) cerr << "\n--> found " << #x << "\n"; return x;
#else
#define RETURN(x) return x;
#endif
and replaced all "return something" by RETURN(something)
I compile the bison/flex files separately and link them afterwards
flex lexa.l && \
bison -d yacca.y && \
g++ -c -DDEBUG -I . lex.yy.c && \
g++ -c -I . yacca.tab.c && \
g++ lex.yy.o yacca.tab.o -o scanner
(working on linux here)
As requested the working example
%{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdio.h>
#define YYDEBUG 1
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
extern int line_num;
void yyerror(const char* s);
%}
// Symbols.
%union
{
char* sval;
};
%token TOK_NAME
%token TOK_SIZE
%token TOK_STRING
%token TOK_ITERATE
%token TOK_DIRECTION
%token TOK_STRAP
%token TOK_WRAP
%token TOK_VIA
%token TOK_EMPTY_LINE
%token TOK_BLOCK
%token TOK_LINE
%token TOK_BEGIN
%token TOK_END
%token END ENDL
%%
language : program ;
program : block
| program block
;
block : TOK_BEGIN TOK_BLOCK TOK_STRING blockcontents TOK_END TOK_STRING
{
cout << endl << "SHAILAVI" << $3 << " ";
}
;
blockcontents : item
| blockcontents item
;
item : TOK_NAME TOK_STRING { cout << endl << "Value:" << $1 << "->" << $2 << " "; }
| TOK_SIZE TOK_STRING { cout << $1 << "->" << $2 " << $2 " << $2 " << $2 << " "; }
| TOK_WRAP TOK_STRING { cout << $1 << "->" << $2 << " "; }
| TOK_VIA TOK_STRING { cout << $1 << "->" << $2 << " " << endl; }
;
%%
int main(void) {
FILE * pt = fopen("./input", "r" );
if(!pt)
{
cout << "Bad Input.Nonexistent file" << endl;
return -1;
}
yyin = pt;
do
{
yydebug = 1;
yyparse();
}while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "parse error on line " << line_num << "! Message: " << s << endl;
exit(-1);
}
extern "C" int yywrap()
{
return (1 == 1);
}
And the lexer
%{
#include
#include
const char s[2] = " ";
#include "yacca.tab.h"
char *token;
#define YY_DECL extern "C" int yylex()
int line_num = 1;
#ifdef DEBUG
#define RETURN(x) cerr << "\n--> found " << #x << "\n"; return x;
#else
#define RETURN(x) return x;
#endif
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT ""
AT "#"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;?#\[\]^_`{|}~]
/* [ \t] ; */
%%
^BEGIN(.*)\r?\n+\s*BEGIN(.*) { printf("\nError : two continous BEGIN is not allowed : "); }
^ENDS(.*)\r?\n+\s*ENDS(.*) { printf("\nError : two continous END is not allowed : \n"); }
NAME { yylval.sval = strdup(yytext);
RETURN(TOK_NAME); }
SIZE { yylval.sval = strdup(yytext);
RETURN(TOK_SIZE); }
ITERATE { yylval.sval = strdup(yytext);
RETURN(TOK_ITERATE); }
DIRECTION { yylval.sval = strdup(yytext);
RETURN(TOK_DIRECTION); }
STRAP { yylval.sval = strdup(yytext);
RETURN(TOK_STRAP); }
WRAP { yylval.sval = strdup(yytext);
RETURN(TOK_WRAP); }
VIA { yylval.sval = strdup(yytext);
RETURN(TOK_VIA); }
ENDS { yylval.sval = strdup(yytext);
RETURN(TOK_END); }
BEGIN { yylval.sval = strdup(yytext);
RETURN(TOK_BEGIN); }
BLOCK { yylval.sval = strdup(yytext);
RETURN(TOK_BLOCK); }
[a-zA-Z0-9_,]+ { yylval.sval = strdup(yytext); RETURN(TOK_STRING); }
^ENDS(.*)$ {}
^{CRLF} { RETURN(TOK_EMPTY_LINE); }
{CRLF} {}
. {}/* ignore unknown chars */
\n { ++line_num; /* RETURN(ENDL); */ }
There's only one problem left. It doesn't really like the EOF. I'll leave that as an exercise.
I am trying to create a simple parser.
cond: T_IF '(' exp ')' '#' stmt_block opt_elseifs opt_else end {if($3 == 0) return;}
opt_elseifs : /* Nothing */
| opt_elseifs T_ELSIF '(' exp ')' '#' stmt_block '#'
;
opt_else : /* Nothing */
| T_ELSE '#' stmt_block '#'
;
end : '#'
;
For Example,
a = 0;
if(a) #
c = 10 + 20;
#
I don't want value of c printed,but this is printing value of c.
What am I doing wrong here?
Found solution after reading bison manual.So,I thought I better also share it here.
I should be doing
cond: T_IF '(' exp ')' { if($3 == 0) return; }
'#' stmt_block opt_elseifs opt_else end
;
So,if the exp is evaluated to be false,it does not parse any further.