4

「C」ソースコード を使用flexして解析しようとしています。yacc残念ながら、1、12、13、14 行目で「'{' トークンの前に識別子または '(' が必要です」というエラーが表示されます。

これは私の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();
}

対応する 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);
}  
*/  

次のコマンドを使用して、生成されたコードをコンパイルしています。

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

1 に答える 1

1

表示されているエラーは 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 ...

コマンドflexを正しい順序で使用しましたが、バイソン入力にファイルを含めましyaccた。これは正しくありません。から作成されたフレックスの出力を含める必要があります。このファイルは. また、これをyacc 入力ファイルの最後に含める必要があります。(これは、@flolo によって検出されたエラーが表示されないためです)。ファイルに必要な変更を加えると、次のようになります。gccmini.lmini.llex.yy.cyacc

%{
#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"

これでコマンド シーケンスを実行すると、コンパイルと実行の両方が行われ、C 言語入力も正しく処理されることがわかります。

あなたが犯した間違いは、新しいユーザーがツールflexおよびを使用する際に犯す一般的なエラーyaccです。

于 2015-04-09T20:53:06.063 に答える