转移/减少野牛的冲突

时间:2014-02-02 17:42:48

标签: c++ bison yacc lex

我试图对一般的html代码进行简单的解析。

这是我的整个野牛文件(example4.y)。

%{
#include <iostream>
#include <cstring>
using namespace std;

extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE *yyin;

void yyerror(const char *str)
{
    cout<<"Error: "<<str<<"\n";
}

int yywrap()
{
    return 0;
}

main()
{
    yyparse();
}

%}

%token NUMBER LANGLE CLOSERANGLE RANGLE SLASH ANYTHING

%union
{
    int intVal;
    float floatVal;
    char *strVal;
}

%%

tag:    |   
        opening_tag anything closing_tag 
        {
          if(strcmp($<strVal>1,$<strVal>3)==0){
                cout<<"\n[i] Tag Matches: "<<$<strVal>1;
                cout <<"\n[!] The text: "<<$<strVal>2;
            } else {
                cout<<"\n[!] Tag Mismatch: "<<$<strVal>1<<" and "<<$<strVal>3;
            }
            $<strVal>$ = $<strVal>2;
        }
        |
        opening_tag tag closing_tag 
        {
          if(strcmp($<strVal>1,$<strVal>3)==0){
                cout<<"\n[i] Tag Matches: "<<$<strVal>1;
                cout <<"\n[!] The text: "<<$<strVal>2;
            } else {
                cout<<"\n[!] Tag Mismatch: "<<$<strVal>1<<" and "<<$<strVal>3;
            }
        }
        ;
opening_tag:
        LANGLE ANYTHING RANGLE
        {
            $<strVal>$ = $<strVal>2;
        }
        ;
anything:
        ANYTHING
        {
            $<strVal>$ = $<strVal>1;
        }
        ;
closing_tag:
        LANGLE SLASH ANYTHING RANGLE
        {
            $<strVal>$= $<strVal>3;
        }        
%%

我得到的错误是:example4.y: conflicts: 1 shift/reduce

我认为它必须与opening_tag tag closing_tag做点什么,但我想不出这里发生了什么? 有什么帮助吗?

2 个答案:

答案 0 :(得分:2)

这是因为有两个以opening_tag开头的规则。解析器必须通过lookint在最前面的一个令牌之间来决定规则,但它不能。 <FOO>可能导致任一规则,这需要两个前瞻标记。

你可以这样做:

 tag     : /* nothing */
         | opening_tag contents closing_tag
         ;
 contents: tag
         | anything
         ;

UPDATE 这种新语法有不同的转移/减少冲突。 (UPDATE2:或者也许是同一个)。由于标记可以为空,因此解析器无法决定在此输入中执行的操作:

<Foo> <...
     ^
     |
     input is here

如果下一个符号是斜杠,那么我们有一个结束标记,并且应该匹配空标记规则。如果下一个符号不是斜杠,那么我们有一个开始标记,并且应该匹配非空标记规则。但解析器无法知道,只允许查看<

解决方案是为</组合创建一个新的令牌LANGLE_SLASH。

答案 1 :(得分:2)

问题是tag可能为空,因此<x><可能是opening_tag tag closing_tagopening_tag opening_tag的开头。因此,在转移tag之前,野牛无法判断是否减少空<

您应该可以通过移除tag的空制作并为opening_tag closing_tag添加显式作品来解决此问题。