- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 infixNotation
(以前的 operatorPrecedence
)编写语法,但我不知道如何使用 setResultsName
有了这个。
我尝试这样做的原因是我在searchparser之上构建了 bool 搜索查询的语法。但对于很长的表达式,它会遇到RecursionError:比较中超出最大递归深度
。
看来,通过使用 infixNotation(searchparser 没有),我可以避免遇到这个错误。因此,我尝试使语法适应 infixNotation,但我的评估很大程度上依赖于结构化解析结果中每个运算符的名称,特别是轻松访问运算符的参数。
我从 pyparsing 书中给出的示例开始:
and_ = CaselessLiteral("and")
or_ = CaselessLiteral("or")
not_ = CaselessLiteral("not")
searchTerm = Word(alphanums) | quotedString.setParseAction( removeQuotes )
searchExpr = infixNotation( searchTerm,
[
(not_, 1, opAssoc.RIGHT),
(and_, 2, opAssoc.LEFT),
(or_, 2, opAssoc.LEFT),
])
那么,如何在此处设置 ParseResultName?
如果我尝试将其设置为运算符:
or_ = CaselessLiteral("or").setResultsName("OR")
该字符串的解析结果('term1 OR term2 OR term3')将如下所示:
<ITEM>
<word>
<word>
<ITEM>term1</ITEM>
</word>
<OR>or</OR>
<word>
<ITEM>term2</ITEM>
</word>
<OR>or</OR>
<word>
<ITEM>term3</ITEM>
</word>
</word>
</ITEM>
这意味着所有术语和运算符都处于同一级别,而我想要这样的东西,其中术语排列为运算符的参数:
<OR>
<OR>
<word>
<ITEM>term1</ITEM>
</word>
<OR>
<word>
<ITEM>term2</ITEM>
</word>
<word>
<ITEM>term3</ITEM>
</word>
</OR>
</OR>
</OR>
我以前的语法中曾经通过类似的方法来实现这一点:
operatorOr << (Group(
operatorAnd + Suppress(Keyword("OR", caseless=True)) + operatorOr
).setResultsName("OR") | operatorAnd)
但我不知道如何将结果名称设置为由运算符及其两个参数组成的组?
最佳答案
我鼓励您考虑使用类作为解析操作,构建操作节点树,而不是使用结果名称。
在下面的代码中,我将 UnOp 和 BinOp 类附加到每个 infixNotation 运算符级别,这会返回这些类的实例,并正确分配了 operator
和 operands
属性:
class OpNode:
def __repr__(self):
return "{}({}):{!r}".format(self.__class__.__name__,
self.operator, self.operands)
class UnOp(OpNode):
def __init__(self, tokens):
self.operator = tokens[0][0]
self.operands = [tokens[0][1]]
class BinOp(OpNode):
def __init__(self, tokens):
self.operator = tokens[0][1]
self.operands = tokens[0][::2]
and_ = CaselessLiteral("and")
or_ = CaselessLiteral("or")
not_ = CaselessLiteral("not")
searchTerm = Word(alphanums) | quotedString.setParseAction(removeQuotes)
searchExpr = infixNotation(searchTerm,
[
(not_, 1, opAssoc.RIGHT, UnOp),
(and_, 2, opAssoc.LEFT, BinOp),
(or_, 2, opAssoc.LEFT, BinOp),
])
这是一个示例字符串,显示如何返回这些节点:
test = "term1 or term2 or term3 and term4 and not term5"
print(searchExpr.parseString(test))
给予:
[BinOp(or):['term1', 'term2', BinOp(and):['term3', 'term4', UnOp(not):['term5']]]]
您可以导航此解析树并根据节点类型和运算符评估不同的节点。
此外,asXML()
并不是转储已解析数据的最佳工具,您最好使用 dump()
方法。
关于python - Pyparsing:将 infixnotation 与 setResultsName 结合起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47184677/
我正在解析具有多个答案的多项选择题,如下所示: ParserElement.setDefaultWhitespaceChars(u""" \t""") in_ = """1) first stem.
我认为我在调用 setResultsName() 时犯了一个错误: from pyparsing import * DEPT_CODE = Regex(r'[A-Z]{2,}').setResults
Pyparsing 文档展示了如何使用 setResultsName(...) 方法来设置生成的字典键。但是,我几次看到这个方法被省略了,只使用了 (...) 。我的意思是: 代替: exp1 = p
我正在尝试解析一些 SQL 语句。这是一个示例: select ms.member_sk a, dd.date_sk b, st.subscription_type,
我正在尝试使用 infixNotation(以前的 operatorPrecedence)编写语法,但我不知道如何使用 setResultsName有了这个。 我尝试这样做的原因是我在searchpa
我是一名优秀的程序员,十分优秀!