parsingbisonyaccjison

How to define variable in jison/bison


I need to store data in my jison variable and then retrieve the stored value and perform a simple arithmetic operation. I tried conditional operation and expression are working fine, but after I added a variable rule I got an error.

My input is:

myvar1=3 myvar2=4 then myvar1+myvar2

And I get this error:

Parse error on line 1:
myvar=4
-----^
Expecting '=', 'EOF', '+', '-', '*', '/', '^', '<', '>', '==', '!=', '=<', '>=', got 'INVALID'

Here is my jison code:

/* description: Parses end executes mathematical expressions. */
/* lexical grammar */

%{

var sym={};
%}
%lex
%%

\s+                   /* skip whitespace */
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
[a-zA-Z]+\b           return 'VARIABLE'
"*"                   return '*'
"/"                   return '/'
"-"                   return '-'
"+"                   return '+'
"^"                   return '^'
"("                   return '('
")"                   return ')'
"PI"                  return 'PI'
"E"                   return 'E'
"<"                    return "<"
"=<"                    return "=<"
">="                    return ">="
">"                    return ">"
"=="                    return "=="
"!="                    return "!="
"IF"                   return "IF"
"THEN"                   return "THEN"
"ELSE"                   return "ELSE"
<<EOF>>               return 'EOF'

.                     return 'INVALID'

/lex

/* operator associations and precedence */
%left '<' '>' '==' '!='  '>=' '=<' '&&'
%left '+' '-'
%left '*' '/'
%left '^'
%left UMINUS

%start statement

%% /* language grammar */

statement
        : expressions
        | VARIABLE '=' expressions{ sym[$1]=$3}
;

expressions
    : e EOF
        {return $1;}
    ;

e
:VARIABLE
{ $$=sym[$1]=$3}
    | e '+' e
        {$$ = $1+$3;}

    | e '-' e
        {
$$ =function(){

return $1-$3;
}($1,$3)}
    | e '*' e
        {$$ = $1*$3;}
    | e '/' e
        {$$ = $1/$3;}
    | e '^' e
        {$$ = Math.pow($1, $3);}
    | '-' e %prec UMINUS
        {$$ = -$2;}
    | '(' e ')'
        {$$ = $2;}
    | NUMBER
        {$$ = Number(yytext);}
    | E
        {$$ = Math.E;}
    | PI
        {$$ = Math.PI;}
| e '<' e
{
$$=function(){
return $1<$3?true:false;
}($1,$3)
}
| e '>' e
{
$$=function(){
return $1>$3?true:false;
}($1,$3)
}

| e '==' e
{
$$=function(){
return $1==$3?true:false;
}($1,$3)
}
| e '!=' e
{
$$=function(){
return $1!=$3?true:false;
}($1,$3)
}
| e '=<' e
{
$$=function(){
return $1==$3?true:false;
}($1,$3)
}
| e '>=' e
{
$$=function(){
return $1>=$3?true:false;
}($1,$3)
}

|'IF''('e')''THEN''('e')''ELSE''('e')' 
{
$$= $3?$7:$11;
}
   ;

Solution

  • Your lexer never produces any = tokens. If you look at your list of token rules, the only one that would match a single = is ., which produces an INVALID token.

    So since the rule VARIABLE '=' expressions expects a = token, the match fails and you get the syntax error telling you that (among other things) a = would have been expected.

    Once you've fixed that, another issue will be that your expressions rule (which seems to be misnamed as it only seems to match a single expression) expects an EOF at the end, so your input file would have to end after the first assignment. In fact, multiple assignments wouldn't be supported anyway because you only ever match a single statement. So to fix this, you should remove the EOF from your expressions rule and instead add a rule that matches multiple statements followed by the end of file (if you need to have an EOF token at all) and then make that rule your starting rule.