我正在解析一个相对简单的文本,其中每一行都描述了一个游戏单元。我对解析技术知之甚少,因此我使用了以下临时解决方案:
class Unit:
# rules is an ordered dictionary of tagged regex that is intended to be applied in the given order
# the group named V would correspond to the value (if any) for that particular tag
rules = (
('Level', r'Lv. (?P<V>\d+)'),
('DPS', r'DPS: (?P<V>\d+)'),
('Type', r'(?P<V>Tank|Infantry|Artillery'),
#the XXX will be expanded into a list of valid traits
#note: (XXX| )* wouldn't work; it will match the first space it finds,
#and stop at that if it's in front of something other than a trait
('Traits', r'(?P<V>(XXX)(XXX| )*)'),
# flavor text, if any, ends with a dot
('FlavorText', r'(?P<V>.*\."?$)'),
)
rules = collections.OrderedDict(rules)
traits = '|'.join('All-Terrain', 'Armored', 'Anti-Aircraft', 'Motorized')
rules['Traits'] = re.sub('XXX', effects, rules['Traits'])
for x in rules:
rules[x] = re.sub('<V>', '<'+x+'>', rules[x])
rules[x] = re.compile(rules[x])
def __init__(self, data)
# data looks like this:
# Lv. 5 Tank DPS: 55 Motorized Armored
for field, regex in Item.rules.items():
data = regex.sub(self.parse, data, 1)
if data:
raise ParserError('Could not parse part of the input: ' + data)
def parse(self, m):
if len(m.groupdict()) != 1:
Exception('Expected a single named group')
field, value = m.groupdict().popitem()
setattr(self, field, value)
return ''
它工作正常,但我觉得我达到了正则表达式功能的极限。具体来说,在 Traits 的情况下,该值最终是一个字符串,我需要稍后将其拆分并转换为列表:例如,obj.Traits 在此代码中将设置为“Motorized Armored”,但在后来的功能改为('机动','装甲')。
我正在考虑将此代码转换为使用 EBNF 或 pyparsing 语法或类似的东西。我的目标是:
- 让这段代码更整洁,更不容易出错
- 避免使用值列表对案例进行丑陋的处理(我需要先在正则表达式中进行替换,然后对结果进行后处理以将字符串转换为列表)
您对使用什么以及如何重写代码有什么建议?
PS我跳过了代码的某些部分以避免混乱;如果我在此过程中引入了任何错误,抱歉 - 原始代码确实有效 :)