我正在尝试为RCS file format创建一个解析器,但是,当尝试在RCSadmin上下文中解析RCSid时,它会经历一个无限循环。删除违规行
Group(ZeroOrMore(RCSid)).setResultsName('access') + \
使挂起不发生。其上的RCSid成功解析字符串。有什么建议吗?
以下是我所拥有的:
from pyparsing import *
import string
# Special characters in the RCS file format
special = '$,.:;@'
RCSdigit = Word(nums, min=1, max=1).setName('RCSdigit')
RCSnum = Word(nums + '.').setName('RCSnum')
RCSidchar = CharsNotIn(special + string.whitespace).setName('RCSidchar')
RCSid = Combine(Optional(RCSnum) + ZeroOrMore(RCSidchar +
ZeroOrMore(RCSidchar | RCSnum))).setName('RCSid')
RCSadmin = \
Keyword('head').suppress() + \
Optional(RCSnum).setResultsName('head') + \
Suppress(';') + \
Optional(Keyword('branch').suppress() +
Optional(RCSnum).setResultsName('branch') +
Suppress(';')
) + \
Keyword('access').suppress() + \
Group(ZeroOrMore(RCSid)).setResultsName('access') + \
Suppress(';')
ids = ['.111abc111', '1111abc111', '1.11', '1', '1abc', 'abc',
'abc1', 'abc1.11', 'abc.1111', '']
for i in ids:
try:
print i, RCSid.parseString(i)
except ParseException, pe:
print pe.markInputline()
for i in ids:
line = 'head 3; branch 1; access ' + i + ';'
try:
print line, RCSadmin.parseString(line)
except ParseException, pe:
print pe.markInputline()
输出(^C处于挂起状态):
.111abc111 ['.111abc111']
1111abc111 ['1111abc111']
1.11 ['1.11']
1 ['1']
1abc ['1abc']
abc ['abc']
abc1 ['abc1']
abc1.11 ['abc1.11']
abc.1111 ['abc.1111']
['']
^Chead 3; branch 1; access .111abc111;
Traceback (most recent call last):
File "sample.py", line 35, in <module>
print line, RCSadmin.parseString(line)
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 1070, in parseString
loc, tokens = self._parse( instring, 0 )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 945, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 2352, in parseImpl
loc, exprtokens = e._parse( instring, loc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 945, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 2604, in parseImpl
return self.expr._parse( instring, loc, doActions, callPreParse=False )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 945, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 2724, in parseImpl
loc, tmptokens = self.expr._parse( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 945, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 2604, in parseImpl
return self.expr._parse( instring, loc, doActions, callPreParse=False )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 945, in _parseNoCache
loc,tokens = self.parseImpl( instring, preloc, doActions )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 2336, in parseImpl
loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False )
File "/usr/lib/pymodules/python2.6/pyparsing.py", line 943, in _parseNoCache
if self.mayIndexError or loc >= len(instring):
KeyboardInterrupt
最佳答案
空字符串真的是有效的RCSid吗?我想不是。现在,在admin语句的access子句中可以省略RCSid,但您已经使用ZeroOrMore处理了这个问题。根据指定的原语定义原语,然后在更高级别的构造中加入可选的、零或更多等因子。
将RCSid更改为:
RCSid = Combine(RCSnum + ZeroOrMore(RCSidchar + ZeroOrMore(RCSidchar | RCSnum))
|
OneOrMore(RCSidchar + ZeroOrMore(RCSidchar | RCSnum))).setName('RCSid')
给出的结果仍然与所有测试用例匹配(匹配“”除外),并正确解析完整的RCSAdmin字符串。
编辑
这是我的完整解析器,与pyparsing 1.5.6一起工作:
# Special characters in the RCS file format
special = '$,.:;@'
RCSdigit = Word(nums, min=1, max=1).setName('RCSdigit')
RCSnum = Word(nums + '.').setName('RCSnum')
RCSidchar = CharsNotIn(special + string.whitespace).setName('RCSidchar')
#~ RCSid = Combine(Optional(RCSnum) + ZeroOrMore(RCSidchar +
#~ ZeroOrMore(RCSidchar | RCSnum))).setName('RCSid')
RCSid = Combine(RCSnum + ZeroOrMore(RCSidchar + ZeroOrMore(RCSidchar | RCSnum))
|
OneOrMore(RCSidchar + ZeroOrMore(RCSidchar | RCSnum))).setName('RCSid')
RCSadmin = \
Keyword('head').suppress() + \
Optional(RCSnum).setResultsName('head') + \
Suppress(';') + \
Optional(Keyword('branch').suppress() +
Optional(RCSnum).setResultsName('branch') +
Suppress(';')
) + \
Keyword('access').suppress() + \
Group(ZeroOrMore(RCSid)).setResultsName('access') + \
Suppress(';')
关于python - Pyparsing:尝试非贪婪会导致无限循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7232768/