2012-01-22 25 views
2

我試圖實現解析查詢的語法。單個查詢由items組成,其中每個項目可以是namename-ref添加對Antlr3語法的引用字符串支持

namemystring(只有字母,無空格)或"my long string"(字母和空格,總是加引號)。 name-refname非常相似,唯一的區別是它應該從ref:ref:mystring,ref:"my long string")開始。查詢應至少包含1個項目(namename-ref)。

這是我有:

NAME: ('a'..'z')+; 
REF_TAG: 'ref:'; 
SP: ' '+; 

name: NAME; 
name_ref: REF_TAG name; 
item: name | name_ref; 
query: item (SP item)*; 

此語法證明什麼,我基本上需要獲取,唯一的特點是,它不支持長引用的字符串(它工作得很好,它沒有名字空格)。

SHORT_NAME: ('a'..'z')+; 
LONG_NAME: SHORT_NAME (SP SHORT_NAME)*; 
REF_TAG: 'ref:'; 
SP: ' '+; 
Q: '"'; 

short_name: SHORT_NAME; 
long_name: LONG_NAME; 
name_ref: REF_TAG (short_name | (Q long_name Q)); 
item: (short_name | (Q long_name Q)) | name_ref; 
query: item (SP item)*; 

但這不起作用。任何想法是什麼問題?可能重要的是:my first query應被視爲3 item s(3 name s)並且"my first query"爲1 item(1 long_name)。

回答

3

ANTLR的詞法分析器貪婪地匹配:這就是爲什麼像my first query這樣的輸入被標記爲LONG_NAME而不是3 SHORT_NAME的空格。

只需刪除LONG_NAME規則並在解析器規則long_name中對其進行定義。

以下語法:

SHORT_NAME : ('a'..'z')+; 
REF_TAG : 'ref:'; 
SP   : ' '+; 
Q   : '"'; 

short_name : SHORT_NAME; 
long_name : Q SHORT_NAME (SP SHORT_NAME)* Q; 
name_ref : REF_TAG (short_name | (Q long_name Q)); 
item  : short_name | long_name | name_ref; 
query  : item (SP item)*; 

將解析輸入:

my first query "my first query" ref:mystring 

如下:

enter image description here

但是,你可以還記號化帶引號的名稱在th然後用一些自定義代碼從中剝離引號。從詞法分析器中刪除空格也是一種選擇。事情是這樣的:

SHORT_NAME : ('a'..'z')+; 
LONG_NAME : '"' ~'"'* '"' {setText(getText().substring(1, getText().length()-1));}; 
REF_TAG : 'ref:'; 
SP   : ' '+ {skip();}; 

name_ref : REF_TAG (SHORT_NAME | LONG_NAME); 
item  : SHORT_NAME | LONG_NAME | name_ref; 
query  : item+ EOF; 

這將如下解析相同的輸入:

enter image description here

注意實際的令牌LONG_NAME將被剝離其開始和結束引號。

+0

有沒有什麼辦法擺脫long_name下的''''我想要for語法,但是在處理解析結果時我不需要它們,真的會喜歡非內聯Java解決方案 – agibalov

+0

@ loki2302,你的意思是從第一個樹形圖像編輯:等等,我看到你接受了我的答案,這意味着你沒有任何問題嗎? –

+0

我剛剛看到你已經更新了答案,是的,基本上我的問題在於 - 是否有方法在沒有Java字符串過程的情況下實現第二種方法? – agibalov

1

這裏是一個要爲你的要求工作語法:

SP: ' '+; 
    SHORT_NAME: ('a'..'z')+; 
    LONG_NAME: '"' SHORT_NAME (SP SHORT_NAME)* '"'; 
    REF: 'ref:' (SHORT_NAME | LONG_NAME); 

    item: SHORT_NAME | LONG_NAME | REF; 
    query: item (SP item)*; 

如果你把這個頂部:

grammar Query; 

    @members { 
     public static void main(String[] args) throws Exception { 
      QueryLexer lex = new QueryLexer(new ANTLRFileStream(args[0])); 
      CommonTokenStream tokens = new CommonTokenStream(lex); 

      QueryParser parser = new QueryParser(tokens); 

      try { 
       TokenSource ts = parser.getTokenStream().getTokenSource(); 
       Token tok = ts.nextToken(); 
       while (EOF != (tok.getType())) { 
       System.out.println("Got a token: " + tok); 
       tok = ts.nextToken(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

您應該看到詞法打破一切的除了很好(我希望; - ))

hi there "long name" ref:shortname ref:"long name" 

應該給:

Got a token: [@-1,0:1='hi',<6>,1:0] 
Got a token: [@-1,2:2=' ',<7>,1:2] 
Got a token: [@-1,3:7='there',<6>,1:3] 
Got a token: [@-1,8:8=' ',<7>,1:8] 
Got a token: [@-1,9:19='"long name"',<4>,1:9] 
Got a token: [@-1,20:20=' ',<7>,1:20] 
Got a token: [@-1,21:33='ref:shortname',<5>,1:21] 
Got a token: [@-1,34:34=' ',<7>,1:34] 
Got a token: [@-1,35:49='ref:"long name"',<5>,1:35] 

我不是100%確定你的語法有什麼問題,但我懷疑這個問題與你沒有引號的LONG_NAME的定義有關。也許你可以看到區別是什麼?

+0

感謝您的回答,但它並沒有消除像引號和'ref:'標籤這樣的輔助字符。 – agibalov

相關問題