2

個人的なプロジェクトでは、ユーザー入力コマンドを処理するために単純なレクサーを作成する必要があります。4 つのパターンとブラケットを含めることができます。

  • 演算子: .+-または%
  • 名前 ([a-zA-Z0-9]) : たとえばfoobarfooZまたはbar2
  • filters ([az]{1}"[some text]") : たとえばa"hello world"p"escaped \"string\""
  • その他のフィルター ([az]{1}~"[some text]") : たとえばa~"hello world"p~"escaped \"string\""

コマンドを分割して、各演算子のエントリ、各名前のエントリ (単一の文字列)、および各フィルタのエントリ (辞書、インスタンス{'a': 'hello world'}または{'p~': 'escaped "string"'})。

したがって、この入力で取得したいものの例を次に示します (演算子の前後のスペースはオプションです)。

foo . bar - (a"hello \"world\"" % (b~"foo" + bar) . (fooZ.(bar2+(c"foo bar".d"bar foo"))))

[
  'foo',
  '.',
  'bar',
  '-',
  [
    {'a': 'hello "world"'},
    '%',
    [
      {'b~': 'foo'},
      '+',
      'bar'
    ]
    '.',
    [
      'fooZ',
      '.',
      [
        'bar2',
        '+',
        [
          {'c': 'foo bar'},
          '.',
          {'d': 'bar foo'}
        ]
      ]
    ]
  ]
]

pyparsing、PLY、pyPEG、Yapps などを調べましたが、どれも使いにくそうで、必要な文法がそれほど複雑ではないため、この種のツールが必要かどうかわかりません。ご提案いただきありがとうございます。

4

1 に答える 1

3

この pyparsing ソリューションが、指定された文法にどのように対処するかを確認してください。

from pyparsing import *
ParserElement.enablePackrat()
import string

name = Word(alphanums)

filter = (Combine(oneOf(list(string.ascii_lowercase)) + Optional('~')) +
          dblQuotedString.setParseAction(removeQuotes))
# convert parsed filter to dict
filter.setParseAction(lambda t:{t[0]:t[1]})

expr = operatorPrecedence(filter | name, 
            [
            (oneOf('. % -'), 2, opAssoc.LEFT),
            ('+', 2, opAssoc.LEFT),
            ])

test = r'foo . bar - (a"hello \"world\"" % (b~"foo" + bar) . (fooZ.(bar2+(c"foo bar".d"bar foo"))))'

print expr.parseString(test, parseAll=True).asList()

版画:

[['foo',
  '.',
  'bar',
  '-',
  [{'a': 'hello \\"world\\"'},
   '%',
   [{'b~': 'foo'}, '+', 'bar'],
   '.',
   ['fooZ', '.', ['bar2', '+', [{'c': 'foo bar'}, '.', {'d': 'bar foo'}]]]]]]
于 2012-07-09T13:30:09.373 に答える