在 pyparsing 中实现 属性 访问运算符
Implementing property access operator in pyparsing
我正在尝试实现用于编写自定义条件表达式的 DSL,其中包括某些对象的关键字和这些对象的属性。例如:
user.foo.bar or user.baz
user
是用当前用户对象代替的关键字。我还基于 existing sample.
实现了 or
、and
和 not
运算符
我已经实现了这样的 属性 访问:
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)
我正在尝试实现用于编写自定义条件表达式的 DSL,其中包括某些对象的关键字和这些对象的属性。例如:
user.foo.bar or user.baz
user
是用当前用户对象代替的关键字。我还基于 existing sample.
or
、and
和 not
运算符
我已经实现了这样的 属性 访问:
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)