0

gEDA回路図/シンボル ファイル形式を取り込むために pyparsing を使用しています。ほとんどは簡単ですが、最初の行の整数フィールドで指定された次の行の数を一致させる方法がわかりません。

テキスト オブジェクトの形式は次のとおりです。

(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

がテーブルにあるのですが、ルールを指定する方法がわかりません。

4

2 に答える 2

0

pyparsing ヘルパー関数 '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']]
于 2011-06-03T16:10:55.973 に答える
0

その場で一致ルールを生成しています...

あなたは実際に正しい軌道に乗っています。その場でルールを作成する方法は、可変長式を Forward() として定義し、次にカウント フィールドが解析されるときに実際のルールを挿入する解析アクションで定義することです。

幸いなことに、pyparsing ではヘルパー メソッドでこれが既に実装されていcountedArrayます。式を次のように変更した場合:

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

これはあなたが望むことをすると思います。次に、「lines」結果名を使用して行の配列を取得できます。

于 2011-06-03T03:53:34.730 に答える