我正在闲逛一些简单的 Markdown 文本来玩和学习 Pyparsing 和一般的语法。我几乎立即遇到了一个我无法解决的问题。我正在尝试解析 CommonMark 规范的一个简单版本以进行强调。在此设置中,允许嵌套强调,因此

*foo *bar* baz*

应该给:
<em>foo <em>bar</em> baz</em>

我尝试使用递归定义来匹配它,但它不起作用。这是一些示例代码:
from pyparsing import *

text = Word(printables,excludeChars="*")
enclosed = Forward()
emphasis = QuotedString("*").setParseAction(lambda x: "<em>%s</em>" % x[0],contents=enclosed)
enclosed << emphasis | text

test = """
*foo *bar* bar*
"""

print emphasis.transformString(test)

但我从中得到的是:
<em>foo </em>bar<em> bar</em>

原谅我的无知;有人可以指出我正确的方向吗?

编辑 :

为了回答 abarnert 的很好的探索性问题,我将提供说明。我只是在玩,所以我可以使用任意限制形式的符号。我会假设只有单个 '*' 出现,并且它们不会彼此相邻出现。这使得空格可以消除歧义: * 后面没有空格打开强调,而 * 前面没有空格关闭它。

即使这样,我也不知道如何进行 Pyparsing。某种基于堆栈的方法,插入打开 * 并在它们验证为关闭时弹出它们?如何使用 Pyparsing 做到这一点?或者有没有更有效的方法?

最佳答案

有了这些附加规则,我认为您根本不需要担心递归,只需在找到开始和结束强调表达式时处理它们,无论它们是否匹配:

from pyparsing import *

openEmphasis = (LineStart() | White()) + Suppress('*')
openEmphasis.setParseAction(lambda x: ''.join(x.asList()+['<em>']))
closeEmphasis = '*' + FollowedBy(White() | LineEnd())
closeEmphasis.setParseAction(lambda x: '</em>')

emphasis = (openEmphasis | closeEmphasis).leaveWhitespace()

test = """
*foo *bar* bar*
"""
print test
print emphasis.transformString(test)

打印:
*foo *bar* bar*

<em>foo <em>bar</em> bar</em>

您不是第一个被此类应用程序绊倒的人。当我在 PyCon'06 上发表演讲时,一位热心的与会者立即开始解析一些 Markdown,输入字符串类似于 "****a** b**** c**" 或其他内容。我们一起进行了一些工作,但是消歧规则对于基本的 pyparsing 解析器来说太过于上下文感知了。

关于python - Pyparsing:嵌套的 Markdown 强调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25780553/

10-12 22:15