Использование pyparsing для анализа выражений фильтраPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Использование pyparsing для анализа выражений фильтра

Сообщение Anonymous »

В настоящее время я пытаюсь написать синтаксический анализатор (используя pyparsing), который может анализировать строки, которые затем можно применить к кадру данных (Pandas) для фильтрации данных. После долгих проб и ошибок я уже добился того, чтобы он работал для всех типов строк-примеров, однако с этого момента у меня возникли проблемы с его дальнейшим расширением.
Во-первых, вот мой текущий код (который должен работать, если вы просто скопируете его, по крайней мере, для моего Python 3.11.9 и pyparsing 3.1.2):

Код: Выделить всё

import pyparsing as pp

# Define the components of the grammar
field_name = pp.Word(pp.alphas + "_", pp.alphanums + "_")
action = pp.one_of("include exclude")
sub_action = pp.one_of("equals contains starts_with ends_with greater_than not_equals not_contains not_starts_with not_ends_with empty not_empty less_than less_than_or_equal_to greater_than_or_equal_to between regex in_list not_in_list")

# Custom regex pattern parser that handles regex ending at the first space
def regex_pattern():
def parse_regex(t):
# Join tokens to form the regex pattern
return ''.join(t[0])
return pp.Regex(r'[^ ]+')("regex").setParseAction(parse_regex)

# Define value as either a quoted string, a regex pattern, or a simple word with allowed characters
quoted_string = pp.QuotedString('"')
unquoted_value = pp.Word(pp.alphanums + "_-;, ") | pp.Regex(r'[^/]+')

value = pp.Optional(quoted_string | regex_pattern() | unquoted_value)("value")

slash = pp.Suppress("/")
filter_expr = pp.Group(field_name("field") + slash + action("action") + slash + sub_action("sub_action") + pp.Optional(slash + value, default=""))

# Define logical operators
and_op = pp.one_of("AND and")
or_op = pp.one_of("OR or")
not_op = pp.one_of("NOT not")

# Define the overall expression using infix notation
expression = pp.infixNotation(filter_expr,
[
(not_op, 1, pp.opAssoc.RIGHT),
(and_op, 2, pp.opAssoc.LEFT),
(or_op, 2, pp.opAssoc.LEFT)
])

# List of test filters
test_filters = [
"order_type/exclude/contains/STOP ORDER AND order_validity/exclude/contains/GOOD FOR DAY",
"order_status/include/regex/^New$ AND order_id/include/equals/123;124;125",
"order_id/include/equals/123;124;125",
"order_id/include/equals/125 OR currency/include/equals/EUR",
"trade_amount/include/greater_than/1500 AND currency/include/equals/USD",
"trade_amount/include/between/1200-2000 AND currency/include/in_list/USD,EUR",
"order_status/include/starts_with/New;Filled OR order_status/include/ends_with/ed",
"order_status/exclude/empty AND filter_code/include/not_empty",
"order_status/include/regex/^New$",
"order_status/include/regex/^New$ OR order_status/include/regex/^Changed$",
"order_status/include/contains/New;Changed"
]

# Loop over test filters, parse each, and display the results
for test_string in test_filters:
print(f"Testing filter: {test_string}")
try:
parse_result = expression.parse_string(test_string, parseAll=True).asList()[0]
print(f"Parsed result: {parse_result}")
except Exception as e:
print(f"Error with filter: {test_string}")
print(e)
print("\n")
Теперь, если вы запустите код, вы заметите, что все тестовые строки анализируются нормально, за исключением первого элемента списка "order_type/exclude/contains/STOP ORDER AND order_validity/exclude/contains/GOOD FOR DAY".
Проблема (насколько я могу судить) заключается в том, что пустое пространство между "STOP" и "ORDER" распознается как конец части «значения» этой части группы, а затем ломается.
Я пробовал использовать Skipsto, чтобы просто перейти к следующему логическому оператор после завершения части sub_action, но это не сработало. Кроме того, я не был уверен, насколько это расширяемо, потому что теоретически должно быть возможно даже иметь множество связанных выражений (например, часть1 И часть2 ИЛИ часть3), где каждая часть состоит из 3-4 элементов (имя_поля, действие, под_действие). и необязательное значение).
Я также пытался расширить unquoted_value, включив в него пустые места, но это тоже ничего не изменило.
Я Я также просмотрел некоторые примеры на https://github.com/pyparsing/pyparsing/ ... r/examples, но я не смог увидеть ничего похожего на мой вариант использования. (Возможно, когда мой код заработает правильно, его можно будет добавить сюда в качестве примера, не уверен, насколько мой случай будет полезен другим).

Подробнее здесь: https://stackoverflow.com/questions/790 ... xpressions
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Использование pyparsing для анализа выражений фильтра
    Anonymous » » в форуме Python
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Использование pyparsing для анализа инфиксного выражения
    Anonymous » » в форуме Python
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous
  • Использование pyparsing для анализа инфиксного выражения
    Anonymous » » в форуме Python
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Использование pyparsing для анализа инфиксного выражения
    Anonymous » » в форуме Python
    0 Ответы
    23 Просмотры
    Последнее сообщение Anonymous
  • Используйте pyparsing для анализа выражения, начинающегося с скобок
    Гость » » в форуме Python
    0 Ответы
    13 Просмотры
    Последнее сообщение Гость

Вернуться в «Python»