2016-01-23 43 views
1

嘗試使用pyparsing解析某些文本時出現意外的行爲。我一行一行地解析一些半結構化的文本,其中一行可能是一行記錄分隔符,包含整行'='字符,如下所示:嘗試使用pyparsing解析重複字符時出錯

'========= ========================================='

也有可能在這一點上有一個空白行,所以我必須嘗試這兩個選項。如果我嘗試使用以下定義(假定爲import pyparsing as pp)解析僅包含空格的行:pp.Word('=', min=10),則會得到一個IndexError: string index out of range錯誤,而不是預期的不匹配的pyparsing異常。定義pp.OneOrMore(pp.Word('='))有預期的行爲,所以我當然會在我的代碼中使用它。我的理解是這些定義在這種情況下應該是等價的,pyparsing應該返回一個ParseException而不是IndexError。我錯過了什麼嗎?

import unittest 
import pyparsing as pp 


class Test(unittest.TestCase): 


    def testSepDetail(self): 
     verbose = True 
     pattern1 = pp.Word('=', min=10) # Throws IndexError: string index out of range 
     pattern2 = pp.OneOrMore(pp.Word('=')) # Works as expected 
     testPattern = pattern1 
     testList = [ 
('=======================','======================='), 
('  ',None)] 
     for test in testList: 
      text, expected = test 
      result = self.harness2(testPattern, text, expected, verbose) 

    def harness2(self,pattern, text, expected, verbose): 
     ''' 
     ''' 

     if verbose: 
      print('\n---Test for: {0}'.format(text)) 
     try: 
      result = pattern.parseString(text) 
      if verbose: 
       print('Parse successful.\n', result.dump()) 
      if expected: 
       self.assertEqual(expected, result[0], "\n\tParse Successful, but data not as expected.\n\tExpected {0}\n\t but got {1}".format(expected, result[0])) 
      return result   
     except pp.ParseException as x: 
      failmsg = "\n---Failed to parse string: {0}\n{1}".format(text,str(x)) 
      print(failmsg) 
      self.fail(failmsg) 


if __name__ == "__main__": 
    #import sys;sys.argv = ['', 'Test.testName'] 
    unittest.main() 
+0

忘了提,這是pyparsing 2.0.7 –

回答

0

這不是對您的部分錯誤,它是在pyparsing的錯誤,重新優化代碼,忘了,它是在一個矛盾的方式預先優化後的結果。這個問題實際上影響了幾個pyparsing類,不僅僅是Word(主要是那些從pyparsing的Token類中繼承而來的)。

在實踐中,這不是一個問題,因爲令牌類型表達式很少單獨使用,而容器表達式(如OneOrMore等)都會陷入IndexError並重新引發ParseException。

例如,這些也將解決該IndexError問題在Word中:

pattern2 = pp.empty + pp.Word('=') 
pattern2 = 1*pp.Word('=') 

我一定會清理它的下一個版本,但在你的應用程序,我想如果你改變的事情會正常工作您的處理程序:

except (pp.ParseException, IndexError) as x: 

然後,當你升級到固定的版本,你只需要改變,而不是所有在你的語法,你用一或更多砍死的地方的人,除非聲明。

注意:您還可以讓你的測試臺寬容的例外情況下,如果你改變了self.fail呼籲:

 if expected is not None: 
      self.fail(failmsg) 
+0

感謝您的分外提示答案!和你特殊的軟件。它真的讓我的生活更輕鬆。 –