java - ANTLR 匹配日期范围

标签 java antlr

好吧,这可能很简单,但无论我喝多少咖啡,我的大脑都不会激活。

我需要将以下模式与 ANTLR 进行匹配:

5 YEARS
5 YEARS 2 MONTHS
5 YEARS 2 MONTHS 3 DAYS
2 MONTHS 3 DAYS
5 YEARS 3 DAYS
etc

所以,我开始遵循以下规则:

atom returns [Object value]
  // start w/ a duration. Returned value will be a Joda Period object
  : (INTEGER ('YEAR'|'YEARS'))? (INTEGER ('MONTH'|'MONTHS'))? (INTEGER ('DAY'|'DAYS')?
  ;

显然这是行不通的。我知道这很简单,但我现在脑子很乱 404。

(一旦我得到正确的规则,我会将定义向下移动到 Lexer 定义)

更新: 由于之前提供的输入,以下规则集有效。再次感谢。

datePeriod returns [Object value]
  : year month? week? day? EOF
  {
    $value = new Period($year.num, $month.num, $week.num, $day.num,0,0,0,0);
  }
  | month week? day? EOF
  {
    $value = new Period(0, $month.num, $week.num, $day.num,0,0,0,0);
  }
  | week day? EOF
  {
    $value = new Period(0,0, $week.num, $day.num,0,0,0,0);
  }
  | day EOF
  {
    $value = new Period(0, 0, 0, $day.num,0,0,0,0);
  }
  ;

year returns [int num]
  : INTEGER YEAR
  {
    $num = $INTEGER.int;
  }
  ;

month returns [int num]
  : INTEGER MONTH
  {
    $num = $INTEGER.int;
  }
  ;

week returns [int num]
  : INTEGER WEEK
    {
      $num = $INTEGER.int;
    }
  ;

day returns [int num]
  : INTEGER DAY
  {
    $num = $INTEGER.int;
  }
  ;

YEAR: ('YEAR'|'YEARS');
MONTH: ('MONTH'|'MONTHS');
WEEK: ('WEEK'|'WEEKS');
DAY: ('DAY'|'DAYS');

不幸的是,我的 ANTLR IDEA 现在发出警告,例如:

Decision can match input such as "INTEGER MONTH" using multiple alternatives: 1, 2

杰森

最佳答案

下面是一个简单的语法,可以按照您所描述的方式解析日期。请注意,换行符非常重要/不会被跳过,因为“4 YEARS\n4 MONTHS”应该明确解析为两个日期。

grammar dates;

options {  
  language = Java; 
  output = AST;
}                     

parse
    : '\n'* date ('\n'+ date)* '\n'* EOF
    ;

date 
  // start w/ a duration. Returned value will be a Joda Period object
  : year month? day? 
    {System.out.println(String.format("\%dy \%dm \%dd", $year.num, $month.num, $day.num));} 
  | month day?
    {System.out.println(String.format("0y \%dm \%dd", $month.num, $day.num));}
  | day
    {System.out.println(String.format("0y 0m \%dd", $day.num));}
  ;

year returns [int num]
    : INTEGER YEAR
        {$num = $INTEGER.int;}
    ;
month returns [int num]
    : INTEGER MONTH
        {$num = $INTEGER.int;}
    ;
day returns [int num]
    : INTEGER DAY
        {$num = $INTEGER.int;}
    ;
DAY : 'DAY' | 'DAYS'
    ;    
MONTH
    : 'MONTH' | 'MONTHS'
    ;    
YEAR: 'YEAR' | 'YEARS'
    ;    
INTEGER
    : '0' 
    | ('1'..'9')('0'..'9')*
    ;
WS
    : ('\t' | ' ' | '\r') {skip();}
    ;

测试输入:

5 YEARS
5 YEARS 2 MONTHS
5 YEARS 2 MONTHS 3 DAYS
2 MONTHS 3 DAYS
5 YEARS 3 DAYS
7 DAYS
1 MONTH

测试输出:

5y 0m 0d
5y 2m 0d
5y 2m 3d
0y 2m 3d
5y 0m 3d
0y 0m 7d
0y 1m 0d

关于java - ANTLR 匹配日期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13473046/

相关文章:

java - 通过 ANTLR 4 仅使用 java 文件的注释 (/** ..... */) 部分并跳过其余部分

namespaces - ANTLR v3 C# 命名空间

java - 可测试的Java代码: using model beans with a constructor

java - J2me :Displayable. setTicker()自动关闭诺基亚手机

扩展类中的Java反射字段值

c - 如何使用 ANTLR3C 生成介绍性识别器?

java - 如何检查我的电脑中是否安装了 hamcrest.jar

java - RMI 服务器与 RMI 注册表

parsing - 带有字符串文字的 ANTLR 解析器规则

java - 如何在 ANTLR3 词法分析器规则中定义多字符排除?