2012-01-22 24 views
2

私はクエリを解析するための文法を実装しようとしています。単一クエリはitemsで構成され、各項目はnameまたはname-refのいずれかになります。Antlr3文法に引用符で囲まれた文字列を追加する

namemystring(文字のみ、スペースなし)または"my long string"のいずれかである(文字とスペース、常に引用さ)。 name-refnameと非常によく似ていますが、唯一の違いはref:ref:mystring,ref:"my long string")で始まることです。クエリには少なくとも1項目(nameまたはname-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 items(3 names)と扱われ、"my first query"は1 item(1 long_name)となるはずです。ここで

答えて

3

ANTLRのレクサーは貪欲に一致します:その理由は、my first queryのような入力が、3つのSHORT_NAMEの間にスペースを入れてLONG_NAMEとしてトークン化されている理由です。

LONG_NAMEルールを削除し、パーサールールlong_nameで定義します。

次の文法:次のように

my first query "my first query" ref:mystring 

enter image description here

をただし、も引用された名前をトークン化でき

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)*; 

が入力を解析します〜でレクサーとカスタムコードのビットでそれから引用符を削除します。また、レクサーからスペースを削除することもオプションになります。このような何か:

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'ノードの下で '' 'を取り除く方法はありますか?私は構文を欲しいですが、解析の結果を扱うときには必要ありません。インラインではないJavaソリューションには本当に感謝します – agibalov

+0

@あなたはあなたの答えを受け入れるのですか?これはあなたにもう質問はありませんか? –

+0

私はちょうどあなたがあなたの答えを更新したのを見る前に応答しました。まあ、はい、基本的に私の質問はここにあります - Java文字列プロシージャなしで2番目の方法を実装する方法はありますか? – 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

関連する問題