Переменная ident
, определенная в классе Expressions
, не является заполнителем, поэтому, когда вы присваиваете ее в своем методе __init__
, вы не меняете общий анализатор, а просто определение self.ident
(которое создает новый атрибут в экземпляре Expressions и не изменяет идентификатор уровня класса).
Почему бы просто не определить весь синтаксический анализатор в __init__
? Затем вы можете определить ident
, используя заданные имена переменных, и обойти все проблемы атрибутов class-vs-instance и проблемы update-part-of-a-parser-after-the-fact.
А что этот код должен делать?
ids = []
for x in vars:
ids.append(x)
Существуют гораздо более простые способы копирования значений из одного списка в другой, но почему вы даже делаете копию? Просто определите ident
, используя входной список имен переменных (который вы могли бы назвать чем-то, кроме vars
, поскольку это противоречит полезному встроенному методу - возможно, вызовите его var_names
?).
РЕДАКТИРОВАТЬ: еще несколько заметок
Вам нужно исправить fn_call. Как таковой, у вас будет бесконечная рекурсия, потому что все это список разделенных запятыми arith_exprs. Поскольку вы определяете arith_expr с помощью fn_call, существует рекурсия влево. Я думаю, что вы не полностью скопировали это из другого примера, у вас есть действительное выражение для списка аргументов, которые есть в списке аргументов функции, но вам не хватает имени функции и входящих в нее паренов. Добавьте их, и проблема рекурсии исчезнет.
Один из ваших вариантов - v_3,1. Это странно выглядящий идентификатор, но, к счастью, он не конфликтует ни с какими другими битами в вашем парсере. Но если вы отправите идентификатор «3.1» или «42», все будет очень запутанно. Возможно, вы захотите определить выражение valid_identifier, а затем проверить входящие имена переменных с помощью чего-то вроде:
valid_expression = Word(alphas + '_', alphanums + '_,')
if not all(valid_expression.matches(varname) for varname in varnames):
raise WhatWereYouThinkingException("invalid identifier specified")