1

次の入力を解析するために pyparsing を使用しています。

%FSLAX45Y67*%

私が求めている辞書形式の出力形式は次のとおりです。

{
  'notation': 'absolute', 
  'zeros': 'leading', 
  'x': {
    'integer': 4, 
    'decimal': 5
  }, 
  'y': {
    'integer': 6, 
    'decimal': 7,
  }, 
  'gerber-command': 'FS'
}

私が現在得ている出力は次のとおりです。

{
  'notation': 'absolute', 
  'decimal': 6, 
  'zeros': 'leading', 
  'integer': 6, 
  'y': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}), 
  'x': ([6, 6], {'integer': [(6, 0)], 'decimal': [(6, 1)]}), 
  'gerber-command': 'FS'
 }

(私の質問は、出力を正しく見せる方法ではなく、pyparsingでデータを希望どおりに配置する方法に関するものであることに注意してください。)

次のコードを使用します。

single_digit = pyp.Regex(r'(\d)').setParseAction(lambda t: int(t[0]))

cmd_format = pyp.Literal('FS')
cmd_format_opt_leading_zeros = pyp.Literal('L').setParseAction(pyp.replaceWith('leading'))
cmd_format_opt_trailing_zeros = pyp.Literal('T').setParseAction(pyp.replaceWith('trailing'))

format_zeros = ((cmd_format_opt_leading_zeros('zeros')) |
               (cmd_format_opt_trailing_zeros('zeros')))

format_notation = ((cmd_format_opt_absolute('notation')) |
                  (cmd_format_opt_incremental('notation')))

format_data = (single_digit)('integer') + single_digit('decimal')

gformat = (inst_del +
           cmd_format('gerber-command') +
           format_zeros +
           format_notation +
           'X' + (format_data)('x') + 
           'Y' + (format_data)('y') + 
           inst_end +
           inst_del)

(いくつかの些細な定義は省略されています)。助言がありますか?

4

3 に答える 3

2

pyparsing Group を使用して、返されたトークンに構造を追加します。これはおそらく仕事をします:

gformat = (inst_del +
           cmd_format('gerber-command') +
           format_zeros +
           format_notation +
           'X' + pyp.Group(format_data)('x') + 
           'Y' + pyp.Group(format_data)('y') + 
           inst_end +
           inst_del)

Pyparsing のデフォルトの動作は、どの用語がどの順序で追加されたかに基づいて構造を推測しないように、トークンのフラット リストを返すことです。たとえば、これがあった場合:

aword = Word("A")
bword = Word("B")
cword = Word("C")

preface = aword + bword
body = cword
ending = aword + bword

totalExpr = preface + body + ending

print totalExpr.parseString("AA BB CCC A B").asList()

pyparsing はリストだけを返します

['AA', 'BB', 'CCC', 'A', 'B']

構造を適用したい場合 (integer と decimal の重複に見られるように、入れ子になった結果の名前が互いに影響しないようにするためにこれは特に重要です)、Group を使用します。

totalExpr = Group(preface) + body + Group(ending)

与える:

[['AA', 'BB'], 'CCC', ['A', 'B']]

結果名を追加すると、次のようになります。

preface = aword("As") + bword("Bs")
body = cword
ending = aword("As") + bword("Bs")

totalExpr = Group(preface)("preface") + body("body") + Group(ending)("ending")
print totalExpr.parseString("AA BB CCC A B").dump()

与えます:

[['AA', 'BB'], 'CCC', ['A', 'B']]
- body: CCC
- ending: ['A', 'B']
  - As: A
  - Bs: B
- preface: ['AA', 'BB']
  - As: AA
  - Bs: BB

序文と語尾がグループ化されているため、「As」と「Bs」の重複した名前は別々に保持されます。

于 2013-10-13T16:37:02.147 に答える
1

なぜ難しい問題が常に再帰で終わるのか興味深い?

x=\
{
  'notation': 'absolute', 
  'zeros': 'leading', 
  'x': {
    'integer': 4, 
    'decimal': 5
  }, 
  'y': {
    'integer': 6, 
    'decimal': 7,
  }, 
  'gerber-command': 'FS'
}

def superPrint(inidic={},indent='  '):
    for k,v in inidic.items():
        if isinstance(v,dict):
            yield "\n%s'%s': {"%(indent,k)
            for i in superPrint(v,indent+' '*(len(k)+1)):
                yield i
            yield "\n%s},"%indent
        else:
            yield "\n%s'%s': '%s',"%(indent,k,v)

print '{%s\n}'%''.join(superPrint(x))

結果:

{
  'y': {
    'integer': '6',
    'decimal': '7',
  },
  'x': {
    'integer': '4',
    'decimal': '5',
  },
  'zeros': 'leading',
  'notation': 'absolute',
  'gerber-command': 'FS',
}

注、質問の説明によると、辞書の最後の要素に「、」が必要かどうかわかりません。

もっと深く試してください:

x=\
{
  'notation': 'absolute', 
  'zeros': 'leading', 
  'x': {
    'integer': 4, 
    'decimal': 5
  }, 
  'y': {
    'integer': 6, 
    'decimal': {'try':7,
                'tryHarder':{'wow':8,
                             'seemsGood':{'wooow':9}}},
  }, 
  'gerber-command': 'FS'
}

print '{%s\n}'%''.join(superPrint(x))

良いようです:

{
  'y': {
    'integer': '6',
    'decimal': {
            'try': '7',
            'tryHarder': {
                      'wow': '8',
                      'seemsGood': {
                                'wooow': '9',
                      },
            },
    },
  },
  'x': {
    'integer': '4',
    'decimal': '5',
  },
  'zeros': 'leading',
  'notation': 'absolute',
  'gerber-command': 'FS',
}
于 2013-10-13T13:30:36.937 に答える
1

setParseAction必要のない情報を削除するには、自由に使用する必要があります。から出力を受け取り、それを必要な形式に変換format_dataする関数が必要になります。single_digit

def _format_data(x):
    return {"integer": x["integer"][0][0],
            "decimal": x["decimal"][0][0]}

format_data.setParseAction(_format_data)
于 2013-10-13T12:29:32.663 に答える