1
votes

I have a symbol table that holds a variable/symbol's name, its data, and its data type(stored as a char). I would like it so that symbol is seen as an iexpr if its an integer or an rexpr if its a real. These are the rules as i have them now:

iexpr: INT_TOKEN
    | iexpr PLUS iexpr { $$ = $1 + $3; }
    | iexpr MINUS iexpr { $$ = $1 - $3; }
    | iexpr DIVIDE iexpr {$$ = $1/$3;}
    | iexpr MOD iexpr{$$ = $1 % $3;}
    | LPARENT iexpr RPARENT{$$=$2;}
    | SYMBOL {  symrec *s;
                s = getsym($1);
                if(s!=0){
                    if(s->type == 'i'){
                        $$ = atoi(s->data);
                    }
                }
             }
;
rexpr: REAL_TOKEN 
    | rexpr PLUS rexpr {  $$ = $1 + $3; }
    | rexpr MINUS rexpr { $$ = $1 - $3; }
    | iexpr PLUS rexpr {  $$ = (double) $1 + $3; }
    | iexpr MINUS rexpr { $$ = (double) $1 - $3; }
    | rexpr PLUS iexpr {  $$ = $1 + (double) $3; }
    | rexpr MINUS iexpr { $$ = $1 - (double) $3; }
    | rexpr DIVIDE rexpr {$$ = $1/$3;}
    | rexpr MULTIPLY rexpr{$$ = $1 * $3;}
    | rexpr DIVIDE iexpr {$$ = $1 / (double) $3;}
    | rexpr MULTIPLY iexpr {$$= $1 * (double) $3;}
    | iexpr DIVIDE rexpr {$$ = (double) $1 / $3;}
    | iexpr MULTIPLY rexpr {$$ = (double) $1 * $3;}
    | rexpr MOD rexpr {$$ = (int)$1 % (int)$3;}
    | rexpr MOD iexpr {$$ = (int)$1 % $3;}
    | iexpr MOD rexpr {$$ =  $1 % (int)$3;}
    | LPARENT rexpr RPARENT{$$ =$2;}
    | SYMBOL {  symrec *s;
                s = getsym($1);
                if(s!=0){
                    if(s->type == 'r'){
                        $$ = atof(s->data);
                    }
                }
             }
;

However the rule in rexpr is never used as it only ever sees it as an iexpr. How can i make it so that depending on the type descriptor it is seen as that type and not only as an integer?

EDIT: So i tried to change my lex file so that it will return a different token for each type. To do so i need to include my symboltable header file so i may check for that name and return a different symbol based on its type. Here is that code:

[a-zA-Z]+ { yylval.string = strdup(yytext);
            symrec *s;
            s = getsym(yylval.string);
            if(s!=0){
                if(s->type == 'r'){
                    return RSYMBOL;
                }else if(s->type == 'i'){
                    return ISYMBOL;
                }
            }else{
             return SYMBOL;
            }
          }

But now i have an error saying that i have multiple definitions of my header functions since i include it in both files.

2

2 Answers

2
votes

If you want the token type to vary depending on the symbol's declared type, you need to look the symbol up in the lexer (since that is what generates token types).

You'll actually need to return one of three different token types:

  • INT_SYMBOL
  • REAL_SYMBOL
  • UNDECLARED_SYMBOL

Generally speaking, it is better to do type checking in a separate pass over the AST after parsing is complete. (Or you can do it in a semantic action as you do a reduction, if you are not generating an AST.) That will let you produce better error messages, and it makes it much easier to continue the parse after a type error.

1
votes

If you want to do this, you need to have the lexer return different tokens for ISYMBOL and RSYMBOL, otherwise you'll get reduce/reduce conflicts between the two reductions for SYMBOL as the parser doesn't know which it is. That means you'll need to do the symbol tables lookup in the lexer action, not in the parser action.

Generally, trying to do typechecking like this in parser is a bad idea, as it makes the grammar much more complex and leads to many hard to resolve conflicts.