I was without conflicts in my parser.y file. But introducing the actions to construct my syntactic tree resulted in 12 new shift/reduce conflicts. Do you guys have any idea on this?
Down bellow you have my parser.y and the compilation log.
Parser.y:
%{
#include <stdio.h>
#include "main.h"
#include "iks_ast.h"
%}
%union {
struct item_t *symbol;
struct node *tree;
}
%error-verbose
/* Declaração dos tokens da linguagem */
%token TK_PR_INT
%token TK_PR_FLOAT
%token TK_PR_BOOL
%token TK_PR_CHAR
%token TK_PR_STRING
%token TK_PR_IF
%token TK_PR_THEN
%token TK_PR_ELSE
%token TK_PR_WHILE
%token TK_PR_DO
%token TK_PR_INPUT
%token TK_PR_OUTPUT
%token TK_PR_RETURN
%token TK_OC_LE
%token TK_OC_GE
%token TK_OC_EQ
%token TK_OC_NE
%token TK_OC_AND
%token TK_OC_OR
%token<symbol> TK_LIT_INT
%token<symbol> TK_LIT_FLOAT
%token<symbol> TK_LIT_FALSE
%token<symbol> TK_LIT_TRUE
%token<symbol> TK_LIT_CHAR
%token<symbol> TK_LIT_STRING
%token<symbol> TK_IDENTIFICADOR
%token TOKEN_ERRO
%left TK_OC_OR TK_OC_AND
%left '<' '>' TK_OC_LE TK_OC_GE TK_OC_EQ TK_OC_NE
%left '+' '-'
%left '*' '/'
%nonassoc LOWER_THAN_ELSE
%nonassoc TK_PR_ELSE
%start programa
%type<symbol> decl_var
%type<symbol> cabecalho
%type<tree> programa
%type<tree> def_funcao
%type<tree> expressao
%type<tree> controle_fluxo
%type<tree> comando
%type<tree> chamada_funcao
%type<tree> entrada
%type<tree> saida
%type<tree> lista_expressoes
%type<tree> lista_expressoes_nao_vazia
%type<tree> retorna
%type<tree> bloco_comando
%type<tree> seq_comando
%type<tree> atribuicao
%type<tree> vetor_indexado
%%
programa: decl_global programa {$$ = $2;}
| def_funcao programa {$$ = create_node(IKS_AST_PROGRAMA); $$ = insert_child($$,$1); $1 = AST_link($1,$2);}
| {$$=NULL;}
;
decl_global: decl_var ';'
| decl_vetor ';'
| decl_var {error("Faltando o ';' no final do comando.", $1->line); return IKS_SYNTAX_ERRO;}
;
decl_local: decl_var ';' decl_local
|
;
/* Declaracao de variaveis e tipos*/
decl_var
: tipo_var TK_IDENTIFICADOR {$$ = $2;}
;
decl_vetor
: tipo_var TK_IDENTIFICADOR '[' TK_LIT_INT ']'
;
tipo_var: TK_PR_INT
| TK_PR_FLOAT
| TK_PR_BOOL
| TK_PR_CHAR
| TK_PR_STRING
;
/* Declaracao de funcao */
def_funcao: cabecalho decl_local bloco_comando {$$ = create_node(IKS_AST_FUNCAO); $$ = insert_child($$,$3);}
| cabecalho decl_local bloco_comando ';' {error("Declaração de função com ';' no final do comando.\n",$1->line); return IKS_SYNTAX_ERRO;}
;
chamada_funcao
: TK_IDENTIFICADOR '(' lista_expressoes ')' {$$ = AST_ident_exp(IKS_AST_CHAMADA_DE_FUNCAO,$1,$3);}
;
cabecalho: decl_var '(' lista_parametros ')' {$$ = $1;}
;
lista_parametros: lista_parametros_nao_vazia
|
;
lista_parametros_nao_vazia: parametro ',' lista_parametros_nao_vazia
| parametro
;
parametro: decl_var
;
comando: bloco_comando {$$ = $1;}
| controle_fluxo {$$ = $1;}
| atribuicao {$$ = $1;}
| entrada {$$ = $1;}
| saida {$$ = $1;}
| retorna {$$ = $1;}
| decl_var ';' {$$ = NULL;}
| chamada_funcao {$$ = $1;}
| ';' {$$ = NULL;}
;
bloco_comando: '{' seq_comando '}' {$$ = create_node(IKS_AST_BLOCO); $$ = insert_child($$,$2);}
;
seq_comando: seq_comando comando {$$ = AST_link($1,$2); }
| /* empty */ {//não sei se precisa
$$ = NULL;}
;
/* Atribuicoes de variaveis */
atribuicao: TK_IDENTIFICADOR '=' expressao {$$ = AST_ident_exp(IKS_AST_ATRIBUICAO,$1,$3);}
| vetor_indexado '=' expressao {$$ = create_node(IKS_AST_ATRIBUICAO); $$ = insert_child($$,$1); $$ = insert_child($$,$3); }
;
vetor_indexado
: TK_IDENTIFICADOR '[' expressao ']' { $$ = AST_ident_exp(IKS_AST_VETOR_INDEXADO,$1,$3);}
;
/* Entrada e Saida (Input e Output) */
entrada
: TK_PR_INPUT TK_IDENTIFICADOR {$$ = create_node(IKS_AST_INPUT); $$ = AST_input($$,$2);}
;
saida
: TK_PR_OUTPUT lista_expressoes_nao_vazia {$$ = create_node(IKS_AST_OUTPUT); $$ = insert_child($$,$2);}
;
lista_expressoes_nao_vazia: expressao ',' lista_expressoes_nao_vazia {$$ = AST_link($1,$3);}
| expressao {$$ = $1;}
;
retorna: TK_PR_RETURN expressao ';' {$$ = create_node(IKS_AST_RETURN); $$ = insert_child($$,$2);}
;
/* Fluxo de Controle */
controle_fluxo
: TK_PR_IF '(' expressao ')' TK_PR_THEN comando %prec LOWER_THAN_ELSE {$$ = AST_if($3,$6,NULL);}
| TK_PR_IF '(' expressao ')' TK_PR_THEN comando TK_PR_ELSE comando {$$ = AST_if($3,$6,$8);}
| TK_PR_WHILE '(' expressao ')' TK_PR_DO comando {$$ = AST_while(IKS_AST_WHILE_DO,$3,$6);}
| TK_PR_DO comando TK_PR_WHILE '(' expressao ')' {$$ = AST_while(IKS_AST_DO_WHILE,$2,$5);}
;
expressao: TK_IDENTIFICADOR {$$ = AST_ident_literal(IKS_AST_IDENTIFICADOR,$1);}
| TK_IDENTIFICADOR '[' expressao ']' {$$ = AST_ident_exp(IKS_AST_VETOR_INDEXADO,$1,$3);}
| TK_LIT_INT {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_FLOAT {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_FALSE {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_TRUE {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_CHAR {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| TK_LIT_STRING {$$ = AST_ident_literal(IKS_AST_LITERAL,$1);}
| expressao '+' expressao {$$ = create_node(IKS_AST_ARIM_SOMA); $$ = AST_expression($$,$1,$3); }
| expressao '-' expressao {$$ = create_node(IKS_AST_ARIM_SUBTRACAO); $$ = AST_expression($$,$1,$3); }
| expressao '*' expressao {$$ = create_node(IKS_AST_ARIM_MULTIPLICACAO); $$ = AST_expression($$,$1,$3); }
| expressao '/' expressao {$$ = create_node(IKS_AST_ARIM_DIVISAO); $$ = AST_expression($$,$1,$3); }
| expressao '<' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_L); $$ = AST_expression($$,$1,$3); }
| expressao '>' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_G); $$ = AST_expression($$,$1,$3); }
| '+' expressao {$$ = $2;}
| '-' expressao {$$ = create_node(IKS_AST_ARIM_INVERSAO); $$ = AST_expression($$,$2,NULL);}
| '(' expressao ')' {$$ = $2;}
| expressao TK_OC_LE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_LE); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_GE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_GE); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_EQ expressao {$$ = create_node(IKS_AST_LOGICO_COMP_IGUAL); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_NE expressao {$$ = create_node(IKS_AST_LOGICO_COMP_DIF); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_AND expressao {$$ = create_node(IKS_AST_LOGICO_E); $$ = AST_expression($$,$1,$3);}
| expressao TK_OC_OR expressao {$$ = create_node(IKS_AST_LOGICO_OU); $$ = AST_expression($$,$1,$3);}
| '!' expressao {$$ = create_node(IKS_AST_LOGICO_COMP_NEGACAO); $$ = AST_expression($$,$2,NULL);}
| chamada_funcao {$$ = $1;}
;
lista_expressoes: lista_expressoes_nao_vazia {$$ = $1;}
| {$$ = NULL;}
;
%%
error(char *s, int line){
printf("Erro na linha %d: %s", line,s);
}
Log:
[ 10%] [BISON][parser] Building parser with bison 3.0.2
parser.y: warning: 12 shift/reduce conflicts [-Wconflicts-sr]
[ 20%] [FLEX][scanner] Building scanner with flex 2.5.35
Scanning dependencies of target main
[ 30%] Building C object CMakeFiles/main.dir/scanner.c.o
scanner.l:11:1: warning: data definition has no type or storage class [enabled by default]
scanner.l: In function ‘yylex’:
scanner.l:84:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:85:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:87:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:89:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:91:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:93:16: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l:95:17: warning: assignment makes pointer from integer without a cast [enabled by default]
scanner.l: In function ‘install_id’:
scanner.l:145:4: warning: return makes integer from pointer without a cast [enabled by default]
[ 40%] Building C object CMakeFiles/main.dir/parser.c.o
[ 50%] Building C object CMakeFiles/main.dir/src/main.c.o
[ 60%] Building C object CMakeFiles/main.dir/src/comp_tree.c.o
Linking C executable main
[100%] Built target main
The shift-reduce conflicts are all the result of a single production and have nothing to do with the semantic actions.
The production is:
expressao : '!' expressao ;
And the problem is that ! does not appear in the precedence list.
Also, your grammar probably doesn't work the way you expect it to, because you don't have a specific precedence declaration to distinguish the unary + and - operators from their binary versions. As a result -a*b will parse as -(a*b) rather than (-a)*b. Of course, for integer arithmetic, these are the same, but it would be cleaner to get the syntax tree correct. You could fix both of those problems at once by adding
%right '!'
after all the %left declarations, and then adding %prec '!' to the end of the unary + and - productions.
I don't know why the problem manifested when you added semantic actions. Perhaps you also added the production for !.
Related
I'm trying to write a little interpreter with GNU bison.
I wanted to ask if anyone could explain the difference between the directive% right and% left and where my mistake is in the code below.
%token <flo> FLO
%token <name> NAME
%right '='
%left '+' '-'
%left '*' '/' '%'
%left '&' '|' 'x'
%left NEG NOT LOGIC_NOT
%left '^'
%left ARG
%type <flo> exp
%%
language: /* nothing */
| language statment
statment: '\n'
| exp
| error { yyerrok; }
;
exp: FLO { $$ = $1; }
| NAME '(' ')' { $$ = ycall($1); }
| NAME '(' exp ')' { $$ = ycall($1, $3); }
| NAME '(' exp ',' exp ')' { $$ = ycall($1, $3, $5); }
| NAME '=' exp { $$ = 1; ysetvar($1, $3); }
| NAME %prec VAR { $$ = ygetvar($1); }
| '_' exp %prec ARG { $$ = ygetarg($2, args); }
| '(' exp ')' { $$ = $2; }
/* 1 Operand */
| '-' exp %prec NEG { $$ = - $2; }
| '~' exp %prec NOT { $$ = ~ static_cast<int>($2); }
| '!' exp %prec LOGIC_NOT { $$ = ! static_cast<int>($2); }
/* 2 Operands */
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp { $$ = $1 / $3; }
| exp '%' exp { $$ = static_cast<int>($1) % static_cast<int>($3); }
| exp '^' exp { $$ = pow($1, $3); }
| exp '&' exp { $$ = static_cast<int>($1) & static_cast<int>($3); }
| exp '|' exp { $$ = static_cast<int>($1) | static_cast<int>($3); }
| exp 'x' exp { $$ = static_cast<int>($1) ^ static_cast<int>($3); }
;
Look at the y.output file produced by yacc or bison with the -v argument. The first conflict is in state 5:
State 5
7 exp: NAME . '(' ')'
8 | NAME . '(' exp ')'
9 | NAME . '(' exp ',' exp ')'
10 | NAME . '=' exp
11 | NAME .
'=' shift, and go to state 14
'(' shift, and go to state 15
'(' [reduce using rule 11 (exp)]
$default reduce using rule 11 (exp)
In this case the conflcit is when there's a '(' after a NAME -- this is an ambiguity in your grammar in which it might be a call expression, or it might be a simple NAME expression followed by a parenthesized expression, due to the fact that you have no separator between statements in your language.
The second conflict is:
State 13
4 statment: exp .
17 exp: exp . '+' exp
18 | exp . '-' exp
19 | exp . '*' exp
20 | exp . '/' exp
21 | exp . '%' exp
22 | exp . '^' exp
23 | exp . '&' exp
24 | exp . '|' exp
25 | exp . 'x' exp
'+' shift, and go to state 21
'-' shift, and go to state 22
'*' shift, and go to state 23
'/' shift, and go to state 24
'%' shift, and go to state 25
'&' shift, and go to state 26
'|' shift, and go to state 27
'x' shift, and go to state 28
'^' shift, and go to state 29
'-' [reduce using rule 4 (statment)]
$default reduce using rule 4 (statment)
which is essentially the same problem, this time with a '-' -- the input NAME - NAME might be a single binary subtract statements, or it might be two statements -- a NAME followed by a unary negate.
If you add a separator between statements (such as ;), both of these conflicts would go away.
I have started learning about YACC, and I have executed a few examples of simple toy programs. But I have never seen a practical example that demonstrates how to build a compiler that identifies and implements function definitions and function calls, array implementation and so on, nor has it been easy to find an example using Google search. Can someone please provide one example of how to generate the tree using YACC? C or C++ is fine.
Thanks in advance!
Let's parse this code with yacc.
file test contains valid C code that we want to parse.
int main (int c, int b) {
int a;
while ( 1 ) {
int d;
}
}
A lex file c.l
alpha [a-zA-Z]
digit [0-9]
%%
[ \t] ;
[ \n] { yylineno = yylineno + 1;}
int return INT;
float return FLOAT;
char return CHAR;
void return VOID;
double return DOUBLE;
for return FOR;
while return WHILE;
if return IF;
else return ELSE;
printf return PRINTF;
struct return STRUCT;
^"#include ".+ ;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
">" return GT;
"<" return LT;
"." return DOT;
\/\/.* ;
\/\*(.*\n)*.*\*\/ ;
. return yytext[0];
%%
file c.y for input to YACC:
%{
#include <stdio.h>
#include <stdlib.h>
extern FILE *fp;
%}
%token INT FLOAT CHAR DOUBLE VOID
%token FOR WHILE
%token IF ELSE PRINTF
%token STRUCT
%token NUM ID
%token INCLUDE
%token DOT
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE LT GT
%%
start: Function
| Declaration
;
/* Declaration block */
Declaration: Type Assignment ';'
| Assignment ';'
| FunctionCall ';'
| ArrayUsage ';'
| Type ArrayUsage ';'
| StructStmt ';'
| error
;
/* Assignment block */
Assignment: ID '=' Assignment
| ID '=' FunctionCall
| ID '=' ArrayUsage
| ArrayUsage '=' Assignment
| ID ',' Assignment
| NUM ',' Assignment
| ID '+' Assignment
| ID '-' Assignment
| ID '*' Assignment
| ID '/' Assignment
| NUM '+' Assignment
| NUM '-' Assignment
| NUM '*' Assignment
| NUM '/' Assignment
| '\'' Assignment '\''
| '(' Assignment ')'
| '-' '(' Assignment ')'
| '-' NUM
| '-' ID
| NUM
| ID
;
/* Function Call Block */
FunctionCall : ID'('')'
| ID'('Assignment')'
;
/* Array Usage */
ArrayUsage : ID'['Assignment']'
;
/* Function block */
Function: Type ID '(' ArgListOpt ')' CompoundStmt
;
ArgListOpt: ArgList
|
;
ArgList: ArgList ',' Arg
| Arg
;
Arg: Type ID
;
CompoundStmt: '{' StmtList '}'
;
StmtList: StmtList Stmt
|
;
Stmt: WhileStmt
| Declaration
| ForStmt
| IfStmt
| PrintFunc
| ';'
;
/* Type Identifier block */
Type: INT
| FLOAT
| CHAR
| DOUBLE
| VOID
;
/* Loop Blocks */
WhileStmt: WHILE '(' Expr ')' Stmt
| WHILE '(' Expr ')' CompoundStmt
;
/* For Block */
ForStmt: FOR '(' Expr ';' Expr ';' Expr ')' Stmt
| FOR '(' Expr ';' Expr ';' Expr ')' CompoundStmt
| FOR '(' Expr ')' Stmt
| FOR '(' Expr ')' CompoundStmt
;
/* IfStmt Block */
IfStmt : IF '(' Expr ')'
Stmt
;
/* Struct Statement */
StructStmt : STRUCT ID '{' Type Assignment '}'
;
/* Print Function */
PrintFunc : PRINTF '(' Expr ')' ';'
;
/*Expression Block*/
Expr:
| Expr LE Expr
| Expr GE Expr
| Expr NE Expr
| Expr EQ Expr
| Expr GT Expr
| Expr LT Expr
| Assignment
| ArrayUsage
;
%%
#include"lex.yy.c"
#include<ctype.h>
int count=0;
int main(int argc, char *argv[])
{
yyin = fopen(argv[1], "r");
if(!yyparse())
printf("\nParsing complete\n");
else
printf("\nParsing failed\n");
fclose(yyin);
return 0;
}
yyerror(char *s) {
printf("%d : %s %s\n", yylineno, s, yytext );
}
A Makefile to put it together. I use flex-lexer and bison but the example will also work with lex and yacc.
miniC: c.l c.y
bison c.y
flex c.l
gcc c.tab.c -ll -ly
Compile and parse the test code:
$ make
bison c.y
flex c.l
gcc c.tab.c -ll -ly
c.tab.c: In function ‘yyparse’:
c.tab.c:1273:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration]
yychar = yylex ();
^
c.tab.c:1402:7: warning: implicit declaration of function ‘yyerror’ [-Wimplicit-function-declaration]
yyerror (YY_("syntax error"));
^
c.y: At top level:
c.y:155:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
yyerror(char *s) {
^
$ ls
a.out c.l CMakeLists.txt c.tab.c c.y lex.yy.c Makefile README.md test
$ ./a.out test
Parsing complete
For reading resources I can recommend the books Modern Compiler Implementation in C by Andrew Appel and the flex/bison book by John Levine.
I am trying to enforce some parsing errors by defining a non-associative precedence.
Here is part of my grammar file:
Comparison :
Value ComparisonOp Value
{
$2->Left($1);
$2->Right($3);
$$ = $2;
}
;
Expressions like 1 = 2 should parse, but expressions like 1 = 2 = 3 are not allowed in the grammar. To accommodate this, I tried to make my operator non associative as follows:
%nonassoc NONASSOCIATIVE
.
.(rest of the grammar)
.
Comparison :
Value ComparisonOp Value %prec NONASSOCIATIVE
{
$2->Left($1);
$2->Right($3);
$$ = $2;
}
;
1 = 2 = 3 still passes, Could someone please tell me what I am doing wrong?
You need to set the associativity of the ComparisonOp token(s). Either
%nonassoc ComparisonOp NONASSOCIATIVE
if ComparisonOp is a token or something like
%nonassoc '=' '<' '>' NOT_EQUAL GREATOR_OR_EQUAL LESS_OR_EQUAL NONASSOCIATIVE
if you have mulitple tokens and ComparisonOp is a rule that expands to any of them
As a concrete example, the following works exactly like you are requesting:
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
void yyerror(const char *);
%}
%nonassoc '=' '<' '>' CMPOP
%left '+' '-' ADDOP
%left '*' '/' '%' MULOP
%token VALUE
%%
expr: expr cmp_op expr %prec CMPOP
| expr add_op expr %prec ADDOP
| expr mul_op expr %prec MULOP
| VALUE
| '(' expr ')'
;
cmp_op: '=' | '<' | '>' | '<' '=' | '>' '=' | '<' '>' ;
add_op: '+' | '-' ;
mul_op: '*' | '/' | '%' ;
%%
int main() { return yyparse(); }
int yylex() {
int ch;
while(isspace(ch = getchar()));
if (isdigit(ch)) return VALUE;
return ch;
}
void yyerror(const char *err) { fprintf(stderr, "%s\n", err); }
so if you are having other problems, try posting an MVCE that shows the actual problem you are having...
I am writing a simple parser in bison. The parser checks whether a program has any syntax errors with respect to my following grammar:
%{
#include <stdio.h>
void yyerror (const char *s) /* Called by yyparse on error */
{
printf ("%s\n", s);
}
%}
%token tNUM tINT tREAL tIDENT tINTTYPE tREALTYPE tINTMATRIXTYPE
%token tREALMATRIXTYPE tINTVECTORTYPE tREALVECTORTYPE tTRANSPOSE
%token tIF tENDIF tDOTPROD tEQ tNE tGTE tLTE tGT tLT tOR tAND
%left "(" ")" "[" "]"
%left "<" "<=" ">" ">="
%right "="
%left "+" "-"
%left "*" "/"
%left "||"
%left "&&"
%left "==" "!="
%% /* Grammar rules and actions follow */
prog: stmtlst ;
stmtlst: stmt | stmt stmtlst ;
stmt: decl | asgn | if;
decl: type vars "=" expr ";" ;
type: tINTTYPE | tINTVECTORTYPE | tINTMATRIXTYPE | tREALTYPE | tREALVECTORTYPE
| tREALMATRIXTYPE ;
vars: tIDENT | tIDENT "," vars ;
asgn: tIDENT "=" expr ";" ;
if: tIF "(" bool ")" stmtlst tENDIF ;
expr: tIDENT | tINT | tREAL | vectorLit | matrixLit | expr "+" expr| expr "-" expr
| expr "*" expr | expr "/" expr| expr tDOTPROD expr | transpose ;
transpose: tTRANSPOSE "(" expr ")" ;
vectorLit: "[" row "]" ;
matrixLit: "[" row ";" rows "]" ;
row: value | value "," row ;
rows: row | row ";" rows ;
value: tINT | tREAL | tIDENT ;
bool: comp | bool tAND bool | bool tOR bool ;
comp: expr relation expr ;
relation: tGT | tLT | tGTE | tLTE | tNE | tEQ ;
%%
int main ()
{
if (yyparse()) {
// parse error
printf("ERROR\n");
return 1;
}
else {
// successful parsing
printf("OK\n");
return 0;
}
}
The code may look long and complicated, but i think what i am going to ask does not need the full code, but in any case i preferred to write the code. I am sure my grammar is correct, but ambiguous. When i try to create the executable of the program by writing "bison -d filename.y", i get an error saying that conflicts: 13 shift/reduce. I defined the precedence of the operators at the beginning of this file, and i tried a lot of combinations of these precedences, but i still get this error. How can i remove this ambiguity? Thank you
tOR, tAND, and tDOTPROD need to have their precedence specified as well.
If I just add on to the following yacc file, will it turn into a parser?
/* C-Minus BNF Grammar */
%token ELSE
%token IF
%token INT
%token RETURN
%token VOID
%token WHILE
%token ID
%token NUM
%token LTE
%token GTE
%token EQUAL
%token NOTEQUAL
%%
program : declaration_list ;
declaration_list : declaration_list declaration | declaration ;
declaration : var_declaration | fun_declaration ;
var_declaration : type_specifier ID ';'
| type_specifier ID '[' NUM ']' ';' ;
type_specifier : INT | VOID ;
fun_declaration : type_specifier ID '(' params ')' compound_stmt ;
params : param_list | VOID ;
param_list : param_list ',' param
| param ;
param : type_specifier ID | type_specifier ID '[' ']' ;
compound_stmt : '{' local_declarations statement_list '}' ;
local_declarations : local_declarations var_declaration
| /* empty */ ;
statement_list : statement_list statement
| /* empty */ ;
statement : expression_stmt
| compound_stmt
| selection_stmt
| iteration_stmt
| return_stmt ;
expression_stmt : expression ';'
| ';' ;
selection_stmt : IF '(' expression ')' statement
| IF '(' expression ')' statement ELSE statement ;
iteration_stmt : WHILE '(' expression ')' statement ;
return_stmt : RETURN ';' | RETURN expression ';' ;
expression : var '=' expression | simple_expression ;
var : ID | ID '[' expression ']' ;
simple_expression : additive_expression relop additive_expression
| additive_expression ;
relop : LTE | '<' | '>' | GTE | EQUAL | NOTEQUAL ;
additive_expression : additive_expression addop term | term ;
addop : '+' | '-' ;
term : term mulop factor | factor ;
mulop : '*' | '/' ;
factor : '(' expression ')' | var | call | NUM ;
call : ID '(' args ')' ;
args : arg_list | /* empty */ ;
arg_list : arg_list ',' expression | expression ;
Heh
Its only a grammer of PL
To make it a parser you need to add some code into this.
Like there http://dinosaur.compilertools.net/yacc/index.html
Look at chapter 2. Actions
Also you'd need lexical analyzer -- 3: Lexical Analysis