Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex/Lex - How to know if a variable was declared

My grammar allows:

C → id := E // assign a value/expression to a variable (VAR)

C → print(id) // print variables(VAR) values

To get it done, my lex file is:

[a-z]{
    yylval.var_index=get_var_index(yytext);
    return VAR;
}

get_var_index returns the index of the variable in the list, if it does not exist then it creates one. It is working!

The problem is:

  • Everytime a variable is matched on lex file it creates a index to that variable.
  • I have to report if 'print(a)' is called and 'a' was not declared, and that will never happen since print(a) always creates an index to 'a'.*

How can I solve it?

Piece of yacc file:

   %union {
int     int_val;
int var_index;
} 
%token <int_val>   INTEGER
%token <var_index>   VAR
...
| PRINT '(' VAR ')'{
 n_lines++;
printf("%d\n",values[$3]);
}
...
| VAR {$$ =values[$1];}
like image 621
Renaro Santos Avatar asked Oct 31 '22 13:10

Renaro Santos


1 Answers

This does seem a bit like a Computer Science class homework question for us to do.

Normally one would not use bison/yacc in this way. One would do the parse with bison/yacc and make a parse tree which then gets walked to perform semantic checks, such as checking for declaration before use and so on. The identifiers would normally be managed in a symbol table, rather than just a table of values to enable other attributes, such as declared to be managed. It's for these reasons that it looks like an exercise rather than a realistic application of the tools. OK; those disclaimers disposed of, lets get to an answer.

The problem would be solved by remembering what has been declared and what not. If one does not plan to use a full symbol table then a simple array of booleans indicating which are the valid values could be used. The array can be initialised to false and set to true on declaration. This value can be checked when a variable is used. As C uses ints for boolean we can use that. The only changes needed are in the bison/yacc. You omitted any syntax for the declarations, but as you indicated they are declared there must be some. I guessed.

%union {
int     int_val;
int var_index;
} 
int [MAX_TABLE_SIZE] declared; /* initialize to zero before starting parse */
%token <int_val>   INTEGER
%token <var_index>   VAR
...
| DECLARE '(' VAR ')' { n_lines++; declared[$3] = 1; }
...
| PRINT '(' VAR ')'{
 n_lines++;
if (declared[$3]) printf("%d\n",values[$3]);
else printf("Variable undeclared\n");
}
...
| VAR {$$ =value[$1]; /* perhaps need to show more syntax to show how VAR used */}
like image 173
Brian Tompsett - 汤莱恩 Avatar answered Nov 16 '22 12:11

Brian Tompsett - 汤莱恩