解析 Python 中的自定义配置格式



我正在为 Stellaris 游戏编写一个配置文件管理器,他们的格式让我碰壁,他们保留了有关模组和设置的信息。

模组文件:

name="! (Ship Designer UI Fix) !"
path="mod/ship_designer_ui_fix"
tags={
"Fixes"
}
remote_file_id="879973318"
supported_version="1.6"

设置:

language="l_english"
graphics={
size={
x=1920
y=1200
}
min_gui={
x=1920
y=1200
}
gui_scale=1.000000
gui_safe_ratio=1.000000
refreshRate=59
fullScreen=no
borderless=no
display_index=0
shadowSize=2048
multi_sampling=8
maxanisotropy=16
gamma=50.000000
vsync=yes
}
last_mods={
"mod/ship_designer_ui_fix.mod"
"mod/ugc_720237457.mod"
"mod/ugc_775944333.mod"
}

我以为pyparsing会在那里有所帮助(而且可能会),但是我已经很久没有真正做过这样的事情了,而且我对此一无所知。

我必须提取简单的key=value但我正在努力从那里实际移动以便能够提取数组,更不用说多级数组了。

lbrack = Literal("{").suppress()
rbrack = Literal("}").suppress()
equals = Literal("=").suppress()
nonequals = "".join([c for c in printables if c != "="]) + " t"
keydef = ~lbrack + Word(nonequals) + equals + restOfLine
conf = Dict( ZeroOrMore( Group(keydef) ) )
tokens = conf.parseString(data)

正如你所看到的,我还没有走得很远。谁能指出我下一步?我不是在为整个事情要求一个完成的工作解决方案 - 它会让我前进很多,但那:)的乐趣在哪里

好吧,潜入并编写这个解析器是非常诱人的,但你想要为自己带来一些乐趣,这很棒。

在编写任何代码之前,请编写 BNF。这样你就可以写出一个体面而健壮的解析器,而不仅仅是"所有不是等号的东西都必须是标识符"。

这里有很多"某物=某物"的位,看看"="的左右两侧的种类。左边看起来都像是相当有礼貌的标识符:字母、下划线。我也可以想象数字,只要它们不是主角。因此,假设左侧将是标识符:

identifier_leading = 'A'..'Z' 'a'..'z' '_'
identifier_body = identifier_leading '0'..'9'
identifier ::= identifier_leading + identifier_body*

右手边是混合的东西:

  • 整数
  • "是"或"否"布尔值
  • 带引号的字符串
  • 牙套里的东西
">

大括号中的内容"要么是带引号的字符串列表,要么是"identifer = value"对的列表。我将跳过定义浮点数、整数和带引号的字符串的可怕细节,让我们假设我们已经定义了这些:

boolean_value ::= 'yes' | 'no'
value ::= float | integer | boolean_value | quoted_string | string_list_in_braces | key_value_list_in_braces
string_list_in_braces ::= '{' quoted_string * '}'
key_value ::= identifier '=' value
key_value_list_in_braces ::= '{' key_value* '}'

在完全定义之前,您必须使用 pyparseingForward来声明value,因为它用于key_value,但key_value用于key_value_list_in_braces,用于定义value- 递归语法。您已经熟悉Dict(OneOrMore(Group(named_item)))模式,这应该可以为您提供可通过名称访问的字段结构。对于identifierWord可以工作,或者您可以使用去年作为pyparsing_common命名空间类的一部分引入的预定义pyparsing_common.identifier

从BNF到pyparsing的翻译应该是从这里开始的1对1。就此而言,从BNF中,您也可以使用PLY,ANTLR或其他解析库。BNF真的值得花1/2小时或1/2天来整理。

最新更新