【发布时间】:2014-10-13 19:58:11
【问题描述】:
我的主题有问题。我需要实现语法工具 flex。为此,我编写了上下文无关语法。以下是我应该能够处理的示例示例:
№1:
Rname 0|1
String1 {Rname}{Rname}*(111)
String2 {Rname}{Rname}*(000)
%%
№2:
%%
Rname 0|1
String1 {Rname}{Rname}*(111)
String2 {Rname}{Rname}*(000)
%%
{String1} {return 1;}
{String2} {return 1;}
%%
№3:
Name [a-zA-Z][a-zA-Z0-9]*
Words [a-zA-Z0-9]*
%%
{Identifier} {return AP_Name;}
{Words} {return AP_Words;}
%%
最复杂的例子,它考虑了所有选项:
A "abc" | "cba"
B "qwe"
C 111
D rty* | rty+
E ({C | D})*
%%
{String1} {return 1;}
{String2} {return 1;}
{A} {return AP_A;}
{B} {return AP_B;}
{C} {return AP_C;}
{D} {return AP_D;}
{E} {return AP_E;}
%%
我有一个flex文件如下:
%option noyywrap
%option yylineno
%option never-interactive
%{
#include <stdio.h>
#include "bison.tab.h"
%}
%%
[a-zA-Z][a-zA-Z0-9]* {return AP_Name;}
[a-zA-Z0-9]* {return AP_Words;}
\( {return AP_Bracket_open1;}
\) {return AP_Bracket_close1;}
\[ {return AP_Bracket_open2;}
\] {return AP_Bracket_close2;}
\{ {return AP_Bracket_open3;}
\} {return AP_Bracket_close3;}
\+ {return AP_Plus;}
\* {return AP_Multiply;}
\ '|' {return AP_Or;}
'%%' {return AP_Percentage;}
\; {return AP_Semicolon;}
\- {return AP_Dash;}
\" {return AP_Quote;}
%%
还有一个bison的文件如下:
%{
#include <stdio.h>
extern int yylineno;
void yyerror(char const *msg)
{
fprintf(stderr, "%d: %s\n", yylineno, msg);
}
int yyparse();
#define YYPRINT(file, type, value) fprintf(file, "%d", value);
%}
%token AP_Name
%token AP_Words
%token AP_Bracket_open1
%token AP_Bracket_close1
%token AP_Bracket_open2
%token AP_Bracket_close2
%token AP_Bracket_open3
%token AP_Bracket_close3
%token AP_Plus
%token AP_Multiply
%token AP_Or
%token AP_Percentage
%token AP_Semicolon
%token AP_Dash
%token AP_Quote
%%
S : Block1 AP_Percentage Block2 AP_Percentage;
Identifier : AP_Name | AP_Words;
Block1 : AP_Name Patern Block1 | ;
Patern : Regex | Regex Patern;
Regex : Value Plurality /* abc* */ /* abc+ */
| AP_Bracket_open1 Value AP_Bracket_close1 Plurality /* [abc] */ /* [abc]* */ /* [abc]+ */
| AP_Bracket_open2 Value AP_Bracket_close2 Plurality /* (abc) */ /* (abc)* */ /* (abc)+ */
| AP_Bracket_open3 Value AP_Bracket_close3 Plurality; /* {abc} */ /* {abc}* */ /* {abc}+ */
Plurality : AP_Plus | AP_Multiply |; /* + * */
Value : Identifier /* abc */
| AP_Quote Identifier AP_Quote /* "abc" */
| Identifier AP_Or Identifier /* abc | cba*/
| Identifier AP_Dash Identifier; /*abc - cba*/
Block2 : AP_Bracket_open3 Identifier AP_Bracket_close3 /* {abc} */
| AP_Bracket_open3 Identifier AP_Bracket_close3 AP_Bracket_open3 Identifier AP_Bracket_close3 /* {abc}{abc} */
|
;
%%
extern FILE *yyin;
int main()
{
yydebug=1;
yyin = fopen("test.txt","r");
if (yyparse() != 0)
return 0;
else
{
printf("Success\n");
return 0;
}
}
在工作中我使用以下一组参数:
flex lex.l
bison bison.y -d -t
cc lex.yy.c bison.tab.c bison.tab.h
现在我正在尝试处理我的第一个示例,最后出现以下错误:
Reducing stack by rule 4 (line 31):
$1 = token AP_Name (0)
$2 = nterm Patern ()
$3 = nterm Block1 ()
-> $$ = nterm Block1 ()
Stack now 0
Entering state 3
Now at end of input.
1: syntax error
Error: popping nterm Block1 ()
Stack now 0
Cleanup: discarding lookahead token $end (0)
Stack now 0
我是否正确理解野牛想要读取文件末尾,它看到文件末尾并同时关闭文件末尾读取失败的错误?
语法本身还没有完成(不确定我知道如何完成),但我希望它至少在这个阶段可以工作。
对不起我的英语。
更新:
我发现了一个导致错误的规则 - 它 Block1: AP_Name Patern Block1 |; 当我尝试重写语法时,我得到了这个:
%token AP_Name
%token AP_Word
%token AP_Percentage
%token AP_Plus
%token AP_Or
%token AP_Multiply
%token AP_Bracket_open1
%token AP_Bracket_close1
%token AP_Bracket_open2
%token AP_Bracket_close2
%token AP_Bracket_open3
%token AP_Bracket_close3
%token AP_Dash
%token AP_Quote
%%
S : Block1 AP_Percentage Block2 AP_Percentage;
Identifier : AP_Word | AP_Name;
Block1 : AP_Name Regex Block1 | ;
Regex : BracketO Regex
| Identifier AP_Or Regex /* a|b */
| Identifier Regex
| Identifier Plurality Regex /* abc+ or abc* */
| AP_Quote Identifier AP_Quote /* "abc" */
|
;
BracketO : AP_Bracket_open1 Class BracketC Plurality BracketO /* (abc) */
| AP_Bracket_open2 Class BracketC Plurality BracketO /* [abc] */
| AP_Bracket_open3 AP_Name AP_Bracket_close3 Plurality BracketO /* {abc} */
|
;
BracketC : AP_Dash Class BracketC /* [a-b] */
| AP_Or Class BracketC /* [a|b] or (a|b) */
| AP_Bracket_close1 /* ((abc)) */
| AP_Bracket_close2; /* [[abc]] */
Plurality : AP_Multiply | AP_Plus | ; /* * + */
Class : Identifier | BracketO; /* ({Rname}) */
Block2 : AP_Bracket_open3 Identifier AP_Bracket_close3 /* {abc} */
| AP_Bracket_open3 Identifier AP_Bracket_close3 AP_Bracket_open3 Identifier AP_Bracket_close3 /* {abc} {cba} */
|
;
%%
我不喜欢它,但它适用于 36 冲突转移/减少。 (这是我在评论中写的)
【问题讨论】:
-
我遇到了一个班次/减少冲突。你有吗?
-
@Rein:是的,有一个 shift/reduce 冲突,但它被视为警告,而不是错误,所以据我了解它应该可以工作,但要获得响应,需要更多迭代。并且在调试结果中显示(分析中的bison到文件末尾)
-
您不能忽略移位/减少冲突。试着先摆脱它。通常最好先验证语法叶是否真正起作用,然后逐步“向内”移动,每一步都有完整的测试。我猜在你的情况下,冲突导致选择了错误的分支,所以解析器期望的输入比它得到的多。
标签: bison yacc flex-lexer lex