Parsing 修复bison语法中的移位/减少冲突

Parsing 修复bison语法中的移位/减少冲突,parsing,bison,shift-reduce-conflict,Parsing,Bison,Shift Reduce Conflict,我为解析文本文件编写的bison语法为我提供了10个shift/reduce冲突。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_star

我为解析文本文件编写的bison语法为我提供了10个shift/reduce冲突。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
        {

        }
        ;
请帮我把这个修好


谢谢

yacc/bison解析器中的冲突意味着语法不是LALR(1)——这通常意味着某些东西要么不明确,要么需要一个以上的前瞻标记。默认的解决方案是选择总是转换而不是减少,或者选择总是减少第一个规则(用于减少/减少冲突),这将导致解析器识别语法描述的语言子集。这可能没问题,也可能没问题——对于模棱两可的语法,通常情况下“子集”实际上是整个语言,而默认的解析会删除模棱两可的情况。但是,对于需要更多前瞻性的情况以及一些模棱两可的情况,默认解析将导致无法解析语言中的某些内容

要找出任何给定冲突的错误,通常,
.output
文件会提供您所需的一切。在您的例子中,有3个状态存在冲突——通常,单个状态中的冲突都是一个相关的问题


此冲突是
log\u条目
body\u语句
规则之间的歧义:

log_entry: entry_prefix body_statements
         | entry_prefix TIME body_statements
body\u语句
可以是一个或多个
时间
/
日期
/
数据
/
标识符
标记的序列,因此当您有一个带有(eg)
条目前缀时间数据
的输入时,它可以是第一个
log\u条目
规则,其中
时间数据
作为
body\u语句
,也可以是第二个
log\u条目
规则,其中只有
数据
作为
body\u语句

这种情况下的默认解决方案将支持第二条规则(将
时间
作为
日志(log)语句
的一部分,而不是将其减少为
单词
作为
正文(body)语句
的一部分),并将产生一个“子集”这就是整个语言——唯一会被忽略的解析是不明确的。这种情况类似于某些语言中出现的“挂起的其他项”,其中默认的移位可能正是您想要的

要消除这种冲突,最简单的方法就是去掉
log\u entry:entry\u prefix TIME body\u语句
规则。这与默认分辨率的效果相反——现在时间将始终被视为身体的一部分。问题是现在 若您想以不同的方式对待身体中的初始
时间
,那个么您并没有一个单独的规则可以减少。如果您需要做一些特殊的事情,您可以检查以
时间开始的主体的操作


这是另一个模棱两可的问题,这一次是在
section\u body
中,它无法分辨一个
log\u条目的结束和另一个条目的开始。
部分\u正文
由一个或多个
日志\u条目
组成,每个条目都是
条目前缀
,后跟
正文\u语句
。如上所述的
body_语句
可以是一个或多个
word
标记,而
entry_前缀
可以是空的。因此,如果您有一个
节体
,它只是一个
单词
标记序列,那么它可以被解析为单个
日志条目
(不带
条目前缀
)或一个
日志条目
规则序列,每个规则都不带
条目前缀
。默认的转换为reduce resolution将有利于在减少
body_语句
之前将尽可能多的令牌放入单个
语句
,因此将其解析为单个
日志_条目
,这可能是正常的

要消除这种冲突,您需要重构语法。由于
log\u条目
中任何
语句
的尾部可能是另一个
log\u条目
,对于
body\u语句
,没有
entry\u前缀
语句
,因此您非常需要消除这种情况(这是默认冲突解决方法所做的)。假设您已通过删除第二个
log\u条目
规则修复了上一个冲突,则首先取消对
log\u条目
的分解,使问题案例成为自己的规则:

log_entry: ERROR_TOK body_statements
         | WARN_TOK body_statements
         | head_desc

initial_log_entry: log_entry
                 | statements
现在更改
section\u body
规则,使其仅对第一条使用拆分规则:

section_body: initial_log_entry
            | section_body log_entry
冲突消失了


这种冲突是一个前瞻性的模糊问题——因为
日期
时间
标记可以出现在
语句
中,当解析
时间戳
时,它无法分辨
语句
的结束位置和终端
日期
时间
的开始位置。默认分辨率将导致将任何
日期时间
对视为
时间戳
的结尾。现在,由于
时间戳
仅出现在
节头
的末尾,就在
节体
之前,并且
节体
可以以
语句
开头,这也可以


因此,很可能你的语法中的所有冲突都是可以忽略的,这样做甚至是可取的,因为这比重写语法来消除它们要简单。另一方面,冲突的存在使得修改语法变得更加困难,因为无论何时,您都需要重新检查所有冲突,以确保它们仍然是良性的


“冲突的默认解决”和“一个国家的默认行动”有一个令人困惑的问题。这两个默认值彼此无关——第一个是yacc/bison在构建解析器时做出的决策,第二个是解析器在构建时做出的决策
log_entry: ERROR_TOK body_statements
         | WARN_TOK body_statements
         | head_desc

initial_log_entry: log_entry
                 | statements
section_body: initial_log_entry
            | section_body log_entry
state 46
9 word: DATE .
17 time_stamp: statement DATE . TIME
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)