【问题标题】:How can I express this format in EBNF?如何在 EBNF 中表达这种格式?
【发布时间】:2015-05-28 19:31:18
【问题描述】:

我有以下数据:

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。我只是希望能够将其解析为可用/可访问的东西,而无需设计静态解析器以防格式更改。如果稍后格式发生变化,更新 EBNF 似乎比重新编写整个解析器更容易。

【问题讨论】:

  • 好吧,你的语法似乎不正确......但我猜你已经知道了;)我注意到的一些事情:你的语法中没有任何地方出现'='的标记,这是一个您输入的基本部分。我会尝试为 key=value 对添加规则。明天我会再考虑一下。
  • 你需要使用grako吗?或者您只是想在 Python 中将其转换为 JSON?
  • 是的,我不必使用 grako - 只是寻找比编写自定义解析器更容易更改的东西。

标签: python grammar ebnf grako


【解决方案1】:

仅通过一个示例很难确定真正的语法是什么,但希望这足以让您能够完成调整以应对任何奇怪之处。

我们需要Semantics 类来处理将键/值对和它们的列表转换为字典。小心使用 @: 否则就行了。

作为一个建议,当在语法中命名规则时,以它们的本质(列表、字典等)命名它们,而不是它们的样子(大括号、括号)。此外,从一开始就将事情分成许多规则。您以后可以随时合并它们。

#!/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"
        }
    }
}

【讨论】:

  • kvpair 中使用@+:((然后是arg[0])是不必要的。默认情况下,如果没有向规则添加任何装饰,Grako 将返回已解析元素的列表。
  • 我不确定@:( 的作用——我只是在一个例子中看到过;你(或某人)介意给我一个 tl;dr 版本,什么时候使用它,什么时候不使用它?
  • 与每个规则关联的默认语义操作是从规则右侧获取所有值,将它们填充到列表中,然后返回该值。 @: 表示语义操作应该返回 @: 附加到的任何值。例如,在字符串规则中,它指示返回的值应该只是引号之间的内容,而不是由引号、引号之间的内容和另一个引号组成的列表。 (所以'foo' 而不是['"', 'foo', '"']。)
  • 您的答案非常适合我给出的示例,但不适用于“真实”文件(为简洁起见,我将其压缩) - 知道如何找到混淆吗?我想了解您的 EBNF 如何与真实数据相关联,而不是每次都寻求帮助。
  • 嗯,我在该文件中看不到任何不应该解析的内容,它确实为我解析。老版本的grako? Python 文件模式还是 unicode 怪异?您可以尝试将文件编辑成更小的块,看看是哪个块导致了问题。
猜你喜欢
  • 2019-05-22
  • 2016-11-28
  • 2018-12-27
  • 1970-01-01
  • 2022-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多