Python 在pyparsing中实现属性访问操作符
我试图实现一个DSL来编写自定义条件表达式,其中包括特定对象的关键字和这些对象上的属性。例如:Python 在pyparsing中实现属性访问操作符,python,pyparsing,Python,Pyparsing,我试图实现一个DSL来编写自定义条件表达式,其中包括特定对象的关键字和这些对象上的属性。例如: user.foo.bar or user.baz user是用当前用户对象替换的关键字。我还实现了或、和以及非操作符,这些操作符基于 我实现了如下属性访问: from pyparsing import infixNotation, opAssoc, Keyword, Word, alphas class User: pass class PropertyAccess: def _
user.foo.bar or user.baz
user
是用当前用户对象替换的关键字。我还实现了或
、和
以及非
操作符,这些操作符基于
我实现了如下属性访问:
from pyparsing import infixNotation, opAssoc, Keyword, Word, alphas
class User:
pass
class PropertyAccess:
def __init__(self, t):
self.value = reduce(lambda o, p: getattr(o, p, None), t[0][0::2])
user = Keyword('user')
user.setParseAction(User)
identifier = Word(alphas + '_')
property_access_expr = infixNotation(user | identifier, [
('.', 2, opAssoc.LEFT, PropertyAccess)
])
虽然这样做有效,但它也允许像
foo.bar
这样的表达式,这是毫无意义的。属性访问必须以受支持的关键字之一(如user
)开始,否则它们将无效。如何重新实现语法以限制它?您使用infixNotation
使任务变得不必要的困难infixNotation
用于定义具有不同优先级(即操作顺序)的多个不同中缀运算符。但是属性访问只有一个操作符(
),可以通过一个或多个轻松实现:
property_access_expr = user + OneOrMore('.' + identifier)
property_access_expr.setParseAction(PropertyAccess)
像这样更改语法需要对PropertyAccess
类稍作修改。以前输入是嵌套列表,但现在是平面列表。因此,我们必须将t[0][0::2]
更改为t[0::2]
class PropertyAccess:
def __init__(self, t):
self.value = reduce(lambda o, p: getattr(o, p, None), t[0::2])
现在,语法只正确解析以user开头的属性访问。
:
>>> property_access_expr.parseString('user.foo.bar')
([<__main__.PropertyAccess object at 0x0000000002DD4048>], {})
>>> property_access_expr.parseString('foo.bar')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
pyparsing.ParseException: Expected "user" (at char 0), (line:1, col:1)
>>property\u access\u expr.parseString('user.foo.bar'))
([], {})
>>>属性\u访问\u表达式解析字符串('foo.bar')
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
pyparsing.ParseException:应为“用户”(在字符0处),(行:1,列:1)
我只是根据到目前为止我对pyparsing有限的曝光量来拼凑,而infixNotation
是我唯一真正了解的锤子非常感谢。如果抑制“.”字符(使用类似于DOT=suppress(“.”);property\u access\u expr=user+one或more(DOT+identifier)
,那么您就不需要跨步切片了:2
因为点将从解析结果中被抑制。我喜欢使用reduce
连续调用getattr
。