1

タイトルで述べたように、flex と bison を使用してパーサーを作成しようとしています。ただし、ファイルをどのように変更しても、「1行目の構文エラー」というエラーが常に表示されます。

そこで、私の方法が正しいかどうかを確認するために、非常に簡単な例を書くことにしました。

これは単純なファイル「c1.isc」で、次のように読み取られます。

1 nand
2 nor
3 nand
4 nor
5 xor

これは token.l ファイルです。

%{
# include <stdio.h>
# include <string.h>
# include "parse.tab.h"


struct{
    char *symbol;
    int val;
} symtab[]={
"nand", 1,
"nor", 2,
"xor", 3,
"0",0
};

extern int yylval;

%}

DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+

%%

{DIGITS} {yylval=atoi(yytext);return(NUM);}
{ALPHA} {yylval=lookup(yytext);return(TYPE);}
{BLANK} ;

%%
lookup(s)
char* s;
{int i;
for (i=0;symtab[i].val!=0;i++)
{
if(strcmp(symtab[i].symbol,s)==0)
break;
}
return(symtab[i].val);
}

これは parse.y ファイルです

%{
# include <stdio.h>


extern FILE *yyin;

int gi;


%}

%token NUM TYPE

%%

parto: NUM
       {gi=$1;printf("num=%d\t",gi);}
       TYPE
       {gi=$3;printf("type=%d\n",gi);}
       ;

%%

yyerror(s)
char *s;
{
    extern int yylineno;
    extern char yytext[];

    fprintf(stderr, "%s in line %d near <%s>\n", s, yylineno, yytext);
    exit(-1);
}

main()
{FILE *x=fopen("c1.isc","r");
 yyin=x;
 yyparse();
} 

これは最も簡単な例だと思いますが、それでも、パーサーは最初の行を「num=1 gat=1」として出力し、次に「行 1 付近の構文エラー」を出力します。

理由は本当にわかりません。次の方法でテストしたので、トークン ファイルは正しいと確信しています。

%{
# include <stdio.h>
# include <string.h>


struct{
    char *symbol;
    int val;
} symtab[]={
"nand", 1,
"nor", 2,
"xor", 3,
"0",0
};

int val;

%}

DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+

%%

{DIGITS} {val=atoi(yytext);printf("num=%d\t",val);}
{ALPHA} {val=lookup(yytext);printf("type=%d\n",val);}
{BLANK} ;

%%
lookup(s)
char* s;
{int i;
for (i=0;symtab[i].val!=0;i++)
{
if(strcmp(symtab[i].symbol,s)==0)
break;
}
return(symtab[i].val);
}

main()
{
FILE *x=fopen("c1.isc","r");
yyin=x;
yylex();
}

そして、yylex() が機能する可能性があります。

私のコンパイル方法は、 1. flex token.l 2. bison -d parse.y 3. cc lex.yy.c parse.tab.c -lfl です。

次に、を取得a.outし、実行するa.outとエラーが表示されます。

これは、parse.y ファイルのルールが正しくないためだと思いますが、エラーが常に最初の行に表示されるのはなぜでしょうか?

私はそれを機能させるために次のルールを使用しました。

parti: 
     | parti parto
     ;

parto: NUM
       {gi=$1;printf("num=%d\t",gi);}
       TYPE
       {gi=$3;printf("type=%d\n",gi);}
       ;
4

1 に答える 1

2

ここで何かが足りないかもしれませんが、あなたの文法では、入力は単一の NUM と単一の TYPE である必要があるとだけ書かれています。それで全部です。したがって、パーサーがさらに多くのものを見つけると、入力の 2 行目にエラーが発生します。

複数の行を処理するルールを追加する必要があります。このようなもの:

lots_of_partos: parto lots_of_partos | /* empty */ ;
于 2013-03-19T15:57:47.390 に答える