使用自己的 pyparsing class
pyparsing using own class
我正在尝试遵循 this 教程,但很难将教程中使用的语法转换为 pyparsing 语法。该博客的主旨是创建一种表达式语言来解析和执行字典比较。
properties = {
"name": "David Bowie",
"years_active2": 47
}
要计算的表达式:
properties["name"] == "David Bowie"
他们使用的语法是:
expr: literal { return }
| "properties" "[" literal "]" { return PropertyLookup() }
| expr "[" expr "]" { return Index(, ) }
| expr "and" expr { return And(, ) }
| expr "==" expr { return Equals(, ) }
| expr ">" expr { return GreaterThan(, ) }
;
literal: QUOTED_STRING { return Literal() }
| DECIMAL_NUMBER { return Literal() }
;
到目前为止我有:
string_literal = pp.Word(pp.alphas, pp.alphanums)
numeric_literal = pp.Word(pp.nums)
literal = string_literal | numeric_literal
properties = "properties" + "[" + literal + "]"
PropertyLookup()、Index()、And()、Equals() 和 GreaterThan() 是为构建表达式而创建的自定义 classes。
如何更改我的第 4 行属性,使其与第二行的行为相同?我最困惑的是如何将文字传递到自定义 class 中,例如 PropertyLookup()
class PropertyLookup(object):
def evaluate(self, props):
return props[self.key]
感谢任何帮助!
要让 pyparsing 为您构建 classes,请将它们作为解析操作附加到表达式。这是一个如何执行此操作的小示例:
import pyparsing as pp
class Node(object):
def __init__(self, tokens):
self._tokens = tokens
def __repr__(self):
return "{}: ({})".format(self.__class__.__name__, self._tokens.asList())
class AlphaNode(Node): pass
class NumericNode(Node): pass
class BinExprNode(Node): pass
class OperatorNode(Node): pass
alpha_expr = pp.Word(pp.alphas)
numeric_expr = pp.Word(pp.nums)
operand = alpha_expr | numeric_expr
operator = pp.oneOf("+ - * /")
bin_expr = operand + pp.OneOrMore(operator + operand)
# by setting the node classes as each expression's parse action,
# the node instances will be constructed at parse time and returned
# as pyparsing's parse results
alpha_expr.addParseAction(AlphaNode)
numeric_expr.addParseAction(NumericNode)
operator.addParseAction(OperatorNode)
bin_expr.addParseAction(BinExprNode)
result = bin_expr.parseString("a + 27 * X")
print(repr(result[0]))
打印
BinExprNode: ([AlphaNode: (['a']), OperatorNode: (['+']), NumericNode: (['27']), OperatorNode: (['*']), AlphaNode: (['X'])])
您还必须清除语法中的一些左递归 - 您将无法实现以 expr
开头的 expr
,这只会递归自身直到你达到了递归限制。首先将基本操作数表达式定义为:
expr: literal
| "properties" ("[" expr "]")...
;
使用 pyparsing 的 OneOrMore class 重复索引到 "properties"。然后使用 pyparsing 示例中的方法,例如 SimpleBool.py 或 evalArith.py 来构建中缀符号表达式和评估器。
我正在尝试遵循 this 教程,但很难将教程中使用的语法转换为 pyparsing 语法。该博客的主旨是创建一种表达式语言来解析和执行字典比较。
properties = {
"name": "David Bowie",
"years_active2": 47
}
要计算的表达式:
properties["name"] == "David Bowie"
他们使用的语法是:
expr: literal { return }
| "properties" "[" literal "]" { return PropertyLookup() }
| expr "[" expr "]" { return Index(, ) }
| expr "and" expr { return And(, ) }
| expr "==" expr { return Equals(, ) }
| expr ">" expr { return GreaterThan(, ) }
;
literal: QUOTED_STRING { return Literal() }
| DECIMAL_NUMBER { return Literal() }
;
到目前为止我有:
string_literal = pp.Word(pp.alphas, pp.alphanums)
numeric_literal = pp.Word(pp.nums)
literal = string_literal | numeric_literal
properties = "properties" + "[" + literal + "]"
PropertyLookup()、Index()、And()、Equals() 和 GreaterThan() 是为构建表达式而创建的自定义 classes。
如何更改我的第 4 行属性,使其与第二行的行为相同?我最困惑的是如何将文字传递到自定义 class 中,例如 PropertyLookup()
class PropertyLookup(object):
def evaluate(self, props):
return props[self.key]
感谢任何帮助!
要让 pyparsing 为您构建 classes,请将它们作为解析操作附加到表达式。这是一个如何执行此操作的小示例:
import pyparsing as pp
class Node(object):
def __init__(self, tokens):
self._tokens = tokens
def __repr__(self):
return "{}: ({})".format(self.__class__.__name__, self._tokens.asList())
class AlphaNode(Node): pass
class NumericNode(Node): pass
class BinExprNode(Node): pass
class OperatorNode(Node): pass
alpha_expr = pp.Word(pp.alphas)
numeric_expr = pp.Word(pp.nums)
operand = alpha_expr | numeric_expr
operator = pp.oneOf("+ - * /")
bin_expr = operand + pp.OneOrMore(operator + operand)
# by setting the node classes as each expression's parse action,
# the node instances will be constructed at parse time and returned
# as pyparsing's parse results
alpha_expr.addParseAction(AlphaNode)
numeric_expr.addParseAction(NumericNode)
operator.addParseAction(OperatorNode)
bin_expr.addParseAction(BinExprNode)
result = bin_expr.parseString("a + 27 * X")
print(repr(result[0]))
打印
BinExprNode: ([AlphaNode: (['a']), OperatorNode: (['+']), NumericNode: (['27']), OperatorNode: (['*']), AlphaNode: (['X'])])
您还必须清除语法中的一些左递归 - 您将无法实现以 expr
开头的 expr
,这只会递归自身直到你达到了递归限制。首先将基本操作数表达式定义为:
expr: literal
| "properties" ("[" expr "]")...
;
使用 pyparsing 的 OneOrMore class 重复索引到 "properties"。然后使用 pyparsing 示例中的方法,例如 SimpleBool.py 或 evalArith.py 来构建中缀符号表达式和评估器。