2

我正在为 Stellaris 游戏编写配置文件管理器,并且我已经使用他们保存有关 mod 和设置的信息的格式碰壁了。

模组文件:

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)

如你所见,我还没有走多远。谁能指出我下一步?我并不是要为整个事情提供一个完整且可行的解决方案——它会让我前进很多,但其中的乐趣在哪里:)

4

1 回答 1

2

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

在编写任何代码之前,先编写一个 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* '}'

在完全定义之前,您必须使用 pyparsingForward进行声明value,因为它用于 in key_value,但key_value用于key_value_list_in_braces定义value- 递归语法。您已经熟悉该Dict(OneOrMore(Group(named_item)))模式,这应该可以很好地为您提供可按名称访问的字段结构。For identifier, a会起作用,或者您可以只使用去年作为命名空间类的一部分引入Word的预定义。pyparsing_common.identifierpyparsing_common

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

于 2017-05-16T12:12:38.990 回答