ccompiler-errorsbisonyacc

Issue with running a calculator YACC compiler


We are doing a calculator compiler, however, we haven't been able to run it because of file dependencies that we cannot understand.

The beginning of the yacc file is as so:

%{
#include "symtab.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

Table *t;

typedef struct {
    Val value;          // value
    char* type;         // type
    char* lexeme;       // lexeme
} IDAttr;

typedef struct {
    Val value;          // value
    char* type;         // type
} EAttr;

void yyerror(const char *s)
{
    fprintf(stderr, "%s\n", s);
    exit(1);
}

int yylex(void);
%}


%union {
       char* lexeme;        // lexeme
       EAttr eattr;     // attributes for expressions
       char* type;      // type
       IDAttr idattr;       // attributes for variables
       Val value;       // value
      }

Val is also a union, defined in symtab.h and it looks like this:

typedef union {
    int int_value;
    double real_value;
    char* boolean_value;
} Val;

The error is this:

make
flex calc-lex.l;
bison -vd calc-ambiguo.y;
gcc calc-ambiguo.tab.c lex.yy.c symtab.c -ly -ll
In file included from calc-lex.l:5:
calc-ambiguo.y:33:8: error: unknown type name ‘EAttr’
   33 |        EAttr eattr;             // attributes for expressions
      |        ^~~~~
calc-ambiguo.y:35:8: error: unknown type name ‘IDAttr’
   35 |        IDAttr idattr;           // attributes for variables
      |        ^~~~~~
calc-ambiguo.y:36:8: error: unknown type name ‘Val’
   36 |        Val value;               // value
      |        ^~~
...

Changing the order of operations in the makefile didn't fix the problem. As far as I understand Bison has a problem with nesting unions/structures and that's why EAttr and so on aren't recognized by the yacc file.


Solution

  • As far as I understand Bison has a problem with nesting unions/structures and that's why EAttr and so on aren't recognized by the yacc file.

    No, not at all. Bison itself makes no attempt to interpret your data types. It generates C source code in a fairly mechanical fashion, without understanding (or needing to) the C semantics of your data types or semantic actions. Similar for Flex. But you do need to have a certain amount of understanding of how the resulting generated artifacts will be structured and what they will contain, because it is partly on you to ensure that they are suitable for use.

    The prologue section of your grammar file contains definitions of type aliases EAttr and IDAttr, and apparently it causes one for Val to be #included. Bison copies that code into the generated parser file (calc-ambiguo.tab.c). You should see it somewhere near the top if you examine that file in an editor.

    The error messages you report are a bit confusing, because Flex and Bison go out of the way to try to make messages refer to lines of the scanner and parser definition files instead of the C source files generated from them, but note well that they start with ...

    In file included from calc-lex.l:5:

    This tells you that the issue is with building the scanner source (lex.yy.c, generated by Flex), not the parser source. And you will find that the aforementioned type definitions do not appear in that file, nor in the Bison-generated calc-ambiguo.tab.h that it presumably #includes. On the other hand, you will find that calc-ambiguo.tab.h does include a C union declaration derived rather directly from the Bison %union declaration appearing in your grammar file (go ahead, look). That union references types EAttr, IDAttr, and Val, for which no definitions have (yet) appeared in the scanner translation unit. That is the source of the problem.

    Even if your scanner does not assign type EAttr, IDAttr, or Val to any token it produces, it will still need to have definitions of those types. One possible solution would be to move the definitions of the EAttr and IDAttr structures into symtab.h, and add code to your lexer definition to include that header before the parser header. Something along these lines:

    %{
    #include "symtab.h"
    /* Presumably, this one already appears: */
    #include "calc-ambiguo.tab.h"
    %}
    

    If that does not appeal to you then I'm sure you can come up with something that does, now that you understand the nature of the problem.


    Additional notes: