Почему нам нужно указать стандартный лексер Lark, чтобы иметь возможность перехватывать терминалы комментариев?

#python #lark-parser

Вопрос:

Я работаю над проектом на основе Жаворонка, в котором мне нужно уметь «улавливать» комментарии в анализируемом коде.

Однако это не работает при использовании стандартного лексера без явного указания стандартного лексера.

Я взял второй пример из рецептов Жаворонка и изменил его, чтобы использовать синтаксический анализатор по умолчанию и анализировать однострочные комментарии, похожие на 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' лексер, когда он явно не указан? Это ошибка в моем коде или возможная ошибка в Жаворонке?


Дальнейшие эксперименты, по-видимому, указывают на то, что это либо 'dynamic' или 'dynamic_complete' используется в случае по умолчанию ( lexer не указано).

Комментарии:

1. Из кода видно, что со auto значением по умолчанию для лексера и без указания синтаксического анализатора или postlex вы действительно должны получить стандартный лексер… может быть, стоит войти в Lark() вызов и посмотреть, что там происходит

Ответ №1:

Lark поддерживает различные комбинации parser и lexer . Кто-то поддерживает lexer_callbacks , кто-то нет:

синтаксический анализатор лексер lexer_callbacks
лалр стандарт ДА
лалр контекстуальный ДА
эрли стандарт ДА
эрли динамический НЕТ
эрли динамический_полный НЕТ
лалр традиция (Может быть)
эрли традиция (Может быть)

lexer="auto" выбирает лексер в зависимости от синтаксического анализатора: для lalr него выбирает contextual , для earley него выбирает dynamic . Синтаксический анализатор по умолчанию earley , поэтому без выбора parser или lexer , lexer_callbacks не поддерживается.

Вопрос на этот счет уже открывался и снова закрывался.