2016-07-08 74 views
2

我正在開發DOT語言的解析器,並遇到「子圖」語句問題。懷疑pyparsing最長匹配錯誤

我沒有問題讓我的SUBGRAPH解析表達式正常工作(請參見下面的片段),但是當我在STMT中添加它作爲替代時它無法匹配。

簡單的測試:

test = '''subgraph cluster01 { n003 ; n004 ; }''' 
FRAG_1 = SUBGRAPH + StringEnd() 
FRAG_2 = STMT + StringEnd() 

res1 = FRAG_1.parseString(test) # OK 
res2 = FRAG_2.parseString(test) # ParseException - 

錯誤:

subgraph cluster01 { n003 ; n004 ; } 
     ^
ERROR: Expected end of text (at char 9), (line:1, col:10) 

嫌疑這個問題涉及到我的STMT表達 - 它貪婪匹配關鍵字 「子圖」 作爲NODE_STMT而不是匹配爲SUBGRAPH,但是我的期望是通過使用「Or」表達式(「^」),最長匹配算法將選擇SUBGR APH超過NODE_STMT。或者它可能是別的。

我的部分語法低於:

語法片段:

LCURL = Literal("{").suppress() 
RCURL = Literal("}").suppress() 
STMTSEP = Literal(";").suppress() 
ID = Word(alphas, alphanums + "_") 
SUBGRAPH_KW = Keyword("subgraph", caseless=True) 
SUBGRAPH = Forward("SUBGRAPH") 

NODE_ID = ID("NODE_ID") 
NODE_STMT = NODE_ID("NODE") 

STMT = NODE_STMT("NODE")^SUBGRAPH("SUBGRAPH") 
STMT_LIST = ZeroOrMore(STMT("STMT") + Optional(STMTSEP)) 

SUBGRAPH << Group(SUBGRAPH_KW + ID("SUBGRAPHNAME")) + Group(LCURL + STMT_LIST + RCURL) 

回答

1

這是因爲你正在創建的SUBGRAPH對象在此線副本

STMT = NODE_STMT("NODE")^SUBGRAPH("SUBGRAPH") 

調用setResultsName(),其調用語法爲hortcut for,creates a copy of the ParserElement object

這是一個問題,因爲SUBGRAPH是一個Forward對象,並且在該代碼中它尚未完全定義。

你真的不應該爲所有事物,無論何時何地都設置名稱!請在實際需要的時間和地點執行此操作,並記住它會創建ParserElement對象的副本。然而,

intnum = Word(nums).setParseAction(lambda t: int(t[0])) 
realnum = Combine(Word(nums) + '.' + Word(nums)).setParseAction(lambda t: float(t[0])) 
hostname = Word(alphas, alphanums+'-') 
timestamp = Regex(r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d') 
statslogentry = (timestamp('timestamp') + hostname('hostname') + 
       'CPU:' + realnum('cpu') + 
       'DISK_IO:' + intnum('disk_io') + 
       'NETWORK_IO:' + intnum('network_io')) 

使用時Forward這可能對你的工作的是:

+0

太棒了!我將需要考慮ParserElement.setResultName()的正確使用方式實際上是什麼...... – SMagrath

+1

好抓!我還沒有看到這個特殊問題出現在這個特定的表單(結果名稱+前進)之前,肯定需要添加到我的pyparsing陷阱列表中。 – PaulMcG

0

在一般情況下,我建議對分配結果的名字持觀望態度,直到表達式被組裝成一個更高層次的表達,這樣這裏的情況。在OP的代碼的一個特定的錯誤是

SUBGRAPH = Forward("SUBGRAPH") 

我覺得OP試圖使用結果的名稱快捷方式,但實際上是創造與Literal("SUBGRAPH")內容的Forward。此更改爲

SUBGRAPH = Forward()("SUBGRAPH") 

,並從Or表達去除效果的名稱將解決原來的問題。但我仍然認爲這有點陷入「陷阱」範疇。

+0

謝謝保羅。這是很好的建議。此外,非常感謝一個偉大的工具... – SMagrath