Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用函数调用解析算术表达式_Python_Dsl_Pyparsing - Fatal编程技术网

Python 用函数调用解析算术表达式

Python 用函数调用解析算术表达式,python,dsl,pyparsing,Python,Dsl,Pyparsing,我正在使用pyparsing,发现它非常适合开发一个简单的DSL,它允许我从MongoDB中提取数据字段并对其进行简单的算术运算。我现在正在尝试扩展我的工具,这样我就可以将Rank[Person:Height]形式的函数应用于字段,并可能将简单表达式作为函数调用的参数。我正在努力使解析语法正常工作。以下是我到目前为止的情况: # Define parser expr = Forward() integer = Word(nums).setParseAction(EvalConstant) rea

我正在使用pyparsing,发现它非常适合开发一个简单的DSL,它允许我从MongoDB中提取数据字段并对其进行简单的算术运算。我现在正在尝试扩展我的工具,这样我就可以将Rank[Person:Height]形式的函数应用于字段,并可能将简单表达式作为函数调用的参数。我正在努力使解析语法正常工作。以下是我到目前为止的情况:

# 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),
    ])
如果我使用浮点数或算术表达式作为参数,如秩[3+1.1],解析工作正常,如果我简化dbRef语法,使其仅为单词(alphas),则解析工作正常。我一辈子都搞不清楚我的全部语法有什么问题。我尝试过重新排列操作数的顺序,以及简化functionCall语法,但都无济于事。有人能看出我做错了什么吗

一旦我开始工作,我想做最后一步,介绍对表达式中变量赋值的支持

编辑:进一步测试后,如果我从dbRef语法中删除可打印内容,一切正常:

 dbRef = Combine(Word(alphas) + OneOrMore(":") + Word(alphanums) + \
      Optional("_" + Word(alphas)))

但是,如果我将字符“-”添加到dbRef(我需要用于“Class:S-N”之类的DB字段),解析器将再次失败。我认为我的OperatorRecessence中的签名正在使用“-”号?

出现的情况是,测试字符串末尾的
]
字符(
Rank[Person:Height]
)作为
dbRef
标记的一部分被使用,因为此标记中超过首字母
的部分声明为由Word(可打印文件)组成(不幸的是,此字符集包含方括号字符)

然后,解析器尝试生成一个
函数调用
,但缺少结束符
]
,因此出现错误消息

暂时的解决办法是使用不包含方括号的字符集,可能是更明确的字符集,如:

dbRef = Combine(Word(alphas) + ":" + Word(alphas, alphas+"-_./") + \
    Optional(" " + Word(alphas) + " " + Word(alphas)))
编辑
仔细观察,上述内容大致正确,但令牌层次结构是错误的(例如,解析器试图将
functionCall
生成为an
expr
的一个操作数等)。

此外,我建议的修复方案将不起作用,因为
-
符号有歧义,在
dbRef
中,符号应理解为普通字符,在
expr
中,符号应理解为plusOp。这种类型的问题在解析器中很常见,有很多方法可以解决,但我不确定pyparsing到底是如何解决的。

找到了解决方案-问题是我的dbRef语法使用了函数规范中的一些字符。正确使用的新语法:

dbRef = Combine(Word(alphas) + OneOrMore(":") + Word(alphanums) + \
    Optional(oneOf("_ -") + Word(alphas)))

我认为你有一些想法,虽然不是100%正确。在进一步测试之后,如果我从dbRef中删除可打印内容,并且只使用alphanums+“389;”,则一切正常。但是,如果我添加字符“-”,解析器将再次失败。我想我的OperatorRecessence中的签名正在使用“-”字符?我需要破折号“-”字符,因为我的一些数据库字段包含此字符。。我有什么想法可以避免它在操作过程中被消耗?mjv你的编辑被切断了。您建议如何处理模糊的“-”符号和令牌层次结构?@RogerSanchez抱歉。。。我尝试了一些东西,并被提醒PyParsing不是递归下降解析器。我们可能需要放松一下语法。。。很抱歉,我现在得走了,但我会带着一个看似合理的解决方案回来。非常感谢,除了在这一点上处理减号之外,我的程序还在运行。。
dbRef = Combine(Word(alphas) + OneOrMore(":") + Word(alphanums) + \
    Optional(oneOf("_ -") + Word(alphas)))