我正在使用pyparsing,发现它非常适合开发一个简单的DSL,它允许我从MongoDB中提取数据字段并对其进行简单的算术运算。我现在正在尝试扩展我的工具,以便可以应用form Rank的函数[人:身高]并可能包含简单表达式作为函数调用的参数。我正在努力让解析语法正常工作。以下是我目前所掌握的情况:
# Define parser
expr = Forward()
integer = Word(nums).setParseAction(EvalConstant)
real = Combine(Word(nums) + "." + Word(nums)).setParseAction(EvalConstant)
# Handle database field references that are coming out of Mongo,
# accounting for the fact that some fields contain whitespace
dbRef = Combine(Word(alphas) + ":" + Word(printables) + \
Optional(" " + Word(alphas) + " " + Word(alphas)))
dbRef.setParseAction(EvalDBref)
# Handle function calls
functionCall = (Keyword("Rank") | Keyword("ZS") | Keyword("Ntile")) + "[" + expr + "]"
functionCall.setParseAction(EvalFunction)
operand = functionCall | dbRef | (real | integer)
signop = oneOf('+ -')
multop = oneOf('* /')
plusop = oneOf('+ -')
# Use parse actions to attach Eval constructors to sub-expressions
expr << operatorPrecedence(operand,
[
(signop, 1, opAssoc.RIGHT, EvalSignOp),
(multop, 2, opAssoc.LEFT, EvalMultOp),
(plusop, 2, opAssoc.LEFT, EvalAddOp),
])
我的问题是当我测试像Rank这样的简单表达式时[人:身高]我得到一个解析异常:
^{pr2}$如果我使用一个float或算术表达式作为参数,比如Rank[3+1.1],那么解析就正常了;如果我简化了dbRef语法,那么它也可以工作。我的语法不能把我的生活搞得一团糟。我尝试过重新排列操作数的顺序以及简化函数调用语法,但都没有成功。有人能看出我做错了什么吗?在
一旦我完成了这项工作,我想做最后一步,在表达式中引入对变量赋值的支持。。在
编辑:在进一步的测试中,如果我从dbRef语法中删除了可打印文件,那么一切正常:
dbRef = Combine(Word(alphas) + OneOrMore(":") + Word(alphanums) + \
Optional("_" + Word(alphas)))
但是,如果我将字符“-”添加到dbRef(对于DB字段,我需要这个字符,比如等级:S-N),则解析器再次失败。我想“-”正在被我的操作员或接收人使用?在
可能发生的情况是,测试字符串(
Rank[Person:Height]
)末尾的]
字符作为dbRef
标记的一部分被使用,因为该标记中超过初始:
的部分被声明为由Word(可打印文件)组成(不幸的是,这个字符集包括方括号字符)然后解析器试图生成一个
functionCall
,但是缺少结束的]
,因此出现了错误消息。在一个暂时的解决办法是使用不包括方括号的字符集,可能是更明确的,例如:
编辑:
仔细看,上面的内容大致正确,但令牌层次结构是错误的(例如,解析器试图将
functionCall
作为anexpr
的一个操作数等)另外,由于
-
符号的模糊性,我建议的修复方法也不起作用,因为在dbRef
内,它应该被理解为一个普通字符,而在expr
中则应该理解为plusOp。不过,pym的语法分析方法并不常见。在找到了解决方案-问题是我的dbRef语法使用了函数规范中的一些字符。正确运行的新语法:
相关问题 更多 >
编程相关推荐