0
votes

I am working on a compiler using lex & yacc. I am having compilation errors and I believe if I can get one item solved, the rest will fall into place. I compile the project as such:

gcc -ll *.c -o <program_name>

The error I am specifically talking about is the following:

In file included from scanner.lex:11:
y.tab.h:6: error: syntax error before "tree"
y.tab.h:6: warning: no semicolon at end of struct or union
y.tab.h:6: error: syntax error before '}' token
y.tab.h:6: warning: data definition has no type or storage class
y.tab.h:7: error: syntax error before "yylval"
y.tab.h:7: warning: data definition has no type or storage class
scanner.lex: In function `yylex':
scanner.lex:55: error: request for member `i' in something not a structure or union
scanner.lex:56: error: request for member `i' in something not a structure or union
scanner.lex:57: error: request for member `f' in something not a structure or union

I cannot see anything wrong with the struct at all. I am hoping someone can point our the error and suggest a correction. I will post more code if necessary. I am using yacc and lex, not flex or bison. As for the version, I cannot tell you that. GCC is version 3.4.5

I hate doing this but per a request I have added the complete code. Sorry, I really cannot "pair" it down to a compilable version.

The yacc file:

%{

#include "tree.h"

extern tree root;


%}

%token <i> Ident 1 IntConst 2
%token <f> RealConst 3 
%token     And 4 Array 5
%token <i> Begin 6 
%token     Boolean 7 Div 8 Do 9 Else 10
%token     End 11 False 12 For 13 Goto 14 If 15
%token     Imply 16 Integer 17 Label 18 Not 19 Or 20
%token     Own 21 Procedure 22 Real 23 Step 24 String 25
%token     Then 26 True 27 Until 28 Value 29 While 30
%token     Plus 31 Minus 32 Mult 33 Divide 34 Less 35
%token     LessEq 36 Great 37 GreatEq 38 Eq 39 NotEq 40
%token     Comma 41 Colon 42 Semi 43 LParan 44 RParan 45
%token     LBrak 46 RBrak 47 Assign 48 

%start program

%union { tree t; int i; float f; }

%type <t>       program block optdecls decl vardecl type idlist arraydecl arraylist arrayseg
%type <t>       stmts stmt u_stmt assign dummy for_stmt if_stmt var factor term sum
%type <t>       brel relation bsecond bfactor bterm expr a_expr

%%

program 
    : block
            { root = $1; }
    ;

block
    : Begin optdecls stmts End
            { $$  = buildTree(Begin, $2, $3, buildTree(End,NULL, NULL,NULL)); }
    ;

optdecls
    : /* empty */
            { $$ = NULL; }
    | decl Semi optdecls
            { $$ = buildTree(Semi, $1, $3, NULL); }
            /*{$$ = buildTree(Semicol,$1, NULL, NULL);$$->next = $3;} */
    ;

decl    
    : vardecl
            { $$ = $1; }
    | arraydecl
            { $$ = $1; }
    ;

vardecl
    : type idlist
            { $$->next = $2; $$ = $1; } 
    ;

type
    : Real
            { $$ = buildFloatTree(Real, $<f>1); }
    | Integer
            { $$ = buildIntTree(Integer, $<i>1); }
    | Boolean
            { $$ = buildIntTree(Boolean, $<i>1); }
    ;

idlist
    : Ident
            { $$ = buildIntTree(Ident, $1); }
    | Ident Comma idlist
            { $$ = buildTree(Comma, buildIntTree(Ident, $1), $3, NULL); }   
    ;

arraydecl
    : Array arraylist
            { $$ = buildTree(Array, $2, NULL, NULL); }
    | type Array arraylist
            { $$ = buildTree(Array, $1, $3, NULL); }
    ;

arraylist
    : arrayseg
            { $$ = $1; }
    | arrayseg Comma arraylist
            { $$ = buildTree(Comma, $1, NULL, NULL);$$->next=$3 ; }
    ;

arrayseg
    : Ident LBrak a_expr Colon a_expr RBrak
            { $$ = buildTree(LBrak, buildIntTree(Ident, $1), $3, $5); }
    ;

stmts
    : stmt
            { $$ = $1; }
    | stmt Semi stmts
            { $$ = buildTree(Semi, $1, NULL, NULL);$$->next=$3 ; }
    ;

stmt
    : u_stmt
    | if_stmt
    | for_stmt
    ;

u_stmt
    : assign
    | dummy
    | block
    ;

assign
    : var Assign expr
            { $$ = buildTree(Assign, $1, $3, NULL); }
    | var Assign assign
            { $$ = buildTree(Assign, $1, NULL, NULL);$$->next=$3; }
    ;

dummy
    : /* empty */
            { $$ = NULL; }
    ;

for_stmt
    : For var Assign a_expr Step a_expr Until a_expr Do stmt
            { $$ = buildTree(For, $2, $4, buildTree(Step, $6, $8, $10)); }
    ;

if_stmt
    : If expr Then u_stmt
            { $$ = buildTree(If, $2, $4, NULL); }
    | If expr Then u_stmt Else stmt
            { $$ = buildTree(If, $2, $4, $6); }
    | If expr Then for_stmt
            { $$ = buildTree(If, $2, $4, NULL); }
    ;

var
    : Ident
            { $$ = buildIntTree(Ident, $1); }
    | Ident LBrak a_expr RBrak
            { $$ = buildTree(LBrak, buildIntTree(Ident, $1), $3, NULL); }
    ;

factor
    : IntConst
            { $$ = buildIntTree(IntConst, $1); }
    | RealConst
            { $$ = buildFloatTree(RealConst, $1); }
    | var
            { $$ = $1; }
    | LParan expr RParan
            /* {$$ = buildTree(LParen, $2, NULL, NULL);} */
            { $$ = $2; }
    ;

term
    : factor
            { $$ =$1; }
    | term Mult factor
            { $$ = buildTree(Mult, $1, $3, NULL); }
    | term Divide factor
            { $$ = buildTree(Divide, $1, $3, NULL); }
    | term Div factor
            { $$ = buildTree(Div, $1, $3, NULL); }
    ;

sum
    : term
            { $$ = $1; }
    | Plus term
            { $$ = buildTree(Plus, $2, NULL, NULL); }
    | Minus term
            { $$ = buildTree(Minus, $2, NULL, NULL); }
    | sum Plus term
            { $$ = buildTree(Plus, $1, $3, NULL); }
    | sum Minus term
            { $$ = buildTree(Minus, $1, $3, NULL); }
    ;

brel
    : sum
            { $$ = $1; }
    | True
            { $$ = buildTree(True, NULL, NULL, NULL); }
    | False
            { $$ = buildTree(False, NULL, NULL, NULL); }
    | sum relation sum
            { $$ = buildTree($1, $2, $3, NULL); }
    ;

relation
    : Less
            { $$ = buildTree(Less, NULL, NULL, NULL); }
    | LessEq
            { $$ = buildTree(LessEq, NULL, NULL, NULL); }
    | Great
            { $$ = buildTree(Great, NULL, NULL, NULL); }
    | GreatEq
            { $$ = buildTree(GreatEq, NULL, NULL, NULL); }
    | Eq
            { $$ = buildTree(Eq, NULL, NULL, NULL); }
    | NotEq
            { $$ = buildTree(NotEq, NULL, NULL, NULL); }
    ;

bsecond
    : brel
            { $$ = $1; }
    | Not brel
            { $$ = buildTree(Not, $2, NULL, NULL); }
    ;

bfactor
    : bsecond
            { $$ = $1; }
    | bfactor And bsecond
            { $$ = buildTree(And, $1, NULL, NULL); $$->next = $3; }
    ;

bterm
    : bfactor
            { $$ = $1; }
    | bterm Or bfactor
            { $$ = buildTree(Or, $1, NULL, NULL); $$->next = $3; }
    ;

expr    
    : bterm
            { $$ = $1; }
    | If expr Then bterm Else expr
            { $$ = buildTree(If, $2, $4, $6); }
    ;

a_expr
    : sum
            { $$ = $1; }
    | If expr Then sum Else a_expr
            { $$ = buildTree(If, $2, $4, $6); }
    ; 

%%

The lex file:

%{

#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
#include "tree.h"

int line_num = 1, position = 1;;

%}

L       [A-Za-z]
I       [0-9]
R       [0-9][0-9]*\.[0-9][0-9] 

%%

^".C".*         /* comment */;
[ \t]+            position += yyleng;
"and"           { position += 3; return And; }
"array"         { position += 5; return Array; }
"begin"         { position += 5; return Begin; }
"boolean"       { position += 7; return Boolean; }
"div"           { position += 3; return Div; }
"do"            { position += 2; return Do; }
"else"          { position += 4; return Else; }
"end"           { position += 3; return End; }
"false"         { position += 5; return False; }
"for"           { position += 3; return For; }
"goto"          { position += 4; return Goto; }
"if"            { position += 2; return If; }
"imply"         { position += 5; return Imply; }
"integer"       { position += 7; return Integer; }
"label"         { position += 5; return Label; }
"not"           { position += 3; return Not; }
"or"            { position += 2; return Or; }
"own"           { position += 3; return Own; }
"procedure"     { position += 9; return Procedure; }
"real"          { position += 4; return Real; }
"step"          { position += 4; return Step; }
"string"        { position += 6; return String; }
"then"          { position += 4; return Then; }
"true"          { position += 4; return True; }
"until"         { position += 5; return Until; }
"value"         { position += 5; return Value; }
"while"         { position += 5; return While; }

{L}({L}|{I})*   { position += yyleng; yylval.i = lookup (yytext); return Ident; }        
{I}+            { position += yyleng; yylval.i = atoi (yytext); return IntConst; }
{R}*            { position += yyleng; yylval.f = atof (yytext); return RealConst; }

"+"             { position += 1; return Plus; }
"-"             { position += 1; return Minus; }
"*"             { position += 1; return Mult; }
"/"             { position += 1; return Div; }
"<"             { position += 1; return Less; }
"<="            { position += 2; return LessEq; }
">"             { position += 1; return Great; }
">="            { position += 2; return GreatEq; }
"="             { position += 1; return Eq; }
"!="            { position += 2; return NotEq; }
","             { position += 1; return Comma; }
":"             { position += 1; return Colon; }
";"             { position += 1; return Semi; }
"("             { position += 1; return LParan; }
")"             { position += 1; return RParan; }
"["             { position += 1; return LBrak; }
"]"             { position += 1; return RBrak; }
":="            { position += 2; return Assign; }
"\n"            { line_num++; position = 1; newline(); }
.               { position += 1; yyerror ("Bad Character"); } 

%%

int yyerror (char strg[]) {
    printf("Error: %s at line %d, position %d, token %s\n", strg, line_num, position, yytext);
}

typedef char name[20];
    static char Names[200][20] = { "<no name>" };
    int top = 0;

int lookup (char strg[]) {
    int i;
    for (i = 0; i <= top; i++)
        if (strcmp (strg, Names[i]) == 0) return i;
    strcpy (Names[++top], strg);
    return top;
}

void printNames (void) {
    int i = 0;
    for (; i <= top; i++)
        printf("%d\t%strg\n", i, Names[i]);
}

char *id_name (int i) {
    return Names[i];
}

The tree.c:

#include <stdio.h>
#include "tree.h"
#include "y.tab.h"

tree buildTree (int kind, tree one, tree two, tree three)
{
    tree t = (tree)malloc(sizeof (node));
    t->kind = kind;
    t->first = one;
    t->second = two;
    t->third = three;
    t->next = NULL;
    return t;
}

tree buildIntTree (int kind, int val)
{
    tree t = (tree)malloc(sizeof (node));
    t->kind = kind;
    t->value = val;
    t->first = t->second = t->third = NULL;
    t->next = NULL;
    return t;
}

tree buildFloatTree (int kind, float f_val)
{
    tree t;
    t->kind = kind;
    t->value = f_val;
    t->first = t->second = t->third = NULL;
    t->next = NULL;
    return t; 
}

char TokName[][12] = 
    {"<eof>", 
    "Ident", "IntConst", "", "", "", "", "", "", "", "",
    "IF", "THEN", "END", "WHILE", "DO", "ELSE", "", "", "", "",
    "=", "(", ")", "+", "-", "*", "/", ".EQ.", ".NE.", ".LT.",
    ".LE.", ".GT.", ".GE.", "<eoln>", "+", "-", "", "", "", "",
    "<NoType>", "<IntType>", "<BoolType>", "<Prog>", "<Comma>"};
static int indent = 0;
void printTree (tree t)
{
    if (t == NULL) return;
    for (; t != NULL; t = t->next) {
            printf ("%*s%s", indent, "", TokName[t->kind]);
            switch (t->kind) {
                    case Ident: 
                            printf ("  %s (%d)\n", id_name (t->value), t->value);
                            break;
                    case IntConst:
                            printf ("  %d\n", t->value);
                            break;
                    default:
                            printf ("\n");
                            indent += 2;
                            printTree (t->first);
                            printTree (t->second);
                            printTree (t->third);
                            indent -= 2;
                    }
            }
}

The tree.h:

ypedef struct Node {
    int kind, value;
    float f_val;
    struct Node *first, *second, *third, *next;
} node;
typedef node *tree;

extern char TokName[][12];

tree buildTree (int kind, tree first, tree second, tree third);
tree buildIntTree (int kind, int val);
tree buildFloatTree (int kind, float f_val);
void printTree (tree);

And lastly main.c:

#include <stdio.h>
#include "tree.h"

extern FILE *yyin;
extern int yydebug;
tree root;

FILE    *outfile;

main (int argc, char **argv)
{
    if (argc != 2) { 
            fprintf (stderr, "%s: Insufficient Arguments\n", argv[0]); 
            exit(1);
            }
//      if ((yyin = freopen (argv[1], "r", yyin)) == 0L) {
    if ((yyin = fopen (argv[1], "r")) == 0L) {
            fprintf (stderr, "%s: Can't open Input File %s\n", argv[0], argv[1]); 
            exit(1);
            }

    yyparse();
    printTree (root);
    close (yyin);
}
1
I can't reproduce the error, although I don't have enough information to do more than make vague guesses. Instead of posting small parts of your project, please post a minimal compilable example showing the error, and specify the version of gcc and of yacc which you are using. (I suspect you are using byacc, but it might be an old version of bison.) Did you create or edit y.tab.h? And, optionally, why don't you let yacc/bison number the tokens instead of forcing your own defines, which is harder to maintain.rici
The definition of 'tree' needs to be visible to the compiler when it parses y.tab.h. eg. the .h file with 'tree' needs to be included before y.tab.h in scanner.lex.Charlie Burns
@rici Complete code added. Sorry I could not "pair" it down.c_sharp
@CharlieBurns #include "tree.h" is in the yacc file and I built the y.tab.h by yacc -d algol.yc_sharp
@user1318371: yacc doesn't put the contents of %{...%} into the .h file. So what CharlieBurns says is correct. If you were using bison (but I think you are not), you would have a different useful option.rici

1 Answers

1
votes

Your scanner program (lex file) needs to have #include "tree.h" before #include "y.tab.h" -- swap those two lines and it should compile.