代码优先:

// I need, but not allowed
o = (<I_EXIT> | <I_RET> | <I_NOP>)

// Work around, the generated code will do double switch
(o = <I_EXIT> | o = <I_RET> | o = <I_NOP>)

// Work around, introduce new token, will warning
// Warning: Line 59, Column 11: Regular Expression choice : XXX can never be matched as : XXX
// Consider this is a bad practice.
TOKEN:{
    <I_NO_OP: <I_EXIT> | <I_RET> | <I_NOP>>
}
o = <I_NO_OP>

// Work around, introduce new grammar, generate double switch with one more function call, looks awful.
Token oneOp():{
    Token t = null;
}{
    (t = <I_CALL> |t = <I_PUSH> |t = <I_POP> |t = <I_JPC>){return t;}
}
...
o = oneOp() a = operand()


picked

(o = <I_EXIT> | o = <I_RET> | o = <I_NOP>)


看起来好多了。还有其他方法吗?我不确定这是否是正确的方法。

整个jjt为here

最佳答案

(o = <I_EXIT> | o = <I_RET> | o = <I_NOP>)


是一个合理的解决方案。

由于从语法的角度来看,您的三个标记完全可以互换,因此您还可以定义一种标记类型。

TOKEN:{
    <I_NO_OP: "EXIT" | "RET" | "NOP">
}


在这种情况下,您将不会定义I_EXITI_RETI_NOP

10-04 19:45