简体   繁体   English

Yacc和Lex错误

[英]Yacc and Lex error

I'm doing an exercise using Yacc and Lex. 我正在使用Yacc和Lex进行练习。 The exercise is this: 练习是这样的:

image 图片

After created and compiled file .y and .lex i have no error with these 2 commands: 创建并编译文件.y和.lex之后,我对这2条命令没有错误:

bison -vd -o parser.c es.y
flex es.lex

After these i compile the parser.c with: 这些之后,我用以下命令编译parser.c:

gcc -g -c parser.c

and i have these errors: 我有这些错误:

In function yyparse:
parser.c:1304: error: incompatible types in assignment
parser.c:1334: error: incompatible types in assignment 
parser.c:1436: error: incompatible types in assignment
parser.c:1576: error: incompatible types in assignment

and other warnings. 和其他警告。 My lex file is this: 我的lex文件是这样的:

%{
#include "parser.h"
#include "def.h"
Value lexval;
%}
%option noyywrap
delimiter       [ \t\n]
spacing         {delimiter}+
digit           [0-9]
num             {digit}+
id              [a-zA-Z]+
sugar           [()*+=;]
%%
{spacing}       ;
{sugar}         {return(yytext[0]);}
if              {return(IF);}
else            {return(ELSE);}
then            {return(THEN);}
end             {return(END);}
write           {return(WRITE);}
{id}            {lexval.name = newstring(yytext); return(ID);}
{num}           {lexval.val=atoi(yytext); return(NUM);}
.               {return(ERROR);}
%%
char *newstring(char *s)
{
  char *p;
  p = malloc(sizeof(strlen(s)+1));
  strcpy(p, s);
  return(p);
}

my yacc file is: 我的yacc文件是:

%{
#include "def.h"
#define YYSTYPE struct{char *name; int val;}
#define NIL -1
extern Value lexval;
struct SymbTab{char label[30];int value;};
struct SymbTab tab[1000];
int val;
int size=0;
%}
%token ID NUM IF THEN ELSE END WRITE ERROR
%%
program : stat_list
             ;

stat_list : stat ';' stat_list
       | stat
       ;

stat : assign_stat
       | write_stat
       ;

assign_stat : ID {$$.name = lexval.name;} '=' expr {assign($2.name, $4.val);}
                  ;

expr : expr '+' term {$$.val = $1.val + $3.val;}
       | term {$$.val = $1.val;}
       ;

term : term '*' factor {$$.val = $1.val * $3.val;}
       | factor {$$.val = $1.val;}
       ;

factor : '(' expr ')' {$$.val = $2.val;}
       | if_expr {$$.val = $1.val;}
       | ID {if((val =lookup(lexval.name)) == NIL) error(); else $$.val = val;}
       | NUM {$$.val = lexval.val;}
       ;

if_expr : IF expr THEN expr ELSE expr END {$$.val = ($2.val ? $4.val : $6.val);}
       ;

write_stat : WRITE expr {printf("%d\n", $2.val);}
        ;
%%
int isPresent(char *lab)
{
    int i;
    for(i=0; i<size; i++)
        if(strcmp(tab[i].label,lab)==0)
            return i;
    return -1000;
}
void assign(char *l,int n)
{
    if(isPresent(l)==-1000)
    {
        strcpy(tab[size].label,l);
        tab[size].value=n;
        size++;
    }
    else
        tab[isPresent(l)].value=n;
}
int lookup(char *lab)
{
    int i;
    for(i=0; i<size; i++)
        if(strcmp(tab[i].label,lab)==0)
            return tab[i].value;
    return NIL;
}

void error(){ fprintf(stderr, "Syntax error\n"); }


int main(){ yyparse(); return 0; }

and my def.h is: 而我的def.h是:

#include <stdio.h>
#include <stdlib.h>

char *newstring(char*),
     *strcpy(char*, const char*);

void error(),assign(char *l,int n);

int lookup(char *lab),isPresent(char *lab),yylex(),main();

typedef union
{
    int val;
    char *name;
} Value;

I don't know how to resolve the errors that i get in parser.c 我不知道如何解决在parser.c中遇到的错误

The immediate problem is this: 直接的问题是:

#define YYSTYPE struct{char *name; int val;}

Here's a minimal example of what happens with the macro definition; 这是宏定义发生的最小示例; you can try it with your C compiler: 您可以使用C编译器进行尝试:

#define YYSTYPE struct{char *name; int val;}
int main(void) {
  YYSTYPE a = {"", 42};
  YYSTYPE b;
  b = a;
  return 0;
}

I'm unable to reproduce that error message with any version of gcc I have handy. 我无法使用任何方便的gcc版本重现该错误消息。 Both gcc 6.x and gcc 7.x produce the more meaningful error message (along with a large number of warnings): gcc 6.x和gcc 7.x都会产生更有意义的错误消息(以及大量警告):

struct.c:5:5: error: incompatible types when assigning to type ‘struct <anonymous>’ from type ‘struct <anonymous>’

Even so, the error needs a bit of explanation. 即使这样,该错误也需要一些解释。 Since YYSTYPE is a macro, the above code is exactly equivalent to the following in which the macro has been expanded: 由于YYSTYPE是一个宏,因此上面的代码与以下代码完全等效,其中宏已展开:

int main(void) {
  struct{char *name; int val;} a = {"", 42};
  struct{char *name; int val;} b;
  b = a;
  return 0;
}

In this snippet, a and b are of different types , because in C, every occurrence of an anonymous struct (that is, a struct without a tagname) is a distinct type. 在此代码段中, ab具有不同的类型 ,因为在C中,每次出现的匿名struct (即没有标记名的struct )都是不同的类型。

If the declarations of a and b had been in different files compiled separately, there would not be a problem, since the types of a and b are compatible. 如果ab的声明在不同的文件中分别编译,则不会出现问题,因为ab的类型兼容。 But in the same file, in order for aggregate assignment to be valid, the types of the value and the target variable must be the same, not just compatible. 但是在同一个文件中,为了使聚合分配有效,值和目标变量的类型必须相同,而不仅仅是兼容。 Since they are not the same, an error is produced. 由于它们不相同,因此会产生错误。

The simple fix is to make YYSTYPE a type alias rather than a macro: 简单的解决方法是使YYSTYPE成为类型别名,而不是宏:

typedef struct{char *name; int val;} YYSTYPE;

Type aliases are compile-time identifiers for a particular type; 类型别名是特定类型的编译时标识符。 that type is still an anonymous struct but now every declaration of a variable as YYSTYPE is the same anonymous struct . 这个类型仍然是一个匿名struct但是现在每个变量声明为YYSTYPE都是一个匿名struct

But that's not enough for bison/yacc, because you also have to tell it that you are providing your own definition of YYSTYPE . 但这对bison / yacc来说还不够,因为您还必须告诉它您正在提供自己的YYSTYPE定义。 Otherwise, it will insert its own definition (which is a type-alias for int ), and that will create a different compiler error because YYSTYPE will have two incompatible definitions. 否则,它将插入自己的定义(这是int的类型别名),这将创建另一个编译器错误,因为YYSTYPE将具有两个不兼容的定义。 So you need to also include the following rather odd-looking macro definition: 因此,您还需要包括以下看起来很奇怪的宏定义:

#define YYSTYPE YYSTYPE

If YYSTYPE is defined as a macro, then bison/yacc's default definition will not be included. 如果将YYSTYPE定义为宏,那么将不包括bison / yacc的默认定义。 (It's protected with #ifdef YYSTYPE .) The apparently recursive definition is not a problem because the C preprocessor only substitutes a given name once; (它受#ifdef YYSTYPE的保护。)显然,递归定义不是问题,因为C预处理器只替换一次给定名称;因此,C预处理器只替换一次给定名称。 once it replaces YYSTYPE with YYSTYPE , it won't try the replacement again. 一旦将YYSTYPE替换为YYSTYPE ,就不会再尝试替换。


The assignment itself seems to me to betray a woeful lack of knowledge about the yacc/lex toolset. 在我看来,任务本身似乎背叛了对yacc / lex工具集的严重缺乏了解。 The use of lexval instead of using the standard yylval mechanism creates a number of issues for the grammar; 使用lexval而不是使用标准yylval机制会产生很多语法问题。 for example, it forces the use of a mid-rule action in your assignment production. 例如,它会在您的assignment制作中强制使用中间规则操作。 I have no idea why you were asked to do that, and I suspect that much of whatever else you are being taught about yacc and lex is also incorrect. 我不知道为什么要请你这样做,而且我怀疑关于yacc和lex的其他许多知识也是不正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM