期望标识符或'(在Flex中的'{'令牌之前'

时间:2020-12-24 09:40:08

I am trying to use flex and yacc to parse 'C' source code. Unfortunately I am getting the error "expected identifier or '(' before '{' token" on lines 1,12,13,14... . Any ideas why?

我正在尝试使用flex和yacc来解析“C”源代码。不幸的是,我在第1、12、13、14行中得到了“预期标识符”或“(' before '{' token ')”的错误。任何想法为什么?

This is my flex file (called mini.l):

这是我的flex文件(名为mini.l):

%{

%}
digit [0-9]
letter [a-zA-Z]
number (digit)+
id (letter|_)(letter|digit|_)*
integer (int)
character (char)
comma [,]
%%
{integer} {return INT;}
{character} {return CHAR;}
{number} {return NUM;}
{id} {return IDENTIFIER;}
{comma} {return ',';}
[-+*/] {return *yytext;}
. {}
%%
main()
{
   yylex();
}

The corresponding yacc file (called my_yacc.y) is as shown below:

对应的yacc文件(my_yacc.y)如下:

%{
#include <ctype.h>
#include <stdio.h>
/* #include "myhead.h" */
#include "mini.l"
#define YYSTYPE double
# undef fprintf
%}

%token INT
%token CHAR
%token IDENTIFIER
%token NUM
%token ','
%left '+' '-'
%left '*' '/'
%right UMINUS

%%

lines:lines expr '\n' {printf("%g\n",$2);}
      |lines '\n'
      |D
      |     
      ;
expr :expr '*' expr {$$=$1*$3;}
     |expr '/' expr {$$=$1/$3;}
     |expr '+' expr {$$=$1+$3;}
     |expr '-' expr {$$=$1+$3;}
     |'(' expr ')' {$$=$2;}
     |'-' expr %prec UMINUS {$$=-$2;}
     |IDENTIFIER {}
     |NUM   {}  
     ;
T    :INT {}
     |CHAR {}
     ;
L    :L ',' IDENTIFIER {}
     |IDENTIFIER {}
     ;
D    :T L {printf("T is %g, L is %g",$1,$2);}
     ;

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

I am compiling the generated code using the commands:

我使用以下命令编译生成的代码:

flex mini.l
yacc my_yacc.y
gcc y.tab.c -ly

1 个解决方案

#1


1  

The errors you are seeing are coming from the C compiler and are caused by you misunderstanding of how flex and yacc work together. When I run it though the same tools as you, I get the following errors, as you also do, and as noted by @KeithThompson:

您看到的错误来自C编译器,是由于您对flex和yacc如何协同工作的误解造成的。当我使用与您相同的工具运行它时,我将得到以下错误,正如您所做的,并且如@KeithThompson所指出的:

In file included from my_yacc.y:5:0:
mini.l:1:1: error: expected identifier or '(' before '%' token
 %{
 ^
mini.l:5:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before' letter'
 letter [a-zA-Z]
 ^
mini.l:12:11: error: expected identifier or '(' before '{' token
 {integer} {return INT;}
           ^
... elided the rest ...

Although you have used the commands flex, yacc and gcc in the correct sequence, you have included the file mini.l in your bison input. This is incorrect. You should be including the output of the flex that was created from mini.l. This file is called lex.yy.c. It is also necessary to include this at the end on the yacc input file. (This is because if you don't you get the error found by @flolo). If you make the necessary changes to your yacc file, you will have this:

虽然您已经按照正确的顺序使用了flex、yacc和gcc命令,但是您已经包含了file mini。你的野牛输入。这是不正确的。您应该包含从mini.l创建的flex的输出。这个文件叫做lex.yy.c。还需要在yacc输入文件的末尾加上这个。(这是因为如果您没有找到@flolo找到的错误)。如果您对您的yacc文件做了必要的更改,您将得到以下内容:

%{
#include <ctype.h>
#include <stdio.h>
/* #include "myhead.h" */
/* #include "mini.l" */

#define YYSTYPE double
# undef fprintf
%}

%token INT
%token CHAR
%token IDENTIFIER
%token NUM
%token ','
%left '+' '-'
%left '*' '/'
%right UMINUS

%%

lines:lines expr '\n' {printf("%g\n",$2);}
      |lines '\n'
      |D
      |     
      ;
expr :expr '*' expr {$$=$1*$3;}
     |expr '/' expr {$$=$1/$3;}
     |expr '+' expr {$$=$1+$3;}
     |expr '-' expr {$$=$1+$3;}
     |'(' expr ')' {$$=$2;}
     |'-' expr %prec UMINUS {$$=-$2;}
     |IDENTIFIER {}
     |NUM   {}  
     ;
T    :INT {}
     |CHAR {}
     ;
L    :L ',' IDENTIFIER {}
     |IDENTIFIER {}
     ;
D    :T L {printf("T is %g, L is %g",$1,$2);}
     ;

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

#include "lex.yy.c"

If you run your command sequence on this now, you will find it both compiles and runs, and also process C language input correctly.

如果您现在在这个命令序列上运行命令序列,您将发现它同时编译和运行,并且还可以正确地处理C语言输入。

The mistake you made is a common error made by new users to the tools flex and yacc.

您所犯的错误是新用户对flex和yacc工具的常见错误。

#1


1  

The errors you are seeing are coming from the C compiler and are caused by you misunderstanding of how flex and yacc work together. When I run it though the same tools as you, I get the following errors, as you also do, and as noted by @KeithThompson:

您看到的错误来自C编译器,是由于您对flex和yacc如何协同工作的误解造成的。当我使用与您相同的工具运行它时,我将得到以下错误,正如您所做的,并且如@KeithThompson所指出的:

In file included from my_yacc.y:5:0:
mini.l:1:1: error: expected identifier or '(' before '%' token
 %{
 ^
mini.l:5:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before' letter'
 letter [a-zA-Z]
 ^
mini.l:12:11: error: expected identifier or '(' before '{' token
 {integer} {return INT;}
           ^
... elided the rest ...

Although you have used the commands flex, yacc and gcc in the correct sequence, you have included the file mini.l in your bison input. This is incorrect. You should be including the output of the flex that was created from mini.l. This file is called lex.yy.c. It is also necessary to include this at the end on the yacc input file. (This is because if you don't you get the error found by @flolo). If you make the necessary changes to your yacc file, you will have this:

虽然您已经按照正确的顺序使用了flex、yacc和gcc命令,但是您已经包含了file mini。你的野牛输入。这是不正确的。您应该包含从mini.l创建的flex的输出。这个文件叫做lex.yy.c。还需要在yacc输入文件的末尾加上这个。(这是因为如果您没有找到@flolo找到的错误)。如果您对您的yacc文件做了必要的更改,您将得到以下内容:

%{
#include <ctype.h>
#include <stdio.h>
/* #include "myhead.h" */
/* #include "mini.l" */

#define YYSTYPE double
# undef fprintf
%}

%token INT
%token CHAR
%token IDENTIFIER
%token NUM
%token ','
%left '+' '-'
%left '*' '/'
%right UMINUS

%%

lines:lines expr '\n' {printf("%g\n",$2);}
      |lines '\n'
      |D
      |     
      ;
expr :expr '*' expr {$$=$1*$3;}
     |expr '/' expr {$$=$1/$3;}
     |expr '+' expr {$$=$1+$3;}
     |expr '-' expr {$$=$1+$3;}
     |'(' expr ')' {$$=$2;}
     |'-' expr %prec UMINUS {$$=-$2;}
     |IDENTIFIER {}
     |NUM   {}  
     ;
T    :INT {}
     |CHAR {}
     ;
L    :L ',' IDENTIFIER {}
     |IDENTIFIER {}
     ;
D    :T L {printf("T is %g, L is %g",$1,$2);}
     ;

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

#include "lex.yy.c"

If you run your command sequence on this now, you will find it both compiles and runs, and also process C language input correctly.

如果您现在在这个命令序列上运行命令序列,您将发现它同时编译和运行,并且还可以正确地处理C语言输入。

The mistake you made is a common error made by new users to the tools flex and yacc.

您所犯的错误是新用户对flex和yacc工具的常见错误。