如何找出哪些 ParserElements 与 Pyparsing 中的字符串匹配?
我有一个复杂的子 ParserElements 并像这样组合在一起,我计划添加更多。
Group(multi_line ^ macro_parser ^ numeric_assignment ^ assert_parser ^ db ^
charmap_parser ^ comment_parser ^
include_parser ^ label ^ expression ^ macro_call ^
newcharmap_parser ^ popc ^ pushc ^ redef ^ control ^ Literal("\n"))
我遇到了问题,其中一个子 ParserElements 在不应该匹配的情况下会匹配,并且我将得到一个 ParseException,它不告诉我哪个 ParserElement 引发了它。这意味着我必须四处寻找哪些表达式与哪些行匹配,并且需要花费大量时间。
有没有办法在出现异常时获取更多有用的信息?我尝试将 .setDebug() 附加到上面的解析器,但错误消息没有任何帮助。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了帮助您的最终用户通过使用解析器逻辑了解自己的解析失败,有用的事情是通过使用以下方法来增强您自己的 ParserElements 的错误输出:
.setName()
Python-
运算符,而不是+
运算符。.setName()
.setName()
允许您重新-声明您的解析错误输出(以简单的第 8 种形式)等级“英语”句子,或者最简单的 BNF,甚至是助记符),尽管我经常使用由一对三元组 ("""
) 包围的多行 EBNF 文本。默认的
.setName()
,您在 Python 赋值时定义给 ParserElement 的......对于该 Python 变量,是要以文本形式显示其中使用的整个“PyParsing-ese”逻辑的字符串,其中 通常会对普通用户有一点帮助。每当最终用户遇到该变量中发生的
ParseExceptions
时,该 PyParsing 变量的新的更简单的.setName()
文本 将要 。使用减号选择性地
用
-
替换 SOME+
可以帮助您的最终用户(和您)更接近该位置的“更正确”位置偏移 对语法错误有“更准确”的偏移量也有助于 parseException 选择“更正确”的 PyParsing 变量/组。使用正确的变量,其(更好选择的)
.setName()
输出将帮助最终用户能够更快地推断出他们(或您的)错误。然后 parseException 会从包含相关 PyParsing 逻辑 (ParserElement) 的 Python 赋值中输出新的
.setName()
文本字符串。Python 示例
下面是一个在发生
parseException
时输出简化的 EBNF 的示例:通常的输出,
而不是在
parseException
时看到一个很长的默认输出,但看起来很神秘:可读输出
新的输出现在将是
或
或 ,
具体取决于它们破坏解析器逻辑的位置。
总结
使用
.setName()
/minus-operator 二人组,我很少使用 PyParsing 调试器开销(如果有的话)。当然,您的逻辑变得越复杂,就是开始向每个受影响的分配添加
.setName()
的好时机。随着每个 .setName 添加,解决 parseException 的时间会变得越来越短……不仅对您(PyParsing 逻辑的开发人员)而言,而且对您的最终用户而言也是如此。
有一个项目在 named.conf 配置文件中使用 PyParsing 编写了 4,000 多个逻辑。 “nofollow noreferrer”>bind9_parser。 Bind9_parse 很好地利用了这对组合。
Bind9_parser 的最终用户更容易破译解析错误非常重要。
The useful things, to help your end-user to understand their own parse failures from using your parser logic, would be to enhance the error output of your own ParserElements by using:
.setName()
Python method-
operator, instead of+
operator..setName()
.setName()
allows you re-state your parse error output (in plain 8th-grade “English” sentence, or a simplest BNF, or even an mnemonic), Although I’ve often used a multi-line EBNF text surrounded by a pair of triple ("""
).The default of
.setName()
, that you defined to a ParserElement at Python assignment-time … to that Python variable, is to show a string in textualized form of its entire “PyParsing-ese” logic used therewithin, which is often of a little help to the average users.Whenever end-user experiences a
ParseExceptions
that occured within that variable, the new simpler.setName()
text of that PyParsing variable will be shown instead.Using Minus Symbol Selectively
Replacing SOME
+
with-
can help your end-users (and you) to get closer to a “more correct” location offset of that offending character.Having a “more accurate” offset to the syntax error also helps parseException to selects a “more correct” PyParsing variable/group. With the correct variable, its (better-selected)
.setName()
output would help the end-user to be able to deduce their (or your) errors … quicker.Then parseException would output that new
.setName()
text string from the Python assignment containing your PyParsing logic (ParserElement) in question.Example Python
Here is an example of outputting a simplified EBNF in event of a
parseException
:Usual Output
instead seeing a very long ouput for a default but seemingly cryptic at
parseException
time:Readable Output
the new output would now be
or
or
depending on where they broke your parser logic.
Summary
With the
.setName()
/minus-operator duo, I have rarely used PyParsing debugger overhead, if at all.Of course, the more complex your logic grows, is that good time to start adding
.setName()
to each impacted assignment.The meantime to resolution of parseException grows shorter with each .setName added … not only for you, the developer of PyParsing logics, but immediately for your end-users.
There is one project that have over 4,000 logics written in PyParsing for
named.conf
configuration file for ISC Bind9 DNS server in bind9_parser. Bind9_parse made excellent uses of this duo.Easier decipherment of parse errors by end-users of bind9_parser is kinda important.