0
votes

I am trying to write a yacc program which takes up the precedence of its operators from the user and then uses those precedence rules to evaluate an infix expression.

I tried defining the precedence by using character variables beside %left and then assigning these character variables the operator I wanted before calling the yyparse() function. Something like:

%left op1
%left op2
%left op3
%left op4

This failed to work by straight away giving compiling errors and shift/reduce error warnings. I also read about %prec but I don't think I can use that to solve this problem

1
yacc can't do this. It's operator precede me is defined statically.user207421

1 Answers

1
votes

The simple way to do this is to have the lexer return an appropriate tokentype based on the precedence. That means that it is the lexer and not the parser which gets configured with the precedence values. The parser simply has to have enough levels in its (fixed) grammar.

Here's a very simple example, only intended to illustrate the basic idea.

Scanner:

%{
  #include "parser.tab.h"
  extern int precs[256];
%}

%option noinput nounput noyywrap nodefault
%%
[[:space:]]+    ;
[[:digit:]]+    { yylval = atoi(yytext); return INT; }
.    {  yylval = (unsigned char)*yytext ;
        return precs[yylval] ? precs[yylval] : yylval;
     }

Parser:

/* Probably you will need more of these */
%token INT
%left OP1
%left OP2
%left OP3
%left OP4

%%
expr: expr OP1 expr
    | expr OP2 expr
    | expr OP3 expr
    | expr OP4 expr
    | INT

Driver

#include "parser.tab.h"
int precs[0] = { 0 };

int main(void) {
     precs['+'] = precs['-'] = OP1;
     precs['*'] = precs['/'] = OP2;
     return yyparse();
}