【发布时间】:2018-07-16 21:57:26
【问题描述】:
有没有办法使用 ANTLR 解析器作为搜索器,即找到与给定规则 my_rule 匹配的较长字符串 S 的子字符串 ss 的第一个实例?
从概念上讲,我可以通过在位置 S[i] 查找匹配来完成此操作,递增 i 直到我成功检索到匹配或 S 用尽。
但是,在实践中,这并不能很好地工作,因为S 中的前缀可能恰好包含与我的语法中的标记匹配的字符。根据这种情况的发生,S 中的有效字符串 ss 可能会被多次识别,或者不规律地跳过,或者可能会打印很多关于“令牌识别错误”的错误。
是否有我没有想到的方法,或者我不知道的 ANTLR 功能?
我正在使用 ANTLR 的 Python 绑定,如果这很重要的话。
示例:
给定以下语法:
grammar test ;
options { language=Python3; }
month returns [val]
: JAN {$val = 1}
| FEB {$val = 2}
| MAR {$val = 3}
| APR {$val = 4}
| MAY {$val = 5}
;
day_number returns [val]
: a=INT {$val = int($a.text)} ;
day returns [val]
: day_number WS? {$val = int($day_number.start.text)}
;
month_and_day returns [val]
: month WS day {$val = ($month.val, $day.val)}
| day WS ('of' WS)? month {$val = ($month.val, $day.val)}
;
WS : [ \n\t]+ ; // whitespace is not ignored
JAN : 'jan' ('.' | 'uary')? ;
FEB : 'feb' ('.' | 'ruary')? ;
MAR : 'mar' ('.' | 'ch')? ;
APR : 'apr' ('.' | 'il')? ;
MAY : 'may' ;
INT
: [1-9]
| '0' [1-9]
| '1' [0-9]
| '2' [0-3]
;
和下面的脚本来测试它:
import sys
sys.path.append('gen')
from testParser import testParser
from testLexer import testLexer
from antlr4 import InputStream
from antlr4 import CommonTokenStream, TokenStream
def parse(text: str):
date_input = InputStream(text.lower())
lexer = testLexer(date_input)
stream = CommonTokenStream(lexer)
parser = testParser(stream)
return parser.month_and_day()
for t in ['Jan 6',
'hello Jan 6, 1984',
'hello maybe Jan 6, 1984']:
value = parse(t)
print(value.val)
我得到以下结果:
# First input - good
(1, 6)
# Second input - errors printed to STDERR
line 1:0 token recognition error at: 'h'
line 1:1 token recognition error at: 'e'
line 1:2 token recognition error at: 'l'
line 1:3 token recognition error at: 'l'
line 1:4 token recognition error at: 'o '
line 1:11 token recognition error at: ','
(1, 6)
# Third input - prints errors and throws exception
line 1:0 token recognition error at: 'h'
line 1:1 token recognition error at: 'e'
line 1:2 token recognition error at: 'l'
line 1:3 token recognition error at: 'l'
line 1:4 token recognition error at: 'o '
line 1:9 token recognition error at: 'b'
line 1:10 token recognition error at: 'e'
line 1:12 mismatched input 'jan' expecting INT
Traceback (most recent call last):
File "test_grammar.py", line 25, in <module>
value = parse(t)
File "test_grammar.py", line 19, in parse
return parser.month_and_day()
File "gen/testParser.py", line 305, in month_and_day
localctx._day = self.day()
File "gen/testParser.py", line 243, in day
localctx.val = int((None if localctx._day_number is None else localctx._day_number.start).text)
ValueError: invalid literal for int() with base 10: 'jan'
Process finished with exit code 1
要使用我上面概述的增量方法,我需要一种方法来抑制 token recognition error 输出并将异常包装在 try 或类似名称中。感觉我会非常反常,并且很难将这些解析异常与其他出错的事情区分开来。
(META - 我可以发誓我已经在大约 4 个月前的某个地方问过这个问题,但我在 SO、ANTLR GitHub 跟踪器或 ANTLR Google 上找不到任何东西组。)
【问题讨论】:
-
字符串
S是结构化的,还是一些任意文本?规则my_rule的完整表达是什么?没有更多细节很难理解第 3 段。 -
S可能是完全任意的——在我的例子中,它是用户可以输入的文本。我明天回去工作时添加一个示例规则,谢谢。 -
添加到问题的示例。