首页 > 解决方案 > JAVACC:如何始终跳过\ n,除非前面有分号

问题描述

我目前正在制作一个 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”。我曾想过在更改状态之前尝试保存剩余的解析输入,但我不知道如何实现。我真的很感激任何帮助!

标签: parsingjavacc

解决方案


不要从解析器切换词法状态。这几乎从来都不是一个好主意。

如果您想忽略不跟随分号的换行符,也不忽略不跟随分号的换行符,您可以执行以下操作:

// 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>
}

这有糟糕的错误恢复,但这是一个开始。


推荐阅读