在运行时加载语法

时间:2012-04-25 18:10:15

标签: c++ parsing dynamic runtime grammar

我正在用C ++编写一个项目,我正在寻找一种以人类可读/可写的形式输入文本文件(usergrammar.txt)的方法,这是一种定义对象的用户定义语法。 / p>

完成此操作后,我希望能够在代码中实例化其中的一些对象,并将创建的实例保存在另一个文件(instances.txt)中,始终采用人工可访问的格式。第二个文件显然取决于第一个正确读取的文件。

我遇到的问题是如何定义语法并解析它们。我一直在看Boost :: Spirit,但是虽然它会在读取第一个文件时做得很好(因为它的规则是预定义的),但我不认为它适用于第二个文件,因为Spirit语法只是定义了编译时,无法在运行时加载(至少这是我所理解的)。

现在我正在阅读有关ENBF表单的内容,但我也遇到了这样的问题:我不仅拥有语言规则,而且每次将对象包含在另一个对象中时,每个对象都有一个特定的,不同的名称/描述/选项(例如,如果我有对象颜色,其中的整数将被称为红色,蓝色,黄色,而如果对象是标尺,其整数将被称为长度),所以我有办法将这些信息包含到文件中同样,并让它们正确地与相应的值相关联。

你对这样的项目有什么看法/学习/使用/做的指示吗? 提前谢谢。

2 个答案:

答案 0 :(得分:1)

请参阅Earley parsers,它使用从运行时提供的语法中提取的事实来解析上下文自由语言。

另一种方法是使用几乎所有C ++编译器系统都提供可以分叉进程的库这一事实。您可以使用它来分叉shell脚本来运行您喜欢的任何解析器生成器方案(包括Boost:Spirit,要求您从脚本调用C ++编译器,但这并不难)基于任何相应的语法形式,然后使用该脚本调用生成的解析器。如果要处理大型文档,这可能比Earley解析器更有效。实施起来肯定会容易得多。

答案 1 :(得分:0)

如果您对文件格式有一些限制,可以考虑使用XML或JSON来描述您的语法。

你可以有一个看起来像

的语法文件
{
    "ObjectTypes" : {
        "ruler" : { "properties" : [ "length" ] },
        "color" : { "properties" : [ "red", "green", "blue" ] }
    }
}

在读取此文件后(最有可能使用一些预先存在的库),您可以读入另一个具有实际对象的文件。它可能看起来像这样:

{
    "Objects" : [
        { name : "object1", "type" : "ruler", "length" : 5 },
        { name : "object2", "type" : "color", "red" : 5, "blue" : 127, "green" : 150, }
    ]
}

等等。给出了一个更具描述性的JSON概述here,它包含了几个处理JSON的C ++库的链接(我个人最喜欢的是JsonCpp)。