antlr4
を使用して「P3M2D」のようにISO 8601 period expressionsを解析しようとしています。しかし、私はいくつかの障害物に当たっており、助けに感謝します。私は、antlrとコンパイラのどちらにも新しくなっています。antlr4.7では、「ID」ルールの前にISO 8601間隔「P3M2D」のようなルールを解析する方法
私の文法は以下の通りです。テストランで
grammar test_iso ;
// import testLexerRules ;
iso : (date_expr NEWLINE)* EOF;
date_expr
: date_expr op=('+' | '-') iso8601_interval #dateexpr_Interval
| date_expr op='-' date_expr #dateexpr_Diff
| DATETIME_NAME #dateexpr_Named
| '(' inner=date_expr ')' #dateexpr_Paren
;
///////////////////////////////////////////
iso8601_interval
: iso8601_interval_d
{ System.out.println("ISO8601_INTERVAL DATE seen " + $text);}
;
iso8601_interval_d
: 'P' (y=NUMBER_INT 'Y')? (m=NUMBER_INT 'M')? (w=NUMBER_INT 'W')? (d=NUMBER_INT 'D')?
;
///////////////////////////////////////////
// in separate file : test_lexer.g4
// lexer grammar testLexerRules ;
///////////////////////////////////////////
fragment
TODAY
: 'today' | 'TODAY'
;
fragment
NOW
: 'now' | 'NOW'
;
DATETIME_NAME
: TODAY
| NOW
;
///////////////////////////////////////////
NUMBER_INT
: '-'? INT // -3, 45
;
fragment
DIGIT : [0-9] ;
fragment
INT : '0' | [1-9] DIGIT* ;
//////////////////////////////////////////////
//
// identifiers
//
ID
: ALPHA ALPH_NUM*
{ System.out.println("ID seen " + getText()); }
;
ID_SQLFUNC
: 'h$' ALPHA_UPPER ALPHA_UPPER_NUM*
{ System.out.println("SQL FUNC seen " + getText()); }
;
fragment
ALPHA : [a-zA-Z] ;
fragment
ALPH_NUM : [a-zA-Z_0-9] ;
fragment
ALPHA_UPPER : [A-Z] ;
fragment
ALPHA_UPPER_NUM : [A-Z_0-9] ;
//////////////////////////////////////////////
NEWLINE : '\r\n' ;
WS : [ \t]+ -> skip ;
、それはiso8601_interval_d
ルールを打つことはありません、それは常にID
ルールに行く:私はここで一度にレクサーとパーサのルールを組み合わせています。私は「ID」のルールを削除して、再度実行した場合
C:\lab>java org.antlr.v4.gui.TestRig test_iso iso -tokens -tree
now + P3M2D
^Z
ID seen P3M2D
[@0,0:2='now',<DATETIME_NAME>,1:0]
[@1,4:4='+',<'+'>,1:4]
[@2,6:10='P3M2D',<ID>,1:6]
[@3,11:12='\r\n',<'
'>,1:11]
[@4,13:12='<EOF>',<EOF>,2:0]
line 1:6 mismatched input 'P3M2D' expecting 'P'
ISO8601_INTERVAL DATE seen P3M2D
(iso (date_expr (date_expr now) + (iso8601_interval (iso8601_interval_d P3M2D))) \r\n <EOF>)
が、それは必要に応じて、解析します。私も、パーサー規則で、「@」のような特殊文字を前置しようとした
now + P3M2D
^Z
[@0,0:2='now',<DATETIME_NAME>,1:0]
[@1,4:4='+',<'+'>,1:4]
[@2,6:6='P',<'P'>,1:6]
[@3,7:7='3',<NUMBER_INT>,1:7]
[@4,8:8='M',<'M'>,1:8]
[@5,9:9='2',<NUMBER_INT>,1:9]
[@6,10:10='D',<'D'>,1:10]
[@7,11:12='\r\n',<'
'>,1:11]
[@8,13:12='<EOF>',<EOF>,2:0]
ISO8601_INTERVAL DATE seen P3M2D
(iso (date_expr (date_expr now) + (iso8601_interval (iso8601_interval_d P 3 M 2 D))) \r\n <EOF>)
iso8601_interval_d
: '@P' (y=NUMBER_INT 'Y')? (m=NUMBER_INT 'M')? (w=NUMBER_INT 'W')? (d=NUMBER_INT 'D')?
;
が、今、障害の異なる種類
now + @P3M2D
^Z
ID seen M2D
[@0,0:2='now',<DATETIME_NAME>,1:0]
[@1,4:4='+',<'+'>,1:4]
[@2,6:7='@P',<'@P'>,1:6]
[@3,8:8='3',<NUMBER_INT>,1:8]
[@4,9:11='M2D',<ID>,1:9]
[@5,12:13='\r\n',<'
'>,1:12]
[@6,14:13='<EOF>',<EOF>,2:0]
line 1:9 no viable alternative at input '3M2D'
ISO8601_INTERVAL DATE seen @P3M2D
(iso (date_expr (date_expr now) + (iso8601_interval (iso8601_interval_d @P 3 M2D))) \r\n <EOF>)
私はこのようなことに当たった最初の人ではないと確信しています。ここには何の慣用句がありますか?
EDIT - 私が直面している問題を強調するために、ここで省略した文法の他の部分のID
トークンが必要です。
なぜIDトークンが必要ですか? – gtosto
私の問題を浮き彫りにする文法の断片を抽象化しました。私は省略した他のルールのどこかでIDトークンが必要です。 – Dinesh
ダウンヴォートした人は誰でもコメントを残してください。 – Dinesh