您好我为汇编程序定义了语法。 我无法解决歧义问题。
歧义发生在这个
某些操作码的间接寻址模式是操作码'('地址')'
例如,下面的代码是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。
答案 0 :(得分:2)
我不知道使用优先级声明的好解决方案。这可能是可能的,但是在评论中需要更多的解释而不是黑客的价值。
我是这样做的。请注意,我已经消除了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 ')'
;
现在,您编写操作码规则的方式取决于您要实现的精确语法/语义。我从这开始,没有冲突:
opcodes:
OPCODE
| OPCODE '#' subexpr
| OPCODE expr
| OPCODE subexpr 'X'
| OPCODE expr 'Y'
| OPCODE '(' subexpr ')'
| OPCODE '(' subexpr 'X' ')'
| OPCODE '(' subexpr ')' 'Y'
请注意,expr
和(
规则使用了a
(不能以ay
开头);这需要将它们分别与ind
和zpiy
规则区分开来。由于ax
和zpix
之间没有歧义(在后一种情况下X
需要进入括号内),因此可以允许($2222 + $23) X
进行解析它已写成($2222 + $23 X)
,但它很可能会反而表示语法错误。
总的来说,我认为这种语法模糊不清对人类读者来说是困惑的,应该避免,但我相信你有理由。