In one of my projects, I need to provide a very simple parser for finding and replacing variables (mainly for use in paths). Variables are used primarily during startup, and sometimes for accessing files (and not the main function of the program, just loading resources), so the parser should not be high-performance. However, I would prefer it to be thread safe.
The parser should be able to store a set of variables ( map<string, string> at the moment) and be able to replace tokens with the corresponding value in the lines. Variable values may contain other variables that will be resolved when using a variable (and not when adding it, since variables can be added over time).
The current grammar variable looks something like this:
$basepath$/resources/file.txt /$drive$/$folder$/path/file
My current parser uses a pair of stringstream ("output" and "varname"), writes to the stream "output" until it finds the first stream $, "varname" to the second $, then looks up the variable (using the contents of varname.str() ) This is very simple and works great, even when navigating through variable values.
String Parse(String input) { stringstream output, varname; bool dest = false; size_t total = input.length(); size_t pos = 0; while ( pos < total ) { char inchar = input[pos]; if ( inchar != '$' ) { if ( dest ) output << inchar; else varname << inchar; } else {
(error checking and removal)
However, this method does not give me the opportunity when I try to apply it to my desired grammar. I would like something similar to what Visual Studio uses for project variables:
$(basepath)/resources/file.txt /$(drive)/$(folder)/path/file
I would also like to be able to:
$(base$(path))/subdir/file
The recursion in the variable name launched me into the wall, and I'm not sure what is the best way to proceed.
I currently have two possible concepts:
Iterate over the input line until I find $, find (as the next character, then find a match) (counting the levels of inputs and outputs until the correct close pair is reached). Send this bit for analysis, then use the return value as the variable name. It looks like it will be messy and, nevertheless, will cause many copies.
The second concept is to use char * or possibly char * & , and move it forward until it reaches the final zero value. The parser function can use the pointer in recursive calls for itself when parsing variable names. I'm not sure how best to implement this technique, except that each call keeps track of the name it parses and adds the return value of any calls it makes.
The project should only be compiled in VS2010, so STL streams and strings, supported C ++ 0x bits and Microsoft-specific functions are fair game (a general solution is preferable if these changes change, but it is not necessary at this moment). However, using other libraries is not very good, especially not Boost.
Both of my ideas seem more complicated and messy than necessary, so I'm looking for a good clean way to handle this. Codex, ideas or documents discussing how best to do this are very welcome.