对于个人项目,我需要编写一个简单的词法分析器来处理用户输入命令。它们可以包含四种模式和括号:
.
,+
,-
或%
foobar
,fooZ
或bar2
a"hello world"
,p"escaped \"string\""
a~"hello world"
,p~"escaped \"string\""
我想拆分命令,以便有一个分层列表(基于括号),其中包含每个运算符的条目,每个名称的条目(单个字符串),以及每个过滤器的条目(a字典,例如{'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等,但它们似乎都很难使用,我不知道我是否需要这种工具,因为我需要的语法不是很复杂。提前感谢您的建议!
答案 0 :(得分: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'}]]]]]]