3

入力が与えられた"term >1"場合、number(1) と比較演算子(>) は AST で個別のノードを生成する必要があります。これはどのように達成できますか?

私のテストでは、「c」と「1」が「」のようにスペースで区切られている場合にのみ一致が発生しましたterm < 1

現在の文法:

startExpression  : orEx;

expressionLevel4    
: LPARENTHESIS! orEx RPARENTHESIS! | atomicExpression;
expressionLevel3    
: (fieldExpression) | expressionLevel4 ;
expressionLevel2    
: (nearExpression) | expressionLevel3 ;
expressionLevel1    
: (countExpression) | expressionLevel2 ;
notEx   : (NOT^)? expressionLevel1;
andEx   : (notEx        -> notEx)
(AND? a=notEx -> ^(ANDNODE $andEx $a))*;
orEx    : andEx (OR^  andEx)*;

 countExpression  : COUNT LPARENTHESIS WORD RPARENTHESIS RELATION NUMBERS -> ^(COUNT WORD RELATION NUMBERS);

nearExpression  : NEAR LPARENTHESIS (WORD|PHRASE) MULTIPLESEPERATOR (WORD|PHRASE) MULTIPLESEPERATOR NUMBERS RPARENTHESIS -> ^(NEAR WORD* PHRASE* ^(NEARDISTANCE NUMBERS));

fieldExpression : WORD PROPERTYSEPERATOR WORD -> ^(FIELDSEARCH ^(TARGETFIELD WORD) WORD );

atomicExpression 
: WORD
| PHRASE
;

fragment NUMBER : ('0'..'9');
fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'?');
fragment QUOTE     : ('"');
fragment LESSTHEN : '<';
fragment MORETHEN: '>';
fragment EQUAL: '=';
fragment SPACE     : ('\u0009'|'\u0020'|'\u000C'|'\u00A0');
fragment UNICODENOSPACES:  ('\u0021'..'\u0027'|'\u0030'..'\u0039'|'\u003B'..'\u007E'|'\u00A1'..'\uFFFF');
//fragment UNICODENOSPACES  :  ('\u0021'..'\u0039'|'\u003B'..'\u007E'|'\u00A1'..'\uFFFF');

LPARENTHESIS : '(';
RPARENTHESIS : ')';

AND    : ('A'|'a')('N'|'n')('D'|'d');
OR     : ('O'|'o')('R'|'r');
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t');
NOT    : ('N'|'n')('O'|'o')('T'|'t');
COUNT:('C'|'c')('O'|'o')('U'|'u')('N'|'n')('T'|'t');
NEAR:('N'|'n')('E'|'e')('A'|'a')('R'|'r');
PROPERTYSEPERATOR : ':';
MULTIPLESEPERATOR : ',';

WS     : (SPACE) { $channel=HIDDEN; };
RELATION : LESSTHEN? MORETHEN? EQUAL?;
NUMBERS : (NUMBER)+;
PHRASE : (QUOTE)(CHARACTER)+((SPACE)+(CHARACTER)+)+(QUOTE);
WORD   : (UNICODENOSPACES)+;
4

1 に答える 1

4

これは、WORDルールが一致しすぎているためです。ルールも一致">"するため、">1"一緒に記述されると、これらの 2 つの文字は単一のWORD-token としてトークン化されます。

レクサーが何をしているのかわからないときはいつでも、パーサーに任意のタイプの 0 個以上のトークンを一致させ、すべてのトークンのタイプとテキストを出力します。

parse
 : (t=. {System.out.printf("\%-15s '\%s'\n", tokenNames[$t.type], $t.text);})* EOF
 ;

上記のルールを入力に一致させる"term > 1"と、次が出力されます。

WORD '用語'
関係 '>'
単語「1」

と入力の"term" >1

WORD '用語'
単語「>1」

これを回避する方法はありません: lexer が 2 つ (またはそれ以上) の文字 (WORDルール) に一致する場合、単一の文字 (ルール) のみに一致する、その前に定義されたルールよりもそのパスを選択しますRELATION

RELATIONまた、ルールに注意してください:

RELATION : LESSTHEN? MORETHEN? EQUAL?;

空の文字列に一致する可能性があります。すべてのレクサー ルールが少なくとも 1 文字と一致することを確認してください。そうしないと、レクサーが無限ループに陥る可能性があります。

次のようなことをしたほうがいいです:

RELATION
 : (LESSTHEN | MORETHEN)? EQUAL // '<=', '>=', or '='
 | (LESSTHEN | MORETHEN)        // '<' or '>'
 ;
于 2012-12-03T13:36:20.167 に答える