现在的位置: 首页 > 综合 > 正文

学习正则表达式 - WTL80 AppWizMobile之SplitCode函数

2013年03月08日 ⁄ 综合 ⁄ 共 4673字 ⁄ 字号 评论关闭
        在WTL80中,AppWiz应用程序向导与AppWizMobile应用程序向导一个区别是在AppWizMobile中使用了SplitCode函数,目的是在编写WTL向导模板时只需要提供.h文件,使用SplitCode可以在需要时将类成员函数转换到.cpp文件中,而AppWiz应用程序向导则是编写了.h和.cpp文件,根据[!if WTL_USE_CPP_FILES]/[!endif]进行预处理,相比之下使用SplitCode对于向导模板的编写简单的多。

  VisualFC当前版本(0.80.0601)内置的AppWizard和CodeWizard使用与WTL80的AppWiz同样的处理方式,即使用[!if WTL_USE_CPP_FILES]/[!endif]进行预处理。为简化VisualFC向导模板的编写,我们考虑在VisualFC以后版本中模仿WTL80的AppWizMobile向导提供SplitCode函数来进行处理。WTL80向导的SplitCode函数是用JScript完成的,在这里我们可以用boost::regex进行改写,以便在C++程序中直接使用。其中对于C++类及成员函数分析的正则表达式在两种语言中是完全一致的,具体代码如下:


WTL80的AppWizMobile的SplitCode代码
/******************************************************************************
	Description: Add the function members body to a .cpp file and remove them
				 from the matching header. Do nothing if no matching .h file.
		cppPath: Path name to a .cpp file
******************************************************************************/

function SplitCode(cppPath)
{
	var fso = new ActiveXObject('Scripting.FileSystemObject');
	var hPath = cppPath.replace(/.cpp$/, ".h");
	if (!fso.FileExists(hPath))
		return;

	var cppFile = fso.GetFile(cppPath);
	var hFile = fso.GetFile(hPath);
	var tsh = hFile.OpenAsTextStream(1);
	var hText = tsh.ReadAll();
	tsh.Close();
	var tscpp = cppFile.OpenAsTextStream(8);

	var ClassPattern = /^[ /t]*class[ /t]+(/w+)[/s/S]+?(?:^[ /t]*/};$)/mg
	var ClassInfo = hText.match(ClassPattern);
	var numClass = ClassInfo.length;
	for (nc = 0 ; nc < numClass; nc++)
	{
		var ClassText = ClassInfo[nc];
		ClassText.match(ClassPattern);
		var ClassName = RegExp.$1;
		
		var FnPattern = /(^(?:[ /t]+/w+)*[ /t]+(/w+)/([^/)]*/))([/s]*/{([^/}]*/{[^/}]*/})*[^/}]*/}+?)/mg
		var FnPatternIf = /(^(?:#if.+/s+)*(?:[ /t]+/w+)*[ /t]+(/w+)/([^/)]*/))([/s]*/{([^/}]*/{[^/}]*/})*[^/}]*/}+?(?:/s+#e(?:ndif|lif|lse)[^/r/n]*)*)/mg
		var FnInfo = ClassText.match(FnPatternIf);
		var numFn = FnInfo.length;
		for (n = 0 ; n < numFn; n++)
		{
			var FnTextIf = FnInfo[n];
			var FnTextIf = FnTextIf.match(FnPatternIf);
			var FnDef = RegExp.$1;
			var FnName = RegExp.$2;
			var FnBody = RegExp.$3;
		
			var FnFullName = ClassName + "::" + FnName;
			FnDef = FnDef.replace(FnName, FnFullName);
			FnDef = FnDef.replace(/^/t(?:/s*virtual/s+)*/, "");
			FnBody = FnBody.replace(/^/t/mg, ""); 

			tscpp.Write(FnDef);
			tscpp.Write(FnBody);
			tscpp.WriteBlankLines(2);

			var FnText = FnTextIf.input.match(FnPattern);
			var FnDecl = RegExp.$1 + ";";

			ClassText = ClassText.replace(FnText, FnDecl);
		}
		hText = hText.replace(ClassInfo[nc], ClassText);
	}
	tscpp.Close();
	tsh = hFile.OpenAsTextStream(2);
	tsh.Write(hText);
	tsh.Close();
}

使用boost::regex改写的代码,代码稍有不同,没有做文件的处理,直接处理字符串。

void process(const std::string & text)
{
	std::string	regstr = "^[ /t]*class[ /t]+(//w+)[//s//S]+?(?:^[ /t]*//};$)";
	boost::regex expression(regstr,boost::regbase::JavaScript);
	std::string::const_iterator start, end;
	start = text.begin();
	end = text.end();

	boost::match_results<std::string::const_iterator> what;
	boost::match_flag_type flags = boost::match_default;

	std::string file_h = text;
	std::string file_cpp;

	while(boost::regex_search(start, end, what, expression, flags))   
	{
		start = what[0].second;
		std::string class_name = what[1];
		std::string class_text = what[0];
		std::string class_h, class_cpp;
		process_class(class_name,class_text,class_h,class_cpp);
		file_h = boost::regex_replace(file_h,boost::regex(class_text,boost::regbase::literal),class_h);
		file_cpp += class_cpp;
	}
}

void process_class(const std::string & class_name, const std::string & class_text, std::string & class_h, std::string & class_cpp)
{
	std::string FnPattern = "(^(?:[ /t]+//w+)*[ /t]+(//w+)//([^//)]*//))([//s]*//{([^//}]*//{[^//}]*//})*[^//}]*//}+?)";
	std::string FnPatternIf = "(^(?:#if.+//s+)*(?:[ /t]+//w+)*[ /t]+(//w+)//([^//)]*//))([//s]*//{([^//}]*//{[^//}]*//})*[^//}]*//}+?(?://s+#e(?:ndif|lif|lse)[^/r/n]*)*)";

	std::string::const_iterator start, end;
	start = class_text.begin();
	end = class_text.end();

	boost::match_results<std::string::const_iterator> what;
	boost::match_flag_type flags = boost::match_default;
	boost::regex expression(FnPatternIf,boost::regbase::JavaScript);

	class_h = class_text;
	class_cpp = "/r/n//class/t";
	class_cpp += class_name;
	class_cpp += _T("/r/n");

	while(boost::regex_search(start, end, what, expression, flags))   
	{
		start = what[0].second;

		std::string func_buffer = what[0];
		std::string func_def = what[1];
		std::string func_name = what[2];
		std::string func_body = what[3];
		//write cpp function

		std::string func_fullname = std::string(class_name) + "::" + func_name;
		func_def = boost::regex_replace(func_def,boost::regex(func_name),func_fullname);
		func_def = boost::regex_replace(func_def,boost::regex("^/t(?://s*virtual//s+)*"), "");
		func_body= boost::regex_replace(func_body,boost::regex("^/t"), ""); 

		class_cpp += _T("/r/n");
		class_cpp += func_def;
		class_cpp += func_body;
		class_cpp += _T("/r/n/r/n");

		boost::regex_search(func_buffer,what,boost::regex(FnPattern),flags);
		//
		std::string func_decl = (std::string)(what[1]) + ";";
		boost::regex reg(std::string(what.base()),boost::regbase::literal);
		class_h = boost::regex_replace(class_h,reg,func_decl);
	}
}

通过对比,我们也可以看到,由于C++没有内置regex处理,所以代码要比JScript复杂一些

抱歉!评论已关闭.