Antlr を使用してフランスの日付の文字列を解析したいと思います。
私は3種類の日付を持っています:
- date_day : 2004 年 10 月 3 日 (時間/分は午前 0 時)
- date_time : 12h (日、月、年は現在の日付で補完されます)
- date_complete : 2004 年 10 月 3 日 12 時。ご覧のように
date_complete : date_day date_hour
解析したいドキュメントはdate_day
、 ,date_time
とdate_complete
(区切り記号なし) の単なるチェーンです。
解析したい文字列の例を次に示します
3 Octobre 2005 12h 13h 5 Octobre 2004 3 Septembre 2005 11h
Expected : date_complete date_time date_day date_complete
12h
Expected : date_time
3 Octobre 2005 5 Octobre 2004 12h 13h 3 Septembre 2005 11h
Expected : date_day date_complete date_time date_complete
**// NEW REQUIREMENTS**
3 Octobre 2005
Expected : date_day
3 Octobre
Expected : date_day
3
Expected : date_day
私は多くのことを試しましたが、Antlr v3 は常に私の文法があいまいであると言います:
warning(200): /meleo.dates/src/Grammar.g:25:48:
Decision can match input such as "{FRI, MON..TUE, WED} TWO_DIGITS DECEMBER FOUR_DIGITS {FRI..HOURG, MON..WED}" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
|---> date_day (date_day | date_complete | date_hour)+
その文法は何を書くのが適切ですか?
文法は次のとおりです。
grammar MeleoDates;
options {
language = Java;
}
@header {
package meleo.data.dates ;
import rainstudios.meleo.crawler.data.Dates ;
import rainstudios.meleo.crawler.data.EventDate ;
}
@lexer::header {
package meleo.data.dates ;
import rainstudios.meleo.crawler.data.EventDate ;
}
input returns [Dates dates]
@init {Dates r = new Dates() ; } :
( date
{r.addDay($date.date);}
DATE_SEP?)+
EOF
{$dates = r ;}
;
date returns [EventDate date] :
(date_complete)=> date_complete
{$date = $date_complete.date;}
| date_day
{$date = $date_day.date;}
| date_time
{$date = $date_time.date;}
;
date_complete returns [EventDate date]
@init {EventDateBuilder builder = new EventDateBuilder() ; } :
day=date_day
{builder.addDay($day.date);}
HOUR_SEP?
time=date_time
{builder.addTime($time.date);}
{$date = builder.toDate();}
;
date_day returns [EventDate date]
@init {EventDateBuilder builder = new EventDateBuilder() ; } :
(
dayOfWeek=(
MON
| TUE
| WED
| THU
| FRI
| SAT
| SUN
)?
(day=INT)=> INT
{builder.addDay($day.text);}
( m=ID
{builder.addMonth($m.text);}
year=INT ?
{builder.addMonth($year.text);}
)?
)
{$date = builder.toDate();}
;
date_time returns [EventDate date]
@init {EventDateBuilder builder = new EventDateBuilder() ; } :
TIME
{builder.addTime($TIME.text);}
{$date = builder.toDate();}
;
month : DECEMBER | JANUARY ;
MON
: 'lundi'
| 'lun'
;
TUE
: 'mardi'
| 'mar'
;
WED
: 'mercredi'
| 'mer'
;
THU
: 'jeudi'
| 'jeu'
;
FRI
: 'venredi'
| 'ven'
;
SAT
: 'samedi'
| 'sam'
;
SUN
: 'dimanche'
| 'dim'
;
DECEMBER : 'dec' | 'decembre' ;
JANUARY : 'jan' | 'janvier' ;
DATE_SEP : 'et'| ',' | '-';
HOUR_SEP : 'à' | 'a' ;
INT : ('0'..'9')+;
TIME_SEP : ':' | 'h' ;
TIME : INT TIME_SEP INT?;
ID : ('a'..'z'|'A'..'Z')+;
WS : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN;};
**編集:新しい要件を追加(date_dayのオプションの月と年)**