2013-04-08 43 views
2

我试图找出如何使用这个漂亮的LIB解析BIGIP配置文件... 语法应该是这样的:如何解析F5 bigip.conf使用pyparsing

stanza :: name { content } 
name :: several words, might contain alphas nums dot dash underscore or slash 
content:: stanza OR ZeroOrMore(printable characters) 

要使事情变得复杂一些,有一个例外:

如果名称以“规则”开头,则内容不能是“节”

我开始用这样的:

from pyparsing import * 
def parse(config): 
    def BNF(): 
     """ 
     Example: 
     ... 
     ltm virtual /Common/vdi.uis.test.com_80_vs { 
      destination /Common/1.2.3.4:80 
      http-class { 
       /Common/http2https 
      } 
      ip-protocol tcp 
      mask 255.255.255.255 
      profiles { 
       /Common/http { } 
       /Common/tcp { } 
      } 
      vlans-disabled 
     } 
     ... 
     """   
     lcb, rcb, slash, dot, underscore, dash = [c for c in '{}/._-'] 
     name_word = Word(alphas + nums + dot + underscore + slash + dash) 
     name = OneOrMore(name_word).setResultsName("name") 
     stanza = Forward() 
     content = OneOrMore(stanza | ZeroOrMore(OneOrMore(Word(printables)))).setResultsName("content") 
     stanza << Group(name + lcb + content + rcb).setResultsName("stanza") 
     return stanza 


    return [x for x in BNF().scanString(config)] 

上面的代码似乎锁定了一些无限循环。如果“名称”以“规则”开始,那么它也缺少排除查找“节”的要求。

+0

你能提供一些示例输入来测试吗?你有什么异常? – Michael0x2a 2013-04-08 21:23:28

回答

3

OneOrMore(ZeroOrMore(OneOrMore(Word(printables)))将始终匹配,从而导致无限循环。另外,printables包含一个闭合的花括号,它被内容项所消耗,并且不再可用于该节(如果您的内容可以包括闭括号,则需要定义一些内容以便转义它,以区分内容支架和节支架。)

要解决名称规则,您需要另一个内容定义,一个不包含节和一个“规则规则”。

def parse(config): 
    def BNF(): 
     lcb, rcb, slash, dot, underscore, dash = [c for c in '{}/._-'] 
     printables_no_rcb = Word(printables, excludeChars=rcb) 
     name_word = Word(alphas + nums + dot + underscore + slash + dash) 
     name = OneOrMore(name_word).setResultsName("name") 
     rule = Group(Literal('rule') + name).setResultsName("name") 
     rule_content = OneOrMore(printables_no_rcb).setResultsName("content") 
     stanza = Forward() 
     content = OneOrMore(stanza | OneOrMore(printables_no_rcb)).setResultsName("content") 
     stanza << Group(rule + lcb + rule_content + rcb | name + lcb + content + rcb).setResultsName("stanza") 
     return stanza 
    return [x for x in BNF().scanString(config)]