Создание списка Lexer / Parser - PullRequest
2 голосов
/ 15 января 2012

Мне нужно создать лексер / парсер, который работает с входными данными переменной длины и структуры.

Скажем, у меня есть список зарезервированных ключевых слов:

keyWordList = ['command1', 'command2', 'command3']

и пользовательский вводстрока:

userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command 3'
userInputList = userInput.split()

Как мне написать эту функцию:

INPUT:

tokenize(userInputList, keyWordList)

OUTPUT:
[['The', 'quick', 'brown'], 'command1', ['fox', 'jumped', 'over'], 'command 2', ['the', 'lazy', 'dog'], 'command3']

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

RE-решения приветствуются, но мне бы очень хотелось увидеть лежащий в основе алгоритм, поскольку я, вероятно, собираюсь расширить приложение на списки других объектов.а не только строки.

Ответы [ 4 ]

5 голосов
/ 15 января 2012

Примерно так:

def tokenize(lst, keywords):
    cur = []
    for x in lst:
        if x in keywords:
            yield cur
            yield x
            cur = []
        else:
            cur.append(x)

Это возвращает генератор, поэтому поместите ваш вызов в один к list.

2 голосов
/ 15 января 2012

Это легко сделать с некоторым регулярным выражением:

>>> reg = r'(.+?)\s(%s)(?:\s|$)' % '|'.join(keyWordList)
>>> userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command3'
>>> re.findall(reg, userInput)
[('The quick brown', 'command1'), ('fox jumped over', 'command2'), ('the lazy dog', 'command3')]

Теперь вам просто нужно разделить первый элемент каждого кортежа.

Для более чем одного уровня глубины регулярное выражение не может быть хорошим ответом.

На этой странице вы можете выбрать несколько хороших парсеров: http://wiki.python.org/moin/LanguageParsing

Я думаю Лепл хороший.

1 голос
/ 15 января 2012

Или взгляните на PyParsing. Довольно симпатичная комбинация лекс-парсера

1 голос
/ 15 января 2012

Попробуйте это:

keyWordList = ['command1', 'command2', 'command3']
userInput = 'The quick brown command1 fox jumped over command2 the lazy dog command3'
inputList = userInput.split()

def tokenize(userInputList, keyWordList):
    keywords = set(keyWordList)
    tokens, acc = [], []
    for e in userInputList:
        if e in keywords:
            tokens.append(acc)
            tokens.append(e)
            acc = []
        else:
            acc.append(e)
    if acc:
        tokens.append(acc)
    return tokens

tokenize(inputList, keyWordList)
> [['The', 'quick', 'brown'], 'command1', ['fox', 'jumped', 'over'], 'command2', ['the', 'lazy', 'dog'], 'command3']
...