我试图使用pyparsing来分析robotframework,这是一个基于文本的DSL。 sytnax就像下面一样(对不起,但我认为在BNF中描述它有点困难)。 在robotframework单个线可以是这样的:pyparsing空白匹配问题
Library\tSSHClient with name\tnode
\ t是标签,并在robotframework,它被透明转移到2“,“(实际上,它只需调用str.replace( '\ t' 的'')替换标签,但它会修改每行的实际长度,len('\ t')是1,但len('')是2)。 在机器人中,如果单词之间只有1个空格,则会使用2个或多个空格和'\ t'来分割令牌,则这些单词将被视为令牌组。
Library\tSSHClient with name\tnode
实际上分裂为以下令牌如果解析正确:
['Library', 'SSHClient', 'with name', 'node']
由于只有1之间的“与”和“名”的空白,所以解析器认为属于一组语法令牌。
这里是我的代码:
ParserElement.setDefaultWhitespaceChars('\r\n\t ')
source = "Library\tSSHClient with name\tnode"
EACH_LINE = Optional(Word(" ")).leaveWhitespace().suppress() + \
CaselessKeyword("library").suppress() + \
OneOrMore((Word(alphas)) + White(max=1).setResultName('myValue')) +\
SkipTo(LineEnd())
res = EACH_LINE.parseString(source)
print res.myValue
问题:
1)我已经设置了空格,如果我想精确匹配2个或多个空格和一个或多个标签,我想代码想要: 白色(ws ='',min = 2)|白色(ws ='\ t',min = 1) 但这会失败,所以我无法指定空白值?
2)有没有办法获得匹配的结果索引?我尝试了setParseAction,但似乎我无法通过此回调获取索引。我需要开始和结束索引来突出这个词。
3)LineStart和LineEnd的含义是什么?我打印这些值,似乎他们只是正常的字符串,我是否必须在行的前面写一些东西: LineStart()+ balabala ... + LineEnd()?
感谢,但是,没有,我不能代替 '\ t' 到 ''
from pyparsing import *
source = "Library\tsshclient\t\t\twith name s1"
value = Combine(OneOrMore(Word(printables) | White(' ', max=1) + ~White())) #here it seems the whitespace has already been set to ' ', why the result still match '\t'?
linedefn = OneOrMore(value)
res = linedefn.parseString(source)
print res
我
['Library sshclient', 'with name', 's1']
,但我预计 [ '图书馆' 的限制,'sshclient','with name','s1']
保罗麦圭尔,这是我的荣幸,让你回答我的问题,非常感谢。也许我没有让自己清楚,DSL语法是“2个或更多个空格”或者“1个或多个标签”用作语法标记分析器。所以我不能用''替换'tab',否则'\ t'将被平等地视为空白。从pyparsing导入* 我已经更新了最后的问题,请帮忙看看。 – python 2014-10-28 06:09:00
事实上,我试图突出显示DSL令牌,因此我需要准确获取eacth令牌的开始和结束索引,每个令牌之间可以有“1个或多个选项卡”或“2个或更多个空格”,如果我替换''t'to'',这个解析过程会使行的长度发生变化(len('\ t')= 1,但len('')= 2),所以我需要解析行而不用字符串替换。 – python 2014-10-28 06:22:14
谢谢,pyparsing似乎是最优雅的解决方案,非常感谢 – python 2014-10-29 03:22:09