2017-01-02 53 views
1

我正在尝试遵循this教程,并且很难将本教程中使用的语法转换为pyparsing语法。博客的要点是创建表达式语言来解析和执行字典比较。使用自己的类pyparsing

properties = { 
    "name": "David Bowie", 
    "years_active2": 47 
} 

表达来评估:

​​

它们所使用的语法是:

expr: literal      { return $1 } 
    | "properties" "[" literal "]" { return PropertyLookup($3) } 
    | expr "[" expr "]"   { return Index($1, $3) } 
    | expr "and" expr    { return And($1, $3) } 
    | expr "==" expr    { return Equals($1, $3) } 
    | expr ">" expr    { return GreaterThan($1, $3) } 
; 

literal: QUOTED_STRING { return Literal($1) } 
    | DECIMAL_NUMBER { return Literal($1) } 
; 

到目前为止我有:

string_literal = pp.Word(pp.alphas, pp.alphanums) 
numeric_literal = pp.Word(pp.nums) 
literal = string_literal | numeric_literal 
properties = "properties" + "[" + literal + "]" 

PropertyLookup(),索引() ,和(),Equals()和GreaterThan()是自定义的cl为创建表达而创建的屁股。

我该如何改变我的第四行属性,以与第二行相同的方式进行操作?我主要困惑如何将文字传递到一个自定义类,如PropertyLookup()这是

class PropertyLookup(object): 
    def evaluate(self, props): 
     return props[self.key] 

任何帮助表示赞赏!

+0

你有什么尝试?结果是什么?它与你的预期有什么不同?有时,从教程中分离出来的好方法是将其精确地复制*,然后开始进行修改。如果它坏了,回到它仍然有效的位置,然后找出你做了什么破坏了它。 –

回答

3

要使用pyparsing为您构建类,请将它们作为解析操作附加到表达式。下面是如何做到这一点的一个小例子:

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'])]) 

您还必须澄清一些左递归在你的语法 - 你将无法实现一个exprexpr开始,这只会在自己递归,直到你达到递归限制。为索引的重复进入“属性”

expr: literal     
    | "properties" ("[" expr "]")... 
; 

使用pyparsing的一次或更多类:通过定义您的基本操作数表达的开始。然后使用类似SimpleBool.py或evalArith.py等pyparsing示例中的方法来构建中缀表示法和评估器。