【发布时间】:2013-07-22 14:35:47
【问题描述】:
为了处理大量的编译时间和语法的重用,我将我的语法组合成几个按顺序调用的子语法。其中之一(称为:SETUP 语法)提供了解析器的一些配置(通过符号解析器),因此后来的子语法在逻辑上依赖于该配置(同样通过不同的符号解析器)。所以,解析完SETUP后,需要修改以下子文法的符号解析器。
我的问题是,如何在保持子语法之间松散耦合的同时有效地解决这个问题?
目前我只看到两种可能性:
- SETUP 语法的 on_success 处理程序可以完成这项工作,但这会引入一些耦合。
- 在 SETUP 之后,将所有内容解析为一个字符串,构建一个新的解析器(根据更改的符号)并在第二步中解析该字符串。这会留下相当多的开销。
我想要的是一个 on_before_parse 处理程序,它可以由任何需要在每次解析之前做一些工作的语法来实现。从我的角度来看,这将引入更少的耦合,并且解析器的某些设置在其他情况下也可以派上用场。这样的事情可能吗?
更新:
抱歉,我的本意不是这么粗略。
任务是用#task1 和#task2 等关键字解析输入I。但在某些情况下,这些关键字需要不同,例如 $$task1 和 $$task2。
所以解析后的文件将以
开头setup {
#task1=$$task1
#task2=$$task2
}
realwork {
...
}
一些代码草图:Given 是一个主解析器,由几个(至少两个)解析器组成。
template<typename Iterator>
struct MainParser: qi::grammar<Iterator, Skipper<Iterator>> {
MainParser() : MainParser::base_type(start) {
start = setup >> realwork;
}
Setup<Iterator> setup;
RealWork<Iterator> realwork;
qi::rule<Iterator, Skipper<Iterator> > start;
}
Setup 和 RealWork 本身就是解析器(我上面的子解析器)。在设置部分,可能会更改语法的某些关键字,因此设置部分有一个qi::symbols<char, keywords>规则。在开始时,这些符号将包含#task1 和#task2。解析文件的第一部分后,它们包含$$task1 和$$task2。
由于关键字已经改变并且RealWork需要解析I,它需要知道新的关键字。所以我必须在文件配对期间将符号从Setup转移到RealWork。
我看到的两种方法是:
- 让
Setup知道RealWork并在Setup的qi::on_success处理程序中将符号从Setup传输到RealWork。 (坏,耦合) -
切换到两个解析步骤。
start的MainParser看起来像start = setup >> unparsed_rest在
MainParser之后会有第二个解析器。示意图:SymbolTable Table; string Unparsed_Rest; MainParser.parse(Input, (Unparsed_Rest, Table)); RealWordParser.setupFromAlteredSymbolTable(Table); RealWorkParser.parse(Unparsed_Rest);几个解析步骤的开销。
所以,到目前为止,属性还没有发挥作用。只需在解析时更改解析器即可处理多种输入文件。
我希望像qi::on_success 这样的处理程序qi::on_before_parse。从这个想法来看,每次解析器开始解析输入时都会触发这个处理程序。理论上只是解析开始时的拦截,就像我们有拦截on_success和on_error一样。
【问题讨论】:
-
我在一些通用的 cmets 上已经尽力了。希望这些东西能帮助你走上正轨。如果没有,我建议你回来提出一个具体的问题。我更喜欢代码而不是“想法”,因为想法通常对你来说意味着其他东西,而不是对我。
-
@sehe:非常感谢您的努力。我试图更具体一点,语法是如何划分的以及解析应该如何工作。
标签: c++ boost-spirit boost-spirit-qi