Compiler construction yacc中的回文

Compiler construction yacc中的回文,compiler-construction,yacc,palindrome,Compiler Construction,Yacc,Palindrome,我写了一个yacc中数字回文的语法。但它不接受输入字符串。 这是我的语法: T: PAL '\n' {printf("Accepted\n");return 0;}; PAL: "1" PAL "1"| "2" PAL "2"| "3" PAL "3"| "4" PAL "4"| "5" PAL "5"| "6" PAL "6"| "7" PAL "7"| "8" PAL "8"|"1"|"2"|"3"|"4"|"5"|"6"

我写了一个yacc中数字回文的语法。但它不接受输入字符串。 这是我的语法:

T: PAL '\n' {printf("Accepted\n");return 0;};
PAL: "1" PAL "1"|
     "2" PAL "2"|
     "3" PAL "3"|
     "4" PAL "4"|
     "5" PAL "5"|
     "6" PAL "6"|
     "7" PAL "7"|
     "8" PAL "8"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"0"|;
当我输入数字时,它将显示错误消息

这是我的yacc文件内容

朋友
请帮帮我

@Ron是对的。yacc只能解析先行左-右(LALR)语法,回文不是LALR语法。这是因为要确定它是否是回文,需要的不仅仅是一次前瞻。yacc解析LALR(1)语言,这是上下文无关语言(CFL)的一个子类,设计用于在 线性时间。要解析回文,解析器必须能够确定它何时到达回文的中间。只需向前看一眼 (或任何固定数字)这是不可能的


查看此页了解更多详细信息。

最流行的yacc(在linux和许多其他系统中)之一是Bison,yacc的gnu版本有一些额外的功能。 除了LALR(1),它还可以生成LR(1)、GLR

GLR算法可用于该问题

当GLR解析器遇到冲突时,它会分裂 转换为多个解析器,每个解析器对应一个可能的移位或缩减。 然后,这些解析器照常进行,在锁定步骤中使用令牌。 某些堆栈可能会遇到其他冲突并进一步分裂, 结果是一个野牛GLR代替了一系列的状态 解析堆栈实际上是一个状态树

在以下内容中,您将看到一个使用的示例:

  • %glr parse
    选择glr解析器算法
  • 错误
    伪非终端(处理“无效”)
  • 更改了
    “1”
    ,类似于
    “1”
弹性:

野牛:

%{
#include <stdio.h>
int i=0;
%}

%glr-parser

%%

S  : pal   '\n'   {i=1; return 1 ;}
   | error '\n'   {i=0; return 1 ;}

pal: '0' pal '0' 
   | '1' pal '1' 
   ...
   | '0'       
   | '1'     
   |        
   ;
%%

#include "lex.yy.c"

int main() {
    yyparse();
    if(i==1) printf("Valid\n");
    else     printf("inValid\n");
    return 0;
}

int yyerror(char* s) { return 0; }
%{
#包括
int i=0;
%}
%glr解析器
%%
S:pal'\n'{i=1;返回1;}
|错误'\n'{i=0;返回1;}
好友:“0”好友“0”
|“1”朋友“1”
...
| '0'       
| '1'     
|        
;
%%
#包括“lex.yy.c”
int main(){
yyparse();
如果(i==1)printf(“有效\n”);
else printf(“无效\n”);
返回0;
}
int yyerror(char*s){返回0;}

请将获得的结果与原始版本和此版本进行比较,例如与
1
11
111
101101
以及一些无效表达式进行比较。

我在yacc文件中给出的错误消息。LR无法解析回文,不是吗?这并不是说你的语法是回文。除非你是这么说的。:-)你的意见是什么?(最好使用所述输入的十六进制转储)此外,由于语法认为它只会看到数字和“\n”,因此,如果您的lexer反对其他字符,而不是将所有非法标记传递给解析器,这将有助于证明。或者,改变错误以显示“不接受”的内容。但最有可能的是,问题不在于理解回文在LR解析能力之外。。。考虑输入“11”。你有一个问题并不是真正问题的核心:<代码> 1”/代码>与<代码> 1 的输入不匹配。在Y文件中,你需要使用<代码> '1' <代码>来匹配单个字符令牌。在.y文件中使用双引号(
)在大多数情况下会产生非常不直观和无用的效果。@ChrisDodd,谢谢你的重要评论。我一直避免使用
”。。。“
bison中的代币,因为我不知道从lexer中返回它们的好方法:我认为,你发表评论作为答案以澄清这个棘手的陷阱是很重要的☺@朗伯克,我明白你大部分观察的要点。如果你有时间,请检查我的回答是否有意义。清楚全面(+1)!尽管如此,我还是使用野牛的“新”功能添加了一个额外的答案——请检查这是否有意义。
%{
#include "y.tab.h"
%}

%%

\n {return *yytext;}

 . {return *yytext;}

 %%
%option noyywrap
%%
[0-9\n]    {return yytext[0]; }
.          {fprintf(stderr, "Error\n"); exit(1);}
%%
%{
#include <stdio.h>
int i=0;
%}

%glr-parser

%%

S  : pal   '\n'   {i=1; return 1 ;}
   | error '\n'   {i=0; return 1 ;}

pal: '0' pal '0' 
   | '1' pal '1' 
   ...
   | '0'       
   | '1'     
   |        
   ;
%%

#include "lex.yy.c"

int main() {
    yyparse();
    if(i==1) printf("Valid\n");
    else     printf("inValid\n");
    return 0;
}

int yyerror(char* s) { return 0; }