我是C的新手,第一次使用Boost Spirit为我的团队承担学习和使用C的任务(来自Web开发人员背景:))。在互联网上搜索时,我看到了这个社区中的一些很好的例子(特别是Sehe),但由于XML结构的复杂性,我不能完全将所有的东西拼凑在一起来完成这项任务。
这个解析器将充当中间人,将结构代码定义(由其他一些团队编写)转换为XML,供多个集成团队使用,并根据XML结构将其生成为他们选择的语言的代码。
下面是代码结构定义文本的一个小示例(来自外部文件)。此文件可能非常大,具体取决于任务
Class Simple caption;
Class Simple columns "Column Name";
Class Container CONTAINER_NAME (
Complex OBJECT_NAME (
Simple obj_id
Simple obj_property1
Simple obj_attribute enumeration(EnumOption1, EnumOption2,EnumOption3,EnumOption4)
Container OBJECT_ITEMS (
Complex OBJECT_ITEM (
Simple obj_item_name
Container set_value (
Simple obj_item_value
)
)
)
)
);
解析器将计算并生成这种格式的XML
<task>
<class>
<simple>
<identifier>caption</identifier>
<literal>" "</literal>
</simple>
</class>
<class>
<simple>
<identifier>caption</identifier>
<literal>"Column Name"</literal>
</simple>
</class>
<class>
<container>
<identifier>CONTAINER_NAME:CONTAINER_NAME</identifier>
<literal>" "</literal>
<complex>
<identifier>CONTAINER_NAME:OBJECT_NAME</identifier>
<literal>" "</literal>
<simple>
<identifier>CONTAINER_NAME:obj_id</identifier>
<literal>" "</literal>
</simple>
<simple>
<identifier>CONTAINER_NAME:obj_property1</identifier>
<literal>" "</literal>
</simple>
<simple>
<identifier>CONTAINER_NAME:obj_attribute</identifier>
<literal>" "</literal>
<enumeration>
<word>EnumOption1</word>
<word>EnumOption2</word>
<word>EnumOption3</word>
<word>EnumOption4</word>
</enumeration>
</simple>
<container>
<identifier>CONTAINER_NAME:OBJECT_ITEMS</identifier>
<literal>" "</literal>
<complex>
<identifier>CONTAINER_NAME:OBJECT_ITEM</identifier>
<literal>" "</literal>
<simple>
<identifier>CONTAINER_NAME:obj_item_name</identifier>
<literal>" "</literal>
</simple>
<container>
<identifier>CONTAINER_NAME:set_value</identifier>
<literal>" "</literal>
<simple>
<identifier>CONTAINER_NAME:obj_item_value</identifier>
<literal>" "</literal>
</simple>
</container>
</complex>
</container>
</complex>
</container>
</class>
</task>
从我所读到的,我将需要(只是我的思维过程与一个非常基本的知识)以下:
1.语法定义与规则类,容器,复杂,简单,解析代码定义文本(我最大的挑战);
1.为每个组(简单、复杂、容器、类等)创建XML节点的某种语义动作/函数。我看到我可以在这里使用msxml6.dll作为xml生成器,但不知道如何将它们连接起来。
我看到了一些构建AST然后从中构建XML的例子,但是它们使用的XML结构并不完全遵循任何标准,因为Container可以有Complex,但是Complex也可以有Container
任何帮助或指导或例子,以指出我从哪里开始将不胜感激。
已更新
1.分号用于指示CLASS块的结束。
1.注解存在,但将位于单独的行上。无内联注解。
1.代码定义中没有***literal***标签。文字内容在双引号内。参见更新的代码定义结构块第2行。
2条答案
按热度按时间enxuqcxy1#
好的,这些解释帮助我理解了输入和XML之间的对应关系。还有一些...规格不太清楚但我们继续吧
解析
1.#### AST
像往常一样,我从AST开始。这一次,它不是基于示例输入,而是基于输出XML:
到目前为止一切顺利。没有惊喜。主要的是使用递归变量来允许嵌套复杂/容器类型。作为旁注,我将所有类型的公共部分反映为
Base
。让我们调整这些以用作融合序列:现在精神将知道如何传播属性没有进一步的帮助。
1.#### * 语法 *
框架很简单,只需将AST节点Map到规则:
注意,我对词素(即do not allow a skipper)进行了分组,并将
space
skipper封装到了start规则中。因为“classes”可以显式出现,但也可以不带
Class
关键字,所以我将引入一个额外的规则type_
,这样我们就可以说:在可以接受Simple/Complex/Container的情况下,也可以使用
type_
。对于其余的,没有太多的惊喜,所以让我们展示整个构造函数块:
enum_
)。当然,我也可以把它全部保存在simple_
规则中。下面是**Live Demo**打印样本输入的原始AST:
遗憾的是,我所有漂亮的错误处理代码都没有被触发:)输出显然很难看,所以让我们来解决这个问题。
生成XML
我不是Microsoft的粉丝,但我更喜欢其他XML库(请参阅What XML parser should I use in C++?)。
所以我在这里选择PugiXML。
1.####生成器
简单地说,我们必须教计算机如何将任何Ast节点转换为XML:
我不会说我在一瞬间就把它打出来了,但你会认出这个模式:它在阿斯特1:1之后取得了巨大的成功。
完整演示
集成以上所有内容,并打印XML输出:
Live On Compiler Explorer
打印令人垂涎的输出:
CONTAINER_NAME:
“命名空间”是如何工作的,所以我将把它留给你去做。rjzwgtxy2#
再次感谢你给我上了这么棒的一课。要回答有关CONTAINER_NAME的问题,请执行以下操作:命名空间,它只是简单地用于分组(不是我的规则,只是提出定义结构的人希望这样)。
所以如果我们解析这行
那么结果应该是:
添加命名空间标题:,因为这是该类的第一个子级。但是如果我们解析
然后**CONTAINER_NAME:**命名空间将被附加到所有chidren的标识符名称。
我添加以下函数来处理XML结构的名称空间。它完成了这项工作,但我很肯定你只会想出一行来做这件事...:)
然后在处理Simple、Complex和Container的XML时调用此函数
无论如何,我还有很多事情要做,因为我还需要解析if-else,case语句,但这给予了我一个很好的起点。再次感谢您花时间与我分享您的知识。