我上ANTLR4语法工作,用于解析的Python脚本DSL(Python中的一个子集,基本上)与目标设定为Python 3中。我在处理换行时遇到了困难。处理换行与Python靶向
在我的语法,我使用的是移植到Python,使他们能够与Python 3运行时可用于ANTLR,而不是基于Java的Bart Kiers's Python3 grammar for ANTLR4lexer::members
和NEWLINE
嵌入式代码。我的语法与Bart提供的语法不同(它几乎与Python 3 spec中使用的语法相同),因为在我的DSL中,我只需要定位Python的某些元素。基于对语法的广泛测试,我认为语法本身的Python部分本身不是问题的根源,因此我现在不会在这里完整地发布它。
对语法的输入是一个文件,由file_input规则逮住:
file_input: (NEWLINE | statement)* EOF;
语法执行得相当好我的DSL,并产生正确的AST。我唯一的问题是,我的词法分析器规则NEWLINE
凌乱AST节点和\r\n
节点,并试图扩展生成的MyGrammarListener
与我自己ExtendedListener
从它继承时证明麻烦。
这里是我的NEWLINE
词法规则:
NEWLINE
: ({self.at_start_of_input()}? SPACES
| ('\r'? '\n' | '\r' | '\f') SPACES?
)
{
import re
from MyParser import MyParser
new_line = re.sub(r"[^\r\n\f]+", "", self._interp.getText(self._input))
spaces = re.sub(r"[\r\n\f]+", "", self._interp.getText(self._input))
next = self._input.LA(1)
if self.opened > 0 or next == '\r' or next == '\n' or next == '\f' or next == '#':
self.skip()
else:
self.emit_token(self.common_token(self.NEWLINE, new_line))
indent = self.get_indentation_count(spaces)
if len(self.indents) == 0:
previous = 0
else:
previous = self.indents[-1]
if indent == previous:
self.skip()
elif indent > previous:
self.indents.append(indent)
self.emit_token(self.common_token(MyParser.INDENT, spaces))
else:
while len(self.indents) > 0 and self.indents[-1] > indent:
self.emit_token(self.create_dedent())
del self.indents[-1]
};
是NEWLINE
使用的SPACES
词法规则片段是在这里:
fragment SPACES
: [ \t]+
;
我觉得我还要补充一点,既SPACES
和COMMENTS
最终是被语法忽略,但只有在声明NEWLINE
词法分析规则后,据我所知,这应该表示没有不利影响米,但我想包括它以防万一。
SKIP_
: (SPACES | COMMENT) -> skip
;
当输入文件在语句之间没有任何空行的情况下运行时,所有内容都按原样运行。但是,如果有空白行中我的文件(如import语句和可变assignement之间),我收到以下错误:
line 15:4 extraneous input '\r\n ' expecting {<EOF>, 'from', 'import', NEWLINE, NAME}
line 15:0 extraneous input '\r\n' expecting {<EOF>, 'from', 'import', NEWLINE, NAME}
正如我以前说过,当行饲料在我输入文件中省略,则语法和我的ExtendedListener
表现出他们应该的表现,所以问题肯定是\r\n
与NEWLINE
词法分析器规则没有匹配 - 即使我得到的错误陈述说明它与替代NEWLINE
不匹配。
我真的很感激任何帮助,因为我不明白为什么我的NEWLINE
词法规则woud不匹配\r\n
,因为它应该和我想在我的DSL中允许空行。
谢谢您的回答。尽管最终这不是我的问题的根源,但它帮助我意识到我陷入了困境,所以我会接受它并奖励赏金。为了完整起见,在我的情况下,问题是,Python的输入文件必须与它下面另一个*缩进*#评论和语法不能处理一个#评论。再次感谢您的宝贵时间和丰富的答案。 –