Forward 是执行此操作的方法。由于类型声明本身可能包含类型声明,这对于 Forward 的发展方向可能是一个不错的选择:
import pyparsing as pp
type_decl = pp.Forward()
看看你的例子,我知道我们需要一些标点符号,我们可以为这些定义一些抑制表达式,以便它们解析,但不会破坏解析结果:
LANGLE, RANGLE, COMMA = map(pp.Suppress, "<>,")
# if we get an ellipsis, we want to keep it, so use Literal instead of Suppress
ELLIPSIS = pp.Literal("...")
接下来我们可以做简单的类型:
simple_type = pp.oneOf("string int float", asKeyword=True)
现在是两种复杂类型,map 和 array。对于这些,我们将在可能出现复杂类型的地方使用 Forward:
MAP, ARRAY = map(pp.Keyword, ["map", "array"])
map_type = MAP - LANGLE + pp.Group(simple_type + COMMA + (type_decl | ELLIPSIS)) + RANGLE
array_type = ARRAY - LANGLE + type_decl + RANGLE
complex_type = pp.Group(map_type | array_type)
我在这里使用 '-' 运算符,因为如果在看到有效的“map”或“array”关键字后出现语法错误,pyparsing 将在该表达式中给出错误。
此时我们有了复杂和简单的类型,因此我们可以使用<<= 运算符将它们“注入”到先前定义的 Forward 中:
type_decl <<= (complex_type | simple_type)
使用runTests检查:
type_decl.runTests("""\
string
int
float
map<string, map<int, map<string, ...>>>
map<string, map<int, map<string, array<array<string>>>>>
""", fullDump=False)
给予:
string
['string']
int
['int']
float
['float']
map<string, map<int, map<string, ...>>>
[['map', ['string', ['map', ['int', ['map', ['string', '...']]]]]]]
map<string, map<int, map<string, array<array<string>>>>>
[['map', ['string', ['map', ['int', ['map', ['string', ['array', ['array', 'string']]]]]]]]]