我试图对一般的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
做点什么,但我想不出这里发生了什么?
有什么帮助吗?
答案 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_tag
或opening_tag opening_tag
的开头。因此,在转移tag
之前,野牛无法判断是否减少空<
。
您应该可以通过移除tag
的空制作并为opening_tag closing_tag
添加显式作品来解决此问题。