Lex和yacc程序找到回文字符串

时间:2015-01-26 12:20:10

标签: yacc lex

这是我的lex和yacc文件,用于识别回文字符串,但它为有效字符串和无效字符串提供“INVALID”。请帮我找到问题,我是lex和yacc的新手。 Thanx提前

LEX文件

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

%%
a return A;
b return B;
. return *yytext;
%%

YACC文件

%{
#include<stdio.h>
#include "lex.yy.c"
int i=0;
%}
%token A B
%%
S: pal '\n' {i=1;}
pal:
   | A pal A {printf("my3");i=1;}
   | B pal B {printf("my4");i=1;}       
   | A {printf("my1");i=1;}
   | B {printf("my2");i=1;}         
   ;
%%
int main()
{
    printf("Enter Valid string\n");
    yyparse();
    if(i==1)
    printf("Valid");
    return 0;
}
int yyerror(char* s)
{
    printf("Invalid\n");
    return 0;
}

示例:输入的字符串是:aba 预期输出应为有效,但它给出了无效

2 个答案:

答案 0 :(得分:0)

用Yacc解决这个问题是不可能的。

Yacc是LALR(1)解析器生成器。 LALR指的是一类语法。语法是推理解析的数学工具。一个parens指的是前瞻 - 这是我们在确定要遵循哪些替代产品(或“规则”)之前考虑的最大令牌数量。请记住,解析算法是一次通过,它不能回溯并尝试另一种替代方法,就像一些正则表达式引擎那样。

关于你的palindrom问题,当解析器遇到'a'时,它必须以某种方式选择正确的选择

  • 朋友: - 'a'本身就是一个有效的回文,我们称之为内核

  • 朋友:[A]朋友 - 外层,增加筑巢水平

  • 朋友:朋友[A] - 外层,降低筑巢水平

如果没有无限的前瞻,做出正确的选择是不可能的,但是Yacc只有一个前瞻性的标记。


Yacc处理这种语法的方式也很有趣。

如果语法不明确或不符合LR(1),则生成的堆栈自动机是非确定性的。有一些内置工具可以解决它。

第一个工具是优先级和关联性,用于处理编程语言中的运算符(此处不相关)。

另一个是怪癖 - 默认情况下,Yacc更喜欢“转变”为“减少”。这两个是针对解析算法的内部操作的技术性问题。基本上,令牌会“转移”到堆栈中。一旦顶部的一组令牌与规则匹配,就可以“减少”它们,用规则左侧的单个非终端替换整个组。

因此,一旦我们在顶部有'a',我们可以将它减少到朋友,或者我们可以在假设最终会出现嵌套的朋友时转移另一个令牌。 Yacc更喜欢后者。

这种偏好的原因是什么?大多数语言中if-then-else语句都存在同样的含糊之处。考虑两个嵌套的if语句,但只考虑一个else子句。 Yacc将其他内容附加到最内层的if语句中,这样做是正确的。

除了Yacc可以生成一个报告,突出显示语法中的问题,如上面提到的shift-reduce冲突。

答案 1 :(得分:0)

在@ChrisDod和@NickZavaritsky评论的延续中,我添加了一个glr(bison)解析器的工作版本。

%option noyywrap

%%
a    return A;
b    return B;
\n   return '\n';
.    {fprintf(stderr, "Error\n"); exit(1);}
%%

和Yacc / bison

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

%token A B
%glr-parser

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

pal: A pal A
   | B pal B
   | A
   | B
   |
   ;
%%
#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; }

词法分析器中引入了一些变化:(1)\n缺失; (2)未知的字符现在是致命的错误;

错误恢复error用于获取“无效回文”情况。