2014-09-11 58 views
3

我用一些簡單的Markdown文本來玩弄和學習一般的Pyparsing和語法。我幾乎立即遇到了一個問題,即解決問題。我試圖解析一個簡單版本的CommonMark規範的重點。在這種設置中,嵌套的重點是允許的,讓Pyparsing:嵌套Markdown重點

*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> 

原諒我noobishness;有人能指引我走向正確的方向嗎?

編輯

針對abarnert最偉大的探測問題,我將提供澄清。我只是在玩耍,所以我可以使用任意限制的符號形式。我假設只有一個'*'出現,並且它們不會彼此相鄰。這留下了空白,以消除歧義:*沒有跟着空白打開重點,並且*沒有先空白空間關閉它。

即使這樣,我不知道如何繼續Pyparsing。某種基於堆棧的方法,推開*並在驗證爲關閉時彈出它們? Pyparsing如何做到這一點?還是有更有效的方法?

+0

我認爲最簡單的方法來做你想要的版本是放棄自動空白處理和對待空白作爲一個令牌......但我不知道。我會讓我的潛意識去仔細研究它,如果你仍然陷入困境,沒有其他人會回到你身邊,我會在稍後再對它進行一次重擊。 – abarnert 2014-09-11 17:24:38

+0

只要你說「把空白當作一個標記」,我認爲pyparsing開始不是最好的選擇。隱含的空白跳過是其魅力的關鍵部分。 – PaulMcG 2014-09-11 22:49:05

回答

2

有了這些額外的規則,我不認爲你需要擔心的遞歸所有,只是處理的開閉強調錶情,因爲他們發現,它們是否匹配與否:

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上演講時,一位熱心的與會者解決了一些降價問題,輸入字符串如"****a** b**** c**"或其他東西。我們在一起工作了一段時間,但消歧規則對於基本的pyparsing解析器能夠處理的情況來說太具有上下文意義。

+0

非常感謝,保羅!我很佩服你給Pyparsing提供了多少幫助。爲了好奇,你認爲Pyparsing能爲Commonmark生成一個完整的解析器嗎? (我不打算試試它,只是試圖讓我的腳與圖書館和語法一般,但它讓我想知道是否有可能)。 – Winawer 2014-09-11 21:29:26

+0

跳過遞歸意味着,如果給定打破Markdown,他會成功地生成破碎的HTML,而不是失敗,對吧? (我不認爲這是一個問題 - 他從來沒有要求寫一個驗證解析器或生成一個具有重點節點或任何東西的樹 - 我只是想澄清它。) – abarnert 2014-09-11 22:17:16

+0

@Winawer:聽起來它應該是可行的如果您遵循[解析策略](http://jgm.github.io/stmd/spec.html#appendix-aa-parsing-strategy) - 即第一遍構建樹,然後是樹步行。在一些章節中,規範指的是沒有回溯的情況下可以解析的東西,這聽起來像確保他們正在設計LL(k)語言(除非區分預測性和回溯遞歸下降,否則不會談論回溯,對吧? )。 – abarnert 2014-09-11 22:43:10

2

想想你在問什麼。什麼時候第二個*強調,什麼時候打開一個嵌套的重點?你沒有寫出任何規則來區分這一點。因爲它總是100%曖昧,這意味着唯一可能的結果,你可以得到的是:

  • 沒有強調都不能關閉,或者
  • 沒有強調都不能嵌套。

我懷疑你是問如何從第二個切換到第一個。

那麼你在問什麼

您需要實施某種規則來消除這兩種可能性。實際上,如果你閱讀了你鏈接到的文檔,他們有一套複雜的規則來定義何時*可以打開重點,什麼時候打開重點,什麼時候打不開,同樣適用於closng;根據這些規則,如果它仍然含糊不清,它就會強調重點。你必須實現這一點。

+0

感謝您的推動澄清我的想法。我希望我對這個問題的編輯有所幫助。 – Winawer 2014-09-11 17:18:06

+0

優秀的評論。這就是爲什麼我鼓勵人們在跳入「編寫解析器」部分之前,稍微思考一下語法(通常寫一個粗略的BNF)。 – PaulMcG 2014-09-11 22:01:26