我如何在 EBNF 中表达这种格式?
How can I express this format in EBNF?
我有以下数据:
dbCon= {
main = {
database = "db1",
hostname = "db1.serv.com",
maxConnCount = "5",
port = "3306",
slaves = [
{
charset = "utf8",
client = "MYSQL",
compression = "true",
database = "db1_a",
hostname = "db1-a.serv.com",
maxConnCount = "5",
port = "3306",
}
{
charset = "utf8",
client = "MYSQL",
compression = "true",
database = "db1_b",
hostname = "db1-b.serv.com",
maxConnCount = "5",
port = "3306",
}
]
username = "user-1"
}
}
我正在尝试使用 Grako 将其转换为 JSON,但我无法获得正确的 EBNF 格式。这是我拥有的:
import grako
import json
grammar_ebnf = """
final = @:({ any } | { bracketed } | { braced });
braced = '{' @:( { bracketed } | { braced } | { any } ) '}' ;
bracketed = '[' @:( { braced } | { bracketed } | { any } ) ']' ;
any = /^[^\[\{\]\}\n]+/ ;
"""
model = grako.genmodel("final", grammar_ebnf)
with open('out.txt') as f:
ast = model.parse(f.read())
print (json.dumps(ast, indent = 4))
然而,这只是打印出来:
[
"dbCon = "
]
我哪里错了?我从未使用过Grako。我只是希望能够将其解析为 usable/accessible,而无需设计静态解析器以防格式发生变化。如果以后格式发生变化,更新 EBNF 似乎比重新设计整个解析器更容易。
仅通过一个例子很难确定真正的语法是什么,但希望这足以让您能够完成调整以处理任何奇怪的事情。
我们需要 Semantics
class 来处理将 key/value 对及其列表转换为字典。小心使用 @: 否则会起作用。
作为一个建议,当在语法中命名规则时,以它们本身(列表、字典等)而不是它们看起来的样子(大括号、括号)来命名它们。此外,首先将事情分成许多规则。您以后可以随时合并它们。
#!/usr/bin/python
import grako
import json
grammar = """
final = kvpair;
kvpair = key '=' value;
key = /[^\s=]+/;
value = @:(dict | list | string) [','];
list = '[' @:{ value } ']';
string = '"' @:/[^"]*/ '"';
dict = '{' @:{ kvpair } '}';
"""
class Semantics(object):
def kvpair(self, arg):
key, ignore, value = arg
return { key: value }
def dict(self, arg):
d = { }
for v in arg:
d.update(v)
return d
model = grako.genmodel("final", grammar)
with open('out.txt') as f:
ast = model.parse(f.read(), semantics=Semantics())
print json.dumps(ast, indent=4)
这会产生以下输出:
{
"dbCon": {
"main": {
"username": "user-1",
"maxConnCount": "5",
"slaves": [
{
"maxConnCount": "5",
"hostname": "db1-a.serv.com",
"compression": "true",
"database": "db1_a",
"charset": "utf8",
"port": "3306",
"client": "MYSQL"
},
{
"maxConnCount": "5",
"hostname": "db1-b.serv.com",
"compression": "true",
"database": "db1_b",
"charset": "utf8",
"port": "3306",
"client": "MYSQL"
}
],
"database": "db1",
"hostname": "db1.serv.com",
"port": "3306"
}
}
}
我有以下数据:
dbCon= {
main = {
database = "db1",
hostname = "db1.serv.com",
maxConnCount = "5",
port = "3306",
slaves = [
{
charset = "utf8",
client = "MYSQL",
compression = "true",
database = "db1_a",
hostname = "db1-a.serv.com",
maxConnCount = "5",
port = "3306",
}
{
charset = "utf8",
client = "MYSQL",
compression = "true",
database = "db1_b",
hostname = "db1-b.serv.com",
maxConnCount = "5",
port = "3306",
}
]
username = "user-1"
}
}
我正在尝试使用 Grako 将其转换为 JSON,但我无法获得正确的 EBNF 格式。这是我拥有的:
import grako
import json
grammar_ebnf = """
final = @:({ any } | { bracketed } | { braced });
braced = '{' @:( { bracketed } | { braced } | { any } ) '}' ;
bracketed = '[' @:( { braced } | { bracketed } | { any } ) ']' ;
any = /^[^\[\{\]\}\n]+/ ;
"""
model = grako.genmodel("final", grammar_ebnf)
with open('out.txt') as f:
ast = model.parse(f.read())
print (json.dumps(ast, indent = 4))
然而,这只是打印出来:
[
"dbCon = "
]
我哪里错了?我从未使用过Grako。我只是希望能够将其解析为 usable/accessible,而无需设计静态解析器以防格式发生变化。如果以后格式发生变化,更新 EBNF 似乎比重新设计整个解析器更容易。
仅通过一个例子很难确定真正的语法是什么,但希望这足以让您能够完成调整以处理任何奇怪的事情。
我们需要 Semantics
class 来处理将 key/value 对及其列表转换为字典。小心使用 @: 否则会起作用。
作为一个建议,当在语法中命名规则时,以它们本身(列表、字典等)而不是它们看起来的样子(大括号、括号)来命名它们。此外,首先将事情分成许多规则。您以后可以随时合并它们。
#!/usr/bin/python
import grako
import json
grammar = """
final = kvpair;
kvpair = key '=' value;
key = /[^\s=]+/;
value = @:(dict | list | string) [','];
list = '[' @:{ value } ']';
string = '"' @:/[^"]*/ '"';
dict = '{' @:{ kvpair } '}';
"""
class Semantics(object):
def kvpair(self, arg):
key, ignore, value = arg
return { key: value }
def dict(self, arg):
d = { }
for v in arg:
d.update(v)
return d
model = grako.genmodel("final", grammar)
with open('out.txt') as f:
ast = model.parse(f.read(), semantics=Semantics())
print json.dumps(ast, indent=4)
这会产生以下输出:
{
"dbCon": {
"main": {
"username": "user-1",
"maxConnCount": "5",
"slaves": [
{
"maxConnCount": "5",
"hostname": "db1-a.serv.com",
"compression": "true",
"database": "db1_a",
"charset": "utf8",
"port": "3306",
"client": "MYSQL"
},
{
"maxConnCount": "5",
"hostname": "db1-b.serv.com",
"compression": "true",
"database": "db1_b",
"charset": "utf8",
"port": "3306",
"client": "MYSQL"
}
],
"database": "db1",
"hostname": "db1.serv.com",
"port": "3306"
}
}
}