前瞻是做什么的,为什么需要两个标记

What does the lookahead do, and why it takes two tokens

我有这个:

void Identifier() : { Token t;}
{
t = <IDENTIFIER> {jjtThis.setValue(t.image);}
}

void AssignStatement() : { Token t;}
{
(
    LOOKAHEAD(2) Identifier() t = <ASSIGN>
    {
        jjtThis.addOp(t.image);
    }
)+ Expression()
}

Expression() 调用比较,然后 comparison() 调用 logicExpression() 等...(按运算符优先级排序) 我的标记用于赋值运算符、算术和逻辑运算符、比较、分号、if、while、for 语句等... 我知道 LOOKAHEAD(2) 查看接下来的两个标记来决定选择哪个规则,但在我的情况下我不明白。

当parse需要做出选择时,通常是根据输入的下一个token进行选择。在这种情况下,它需要做出留在循环或离开循环的选择。但是通常的一个标记是不够的,因为如果下一个标记是 <IDENTIFIER>,那可能是 Identifier 的开始或 Expression 的开始。然而,2 个前瞻标记就足够了:在接下来的两个标记中 <IDENTIFIER> <ASSIGN>,它应该留在循环中,因为它不能成为表达式的开始。而 while 和表达式可能只是一个 <IDENTIFIER> 一个 <ASSIGN> 不能跟在一个 AssignStatement.

之后

AssignStatement 的生成代码看起来像这样,忽略了树构建代码。

call Identifier
if the next token is not an <ASSIGN> error
read the next token, call it t
while the next two tokens are <IDENTIFIER> <ASSIGN>
    call Identifier
    if the next token is not an <ASSIGN> error
    read the next token, call it t
call Expression