我目前正在制作一个SQL解析器,并且希望为每个新输入打印一个提示。
< STATE >
TOKEN:
{
< ENTER : "\n" > : DEFAULT
| < ELSE: ~[] > : DEFAULT
}
<DEFAULT>
TOKEN:
{ <DESC: "desc">
|....
}
[...]
(
q = query()
< SEMICOLON >
{
token_source.SwitchTo(STATE) ;
if(getToken(1).image == "\n")
{
printMessage(q);
getNextToken();
System.out.print("INPUT > ");
}
else
printMessage(q);
token_source.SwitchTo(DEFAULT);
if(getToken(0).image == ";") getNextToken();
}
)+
当我输入这样的内容时出现问题:“ desc a; desc a;”,换句话说,当两个查询之间没有空格时。我相信这是因为一旦状态更改为STATE,“ desc”就不再被视为“ desc”,而是被视为“ d”。我已经考虑过尝试在更改状态之前保存其余的解析输入,但是我不知道如何实现。我真的很感谢您的帮助!
不要从解析器切换词法状态。这几乎从来不是一个好主意。
[如果您要忽略不使用分号的换行符,而不要忽略不使用分号的换行符,则可以执行以下操作:
// Skip white space, but stay in the same state so a newline follows white space
// that follows a semicolon, it will be treated as a token.
< * > SKIP: { " " | "\t" | "\f" }
// Skip newlines that don't follow semicolons
< DEFAULT > SKIP: { "\n" | "\r" }
// Other newlines result in ENTER tokens
< AFTER_SEMICOLON > TOKEN: {
< ENTER : "\n" | "\r" > : DEFAULT }
<*> TOKEN : {
< SEMI_COLON : ";" > : AFTER_SEMICOLON
|
< DESC : "desc" > : DEFAULT
|
<ID : (["a"-"z","A"-"Z"])+ > : DEFAULT
//etc etc
|
<UNEXPECTED_CHARACTER : ~[] > : DEFAULT
}
void many_lines() :
{}
{
{ System.out.print( ">" ) ; }
(
one_line()
many_lines()
|
<EOF>
)
}
void one_line() :
{}
{
expr() <SEMI_COLON>
(
<ENTER>
|
one_line()
)
}
void expr() :
{}
{
<DESC> <ID>
}
这具有糟糕的错误恢复,但这是一个开始。