【发布时间】:2023-04-06 22:47:01
【问题描述】:
我在使用 ANTLR 解析器规则的语义谓词时遇到了一些问题。这是我的语法,旨在识别几种不同的日期格式:
grammar sample ;
options { language=Python3; }
@parser::header {
from datetime import datetime
}
month_number returns [val] : INTEGER { 1 <= int($INTEGER.text) <= 12 }? {$val = int($INTEGER.text)} ;
day_number returns [val] : INTEGER { 1 <= int($INTEGER.text) <= 31 }? {$val = int($INTEGER.text)} ;
year_4digit returns [val] : INTEGER { 1900 <= int($INTEGER.text) <= 2100 }? {$val = int($INTEGER.text)} ;
year_2digit returns [val] : '\''? INTEGER {(int($INTEGER.text) >= 65 or int($INTEGER.text) < 40)}?
{$val = (1900 + int($INTEGER.text)) if (int($INTEGER.text) >= 65) else (2000 + int($INTEGER.text))} ;
year_digits returns [val]
: year_4digit {$val = $year_4digit.val}
| year_2digit {$val = $year_2digit.val}
;
mdy returns [val]
: month_number '-' day_number '-' year_digits {$val = datetime($year_digits.val, $month_number.val, $day_number.val)}
| month_number '/' day_number '/' year_digits {$val = datetime($year_digits.val, $month_number.val, $day_number.val)}
;
ymd returns [val]
: year_4digit '-' month_number '-' day_number {$val = datetime($year_4digit.val, $month_number.val, $day_number.val)}
| year_4digit '/' month_number '/' day_number {$val = datetime($year_4digit.val, $month_number.val, $day_number.val)}
;
date_as_numbers returns [val]
: ymd {$val = $ymd.val}
| mdy {$val = $mdy.val}
;
INTEGER: '0'..'9'+ ;
我使用以下程序对其进行测试:
from myPackage.sampleParser import sampleParser
from myPackage.sampleLexer import sampleLexer
from antlr4 import CommonTokenStream
from antlr4 import InputStream
date_input = InputStream("2/12/2017".lower())
lexer = sampleLexer(date_input)
stream = CommonTokenStream(lexer)
parser = sampleParser(stream)
result = parser.date_as_numbers()
print(result.val)
这会导致以下错误:
line 1:1 rule year_4digit failed predicate: { 1900 <= int($INTEGER.text) <= 2100 }?
line 1:9 rule day_number failed predicate: { 1 <= int($INTEGER.text) <= 31 }?
Traceback (most recent call last):
File "/Users/kwilliams/Library/Preferences/IntelliJIdea2017.3/scratches/scratch_1.py", line 11, in <module>
result = parser.date_as_numbers()
File "/Users/kwilliams/git/myPackage/sampleParser.py", line 482, in date_as_numbers
localctx._ymd = self.ymd()
File "/Users/kwilliams/git/myPackage/sampleParser.py", line 436, in ymd
localctx.val = datetime(localctx._year_4digit.val, localctx._month_number.val, localctx._day_number.val)
TypeError: an integer is required (got type NoneType)
所以我认为正在发生的事情是 year_4digit 中的谓词引发异常,因为数字 2 不在其范围内,但无论如何它返回一个 year_4digit 匹配,它还没有它的 @ 987654327@ 属性已填充,导致有关 NoneType 的下游错误。对吗?
如果是这样 - 什么是好的解决方案?我需要将语义谓词放在规则的前面吗?如果这是正确的解决方案,我将如何提前查看 INTEGER 令牌?
(另外 - 我希望能够使用 $INTEGER.int 而不是 int($INTEGER.text),但这可能在 Python 目标中不可用?切线和小问题。)
顺便说一句,上面的语法是我真实语法的一小部分摘录,我希望有一个不需要对这部分进行重大更改的解决方案,可能会导致可能需要一段时间才能解决的连锁反应。
谢谢。
【问题讨论】:
-
我修正了我的例子,我错误地直接调用
ymd而不是date_as_numbers规则。
标签: python antlr grammar predicate