野牛模糊规则创建汇编语法

时间:2015-02-18 18:05:32

标签: bison

您好我为汇编程序定义了语法。 我无法解决歧义问题。

歧义发生在这个

某些操作码的间接寻址模式是操作码'('地址')'

例如,下面的代码是jmps到$ 2AFD的内容

jmp ($2AFD)

我允许地址为expr

jsr ($2222 + $23) * 2

是$ 448A的绝对跳转子程序

我有一个规则,其中的表达式包含在'('')'允许

这是我的操作码规则

opcodes:
    OPCODE                                              { $$ = opcode($1,    i, 0);                     }
    | OPCODE '#' expr                                   { $$ = opcode($1,    I, 1, $3);                 }
    | OPCODE expr                                       { $$ = opcode($1,    a, 1, $2);                 }
    | OPCODE expr 'X'                                   { $$ = opcode($1,   ax, 1, $2);                 }
    | OPCODE expr 'Y'                                   { $$ = opcode($1,   ay, 1, $2);                 }
    | OPCODE '(' expr ')'                               { $$ = opcode($1,  ind, 1, $3);                 }
    | OPCODE '(' expr 'X' ')'                           { $$ = opcode($1, zpix, 1, $3);                 }
    | OPCODE '(' expr ')' 'Y'                           { $$ = opcode($1, zpiy, 1, $3);                 }

这是我的表达规则

expr:
    INTEGER                                             { $$ = con($1);                                 }
    | SYMBOL                                            { $$ = id($1);                                  }
    | '-' expr %prec UMINUS                             { $$ = opr(UMINUS, 1, $2);                      }
    | math                                              { $$ = $1;                                      }
    | compares                                          { $$ = $1;                                      }
    | '(' expr ')'                                      { $$ = $2;                                      }
    ;

math: 
    expr OR expr                                        { $$ = opr(OR, 2, $1, $3);                      }
    | expr AND expr                                     { $$ = opr(AND, 2, $1, $3);                     }
    | expr '|' expr                                     { $$ = opr('|', 2, $1, $3);                     }
    | expr '&' expr                                     { $$ = opr('&', 2, $1, $3);                     }
    | expr '^' expr                                     { $$ = opr('^', 2, $1, $3);                     }
    | '~' expr                                          { $$ = opr('~', 1, $2);                         }
    | expr '+' expr                                     { $$ = opr('+', 2, $1, $3);                     }
    | expr '-' expr                                     { $$ = opr('-', 2, $1, $3);                     }
    | expr '*' expr                                     { $$ = opr('*', 2, $1, $3);                     }
    | expr '/' expr                                     { $$ = opr('/', 2, $1, $3);                     }
    ;

compares: 
    expr '<' expr                                       { $$ = opr('<', 2, $1, $3);                     }
    | expr '>' expr                                     { $$ = opr('>', 2, $1, $3);                     }
    | expr GE expr                                      { $$ = opr(GE, 2, $1, $3);                      }
    | expr LE expr                                      { $$ = opr(LE, 2, $1, $3);                      }
    | expr NE expr                                      { $$ = opr(NE, 2, $1, $3);                      }
    | expr EQ expr                                      { $$ = opr(EQ, 2, $1, $3);                      }
    ;

我的问题是如何最好地解决歧义。

默认规则正常工作,但我不希望100 sr冲突和2 rr冲突。我不想用%expect隐藏问题。 我想像使用UMINUS一样使用%prec。 我也在这个项目中使用flex。

1 个答案:

答案 0 :(得分:2)

我不知道使用优先级声明的好解决方案。这可能是可能的,但是在评论中需要更多的解释而不是黑客的价值。

我是这样做的。请注意,我已经消除了mathcompares之间的区别,因为我没有看到该值,并且它最终每次都会执行无用的单位缩减。但是,如果您的真实代码具有更复杂的操作,实际上根据差异执行某些操作,请务必将其还原。这与解决冲突无关。

这里的要点是避免将( expr )解析为表达式,除非它是表达式的一部分。因此,顶级expr不能有多余的括号,而子表达式可以用圆括号包围。

expr: INTEGER
    | SYMBOL
    | '-' subexpr %prec UMINUS
    | '~' subexpr %prec UMINUS  /* See note 1 below */
    | subexpr '+' subexpr
    | ...                       /* Everything which was in math */
    | subexpr '<' subexpr
    | ...                       /* Everything which was in compares */
    ;
subexpr:
      expr
    | '(' subexpr ')'
    ;

现在,您编写操作码规则的方式取决于您要实现的精确语法/语义。我从这开始,没有冲突:

opcodes:
      OPCODE
    | OPCODE '#' subexpr
    | OPCODE expr
    | OPCODE subexpr 'X'
    | OPCODE expr 'Y'
    | OPCODE '(' subexpr ')'
    | OPCODE '(' subexpr 'X' ')'
    | OPCODE '(' subexpr ')' 'Y'

请注意,expr(规则使用了a(不能以ay开头);这需要将它们分别与indzpiy规则区分开来。由于axzpix之间没有歧义(在后一种情况下X需要进入括号内),因此可以允许($2222 + $23) X进行解析它已写成($2222 + $23 X),但它很可能会反而表示语法错误。

总的来说,我认为这种语法模糊不清对人类读者来说是困惑的,应该避免,但我相信你有理由。


注意:

  1. 通常,所有前缀运算符都具有完全相同的优先级。如果使用优先级声明,我更喜欢使用相同的优先级标记来标记所有前缀运算符。但每个人都有自己的风格。 (所有后缀运算符通常也具有相同的优先级,对于运算符前缀更高。)