为什么我们需要指定标准的 Lark 词法分析器来捕获评论终端?

Why do we need to specify the standard Lark lexer to be able to catch comment terminals?

我正在做一个基于 Lark 的项目,我需要能够在被解析的代码中“捕获”注释。

但是,在未明确指定标准词法分析器的情况下使用标准词法分析器时,它不起作用。

我从 the Lark recipes 中获取了第二个示例并将其修改为使用默认解析器并解析类似 C++ 的单行注释:

import lark

comments = []

grammar = r'''
start: INT*

COMMENT: "//" /[^\n]*/

%import common (INT, WS)
%ignore COMMENT
%ignore WS
'''

# This doesn't work, comments are not appended to the list
# parser = lark.Lark(grammar, lexer_callbacks={'COMMENT': comments.append})

# But this does work
parser = lark.Lark(grammar, lexer='standard', lexer_callbacks={'COMMENT': comments.append})

source = r'''
1 2 3  // hello
// world
4 5 6
'''

parser.parse(source)

print(comments)

如果我没有 lexer='standard' 结果是一个空列表。

但是,当没有明确指定时,它不应该已经在使用 'standard' 词法分析器了吗?是我的代码有误,还是 Lark 的 bug?


进一步的实验似乎表明在默认情况下使用的是 'dynamic''dynamic_complete'lexer 未指定)。

Lark支持parserlexer的不同组合。有的支持lexer_callbacks,有的不支持:

parser lexer lexer_callbacks
lalr standard Yes
lalr contextual Yes
earley standard Yes
earley dynamic No
earley dynamic_complete No
lalr custom (Maybe)
earley custom (Maybe)

lexer="auto" 根据解析器选择词法分析器:lalr 选择 contextualearley 选择 dynamic。默认解析器是 earley,所以不选择 parserlexer,不支持 lexer_callbacks

这方面的一个issue已经打开又关闭了