前瞻是做什么的,为什么需要两个标记
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
我有这个:
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