Bison 歧义规则创建汇编语法
Bison ambiguous rule creating assembler grammar
你好,我有一个为汇编程序定义的语法。
我无法解决歧义。
歧义由此产生
一些操作码的间接寻址模式是操作码'('address')'
例如下面的代码跳转到 $2AFD
的内容
jmp (AFD)
我允许地址是一个表达式
但是
jsr (22 + ) * 2
是 $448A 的绝对跳转子程序
我有一个规则,允许包含在'(' ')'中的表达式
这是我的操作码规则
opcodes:
OPCODE { $$ = opcode(, i, 0); }
| OPCODE '#' expr { $$ = opcode(, I, 1, ); }
| OPCODE expr { $$ = opcode(, a, 1, ); }
| OPCODE expr 'X' { $$ = opcode(, ax, 1, ); }
| OPCODE expr 'Y' { $$ = opcode(, ay, 1, ); }
| OPCODE '(' expr ')' { $$ = opcode(, ind, 1, ); }
| OPCODE '(' expr 'X' ')' { $$ = opcode(, zpix, 1, ); }
| OPCODE '(' expr ')' 'Y' { $$ = opcode(, zpiy, 1, ); }
这是我的表达规则
expr:
INTEGER { $$ = con(); }
| SYMBOL { $$ = id(); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, ); }
| math { $$ = ; }
| compares { $$ = ; }
| '(' expr ')' { $$ = ; }
;
math:
expr OR expr { $$ = opr(OR, 2, , ); }
| expr AND expr { $$ = opr(AND, 2, , ); }
| expr '|' expr { $$ = opr('|', 2, , ); }
| expr '&' expr { $$ = opr('&', 2, , ); }
| expr '^' expr { $$ = opr('^', 2, , ); }
| '~' expr { $$ = opr('~', 1, ); }
| expr '+' expr { $$ = opr('+', 2, , ); }
| expr '-' expr { $$ = opr('-', 2, , ); }
| expr '*' expr { $$ = opr('*', 2, , ); }
| expr '/' expr { $$ = opr('/', 2, , ); }
;
compares:
expr '<' expr { $$ = opr('<', 2, , ); }
| expr '>' expr { $$ = opr('>', 2, , ); }
| expr GE expr { $$ = opr(GE, 2, , ); }
| expr LE expr { $$ = opr(LE, 2, , ); }
| expr NE expr { $$ = opr(NE, 2, , ); }
| expr EQ expr { $$ = opr(EQ, 2, , ); }
;
我的问题是如何最好地解决歧义。
默认规则可以正常工作,但我不希望出现 100 次 sr 冲突和 2 次 rr 冲突。我不想用 %expect 来隐藏问题。
我想像对 UMINUS 一样使用 %prec。
我也在这个项目中使用了flex。
我不知道使用优先声明的好的解决方案。这可能是可能的,但它需要在评论中进行更多的解释,而不是黑客的价值。
这是我的做法。请注意,我已经消除了 math
和 compares
之间的区别,因为我看不到该值,并且每次都只是执行无用的单位缩减。但是,如果您的真实代码具有更复杂的操作,实际上根据差异执行某些操作,则一定要恢复它。它与解决冲突无关。
这里的重点是避免 ( 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 ')'
;
现在,您如何编写操作码规则取决于您要实现的精确 syntax/semantics。我将从这个开始,它没有冲突:
opcodes:
OPCODE
| OPCODE '#' subexpr
| OPCODE expr
| OPCODE subexpr 'X'
| OPCODE expr 'Y'
| OPCODE '(' subexpr ')'
| OPCODE '(' subexpr 'X' ')'
| OPCODE '(' subexpr ')' 'Y'
请注意,我为 a
和 ay
规则使用了 expr
(不能以 (
开头);这需要将它们分别与 ind
和 zpiy
规则区分开来。由于 ax
和 zpix
之间没有歧义(在后一种情况下 X
需要放在括号内),因此可以允许 (22 + ) X
被解析为它被写成 (22 + X)
但它很可能应该表示语法错误。
总的来说,我认为这种句法近乎歧义的做法会让人类读者感到困惑,应该避免,但我相信你有自己的理由。
备注:
- 通常,所有前缀运算符都具有完全相同的优先级。如果使用优先级声明,我更愿意用相同的优先级标记标记所有前缀运算符。但每个人都有自己的风格。 (所有后缀运算符也具有相同的优先级,通常高于前缀运算符。)
你好,我有一个为汇编程序定义的语法。 我无法解决歧义。
歧义由此产生
一些操作码的间接寻址模式是操作码'('address')'
例如下面的代码跳转到 $2AFD
的内容jmp (AFD)
我允许地址是一个表达式
但是
jsr (22 + ) * 2
是 $448A 的绝对跳转子程序
我有一个规则,允许包含在'(' ')'中的表达式
这是我的操作码规则
opcodes:
OPCODE { $$ = opcode(, i, 0); }
| OPCODE '#' expr { $$ = opcode(, I, 1, ); }
| OPCODE expr { $$ = opcode(, a, 1, ); }
| OPCODE expr 'X' { $$ = opcode(, ax, 1, ); }
| OPCODE expr 'Y' { $$ = opcode(, ay, 1, ); }
| OPCODE '(' expr ')' { $$ = opcode(, ind, 1, ); }
| OPCODE '(' expr 'X' ')' { $$ = opcode(, zpix, 1, ); }
| OPCODE '(' expr ')' 'Y' { $$ = opcode(, zpiy, 1, ); }
这是我的表达规则
expr:
INTEGER { $$ = con(); }
| SYMBOL { $$ = id(); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, ); }
| math { $$ = ; }
| compares { $$ = ; }
| '(' expr ')' { $$ = ; }
;
math:
expr OR expr { $$ = opr(OR, 2, , ); }
| expr AND expr { $$ = opr(AND, 2, , ); }
| expr '|' expr { $$ = opr('|', 2, , ); }
| expr '&' expr { $$ = opr('&', 2, , ); }
| expr '^' expr { $$ = opr('^', 2, , ); }
| '~' expr { $$ = opr('~', 1, ); }
| expr '+' expr { $$ = opr('+', 2, , ); }
| expr '-' expr { $$ = opr('-', 2, , ); }
| expr '*' expr { $$ = opr('*', 2, , ); }
| expr '/' expr { $$ = opr('/', 2, , ); }
;
compares:
expr '<' expr { $$ = opr('<', 2, , ); }
| expr '>' expr { $$ = opr('>', 2, , ); }
| expr GE expr { $$ = opr(GE, 2, , ); }
| expr LE expr { $$ = opr(LE, 2, , ); }
| expr NE expr { $$ = opr(NE, 2, , ); }
| expr EQ expr { $$ = opr(EQ, 2, , ); }
;
我的问题是如何最好地解决歧义。
默认规则可以正常工作,但我不希望出现 100 次 sr 冲突和 2 次 rr 冲突。我不想用 %expect 来隐藏问题。 我想像对 UMINUS 一样使用 %prec。 我也在这个项目中使用了flex。
我不知道使用优先声明的好的解决方案。这可能是可能的,但它需要在评论中进行更多的解释,而不是黑客的价值。
这是我的做法。请注意,我已经消除了 math
和 compares
之间的区别,因为我看不到该值,并且每次都只是执行无用的单位缩减。但是,如果您的真实代码具有更复杂的操作,实际上根据差异执行某些操作,则一定要恢复它。它与解决冲突无关。
这里的重点是避免 ( 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 ')'
;
现在,您如何编写操作码规则取决于您要实现的精确 syntax/semantics。我将从这个开始,它没有冲突:
opcodes:
OPCODE
| OPCODE '#' subexpr
| OPCODE expr
| OPCODE subexpr 'X'
| OPCODE expr 'Y'
| OPCODE '(' subexpr ')'
| OPCODE '(' subexpr 'X' ')'
| OPCODE '(' subexpr ')' 'Y'
请注意,我为 a
和 ay
规则使用了 expr
(不能以 (
开头);这需要将它们分别与 ind
和 zpiy
规则区分开来。由于 ax
和 zpix
之间没有歧义(在后一种情况下 X
需要放在括号内),因此可以允许 (22 + ) X
被解析为它被写成 (22 + X)
但它很可能应该表示语法错误。
总的来说,我认为这种句法近乎歧义的做法会让人类读者感到困惑,应该避免,但我相信你有自己的理由。
备注:
- 通常,所有前缀运算符都具有完全相同的优先级。如果使用优先级声明,我更愿意用相同的优先级标记标记所有前缀运算符。但每个人都有自己的风格。 (所有后缀运算符也具有相同的优先级,通常高于前缀运算符。)