2011-05-03 78 views
1

我知道这可能最终成为语言特定的,Java或Python解决方案是可以接受的。如何检查ANTLR 3中的数字范围?

鉴于语法

MONTH : DIGIT DIGIT ; 
DIGIT : ('0'..'9') ; 

我要上MONTH检查约束,以确保值是0112之间我从哪里开始找,以及如何指定此约束的规则?

+0

这取决于其他标记的定义。什么应该'13'被标记为? – 2011-05-03 06:29:31

+0

在这种情况下,任何'< 1' and '> 12'都应该抛出一个错误,这将嵌入另一个规则中,该规则指定格式化规则中的MONTH。 – 2011-05-03 06:32:09

回答

1

您可以通过围绕它包装{}来嵌入自定义代码。所以,你可以这样做:

MONTH 
    : DIGIT DIGIT 
    { 
     int month = Integer.parseInt(getText()); 
     // do your check here 
    } 
    ; 

正如你所看到的,我叫getText()获得令牌的匹配文本的保持。

请注意,我认为您是从另一个词法分析规则引用此MONTH规则。如果你要抛出一个异常,如果1 > month > 12,那么只要你的源文件包含非法的月份值,就不会匹配任何解析器规则。虽然词法分析器和解析器规则可以混合在一个.g语法文件中,但输入源首先基于词法分析器规则进行标记,一旦发生,就只有解析器规则匹配。

+0

我无法让'super.getText()'调用起作用; '$ month.text'确实有效。但是我对将日期解析逻辑放在语法中持怀疑态度,如果您尝试并支持所有可选符号和边界情况,ISO 8061规范会变得相当复杂。 – 2011-05-03 15:41:42

+0

@Jarrod,嗯,也许ANTLR只接受'getText()'而没有'super'关键字。没有测试过,对不起。 – 2011-05-03 15:43:31

-1

您可以使用此免费在线实用程序Regex_For_Range为任何连续整数范围生成正则表达式。对于值01-12(允许有前导0)的实用工具为:

0*([1-9]|1[0-2]) 

从这里你可以看到,如果要约束这仅仅是2位数的字符串“01”到“12”然后调整这个阅读:

0[1-9]|1[0-2] 

对于天01-31我们得到:

0*([1-9]|[12][0-9]|3[01]) 

而且对于几年2000-2099表达的无非是:

20[0-9]{2} 
+0

尽管这很酷且令人讨厌,但这使得我更像一个维护噩梦,而ANTLR并没有使用正则表达式来匹配,而是一个LL解析器。我不可能知道哪里会比使用自编文件的本地语言数字比较更好。 **如果你有问题,现在用正则表达式解决,你有两个问题!** – 2011-05-03 15:39:04