2015-07-21 72 views
2

在我正在處理的應用程序中,我們有一個DSL將一些字符組合在一起,它們可以分組或不分組。括號決定組。例如,良好的輸入:與OneOrMore相匹配的括號

123 
12(34) 
1(234) 

壞輸入:

12(34 

基本上我想要的任何不匹配的括號不解析,就好象這應該是我在做什麼,目的有語法錯誤。我做了這個MVCE展示我和我的pyparsing代碼遇到的問題:

import pyparsing as pp 

def Syntax(): 
    lpar = pp.Literal('(').suppress() 
    rpar = pp.Literal(')').suppress() 
    rank = pp.Word('12345678', exact=1) #card ranking 
    ranks = pp.OneOrMore(rank) 
    rank_grouping = pp.Group(lpar + ranks + rpar) 
    atom = ranks | rank_grouping 
    return pp.OneOrMore(atom) 

mvce_parser = Syntax() 
try: 
    mvce_parser.parseString("(76)(54") 
except pp.ParseException: 
    print("Exception1 was thrown!") 
else: 
    print("Exception1 not thrown :(") 

try: 
    mvce_parser.parseString("(76(54)") 
except pp.ParseException: 
    print("Exception2 was thrown!") 
else: 
    print("Exception2 not thrown :(") 

輸出:

$ python test.py 
Exception1 not thrown :(
Exception2 was thrown! 

我這裏的問題是,第一個例子串(76)(54這裏解析並返回[['7','6']]但不會拋出我想要的ParseException。然而第二個卻沒有按預期那樣失敗。

我懷疑這是OneOrMore的結果,抑制了其餘部分的異常,然後返回到目前爲止的結果。

如何更改我的代碼以避免這種不一致性問題?即使OneOrMore很方便有沒有使用OneOrMore這樣做的一些其他方式嗎?

回答

3

所以你想分析整個字符串。

要做到這一點,你要麼需要顯式地添加到StringEnd()你的語法

return pp.OneOrMore(atom) + pp.FollowedBy(pp.StringEnd()) 

或與parseAll = True參數

mvce_parser.parseString("(76)(54", parseAll=True) 
+2

它不應該是必要的供應parseString呼叫包'StringEnd( )''在'FollowedBy'中,你可以在'OneOrMore(atom)'之後添加它。但這是舊式解決方法 - 使用'parseAll = True'是首選解決方案。 – PaulMcG

+0

@PaulMcGuire相關知識(感謝真棒圖書館!) – shuttle87