To handle large compile times and reuse of grammars I've composed my grammar into several sub-grammars which are called in sequence. One of them (call it: SETUP grammar) offers some configuration of the parser (via symbols parser), so later sub grammars logically depend on that one (again via different symbols parsers). So, after SETUP is parsed, the symbols parsers of the following sub grammars need to be altered.
My question is, how to approach this efficiently while preserving loose coupling between the sub grammars?
Currently I see only two possibilities:
- The on_success handler of the SETUP grammar, which could do the work, but this would introduce quite some coupling.
- After the SETUP, parse everything into a string, build up a new parser (from the altered symbols) and parse that string in a second step. This would leave quite some overhead.
What I would like to have is a on_before_parse handler, which could be implemented by any grammar which needs to do some work before each parsing. From my point of view, this would introduce less coupling and some setup of the parser could come handy in other situations, too. Is something like this possible?
Update:
Sorry for being sketchy, that wasn't my intention.
The task is to parse an input I with some keywords like #task1
and #task2
. But there will be cases where these keywords need to be different, say $$task1
and $$task2
.
So the parsed file will start with
setup {
#task1=$$task1
#task2=$$task2
}
realwork {
...
}
Some code sketches: Given is a main parser, consisting of several (at least two) parsers.
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
and RealWork
are themselves parsers (my sub parsers from above). During the setup part, some keywords of the grammar may be altered, so the setup part has a qi::symbols<char, keywords>
rule. In the beginning these symbols will contain #task1
and #task2
. After parsing the first part of the file, they contain $$task1
and $$task2
.
Since the keywords have changed and since RealWork
needs to parse I, it needs to know about the new keywords. So I have to transfer the symbols from Setup
to RealWork
during the paring of the file.
The two approaches I see are:
- Make the
Setup
aware ofRealWork
and transfer the symbols fromSetup
toRealWork
in theqi::on_success
handler ofSetup
. (bad, coupling) Switch to two parsing steps.
start
ofMainParser
will look likestart = setup >> unparsed_rest
and there will be a second parser afer
MainParser
. Schematically:SymbolTable Table; string Unparsed_Rest; MainParser.parse(Input, (Unparsed_Rest, Table)); RealWordParser.setupFromAlteredSymbolTable(Table); RealWorkParser.parse(Unparsed_Rest);
Overhead of several parsing steps.
So, up to now, attributes are not into play. Just changing the parser at parse time to handle several kinds of input files.
My hope is a handler qi::on_before_parse
like qi::on_success
. From the idea this handler would be triggered each time the parser starts parsing an input. Theoretically just an interception at the beginning of parsing, like we have the interceptions on_success
and on_error
.