Yacc reading only the first grammar rule - grammar

I have this yacc file
%error-verbose
%token END
%token ID
%token INT
%token IF
%token ELSE
%token WHILE
%token FOR
%token BREAK
%token CONTINUE
%token RETURN
%token SEM
%token LPAR
%token RPAR
%token PLUS
%token MINUS
%token MULT
%token DIV
%token MOD
%token GT
%token LT
%token GTE /* >= */
%token LTE /* <= */
%token EQUAL /* == */
%token NEQUAL /* != */
%token AND
%token OR
%token EQ
%token COM
%token PRINT
%token READ
%token FLOAT
%token LABR
%token RABR
%token NUM
%token STR
/*
* precedentce tabLTE
*/
%right EQ PE ME TE DE RE
%left OR
%left AND
%left EQUAL NEQUAL
%left LT GT GTE LTE
%left PLUS MINUS
%left MULT DIV MOD
%right PP MM
%{
#include<stdio.h>
extern char *yyname;
extern char *yytext;
extern int yylineno;
void yyerror(char const *msg)
{
fprintf(stderr,"%s:%d:%s\n", yyname,yylineno,msg);
}
%}
%%
program
: definitions
;
definitions
: definition
| definitions definition
;
definition:
| declaration
;
declarations
: /* null */
| declarations declaration
;
declaration
: INT declarator_list SEM
;
declarator_list
: ID
| declarator_list COM ID
;
statements
: /* null */
| statements statement
;
statement
: expression SEM
| SEM /* null statement */
| if_prefix statement
| if_prefix statement ELSE statement
| loop_prefix statement
;
if_prefix
: IF LPAR expression RPAR
;
loop_prefix
: WHILE LPAR expression RPAR
;
expression
: binary
| expression COM binary
;
binary
: ID
| LPAR expression RPAR
| ID LPAR optional_argument_list RPAR
| binary PLUS binary
| binary MINUS binary
| binary MULT binary
| binary DIV binary
| binary MOD binary
| binary GT binary
| binary LT binary
| binary GTE binary
| binary LTE binary
| binary EQUAL binary
| binary NEQUAL binary
| binary AND binary
| binary OR binary
| ID EQ binary
| ID PE binary
| ID ME binary
| ID TE binary
| ID DE binary
| ID RE binary
;
optional_argument_list
: /* no actual arguments */
| argument_list
;
argument_list
: binary
| argument_list COM binary
;
%%
#include <stdlib.h>
extern FILE *yyin;
int main(int argc, char **argv)
{
int ok;
if (argc != 2) {
fprintf(stderr, "%s: Wrong arguments\n", argv[0]);
return EXIT_FAILURE;
}
yyname = argv[1];
if ((yyin = fopen(yyname, "r")) == NULL) {
fprintf(stderr, "%s: %s: Invalid file\n", argv[0], argv[1]);
return EXIT_FAILURE;
}
return (yyparse() ? EXIT_SUCCESS : EXIT_FAILURE);
}
when the input is
int x;
everything works fine, but when the input is something other than "INT"
lets say FOR it throws an error:
unexpected FOR expecting INT or $end
so it's actually reading only the first rule from the set of rules..
Besides, it keeps showing useless non terminals and terminals warning when bison command is applied.
What is wrong with this yacc file?

The trouble is that the rules:
program
: definitions
;
definitions
: definition
| definitions definition
;
definition:
| declaration
;
declarations
: /* null */
| declarations declaration
;
declaration
: INT declarator_list SEM
;
only allow declarations through; nothing allows statements as part of a program. Your FOR is not a declaration, so the grammar rejects it.
The 'useless non-terminals' warning is trying to tell you:
You have goofed big time; there is a bug in your grammar. You have tried to write rules for some production, but you never let it be recognized, so there was no point in adding it.
Or thereabouts...
Maybe you need:
program
: definitions statements
;
Or maybe you need to allow functions as a definition too, and then the FOR statement will be part of the body of a function.

Asking my LL oracle about your amended grammar:
Out of 15 non-terminals, 14 are reachable, 1 are unreachable:
'declarations'
Circular symbols:
definitions
definitions
The complaint about circular symbols means that 'definitions' can derive itself. For example, 'definitions' can produce 'definitions definition', but 'definition' is nullable, so 'definitions' can produce just itself, kinduva infinite loop few parser generators care to deal with in any sensible way. Looking at it another way, you've defined 'definitions' to be a list of nullable symbols, so how many epsilons would you like to match? How about infinity? :-)
This is a drawback of the yacc/bison style of trying to produce some parser even if there are problems in the grammar; quite convenient if you know exactly what you're doing, but quite confusing otherwise.
But, to the narrow point of what to do about the grammar circularity that's giving you a very unuseful (but by gum compilable!) parser. How about you allow 'definitions' be nullable but not 'definition'? IOW:
definitions : | definitions definition ;
definition : declaration ;
Try to not stack nullability on top of nullability. So when you later change to:
definition : declarations ;
Don't make 'declarations' nullable (that's already handled by 'definitions' being nullable). Instead, change it to:
declarations : declaration | declarations declaration ;
That should get you past the immediate problem and onto some new ones :-)

Related

lex and yacc warning's and not working as expected

Lexer.l
%{
#include "y.tab.h"
%}
%%
"define" return(TK_KEY_DEFINE);
"as" return(TK_KEY_AS);
"is" return(TK_KEY_IS);
"if" return(TK_KEY_IF);
"then" return(TK_KEY_THEN);
"else" return(TK_KEY_ELSE);
"endif" return(TK_KEY_ENDIF);
"with" return(TK_KEY_WITH);
"DEFINE" return(TK_KEY_DEFINE_UC);
"AS" return(TK_KEY_AS_UC);
"IS" return(TK_KEY_IS_UC);
"IF" return(TK_KEY_IF_UC);
"THEN" return(TK_KEY_THEN_UC);
"ELSE" return(TK_KEY_ELSE_UC);
"ENDIF" return(TK_KEY_ENDIF_UC);
"WITH" return(TK_KEY_WITH_UC);
"+" return(TK_PLUS);
"-" return(TK_MINUS);
"*" return(TK_MUL);
"/" return(TK_DIV);
"~" return(TK_NOT);
"&" return(TK_AND);
"|" return(TK_OR);
"<=" return(TK_LEQ);
"<" return(TK_LESS);
">=" return(TK_GEQ);
">" return(TK_GT);
"==" return(TK_EQ);
"=" return(TK_ASSIGN);
"(" return(TK_OPEN);
")" return(TK_CLOSE);
";" return(TK_SEMI);
"," return(TK_COMMA);
[[:alpha:]_][[:alnum:]_]* return(IDENTIFIER);
[+-]?[0-9]+ return(INTEGER);
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+) return(REAL);
[[:space:]]+ ;
%%
int yywrap(void)
{
return 1;
}
Parser.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start Program
%token TK_KEY_DEFINE TK_KEY_DEFINE_UC
%token TK_KEY_AS TK_KEY_AS_UC
%token TK_KEY_IS TK_KEY_IS_UC
%token TK_KEY_IF TK_KEY_IF_UC
%token TK_KEY_THEN TK_KEY_THEN_UC
%token TK_KEY_ELSE TK_KEY_ELSE_UC
%token TK_KEY_ENDIF TK_KEY_ENDIF_UC
%token TK_KEY_WITH TK_KEY_WITH_UC
%token TK_PLUS TK_MINUS
%token TK_MUL TK_DIV
%token TK_NOT
%token TK_AND
%token TK_OR
%token TK_LEQ TK_LESS TK_GEQ TK_GT
%token TK_EQ
%token TK_ASSIGN
%token TK_OPEN TK_CLOSE
%token TK_SEMI
%token TK_COMMA
%token IDENTIFIER
%token INTEGER
%token REAL
%left TK_PLUS TK_MINUS
%left TK_MUL TK_DIV
%left TK_LEG TK_LESS TK_GEQ TK_GT
%left TK_AND TK_OR
%left TK_EQ
%right TK_NOT TK_ASSIGN
%%
Program : Macros Statements;
Macros : /* empty */
| Macro Macros
;
Macro : TK_KEY_DEFINE MacroTemplate TK_KEY_AS Expression;
MacroTemplate : IDENTIFIER MT;
MT : /*empty*/
| TK_OPEN IdentifierList TK_CLOSE
;
IdentifierList : IDENTIFIER I;
I : /*empty*/
| TK_COMMA IdentifierList
;
Statements : /*empty*/
| Statement Statements
;
IfStmt : TK_KEY_IF Condition TK_KEY_THEN Statements TK_KEY_ELSE Statements TK_KEY_ENDIF;
Statement : AssignStmt
| IfStmt
;
AssignStmt : IDENTIFIER TK_KEY_IS Expression;
Condition : C1 C11;
C11 : /*empty*/
| TK_OR C1 C11
;
C1 : C2 C22;
C22 : /*empty*/
| TK_AND C2 C22
;
C2 : C3 C33;
C33 : TK_EQ C3 C33;
C3 : C4 C44;
C44 : /*empty*/
| TK_LESS C4 C44
| TK_LEQ C4 C44
| TK_GT C4 C44
| TK_GEQ C4 C44
;
C4 : TK_NOT C5 | C5;
C5 : INTEGER | REAL | TK_OPEN Condition TK_CLOSE;
Expression : Term EE;
EE : /*empty*/
| TK_PLUS Term EE
| TK_MINUS Term EE
;
Term : Factor TT;
TT : /*empty*/
| TK_MUL Factor TT
| TK_DIV Factor TT
;
Factor : IDENTIFIER | REAL | INTEGER | TK_OPEN Expression TK_CLOSE;
%%
int main (void) {return yyparse ( );}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror (char *s)
{
fprintf (stderr, "%s\n", s);
}
I wish the output to a parse tree if no errors and indicate error if any .
But I get a lot of warnings such as
warning: rule useless in grammar
warning: nonterminal useless in grammar
I understood the reason of this by reading other similar questions but could not correct it myself. Please help me solve this . Thanks !
Hi rici ,
Thank you so much , so I need not worry about left recursion , left factored grammar etc and directly go ahead and use something like below in yacc ?
%%
Program : Macros Statements;
Macros : /*empty*/
|Macro Macros
;
Macro : TK_KEY_DEFINE MacroTemplate TK_KEY_AS Expression;
MacroTemplate : VarTemplate
| FunTemplate
;
VarTemplate : IDENTIFIER;
FunTemplate : IDENTIFIER TK_OPEN IdentifierList TK_CLOSE;
IdentifierList : IDENTIFIER TK_COMMA IdentifierList
| IDENTIFIER
;
Statements : /*empty*/
| Statement Statements
;
IfStmt : TK_KEY_IF Condition TK_KEY_THEN Statements TK_KEY_ELSE Statements TK_KEY_ENDIF;
Statement : AssignStmt
| IfStmt
;
AssignStmt : IDENTIFIER TK_KEY_IS Expression;
Condition : Condition TK_AND Condition
| Condition TK_OR Condition
| Condition TK_LESS Condition
| Condition TK_LEQ Condition
| Condition TK_GT Condition
| Condition TK_GEQ Condition
| Condition TK_EQ Condition
| TK_NOT Condition
| TK_OPEN Condition TK_CLOSE
| INTEGER
| REAL
;
Expression : Expression TK_PLUS Expression
| Expression TK_MINUS Expression
| Expression TK_MUL Expression
| Expression TK_DIV Expression
| TK_OPEN Expression TK_CLOSE
| IDENTIFIER
| INTEGER
| REAL
;
%%
Also yes , I noted your last point :)
Unlike C11, C22, C44 and other "tail" rules, which can produce %empty, C33 has only one production:
C33 : TK_EQ C3 C33;
Since it has no non-recursive production, it cannot possibly produce a sentence (consisting only of non-terminals). And since it is part of the only production for C2 which is part of the only production for C1 which is part of the only production for Condition which is part of the only production for IfStmt, none of those can produce any sentence either. A rule which cannot produce any sentence is technically described as "useless" and a non-terminal all of whose rules are useless (or whose only rule is useless) is a "useless non-terminal".
There is another category of useless non-terminals: those which cannot be produced by any useful rule. That will be the case with C4 (which can only be produced by C3, which has been discovered to be useless) and thus with C44 and C5.
It should be evident how to fix that, but I'd like to note that you are tying yourself into knots by trying to avoid left-recursion, which is both unnecessary and counter-productive when using a bottom-up parser generator such as bison/yacc. (See the last paragraph of this answer for a longer grumble about this.) The artificial productions (C33 and friends) serve only to complicate the parse tree.
Also, since your grammar is not ambiguous -- in effect, the production rules clearly define operator binding strengths -- the various precedence declarations are pointless. (Unlike "useless", that is not a technical term :-) ). Precedence declarations are only applied to resolve grammatical ambiguity, which is not present here.
Finally, I think you should re-examine your grammar for Conditions. What, for example, is the meaning of ~3 < ~4? And why is x * 2 < y not valid?

YACC Rules not reduced

This is my code calc.y. I keep getting the error:
yacc: 1 rule never reduced
yacc: 3 reduce/reduce conflicts
not really sure what this means
Ive done some research in other places but I am now lost. Im guessing the rules being referred to is program and statement but even so... what does the reduce rule mean?
%{
#include <stdio.h>
FILE *outfile;
int yyline = 1;
int yycolumn = 1;
%}
%union{
int nw;
struct{
int v;
char s[1000];
}attr;
}
%token SEMInumber
%token LPARENnumber
%token <nw> ICONSTnumber
%token BEGINnumber
%token PROGRAMnumber
%token MINUSnumber
%token TIMESnumber
%token <nw> VARnumber
%token INTnumber
%token EOFnumber
%token COMMAnumber
%token RPARENnumber
%token <nw>IDnumber
%token ENDnumber
%token ISnumber
%token PLUSnumber
%token DIVnumber
%token PRINTnumber
%token EQnumber
%type <attr> exp
%type <attr> term
%type <attr> factor
%%
program: PROGRAMnumber IDnumber ISnumber compstate
;
compstate: BEGINnumber {print_header();} statement ENDnumber{print_end();}
| BEGINnumber {print_header();} statement SEMInumber statement ENDnumber{print_end();}
;
statement: IDnumber EQnumber exp
| PRINTnumber exp
| declaration
;
declaration: VARnumber IDnumber
| VARnumber IDnumber COMMAnumber IDnumber
;
exp: term {$$.v = $1.v; strcpy($$.s, $1.s);}
| exp PLUSnumber term {$$.v = $1.v + $3.v; sprintf($$.s, "(%s) + (%s)", $1. s, $3.s);}
| exp MINUSnumber term {$$.v = $1.v - $3.v; sprintf($$.s, "(%s) - (%s)", $1. s, $3.s);}
;
term: factor {$$.v = $1.v; strcpy($$.s, $1.s);}
| term TIMESnumber factor {$$.v = $1.v * $3.v; sprintf($$.s, "(%s) * (%s)", $1.s, $3.s);}
| term DIVnumber factor {$$.v = $1.v / $3.v; sprintf($$.s, "(%s) / (%s)", $1.s, $3.s);}
;
factor: ICONSTnumber {$$.v = $1; sprintf($$.s, "%d", $1);}
| IDnumber {$$.v = $1.v; strcpy($$.s, $1.s);}
| LPARENnumber exp RPARENnumber {$$.v = $2.v; strcpy($$.s, $2.s);}
;
%%
int main()
{
if(!yyparse())
{
printf("accept\n");
}
else
printf("reject\n");
}
void print_header() {}
void print_end(){}
void yyerror(const char *str)
{
printf("yyerror: %s at line %d\n", str, yyline);
}
When compstate shifts the BEGINnumber token, two inner rules for the mid rule action {print_header();} can be both reduced resulting in a R/R conflict. Youe can replace
compstate: BEGINnumber {print_header();} statement ENDnumber{print_end();}
| BEGINnumber {print_header();} statement SEMInumber statement
ENDnumber{print_end();}
;
with, for example
begin_number:
BEGINnumber { print_header(); }
compstate: begin_number statement ENDnumber{print_end();}
| begin_number statement SEMInumber statement
ENDnumber{print_end();}
;
to solve the conflict.
Informative Messages
%s: %d rules never reduced
Some rules are never used, either because they weren't used in the grammar or because they
were on the losing end of shift/reduce or reduce/reduce conflicts. Either change the
grammar to use the rules or remove them.

bison grammar rules for a custom pascal like language

I'm trying to make a compiler for a custom pascal like language using bison and flex and I end up getting syntax errors for programs that should be correct according to my custom grammar.
My custom grammar:
<program> ::= program id
<block>
<block> ::= {
<sequence>
}
<sequence> ::= <statement> ( ; <statement> )*
<brackets-seq> ::= { <sequence> }
<brack-or-stat> ::= <brackets-seq> |
<statement>
<statement> ::= ε |
<assignment-stat> |
<if-stat> |
<while-stat>
<assignment-stat> ::= id := <expression>
<if-stat> ::= if (<condition>)
<brack-or-stat>
<elsepart>
<elsepart> ::= ε |
else <brack-or-stat>
<while-stat> ::= while (<condition>)
<brack-or-stat>
<expression> ::= <optional-sign> <term> ( <add-oper> <term>)*
<term> ::= <factor> (<mul-oper> <factor>)*
<factor> ::= constant |
(<expression>) |
id
<condition> ::= <boolterm> (and <boolterm>)*
<boolterm> ::= <boolfactor> (or <boolfactor>)*
<boolfactor> ::= not [<condition>] |
[<condition>] |
<expression> <relational-oper> <expression>
<relational-oper> ::= == | < | > | <> | <= | >=
<add-oper> ::= + | -
<mul-oper> ::= * | /
<optional-sign> ::= ε | <add-oper>
My grammar implementation on bison:
%{
#include <stdio.h>
#include <string.h>
int yylex(void);
void yyerror(char *s);
%}
%union {
int i;
char *s;
};
%token <i> INTEGERNUM
%token PROGRAM;
%token OR;
%token AND;
%token NOT;
%token IF;
%token ELSE;
%token WHILE;
%token PLUS;
%token MINUS;
%token MUL;
%token DIV;
%token LSB;
%token RSB;
%token LCB;
%token RCB;
%token LEFTPAR;
%token RIGHTPAR;
%token ID;
%token INT;
%token ASSIGN;
%token ISEQUAL;
%token LTHAN;
%token GTHAN;
%token NOTEQUAL;
%token LESSEQUAL;
%token GREATEREQUAL;
%left '+' '-'
%left '*' '/'
%%
program:
PROGRAM ID block
;
block:
LCB RCB
|LCB sequence RCB
;
sequence:
statement ';'sequence
|statement ';'
;
bracketsSeq:
LCB sequence RCB
;
brackOrStat:
bracketsSeq
|statement
;
statement:
assignmentStat
|ifStat
|whileStat
|
;
assignmentStat:
ID ':=' expression
ifStat:
IF LEFTPAR condition RIGHTPAR brackOrStat elsepart
;
elsepart:
ELSE brackOrStat
|
;
whileStat:
WHILE LEFTPAR condition RIGHTPAR brackOrStat
;
expression:
addOper expression
|expression addOper expression
|term
;
term:
term mulOper term
|factor
;
factor:
INT
|LEFTPAR expression RIGHTPAR
|ID
;
condition:
condition AND condition
|boolterm
;
boolterm:
boolterm OR boolterm
|boolfactor
;
boolfactor:
NOT LSB condition RSB
|LSB condition RSB
|expression relationalOper expression
;
relationalOper:
ISEQUAL
|LTHAN
|GTHAN
|NOTEQUAL
|LESSEQUAL
|GREATEREQUAL
;
addOper:
PLUS
|MINUS
;
mulOper:
MUL
|DIV
;
optionalSign
|addOper
;
%%
int main( int argc, char **argv )
{
extern FILE *yyin;
++argv, --argc; /* skip over program name */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
else
yyin = stdin;
do
yyparse();
while(!feof(yyin));
}
My flex implementation is pretty straightforward where I just return tokens for each symbol or identifier needed.
Using my implementation on the following simple program:
program circuit
{
a:=b;
}
I end up getting a syntax error. Specifically when the parsing reaches the point right after := according to my debugging prints I use:
$ ./a.exe verilog.txt
text = program
text = circuit val = circuit
text = {
text = a val = a
text = :=
syntax error
This is the first time I use flex and bison so I'm guessing that I made a wrong implementation of my original grammar to bison since after the ./bison.exe -dy comp.y command I get:
bison conflicts 64 shift/reduce
Any ideas would be helpful. Thanks!
This rule :
assignmentStat: ID ':=' expression
uses a token ':=' which bison gives a code distinct from any other token, and which your lexer has no way of knowing, so you're almost certainly not returning it. You're probably returning ASSIGN for the character sequence ':=', so you want:
assignmentStat: ID ASSIGN expression
For the shift-reduce conflicts, they mean that the parser doesn't match exactly the language you specified, but rather some subset (as determined by the default shift instead of reduce). You can use bison's -v option to get a complete printout of the parser state machine (including all the conflicts) in a .output file. You can then examine the conflicts and determine how you should change the grammar to match what you want.
When I run bison on your example, I see only 9 shift/reduce conflicts, all arising from expr: expr OP expr-style rules, which are ambiguous (may be either right- or left- recursive). The default resolution (shift) makes them all right-recursive, which may not be what you want. You can either change the grammar to not be ambiguous, or use bison's built-in precedence resolution tools to resolve them.

type error for rule in yacc

I wrote the following code as a part of my yacc file.
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
FILE *fp;
%}
%token LINE CIRCLE POLYGON
%token CENTRE RADIUS WITHIN
%token END
%union
{
char *string;
int number;
}
%token <number> NUM
%token <string> CORDINATE
%start Input
%%
Input:
| Input Statement
;
Statement :
END
| LINE CORDINATE CORDINATE END {fprintf(fp,"\n\\newline\n\\psline%s%s\n",$2,$3,$2,$3);}
| SCirc END
| POLYGON Mcords {fprintf(fp,"\n\\newline\n\\pspolygon%s",$2);}
;
SCirc :
CIRCLE RADIUS NUM CENTRE CORDINATE {fprintf(fp,"\n\\newline\n\\pscircle%s{%d}\n",3*$3,3*$3,$5,$3);}
| CIRCLE CENTRE CORDINATE RADIUS NUM {fprintf(fp,"\n\\newline\n\\pscircle%s{%d}\n",-2*$5,-2*$5,2*$5,2*$5,$3,$5);}
;
Mcord :
CORDINATE CORDINATE CORDINATE {$$ = strcat(strcat($1,$2),$3);}
| Mcord CODINATE {$$ = strcat($1,$2); }
;
%%
int yyerror(char *s) {
printf("%s\n",s);
}
int main(void) {
/* some stuff */
yyparse();
fprintf(fp,"\\end{pspicture}\n\\end{document}");
fclose(fp);
}
and i end up getting an error as
parser.y:41.42-43: $$ of `Mcord' has no declared type
I mean, the following example works correctly where $$ ends up as a number
Expression :
Number {$$ = $1;}
| Expression '+' Expression {$$ = $1+$2;}
I want Mcord to be as a concatinaiton of many CORDINATE.
How do I do that?
Is there any way of defining type for rules too?
Yes, nonterminal symbols have to be declared has having a type using %type <...> rather than %token <...>. Do you not have a good reference manual for Yacc? The GNU Bison manual is quite good, even if you're using some other Yacc.

Why am I getting conflicts: 1 shift/reduce

I'm new to bison and I'm getting a "conflicts: 1 shift/reduce" error. Can anyone shed some light on this?
Here's the y file.
test.y:
%{
#include <stdio.h>
#include <string.h>
#define YYERROR_VERBOSE
#define YYDEBUG 1
void yyerror(const char *str);
int yywrap();
%}
%union
{
int integer;
char *string;
}
%token <string> VAR_LOCAL
%token <integer> LIT_NUMBER
%token <string> LIT_STRING
%token WS_LINEBRK
//%token SYMB_EQL
%token SYMB_PLUS
%token SYMB_MINUS
%token SYMB_MUL
%token SYMB_DIV
%%
/*
// Sample input
num = 10
str = "this is a string"
*/
inputs: /* empty token */
| literal
| variable
| inputs stmt WS_LINEBRK
;
stmt: variable "=" exps
;
exps: variable op literal
| variable op variable
| literal op literal
| literal op variable
;
op: SYMB_PLUS | SYMB_MINUS | SYMB_MUL | SYMB_DIV ;
variable: VAR_LOCAL
{
printf("variable: %s\n", $1);
}
;
literal:
number | string
;
string: LIT_STRING
{
printf("word: %s\n", $1);
}
;
number: LIT_NUMBER
{
printf("number: %d\n", $1);
}
;
%%
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
Here's the lex file
test.l:
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
int line_no = 0;
%}
%%
[a-z][a-zA-Z0-9]* {
// local variable
yylval.string=strdup(yytext);
return VAR_LOCAL;
}
[0-9]+ {
//number literal
yylval.integer=atoi(yytext);
return LIT_NUMBER;
}
= return SYMB_EQL;
\+ return SYMB_PLUS;
\- return SYMB_MINUS;
\* return SYMB_MUL;
\/ return SYMB_DIV;
\"[-+\!\.a-zA-Z0-9' ]+\" {
// word literal
yylval.string=strdup(yytext);
return LIT_STRING;
}
\n {
// line break
printf("\n");
return WS_LINEBRK;
}
[ \t]+ /* ignore whitespace */;
%%
bison -r test.y will write a file test.output with a detailed description of the generated state machine that allows you to see what's going on - such as the state where the shift/reduce conflict occurs.
In your case, the problem is in the start state (corresponding to your start nonterminal, inputs). Say the first token is VAR_LOCAL. There's two things your parser could do:
It could match the variable case.
It could also match the inputs stmt WS_LINEBRK case: inputs matches the empty string (first line), and stmt matches variable "=" exps.
With the one token of lookahead that bison parsers use, there's no way to tell. You need to change your grammar to get rid of this case.
To fix the grammar, as Fabian has suggested, move the variable and literal to the end of exps from inputs
inputs:
| variable
| literal
exps:
...
| variable
| literal
That allows x= y,x="aliteral" syntax.
To allow for empty input lines, change the /* empty token */ rule to WS_LINEBREAK:
inputs: WS_LINEBRK
| stmt WS_LINEBRK
| inputs stmt WS_LINEBRK
;
On another note, since the scanner still looks for the SYMB_ EQUAL ; but the parser no longer defines it (its commented out), something needs to be done in order to compile. One option is to uncomment the %token definition and use SYMB_ EQUAL instead of the literal "=" in the parser .y file.