我为解析文本文件而编写的野牛语法给了我10个移位/减少冲突。 parser.output文件对我没有帮助。该文件提供了以下信息:
State 38 conflicts: 5 shift/reduce
State 40 conflicts: 4 shift/reduce
State 46 conflicts: 1 shift/reduce
Grammar
0 $accept: session $end
1 session: boot_data section_start
2 boot_data: head_desc statement head_desc head_desc
3 head_desc: OPEN_TOK BOOT_TOK statement CLOSE_TOK
4 | OPEN_TOK statement CLOSE_TOK
5 statement: word
6 | statement word
7 word: IDENTIFIER
8 | TIME
9 | DATE
10 | DATA
11 section_start: section_details
12 | section_start section_details
13 | section_start head_desc section_details
14 $@1: /* empty */
15 section_details: $@1 section_head section_body section_end
16 section_head: START_TOK head_desc START_TOK time_stamp
17 time_stamp: statement DATE TIME
18 section_body: log_entry
19 | section_body log_entry
20 log_entry: entry_prefix body_statements
21 | entry_prefix TIME body_statements
22 body_statements: statement
23 | head_desc
24 entry_prefix: ERROR_TOK
25 | WARN_TOK
26 | /* empty */
27 $@2: /* empty */
28 section_end: END_TOK statement $@2 END_TOK head_desc
state 38
8 word: TIME .
21 log_entry: entry_prefix TIME . body_statements
OPEN_TOK shift, and go to state 1
TIME shift, and go to state 6
DATE shift, and go to state 7
DATA shift, and go to state 8
IDENTIFIER shift, and go to state 9
OPEN_TOK [reduce using rule 8 (word)]
TIME [reduce using rule 8 (word)]
DATE [reduce using rule 8 (word)]
DATA [reduce using rule 8 (word)]
IDENTIFIER [reduce using rule 8 (word)]
$default reduce using rule 8 (word)
head_desc go to state 39
statement go to state 40
word go to state 11
body_statements go to state 45
state 39
23 body_statements: head_desc .
$default reduce using rule 23 (body_statements)
state 40
6 statement: statement . word
22 body_statements: statement .
TIME shift, and go to state 6
DATE shift, and go to state 7
DATA shift, and go to state 8
IDENTIFIER shift, and go to state 9
TIME [reduce using rule 22 (body_statements)]
DATE [reduce using rule 22 (body_statements)]
DATA [reduce using rule 22 (body_statements)]
IDENTIFIER [reduce using rule 22 (body_statements)]
$default reduce using rule 22 (body_statements)
word go to state 19
state 46
9 word: DATE .
17 time_stamp: statement DATE . TIME
TIME shift, and go to state 48
TIME [reduce using rule 9 (word)]
$default reduce using rule 9 (word)
我语法的等同部分是:
statement : word
{
printf("WORD\n");
$$=$1;
}
|statement word
{
printf("STATEMENTS\n");
$$=$1;
printf("STATEMENT VALUE== %s\n\n",$$);
}
;
word : IDENTIFIER
{
printf("IDENTIFIER\n");
$$=$1;
}
|TIME
{
printf("TIME\n");
$$=$1;
}
|DATE
{
printf("DATE\n");
$$=$1;
}
|DATA
{
}
;
section_start : section_details
{
printf("SINGLE SECTIONS\n");
}
|section_start section_details
{
printf("MULTIPLE SECTIONS\n");
}
|section_start head_desc section_details
;
section_details :
{
fprintf(fp,"\n%d:\n",set_count);
}
section_head section_body section_end
{
printf("SECTION DETAILS\n");
set_count++;
}
;
section_head : START_TOK head_desc START_TOK statement time_stamp
{
printf("SECTION HEAD...\n\n%s===\n\n%s\n",$2,$4);
fprintf(fp,"%s\n",$4);
}
;
time_stamp : DATET TIME
{
}
;
section_body :log_entry
{
}
|section_body log_entry
{
}
;
log_entry : entry_prefix body_statements
{
}
|entry_prefix TIME body_statements
{
}
;
body_statements : statement
{
}
|head_desc
{
}
;
请帮我解决这个问题..
由于
答案 0 :(得分:6)
yacc / bison解析器中的冲突意味着语法不是LALR(1) - 这通常意味着某些内容不明确或需要超过1个前瞻标记。默认分辨率是选择始终转换为缩小,或选择始终缩小第一个规则(用于减少/减少冲突),这将导致解析器识别语法描述的语言的子集。这可能是也可能不是 - 在模糊语法的情况下,通常情况是"子集"事实上是整个语言,默认的分辨率削减了模糊的情况。但是,对于需要更多前瞻的案例,以及一些不明确的案例,默认解决方案将导致无法解析语言中的某些内容。
要弄清楚在任何给定冲突中出现了什么问题,.output
文件通常会为您提供所需的一切。在您的情况下,您有3个冲突状态 - 通常单个州的冲突都是一个相关的问题。
state 38
8 word: TIME .
21 log_entry: entry_prefix TIME . body_statements
这种冲突在log_entry
和body_statements
的规则之间存在歧义:
log_entry: entry_prefix body_statements
| entry_prefix TIME body_statements
body_statements
可以是一个或多个TIME
/ DATE
/ DATA
/ IDENTIFIER
令牌的序列,因此当您输入时(例如)entry_prefix TIME DATA
,它可以是第一个log_entry
规则,TIME DATA
为body_statements
,第二个log_entry
规则只有DATA
body_statements
。
在这种情况下,默认解决方案将支持第二条规则(转而将TIME
视为log_statements
的一部分,而不是将其缩减为word
,使其成为{{1}的一部分}}),并将导致"子集"这就是整个语言 - 唯一会错过的解析是模棱两可的。这是一个类似于"悬挂其他"在某些语言中显示,默认转移可能完全符合您的要求。
要消除这种冲突,最简单的方法就是摆脱body_statements
规则。这与默认分辨率具有相反的效果 - 现在TIME将始终被视为BODY的一部分。问题是现在
如果你想以不同的方式对待身体中的初始log_entry: entry_prefix TIME body_statements
,你就不会有单独的规则来减少。如果您需要做一些特别的事情,您可以检查以TIME
开头的正文的操作。
TIME
这是另一个模棱两可的问题,这次是state 40
6 statement: statement . word
22 body_statements: statement .
,它无法告诉一个section_body
结束而另一个开始的位置。 log_entry
由一个或多个section_body
组成,每个log_entries
都是entry_prefix
,后跟body_statements
。如上所述,body_statements
可能是一个或多个word
令牌,而entry_prefix
可能是空的。因此,如果您的section_body
只是一个word
令牌序列,则可以将其解析为单个log_entry
(没有entry_prefix
)或序列log_entry
个规则,每个规则都没有entry_prefix
。默认转换为降低分辨率有利于在减少statement
之前将尽可能多的令牌放入单个body_statement
中,因此将其解析为单个log_entry
,这可能没问题。< / p>
要消除这种冲突,您需要重构语法。由于statement
中任何log_entry
的尾部可能是另一个log_entry
,而entry_prefix
没有statement
而body_statements
log_entry
,因此您非常需要消除这种情况(这是默认的冲突解决方案)。假设您已删除第二个log_entry
规则修复了之前的冲突,请首先解除log_entry: ERROR_TOK body_statements
| WARN_TOK body_statements
| head_desc
initial_log_entry: log_entry
| statements
以使问题案例成为其自己的规则:
section_body
现在更改section_body: initial_log_entry
| section_body log_entry
规则,使其仅针对第一个使用拆分规则:
state 46
9 word: DATE .
17 time_stamp: statement DATE . TIME
冲突消失了。
DATE
这种冲突是一种前瞻性歧义问题 - 因为TIME
和statement
令牌可以出现在time_stamp
中,在解析statement
时它无法分辨DATE
结束且终端TIME
/ DATE TIME
开始的位置。默认解决方案将导致将time_stamp
对视为time_stamp
的结尾。既然section_head
仅出现在section_body
的{{1}}末尾,而section_body
可能以statement
开头,那么这可能就好了好。
所以很可能你的语法中的所有冲突都是可以忽略的,甚至可能这样做,因为这比重写语法以摆脱它们更简单。另一方面,冲突的存在使修改语法变得更加困难,因为任何时候你都需要重新检查所有冲突,以确保它们仍然是良性的。
&#34;冲突的默认解决方案&#34;是一个令人困惑的问题。和&#34;状态&#34;中的默认操作。这两个默认值彼此无关 - 第一个是yacc / bison在构建解析器时做出的决定,第二个是解析器在运行时做出的决定。所以当你在输出文件中有一个状态时:
state 46
9 word: DATE .
17 time_stamp: statement DATE . TIME
TIME shift, and go to state 48
TIME [reduce using rule 9 (word)]
$default reduce using rule 9 (word)
这告诉你,野牛已确定此状态的可能操作是转换到状态48还是减少规则9.只有在前瞻标记是TIME
时才能执行转移操作,而减少许多先行令牌都可以采取行动,包括时间。因此,为了最小化表大小,而不是枚举reduce操作的所有可能的下一个令牌,它只是说$default
- 这意味着只要没有先前的操作与前瞻令牌匹配,解析器就会执行reduce操作。 $default
操作始终是该州的最后一个操作。
因此,处于此状态的解析器代码将在操作列表中向下运行,直到找到与前瞻令牌匹配并执行该操作的操作。仅包含TIME [reduce
...操作,以明确表示此状态存在冲突,并且当前瞻为reduce
时,禁止行动TIME
的野牛解决了该问题。因此,为此状态构造的实际操作表将只有一个操作(在令牌TIME
上移位),然后是默认操作(在任何令牌上减少)。
请注意,尽管事实并非所有令牌在word
之后都是合法的,但它仍然可以减少任何令牌。这是因为即使下一个令牌是非法的,因为减少不会从输入读取它(它仍然是前瞻),后来的状态(在可能多次默认减少之后)将看到(并报告)错误。