Syntax error while parsing file using flex and bison - parsing

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.

Related

How can I resolve the error "undefined reference to `yyerror'"?

I've been following the youtube video https://www.youtube.com/watch?v=fFRxWtRibC8
I've created the lexer.l file with the following:
%{
/* definitions */
#include "parser.tab.h"
%}
/* rules */
%%
[0-9]+ {yylval.num = atoi(yytext); return NUMBER; }
\n {return EOL;}
. {}
%%
yywrap() {}
int main() {
yylex();
return 0;
}
and the parser.y file with the following:
%{
/* definitions */
%}
%union{
int num;
char sym;
}
%token EOL
%token<num> NUMBER
%type<num> exp
%token PLUS
/* rules */
%%
input:
exp EOL {printf("%d\n", $1); }
| EOL;
exp:
NUMBER { $$ = $1; }
| exp PLUS exp { $$ = $1 + $3; }
;
%%
int main() {
yyparse();
return 0;
}
void yyerror (char* s) {
printf ("ERROR: %s\n", s);
return 0;
}
When running the command "gcc lex.yy.c parser.tab.c", I'm getting the following error:
undefined reference to `yyerror'
collect2.exe: error: ld returned 1 exit status

How to solve yacc error "... has no declared type"

I have problem on Yacc/Bison.
We use Kotlin grammar.
This is my code :
%token BOOL
%token BREAK
%token CHAR
%token CONTINUE
%token DO
%token ENUM
%token EXTERN
%token FALSE
%token FLOAT
%token FOR
%token FN
%token IN
%token INT
%token LET
%token LOOP
%token MATCH
%token MUT
%token PRINT
%token PRINTLN
%token PUB
%token RETURN
%token SELF
%token STATIC
%token STR
%token STRUCT
%token TRUE
%token USE
%token WHERE
%token IF
%token ELSE
%token <Token> INTEGER
%token <Token> STRING
%token <Token> REAL
%token <Token> ID
%type <Token> arrDec type expression integerExpr realExpr boolExpr stringExpr functionInvoc
varDec: LET MUT ID ':' type ';' {
Trace("Reducing to varDec Form LET MUT ID ':' type ';'\n");
variableEntry ve = ve_basic_notInit($3.stringVal, $5.tokenType, false);
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type== T_INT)
fp << "field static int " << ve.name << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID '=' expression ';' {
Trace("Reducing to varDec Form LET MUT ID '=' expression ';'\n");
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
if ($5.tokenType == T_INT)
ve.data.intVal = $5.intVal;
else if ($5.tokenType == T_FLOAT)
ve.data.floatVal = $5.floatVal;
else if ($5.tokenType == T_BOOL)
ve.data.boolVal = $5.boolVal;
else if ($5.tokenType == T_STRING)
ve.data.stringVal = $5.stringVal;
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type == T_INT)
fp << "field static int " << ve.name << " = " << ve.data.intVal << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << " = " << ve.data.boolVal << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
printTabs();
if (ve.type == T_INT)
fp << "istore " << ve.stackIndex << endl;
else if (ve.type == T_BOOL)
fp << "istore " << ve.stackIndex << endl;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID ':' type '=' expression ';' {
Trace("Reducing to varDec Form LET MUT ID ':' type '=' expression ';'\n");
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
if ($5.tokenType == T_FLOAT && $7.tokenType == T_INT)
ve.data.floatVal = $7.intVal;
else if ($5.tokenType != $7.tokenType)
yyerror("expression is not equal to expression");
else if ($7.tokenType == T_INT)
ve.data.intVal = $7.intVal;
else if ($7.tokenType == T_FLOAT)
ve.data.floatVal = $7.floatVal;
else if ($7.tokenType == T_BOOL)
ve.data.boolVal = $7.boolVal;
else if ($7.tokenType == T_STRING)
ve.data.stringVal = $7.stringVal;
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
if (ve.type == T_INT)
fp << "field static int " << ve.name << " = " << ve.data.intVal << endl;
else if (ve.type == T_BOOL)
fp << "field static int " << ve.name << " = " << ve.data.boolVal << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
printTabs();
if (ve.type == T_INT)
fp << "istore " << ve.stackIndex << endl;
else if (ve.type == T_BOOL)
fp << "istore " << ve.stackIndex << endl;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
| LET MUT ID ';' {
Trace("Reducing to varDec Form LET MUT ID ';'\n");
variableEntry ve = ve_basic_notInit($3.stringVal, T_INT, false);
if (symTabs.isNowGlobal())
{
ve.isGlobal = true;
printTabs();
fp << "field static int " << ve.name << endl;
}
else
{
ve.isGlobal = false;
ve.stackIndex = nowStackIndex;
nowStackIndex++;
}
if (!symTabs.addVariable(ve))
yyerror("Re declaration.");
}
;
I didn't paste them all.
The errors are here.
I don't know how to fix them.
yacc.y:188.33-34: error: symbol ID is used, but is not defined as a token and has no rules
varDec: LET MUT ID ':' type ';' {
^^
yacc.y:191.173-174: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic_notInit($3.stringVal, $5.tokenType, false);
^^
yacc.y:216.165-166: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
^^
yacc.y:256.165-166: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic($3.stringVal, $5.tokenType, false);
^^
yacc.y:300.173-174: error: $3 of ‘varDec’ has no declared type
variableEntry ve = ve_basic_notInit($3.stringVal, T_INT, false);
Please help me solve problem, thanks.

FLEX/YACC program not behaving as expected : can't grab int value from sequence of ints

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);}
;

yacc/lex parser not catching certain terminals

I built a scanner->parser meant to catch modified Java. When testing it, I noticed that codeBlock never triggers but varDecls triggers. I'm not entirely sure why this happens.
Here is my parser
%{
#include <stdio.h>
extern int yylex(void);
void yyerror(char *s) {
fprintf(stderr, "error: %s\n", s);
}
int yywrap(){ return 1;}
%}
%token INT FLOAT STRING
%union {
int ival;
float fval;
char *sval;
int bval;
}
%token <ival> NegInt
%token <ival> Int
%token <fval> Float
%token <bval> Bool
%token <sval> ifHeader
%token <sval> thenHeader
%token <sval> elseHeader
%token <sval> forHeader
%token <sval> whileHeader
%token <sval> ID
%token <sval> BinOperator
%token <sval> BoolOperator
%token <sval> Assignment
%token <sval> Quotation
%token <sval> LBracket
%token <sval> RBracket
%token <sval> LFBracket
%token <sval> RFBracket
%token <sval> Semi
%token <sval> LABracket
%token <sval> RABracket
%token <sval> Comma
%token <sval> String
%%
codeBlock: varDecls {printf("why doth this triggering?\n");}
| ifExprs {printf("codeBlock Statement \n");}
;
ifExprs: ifExprs ifStmt
| ifStmt
;
ifStmt: ifExpr | ifExprElse;
ifExprElse: ifExpr elseExpr;
ifExpr: ifHeader LBracket boolExpr RBracket thenExpr;
thenExpr: thenHeader LFBracket varDecls RFBracket;
elseExpr: elseHeader LFBracket varDecls RFBracket;
varDecls: varDecls varDecl
| varDecl
;
varDecl: ID Assignment numStmt Semi
| ID Assignment strExpr Semi
| ID Assignment boolExpr Semi
| ID Assignment Bool Semi {printf("why is this triggering?\n");}
;
boolExpr: ID BoolOperator ID
| ID BoolOperator numExpr
| ID BoolOperator Bool
;
strExpr: Quotation ID Quotation
;
numStmt: numStmt BinOperator numExpr
| numExpr
;
numExpr: LBracket numStmt RBracket
| Int
| Float
| NegInt
;
%%
int main(int argc, char* argv[]) {
yyparse();
}
Here is my scanner:
%{
#include "y.tab.h"
extern YYSTYPE yylval;
%}
%option yylineno
Digit [0-9]
Letter [a-zA-Z]
Word [a-z][a-zA-Z0-9_]*
%%
"-"{Digit}+ {
//printf("\n An assignment: %s \n", yytext);
yylval.ival = atoi(yytext);
return NegInt;
}
{Digit}+ {
//printf("\n An assignment: %s \n", yytext);
yylval.ival = atoi(yytext);
return Int;
}
{Digit}+"."{Digit}+ {
//printf("\n A float: %s (%f)\n", yytext, atof(yytext));
yylval.ival=atof(yytext);
return Float;
}
True|False {
//printf("\n A Boolean: %s \n", yytext);
yylval.bval = atoi(yytext);
return Bool;
}
if {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return ifHeader;
}
then {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return thenHeader;
}
else {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return elseHeader;
}
for {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return forHeader;
}
while {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return whileHeader;
}
{Word} {
//printf("\n An Identifier: %s \n", yytext);
yylval.sval = yytext;
return ID;
}
"'" {
//printf("\n An Identifier: %s \n", yytext);
yylval.sval = yytext;
return Quotation;
}
"+"|"-"|"*"|"/" {
//printf("\n An Operator: %s \n", yytext);
yylval.sval = yytext;
return BinOperator;
}
"<"|">"|"!="|"<="|">="|"==" {
//printf("\n An comparison: %s \n", yytext);
yylval.sval = yytext;
return BoolOperator;
}
"=" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return Assignment;
}
"(" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return LBracket;
}
")" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return RBracket;
}
"{" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return LFBracket;
}
"}" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return RFBracket;
}
";" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return Semi;
}
"[" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return LABracket;
}
"]" {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return RABracket;
}
"," {
//printf("\n An assignment: %s \n", yytext);
yylval.sval = yytext;
return Comma;
}
%
As you can see with my print statements, I was trying to trigger my parser to print out "why doth this triggering" but instead varDecls is triggered instead.
Additionally, varDecl also triggers. Is that supposed to happen?
Help would be very appreciated. Thank you

Bison syntax error

I recently started learning bison and I already hit a wall. The manual sections are a little bit ambiguous, so I guess an error was to be expected. The code below is the first tutorial from the official manual - The Reverse Polish Notation Calculator, saved in a single file - rpcalc.y.
/* Reverse polish notation calculator */
%{
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int yylex (void);
void yyerror (char const *);
%}
%define api.value.type {double}
%token NUM
%% /* Grammar rules and actions follow. */
input:
%empty
| input line
;
line:
'\n'
| exp '\n' {printf ("%.10g\n", $1);}
;
exp:
NUM {$$ = $1; }
| exp exp '+' {$$ = $1 + $2; }
| exp exp '-' {$$ = $1 - $2; }
| exp exp '*' {$$ = $1 * $2; }
| exp exp '/' {$$ = $1 / $2; }
| exp exp '^' {$$ = pow ($1, $2); }
| exp 'n' {$$ = -$1; }
;
%%
/* The lexical analyzer */
int yylex (void)
{
int c;
/* Skip white space */
while((c = getchar()) == ' ' || c == '\t')
continue;
/* Process numbers */
if(c == '.' || isdigit (c))
{
ungetc (c, stdin);
scanf ("%lf", $yylval);
return NUM;
}
/* Return end-of-imput */
if (c == EOF)
return 0;
/* Return a single char */
return c;
}
int main (void)
{
return yyparse ();
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
Executing bison rpcalc.y in cmd returns the following error:
rpcalc.y:11.24-31: syntax error, unexpected {...}
What seems to be the problem?
The fault is caused by you using features that are new to the 3.0 version of bison, whereas you have an older version of bison installed. If you are unable to upgrade to version 3.0, it is an easy change to convert the grammar to using the features of earlier versions of bison.
The %define api.value.type {double} can be changed to a %type command, and the %empty command removed. The resulting bison program would be:
/* Reverse polish notation calculator */
%{
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int yylex (void);
void yyerror (char const *);
%}
%type <double> exp
%token <double> NUM
%% /* Grammar rules and actions follow. */
input:
| input line
;
line:
'\n'
| exp '\n' {printf ("%.10g\n", $1);}
;
exp:
NUM {$$ = $1; }
| exp exp '+' {$$ = $1 + $2; }
| exp exp '-' {$$ = $1 - $2; }
| exp exp '*' {$$ = $1 * $2; }
| exp exp '/' {$$ = $1 / $2; }
| exp exp '^' {$$ = pow ($1, $2); }
| exp 'n' {$$ = -$1; }
;
%%
/* The lexical analyzer */
int yylex (void)
{
int c;
/* Skip white space */
while((c = getchar()) == ' ' || c == '\t')
continue;
/* Process numbers */
if(c == '.' || isdigit (c))
{
ungetc (c, stdin);
scanf ("%lf", $yylval);
return NUM;
}
/* Return end-of-imput */
if (c == EOF)
return 0;
/* Return a single char */
return c;
}
int main (void)
{
return yyparse ();
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
This runs in a wider range of bison versions.

Resources