如何在Bison中明确定义一个语句开关分支?

如何在Bison中明确定义一个语句开关分支?,bison,Bison,我们希望定义一个分支,其中分支的定义被大括号包围,但是对于单个语句分支,大括号可以省略,比如单个语句if块 所需语法的示例(为清晰起见,以白色分隔): 我有以下语法,但它有移位/减少冲突: %token <union_string> T_ID "identifier" %% // begin rules program: statement_list ; statement_list: statement_list statement | e

我们希望定义一个分支,其中分支的定义被大括号包围,但是对于单个语句分支,大括号可以省略,比如单个语句
if

所需语法的示例(为清晰起见,以白色分隔):

我有以下语法,但它有移位/减少冲突:

%token <union_string> T_ID   "identifier"

%% // begin rules

program:
    statement_list
    ;

statement_list:
    statement_list statement
    | empty
    ;

statement:
    T_ID //added for completeness
    | "switch" switch_branch_list //the subject of the switch is elided for brevity
    ;

switch_branch_list:
    switch_branch_list "|" switch_branch
    | switch_branch
    ;

switch_branch:
    T_ID statement
    | T_ID "{" statement_list "}"
    ;

empty:
    ;
...
State 9

    5 statement: "switch" switch_branch_list .
    6 switch_branch_list: switch_branch_list . "|" switch_branch

    "|"  shift, and go to state 13

    "|"       [reduce using rule 5 (statement)]
    $default  reduce using rule 5 (statement)
...

如何解决给定语法中的shift/reduce冲突?

没有任何东西会终止switch语句,因此如果switch分支的目标是另一个switch语句,则程序将变得不明确

我建议不要让switch(或其他复合语句)成为分支的直接目标。坚持用大括号把它围起来

所以你会得到这样的结果:

statement:          simple_statement | compound_statement
simple_statement:   expr
                    | '{' statement_list '}'
                    | ...
compound_statement: switch_statement
                    | ...
statement_list      /* empty */ | statement_list statement  

switch_statement:   "switch" expr branch_list
branch_list:        branch | branch_list '|' branch
branch:             T_ID simple_statement
注意,我将块语句语法(
'{'statement\u list'}'
)作为
简单语句
的产品之一。通常情况下,这就是它的含义,就像括号中的表达式是标准表达式语法中
术语
的产物一样。但这只是一个建议

statement:          simple_statement | compound_statement
simple_statement:   expr
                    | '{' statement_list '}'
                    | ...
compound_statement: switch_statement
                    | ...
statement_list      /* empty */ | statement_list statement  

switch_statement:   "switch" expr branch_list
branch_list:        branch | branch_list '|' branch
branch:             T_ID simple_statement