упрощающее И ИЛИ Булево Выражение - PullRequest
0 голосов
/ 17 января 2019

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

 "a OR (b AND c)"
into
  a OR bc

если выражение похоже на

"a AND (b OR c)"

 then gives

  ab OR ac

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

  • Безопасность ИЛИ ((Интернет ИЛИ ИЛИ БЕСПЛАТНО) или И (банк *)) И (мобильный ИЛИ сотовый ИЛИ телефон или доступ) ИЛИ легко ИЛИ В СЕТИ В БАНКЕ ИЛИ транзакция ИЛИ Мумбаи ИЛИ Дели РЯДОМ / 10 агаров ИЛИ ( онлайн или интернет) И (банк) ИЛИ НЕ ИЛИ (яблоко) ИСКЛЮЧИТЬ (монго)

Если я введу подобное, это решит и этот тип выражения.

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Pyparsing позволяет легко определить синтаксический анализатор выражений для этого вида нотации. Думайте о ваших ключевых словах AND, OR и т. Д., Как будто они были операторами, а ваши термины, такие как «безопасность» и т. Д., Как операнды в грамматике инфиксной нотации, и вы можете использовать генератор грамматики pyparsing infixNotation для определения вашего синтаксического анализатора:

sample = "security OR ((internet OR online OR paperless) AND (bank*)) AND (mobile OR cell OR phone OR access) OR easy OR online WITHIN bank OR transaction OR mumbai OR delhi NEAR/10 agar OR (online OR internet) AND (bank) OR not OR (apple) EXCLUDE (mongo)"

import pyparsing as pp
# enable packrat parsing, since this infix notation gets more complex than usual
pp.ParserElement.enablePackrat()

term = pp.Word(pp.alphas + '*')
SLASH = pp.Suppress('/')

AND = pp.Keyword("AND")
OR = pp.Keyword("OR")
WITHIN = pp.Keyword("WITHIN")
EXCLUDE = pp.Keyword("EXCLUDE")
NEAR_op = pp.Group(pp.Keyword("NEAR") + SLASH + pp.pyparsing_common.integer)
expr = pp.infixNotation(term,
                        [
                            (NEAR_op, 2, pp.opAssoc.LEFT),
                            (WITHIN, 2, pp.opAssoc.LEFT),
                            (AND, 2, pp.opAssoc.LEFT),
                            (OR, 2, pp.opAssoc.RIGHT),
                            (EXCLUDE, 2, pp.opAssoc.LEFT),
                        ])

expr.parseString(sample).pprint()

Печать:

[[['security',
   'OR',
   [[[['internet', 'OR', ['online', 'OR', 'paperless']], 'AND', 'bank*'],
     'AND',
     ['mobile', 'OR', ['cell', 'OR', ['phone', 'OR', 'access']]]],
    'OR',
    ['easy',
     'OR',
     [['online', 'WITHIN', 'bank'],
      'OR',
      ['transaction',
       'OR',
       ['mumbai',
        'OR',
        [['delhi', ['NEAR', 10], 'agar'],
         'OR',
         [[['online', 'OR', 'internet'], 'AND', 'bank'],
          'OR',
          ['not', 'OR', 'apple']]]]]]]]],
  'EXCLUDE',
  'mongo']]

(Отказ от ответственности: я автор pyparsing.)

Страница GitHub: https://github.com/pyparsing/pyparsing

Документы: https://pyparsing -docs.readthedocs.io / en / latest /

Установка: pip install pyparsing

0 голосов
/ 17 января 2019

Имо, здесь вам нужно использовать парсер, например PLY. Вам нужно определить все свои кубики и затем построить синтаксическое дерево, с помощью которого вы можете делать все, что захотите.
Примером может быть:

import ply.lex as lex

# List of token names.   This is always required
tokens = (
    'VARIABLE',
    'WHITESPACE',
    'OR',
    'AND',
    'NOT',
    'PAR_OPEN',
    'PAR_CLOSE',
)

# Regular expression rules for simple tokens
t_VARIABLE      = r'\b[a-z]+\b'
t_WHITESPACE    = r'\s+'
t_OR            = r'\bOR\b'
t_AND           = r'\bAND\b'
t_NOT           = r'\bNOT\b'
t_PAR_OPEN      = r'\('
t_PAR_CLOSE     = r'\)'

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# Build the lexer
lexer = lex.lex()
lexer.input("a OR (b AND c)")

while True:
    token = lexer.token()
    if not token:
        break
    else:
        print(token)

Это даст

LexToken(VARIABLE,'a',1,0)
LexToken(WHITESPACE,' ',1,1)
LexToken(OR,'OR',1,2)
LexToken(WHITESPACE,' ',1,4)
LexToken(PAR_OPEN,'(',1,5)
LexToken(VARIABLE,'b',1,6)
LexToken(WHITESPACE,' ',1,7)
LexToken(AND,'AND',1,8)
LexToken(WHITESPACE,' ',1,11)
LexToken(VARIABLE,'c',1,12)
LexToken(PAR_CLOSE,')',1,13)

Он будет работать даже с вложенными скобками, и вы сможете анализировать меньшие части (например, от PAR_OPEN до PAR_CLOSE и т. Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...