2011-06-02 88 views
0

我正在使用pyparsing来摄取gEDA原理图/符号文件格式。大多数是直截了当的,但我不知道如何匹配最初一行上的整数字段指定的以下几行。从先前解析的值解析特定数量的行

文本对象具有类似的格式:

(other objects) 
T x y color size vis snv angle align num_lines 
Text line one 
Line two of the text 
Finally, the 'num_lines'th line 
(other objects) 

NUM_LINES的整数。这种风格也用于其他一些类型。

作为解决方法,我将这样的行定义为匹配有效对象类型的任何东西而不是。从技术上讲,这种类似对象的线被允许在文本对象

text_meta = Type("T") + coord + color + size + visibility + show_name_value \ 
      + angle + alignment + num_lines + EOL         
text_data_line = ~obj + LineStart() + SkipTo(LineEnd()) + EOL     
text_data = Group(OneOrMore(text_data_line)).setResultsName('text')    
text_data = text_data.setParseAction(lambda t: '\n'.join(t[0]))     
text = text_meta + text_data 

生成匹配规则对飞象:

def genLineMatcher(n): 
    return (LineStart() + Skipto(LineEnd()) + EOL)*n 

在桌子上,但我不知道如何指定规则。

回答

0

生成的飞行比赛规则......

你实际上是在正确的轨道上。实时创建规则的方式是将可变长度表达式定义为Forward(),然后在解析操作时插入实际规则。

幸运的是,pyparsing已经有这个实施,在助手方法countedArray。如果你改变你的表情为:

text_meta = (Type("T") + coord + color + size + visibility + show_name_value + 
       angle + alignment + countedArray(EOL + restOfLine)("lines")) 

我认为这会做你想做的。然后,您可以使用“行”结果名称检索行数组。

+0

谢谢你的提示,浏览器缓存和“回家“早些时候找到了算数阵营。这样的能力会使pyparsing成为一个转到工具,感谢您的写作和分享! – etihwnad 2011-06-03 16:16:01

0

pyparsing helper函数'countedArray(expr)'几乎是需要的。分析器定义和修饰的辅助功能:

def numLinesList(expr, name=None):                                           
    """Helper to snarf an end-of-line integer and match 'expr' N times after.                               
    Almost exactly like pyparsing.countedArray.                                      
    Matches patterns of the form::                                         
     ... num_lines                                             
     line one                                              
     line two                                              
     num_lines'th line                                            
    """                                                
    arrayExpr = Forward()                                            
    def numLinesAction(s, l, t):                                          
     n = int(t[0])                                             
     arrayExpr << (n and Group(And([expr]*(n+1))) or Group(empty))                                 
     return []                                              
    matcher = Word(nums).setParseAction(numLinesAction, callDuringTry=True) \                               
       + arrayExpr                                            
    # remove first empty string                                          
    matcher.addParseAction(lambda t: [t[0][1:]])                                      
    if name: 
     matcher = matcher.setResultsName(name)                                       
    return matcher 

text_meta = Type("T") + coord + color + size + visibility + show_name_value \ 
     + angle + alignment 
text_data_line = SkipTo(LineEnd()) + EOL 
text_data = numLinesList(text_data_line, 'text') 
text = text_meta + text_data 

对于输入片段:

... 
T 41600 47800 9 10 1 0 0 0 2                                           
This is line 1                                              
line 2 is here...                                              
T 41600 47000 9 10 1 0 0 0 2                                           
Another first line                                             
second line foo 

此输出:

['T', 41600, 47800, '9', 10, True, '0', 0, 0, ['This is line 1', 'line 2 is here...']] 
['T', 41600, 47000, '9', 10, True, '0', 0, 0, ['Another first line', 'second line foo']]