Объединение операторов OR с Python SLY

Я использую СЛИ с Python для анализа текста с относительно простой грамматикой. Строки, которые я хотел бы проанализировать, содержат имена сигналов из определенной системы, объединенные с помощью операторов AND или OR. То есть что-то вроде "(SIG1 OR SIG2 OR SIG3 OR SIG4 OR SIG5) AND SIG6".

Одной из характеристик данных является то, что в них преобладают длинные списки сигналов, объединенных по ИЛИ. Синтаксический анализатор, который я построил до сих пор (см. Ниже), понимает только операторы ИЛИ или И как двоичные, и поэтому выводит вложенный кортеж, подобный следующему:

Учитывая список операторов, объединенных ИЛИ, было бы неплохо объединить их в операторы ИЛИ произвольной длины: ('AND', ('OR', ('OR', ('OR', ('OR', 'SIG1', 'SIG2'), 'SIG3'), 'SIG4'), 'SIG5'), 'SIG6')

Думаю, мне нужно отредактировать синтаксический анализатор, но я не знаю, как это сделать, и буду признателен за любые подсказки, которые вы можете мне дать.

class BoolLexer(Lexer):
    tokens = { ID, LPAREN, RPAREN, AND, OR }
    ignore = ' \t\n'

    ID      = r'[a-zA-Z_\.][a-zA-Z0-9_\.]*'
    LPAREN  = r'\('
    RPAREN  = r'\)'

    ID['AND'] = AND
    ID['OR'] = OR

class BoolParser(Parser):
    tokens = BoolLexer.tokens

    @_('expr AND term')
    def expr(self, p):
        return ('AND', p.expr, p.term)

    @_('expr OR term')
    def expr(self, p):
        return ('OR', p.expr, p.term)

    @_('term')
    def expr(self, p):
        return p.term

    @_('ID')
    def term(self, p):
        return p.ID

    @_('LPAREN expr RPAREN')
    def term(self, p):
        return p.expr
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
988
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сделать это несколькими способами. Самый простой способ, если вы хотите уловить все случаи (включая, например, "(SIG1 OR SIG2) OR (SIG3 OR SIG4)"), — это сначала построить AST, а затем рекурсивно пройтись по AST, упростив каждый узел.

Вы также можете сделать упрощение при создании узла AST, но это не уловит упомянутый выше случай:

@_('expr OR term')
def expr(self, p):
    if (isinstance(expr, tuple) and expr[0] is "OR"):
        return p.expr + (p.term,)
    else:
        return ('OR', p.expr, p.term)

Однако я нахожу это довольно уродливым из-за теста в строке 3. Более чистое решение — разделить падежи в грамматике. (Примечание: как и ваша грамматика, следующее дает AND и OR равный приоритет, просто связывая слева направо. Это нет обычный способ записи логических выражений.)

@_('and_expr',
   'or_expr',
   'term)
def expr(self, p):
    return p[0]

@_('term OR term')
def or_expr(self, p):
    return ('OR', p.term0, p.term1)

@_('or_expr OR term')
def or_expr(self, p):
    return p.or_expr + (p.term,)

@_('term AND term')
def and_expr(self, p):
    return ('AND', p.term0, p.term1)

@_('and_expr AND term')
def and_expr(self, p):
    return p.and_expr + (p.term,)

(Я никогда не использовал SLY и не проверял приведенный выше код. Если он не работает, дайте мне знать.)

Спасибо. Это сработало. В вашем первом блоке кода есть небольшая ошибка - строка 4: должно быть возвращено p.expr + (p.term,) У меня небольшие трудности с отслеживанием логики во втором блоке кода, но это связано с моим незнание парсеров. Спасибо за вашу помощь.

smolloy 10.04.2019 10:19

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