5

私は flex/bison を理解しようとしていますが、ドキュメンテーションは私にとって少し難しく、おそらく何かをひどく誤解しています。ここにテストケースがあります: http://namakajiri.net/misc/bison_charlit_test/

ファイル "a" には 1 文字の "a" が含まれています。「foo.y」には、次のような簡単な文法があります。

%%

file: 'a' ;

生成されたパーサーはファイル "a" を解析できません。構文エラーが発生します。

文法「bar.y」はほぼ同じですが、名前付きトークンの文字リテラルを変更しただけです。

%token TOK_A;

%%

file: TOK_A;

そして、bar.lex で:

a       { return TOK_A; }

これはうまく機能します。

ドキュメントのように、文字リテラルをバイソン端末として直接使用しようとすると、何が間違っていますか?

文法を「statement: selector '{' property ':' value ';'」のようにしたい '}'" ではなく、"ステートメント: セレクター LBRACE プロパティ COLON 値 SEMIC RBRACE"...

debian wheezy で bison 2.5 と flex 2.5.35 を実行しています。

4

1 に答える 1

4

リライト

問題は実行時の問題であり、コンパイル時の問題ではありません。

問題は、根本的に異なる 2 つの語彙アナライザーがあることです。

bar.lexアナライザーは入力内の を認識し、それaを TOK_A として返し、それ以外はすべて無視します。

foo.lexアナライザーはすべての文字をエコーし​​ますが、それだけです。

foo.lex — 書かれているとおり

%{
#include "foo.tab.h"
%}

%%

foo.lex — 同等

%{
#include "foo.tab.h"
%}

%%
. { ECHO; }

foo.lex — 必須

%{
#include "foo.tab.h"
%}

%%
. { return *yytext; }

作業コード

これは、診断印刷を配置した実用的なコードです。

foo-lex.l

%%
. { printf("Flex: %d\n", *yytext); return *yytext; }

foo.y

%{
#include <stdio.h>
void yyerror(char *s);
%}

%%

file: 'a' { printf("Bison: got file!\n") }
    ;

%%

int main(void)
{
    yyparse();
}

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

コンパイルと実行

$ flex foo-lex.l
$ bison foo.y
$ gcc -o foo foo.tab.c lex.yy.c -lfl
$ echo a | ./foo
Flex: 97
Bison: got file!

$

詳細のポイント: その空白行はどのようにして出力に組み込まれたのでしょうか? 回答: 字句解析器がそこに配置しました。パターン.は改行と一致しないため、改行はルールがあるかのように扱われました。

\n    { ECHO; }

これが、入力が受け入れられた理由です。foo-lex.lファイルを次のように変更した場合:

%%
.       { printf("Flex-1: %d\n", *yytext); return *yytext; }
\n      { printf("Flex-2: %d\n", *yytext); return *yytext; }

その後、再コンパイルして再度実行すると、出力は次のようになります。

$ echo a | ./foo
Flex-1: 97
Bison: got file!
Flex-2: 10
syntax error
$

空白行なし。これは、有効な「ファイル」に改行を入れることが文法で許可されていないためです。

于 2012-11-02T15:31:06.833 に答える