2

对于个人项目,我需要编写一个简单的词法分析器来处理用户输入命令。它们可以包含四种模式和括号:

  • 运算符 : ., +,-%
  • 名称 ([a-zA-Z0-9]) :例如foobarfooZbar2
  • 过滤器 ([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 回答