2014-07-15 112 views
1

我們正在研究縮減Make語法的語法,並遇到了嵌套擴展的問題。解析使用pyparsing進行擴展

下面是我們要解析的內容示例:

$(error Not implemented for this OS: $(filter XYZ_OS_%, $(.VARIABLES))) 

這是嵌套表達問題的變體,很多人看起來與奮鬥。這有點困難,因爲嵌套表達式可以包含自由形式的字符串,包括括號和美元:($字符與重複此轉義)

$(error Something went wrong (you owe me $$$$$$.)) 

我對此有一個初步的語法,但我想不出一種定義text規則的方法。

name = Word(alphanums + '_') 
text = CharsNotIn('$)') # This does not work generally. 

expansion = Suppress('$(') + name + Suppress(')') 

sub_expression = Forward() 
expression = ZeroOrMore(sub_expression) 

error = Suppress('$(error ') + expression + Suppress(')') 
info = Suppress('$(info ') + expression + Suppress(')') 
pattern = Word(alphanums + '._%') 
filter = Suppress('$(filter ') + pattern + Suppress(',') + expression + Suppress(')') 

sub_expression << (text | error | filter | info | expansion) 

# This accepts all kinds of invalid Make syntax, 
# but is useful for testing line-by-line. 
test_grammar = OneOrMore(text | expansion | error | filter | info) 

這捕獲了天真的情況,但括號和美元不屬於擴展失敗。

任何想法?謝謝!

+0

我想你應該像處理一般變量擴展一樣處理'error','filter'等等。 –

+0

@Antti,謝謝,我想我們剛剛得出同樣的結論。不幸的是,它似乎沒有幫助將文本內容與擴展分開。 –

+0

這就是爲什麼它是一個評論...你應該知道Make是如何首先解析擴展,然後複製它,最簡單的方法。 –

回答

0

我們知道了!

我們意識到Make允許在$(error)和朋友中使用圓括號,但前提是平衡。它必須這樣,否則將不知道該怎麼樣懸空表情做:

$(error This(thing(is)crazy) 

所以我們缺少語法的一個重要組成部分:否則不透明文本中括號內的文字相匹配的規則。我們終於找到了SkipTo,這是我們最初尋找的東西。它消耗的所有文字,直到傳遞給它匹配的規則,它可以讓我們做(減少):

name = Word(alphanums + '_') 
expansion = Suppress('$(') + name + Suppress(')') 

end_of_text = Literal('$(') | Literal('(') | Literal(')') 
text = NotAny(end_of_text) + SkipTo(end_of_text).leaveWhitespace() 
parenthesized_text = Combine(Literal('(') + SkipTo(')').leaveWhitespace() + Literal(')')) 

sub_expression = Forward() 
expression = ZeroOrMore(sub_expression | parenthesized_text | text) 

error = Suppress('$(error ') + expression + Suppress(')') 

sub_expression << (error | expansion) 

grammar = OneOrMore(error) 

我們看到,當我們在表達式中,短信來與括號內的文字和擴展交錯塊。要識別文字我們尋找$(,開始擴展,(,開始加括號的文本和),這結束了整個事情。

本質上,error匹配$(error後跟一系列表達式並將它們整齊地返回爲樹。例如。

$(error Something went wrong (you owe me.) Status: $(status)) 

解析爲:

error: $(error 
    text: Something went wrong 
    parenthesized_text: (you owe me.) 
    text: Status: 
    expansion: $(status) 

我現在看到,這可能是不正確的,例如我們無法識別加括號的文本內的擴展。我們會看看我們能否弄清楚。

我唯一不能解釋的是爲什麼NotAnytext中是必要的,解析器沒有掛起,所以我想它需要一些東西來啓動規則。

希望這可以幫助別人!