在 bison 中使用字符文字作为终端

mel*_*iko 5 c yacc lex bison flex-lexer

我正在尝试了解 flex/bison,但文档对我来说有点困难,而且我可能严重误解了某些内容。这是一个测试用例:http : //namakajiri.net/misc/bison_charlit_test/

文件“a”包含单个字符“a”。“foo.y”有一个像这样的简单语法:

%%

file: 'a' ;
Run Code Online (Sandbox Code Playgroud)

生成的解析器无法解析文件“a”;它给出了一个语法错误。

语法“bar.y”几乎相同,只是我更改了命名标记的字符文字:

%token TOK_A;

%%

file: TOK_A;
Run Code Online (Sandbox Code Playgroud)

然后在 bar.lex 中:

a       { return TOK_A; }
Run Code Online (Sandbox Code Playgroud)

这个工作得很好。

我在尝试将字符文字直接用作野牛终端时做错了什么,就像在文档中一样?

我希望我的语法看起来像“statement: selector '{' property ':' value ';' '}'" 而不是 "statement: selector LBRACE property COLON value SEMIC RBRACE"...

我在 debian wheezy 中运行 bison 2.5 和 flex 2.5.35。

Jon*_*ler 4

改写

\n\n

该问题是运行时问题,而不是编译时问题。

\n\n

问题是你有两个完全不同的词法分析器。

\n\n

分析器识别输入中的bar.lexana并将其作为 TOK_A 返回并忽略其他所有内容。

\n\n

分析器foo.lex会回显每一个字符,但仅此而已。

\n\n

foo.lex \xe2\x80\x94 写入

\n\n
%{\n#include "foo.tab.h"\n%}\n\n%%\n
Run Code Online (Sandbox Code Playgroud)\n\n

foo.lex \xe2\x80\x94 等效项

\n\n
%{\n#include "foo.tab.h"\n%}\n\n%%\n. { ECHO; }\n
Run Code Online (Sandbox Code Playgroud)\n\n

需要 foo.lex \xe2\x80\x94

\n\n
%{\n#include "foo.tab.h"\n%}\n\n%%\n. { return *yytext; }\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

工作代码

\n\n

这是一些带有诊断打印的工作代码。

\n\n

foo-lex.l

\n\n
%%\n. { printf("Flex: %d\\n", *yytext); return *yytext; }\n
Run Code Online (Sandbox Code Playgroud)\n\n

foo.y

\n\n
%{\n#include <stdio.h>\nvoid yyerror(char *s);\n%}\n\n%%\n\nfile: \'a\' { printf("Bison: got file!\\n") }\n    ;\n\n%%\n\nint main(void)\n{\n    yyparse();\n}\n\nvoid yyerror(char *s)\n{\n    fprintf(stderr, "%s\\n", s);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

编译执行

\n\n
$ flex foo-lex.l\n$ bison foo.y\n$ gcc -o foo foo.tab.c lex.yy.c -lfl\n$ echo a | ./foo\nFlex: 97\nBison: got file!\n\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

细节点:那个空行是如何进入输出的?答:词法分析器把它放在那里。该模式.与换行符不匹配,因此换行符被视为存在规则:

\n\n
\\n    { ECHO; }\n
Run Code Online (Sandbox Code Playgroud)\n\n

这就是接受输入的原因。如果您将foo-lex.l文件更改为:

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

然后重新编译并再次运行,输出为:

\n\n
$ echo a | ./foo\nFlex-1: 97\nBison: got file!\nFlex-2: 10\nsyntax error\n$\n
Run Code Online (Sandbox Code Playgroud)\n\n

没有空行。这是因为语法不允许换行符出现在有效的“文件”中。

\n