在 pyparsing 中实现 属性 访问运算符

Implementing property access operator in pyparsing

我正在尝试实现用于编写自定义条件表达式的 DSL,其中包括某些对象的关键字和这些对象的属性。例如:

user.foo.bar or user.baz

user是用当前用户对象代替的关键字。我还基于 existing sample.

实现了 orandnot 运算符

我已经实现了这样的 属性 访问:

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 对于定义多个具有不同优先级(即操作顺序)的不同中缀运算符很有用。但是 属性 访问只有一个运算符 (.),并且很容易用 OneOrMore:

实现
property_access_expr = user + OneOrMore('.' + identifier)
property_access_expr.setParseAction(PropertyAccess)

像这样更改语法需要对 PropertyAccess class 进行少量修改。以前输入是嵌套列表,但现在是平面列表。因此,我们必须将 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)