несколько лексеров для одного парсера с PLY? - PullRequest
3 голосов
/ 12 ноября 2009

Я пытаюсь реализовать синтаксический анализатор python с использованием PLY для языка Kconfig, используемого для генерации параметров конфигурации для ядра linux.

Существует ключевое слово source, которое выполняет включение, так что я делаю так, что когда лексер встречает это ключевое слово, я меняю состояние лексера, чтобы создать новый лексер, который собирается лексировать исходный файл:

def t_begin_source(t):
    r'source '
    t.lexer.begin('source')

def t_source_path(t):
    r'[^\n]+\n+'
    t.lexer.begin('INITIAL') 
    global path
    source_lexer = lex.lex(errorlog=lex.NullLogger())
    source_file_name = (path +  t.value.strip(' \"\n')) 
    sourced_file = file(path + t.value.strip(' \"\n')).read()

    source_lexer.input(sourced_file)

    while True:
        tok = source_lexer.token()
        if not tok:
            break

Где-то еще у меня есть эта строка

lexer = lex.lex(errorlog=lex.NullLogger()) 

Это лексер "main" или "root", который будет вызываться парсером.

Моя проблема в том, что я не знаю, как сказать парсеру использовать другой лексер или сказать "source_lexer", чтобы он возвращал что-то ...

Может быть, следует использовать функцию клона ...

Спасибо

Ответы [ 3 ]

2 голосов
/ 04 декабря 2009

По интересному совпадению ссылка из того же поиска Google, которая привела меня к этому вопросу, объясняет, как написать свой собственный лексер для анализатора PLY . Пост объясняет это просто и хорошо, но это вопрос четырех переменных экземпляра и одного token метода.

2 голосов
/ 12 ноября 2009

Я не знаю о деталях PLY, но в других подобных системах, которые я построил, было наиболее разумно иметь один лексер, который управлял стеком включаемых файлов. Таким образом, лексер будет возвращать единый поток токенов, открывая и закрывая включаемые файлы по мере их обнаружения.

0 голосов
/ 13 ноября 2009

Хорошо,

Итак, что я сделал, так это построил список всех токенов, который создается до фактического анализа.

Анализатор больше не вызывает лексер, потому что вы можете переопределить функцию getToken, используемую анализатором, используя параметр tokenfunc при вызове функции синтаксического анализа.

result = yacc.parse(kconfig,debug=1,tokenfunc=my_function)

и моя функция, которая теперь является функцией, вызываемой для получения следующего токена, выполняет итерацию по списку ранее созданных токенов.

Учитывая лексизм, когда я сталкиваюсь с ключевым словом источника, я клонирую свой лексер и изменяю ввод для включения файла.

def sourcing_file(source_file_name):
    print "SOURCE FILE NAME " , source_file_name
    sourced_file = file(source_file_name).read()
    source_lexer = lexer.clone()
    source_lexer.input(sourced_file)
    print 'END OF SOURCING FILE'

    while True:
        tok = source_lexer.token()
        if not tok:
            break
        token_list.append(tok)
...