Невозможно определить приоритет правила в грамматике грако для обработки специальных токенов

Я пытаюсь проанализировать некоторые документы с помощью грамматики, сгенерированной с помощью Grako, которая должна анализировать простые предложения для дальнейшего анализа, но сталкивается с некоторыми трудностями с некоторыми специальными токенами.

(Грако-стиль) EBNF выглядит так:

abbr::str = "etc." | "feat.";
word::str = /[^.]+/;
sentence::Sentence = content:{abbr | word} ".";
page::Page = content:{sentence};

Я использовал верхнюю грамматику для следующего содержания:

Это предложение. Это подвиг предложения. сокращение. Теперь я не подвиг. и т. д. знать английский.

Результат с использованием простого NodeWalker:

[
    'This is a sentence.',
    'This is a sentence feat.',
    'an abbrevation.',
    "I don't know feat.",
    'etc. feat. know English.'
]

Мое ожидание:

[
    'This is a sentence.',
    'This is a sentence feat. an abbrevation.',
    "I don't know feat. etc. feat. know English."
]

Я понятия не имею, почему это происходит, особенно в последнем предложении, где сокращения являются частью предложения, а не в предыдущих предложениях. Чтобы было ясно, я хочу, чтобы правило abbr в определении предложения имело более высокий приоритет, чем слово rule, но я не знаю, как этого добиться. Я играл с негативным и позитивным взглядом без успеха. Я знаю, как добиться ожидаемых результатов с помощью регулярных выражений, но для дальнейшего анализа требуется не зависящая от контекста грамматика, поэтому я хочу поместить все в одну грамматику для удобства чтения. Прошло много времени с тех пор, как я последний раз использовал грамматики таким образом, но я не помню, чтобы я сталкивался с подобными проблемами. Некоторое время я искал через Google, но безуспешно, поэтому, возможно, сообщество может поделиться своим пониманием.

Заранее спасибо.

Код, который я использовал для тестирования, если требуется:

from grako.model import NodeWalker, ModelBuilderSemantics
from parser import MyParser

class MyWalker(NodeWalker):
    def walk_Page(self, node):
        content = [self.walk(c) for c in node.content]
        print(content)

    def walk_Sentence(self, node):
        return ' '.join(node.content) + "."

    def walk_str(self, node):
        return node

def main(filename: str):
    parser = MyParser(semantics=ModelBuilderSemantics())
    with open(filename, 'r', encoding='utf-8') as src:
        result = parser.parse(src.read(), 'page')
    walker = HRBWalker()
    walker.walk(result)

Используемые пакеты: Python 3.5.2 Grako 3.16.5

1 ответ

Решение

Проблема с регулярным выражением, которое вы используете для word править. Регулярные выражения будут анализировать все, что вы им скажете, и это регулярное выражение поглощает пробелы.

Эта измененная грамматика делает то, что вы хотите:

@@grammar:: Pages

abbr::str = "etc." | "feat.";
word::str = /[^.\s]+/;
sentence::Sentence = content:{abbr | word} ".";
page::Page = content:{sentence};

start = page ;

--trace бежать сразу же обнаружил проблему.

Другие вопросы по тегам