在我的一个项目中,我需要能够提供一个非常简单的变量查找和替换解析器(主要用于路径中)。变量主要在启动期间使用,偶尔用于访问文件(不是程序的主要功能,只是加载资源),因此解析器不需要高性能。但是,我非常希望它是线程安全的。
解析器需要能够存储一组变量(map<string, string>
目前)并且能够用字符串中的相应值替换标记。变量值可能包含其他变量,这些变量将在使用变量时解析(而不是在添加时,因为变量可能会随着时间的推移而添加)。
当前的变量语法看起来像:
$basepath$/resources/file.txt
/$drive$/$folder$/path/file
我当前的解析器使用一对stringstream
s(“output”和“varname”),写入“output”流直到找到第一个 $,“varname”流直到找到第二个 $,然后查找变量(使用)的内容varname.str()
。它非常简单并且运行良好,即使在对变量值进行递归时也是如此。
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 {
// Is a varname start/end
if ( !dest )
{
varname.clear();
dest = true;
} else {
// Is an end
Variable = mVariables.find(varname.str());
output << Parse(Variable.value());
dest = false;
}
}
++pos;
}
return output.str();
}
(错误检查等已删除)
但是,当我尝试将其应用于所需的语法时,该方法失败了。我想要类似于 Visual Studio 用于项目变量的东西:
$(basepath)/resources/file.txt
/$(drive)/$(folder)/path/file
我也希望能够做到:
$(base$(path))/subdir/file
递归变量名让我陷入困境,我不确定最好的方法。
目前,我有两个可能的概念:
遍历输入字符串,直到找到 $,查找 ( 作为下一个字符,然后找到匹配的 )(计数进出级别,直到达到正确的关闭参数)。发送该位进行解析,然后使用返回的值作为变量名。但是,这似乎会很混乱并导致大量复制。
第二个概念是使用 a char *
,或者也许char * &
,并将其向前移动,直到我到达一个终止的空值。解析器函数可以在解析变量名称时在递归调用中使用指针。我不确定如何最好地实现这种技术,除了让每个调用跟踪它解析出来的名称,并附加它所做的任何调用的返回值。
该项目只需要在 VS2010 中编译,因此 STL 流和字符串、C++0x 支持的位以及 Microsoft 特定的功能都是公平的游戏(如果这些要求发生变化,最好使用通用解决方案,但此时没有必要观点)。但是,使用其他库并不好,尤其是 Boost。
我的两个想法似乎都比需要的更复杂和混乱,所以我正在寻找一种干净的方式来处理这个问题。非常欢迎讨论如何最好地做到这一点的代码、想法或文档。