专题:一个自制代码生成器(嵌入式脚本语言)之辅助逻辑

初级代码游戏的专栏介绍与文章目录-****博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


专题:一个自制代码生成器(嵌入式脚本语言)之总述-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之对象模型-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之堆栈结构和总入口-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之核心逻辑-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之辅助逻辑-****博客(本篇)

专题:一个自制代码生成器(嵌入式脚本语言)之应用实例-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之模型开发-****博客

专题:一个自制代码生成器(嵌入式脚本语言)之代码模板详解-****博客


目录

一、处理变量替换

二、处理表达式

三、寻找块结束

四、查找对象


一、处理变量替换

        变量替换使用“${”和“}”包裹。

	//处理没有控制块的纯替换
	bool _ProcessNoBlock(string const& _source, long start, long end, stringstream& ss, CCTObject& O, CCTStack& S)
	{
		string source = _source.substr(start, end - start);
		DEBUG_LOG << "---------------------------------- " << start << " " << end << endl << source << endi;
		size_t pos = 0;//标记开始处
		size_t pos2 = 0;//指向未处理部分
		while (string::npos != (pos = source.find("${", pos2)))
		{
			ss << source.substr(pos2, pos - pos2);
			pos2 = source.find("}", pos + 2);
			if (source.npos == pos2)
			{
				thelog << "没找到匹配的 } :" << source.substr(pos) << ende;
				return false;
			}

			string objname = source.substr(pos, pos2 + 1 - pos);
			bool INCafterUsed = false;//带有后++
			objname = _makeobjname(objname);//脱壳
			if (objname.size() > 2 && "++" == objname.substr(objname.size() - 2))
			{
				INCafterUsed = true;
				objname.erase(objname.size() - 2);
			}

			if ("__LOG__" == objname)
			{
				ss << "thelog << " << _getLineNumber(_source.c_str(), start + pos) << " << \" \"";
			}
			else if ("__DEBUG_LOG__" == objname)
			{
				ss << "DEBUG_LOG << " << _getLineNumber(_source.c_str(), start + pos) << " << \" \"";
			}
			else
			{
				CCTObject* p = _FindObject(objname, O, S);
				if (NULL == p)
				{
					thelog << "对象不存在 [" << objname << "] line : " << _getLineNumber(_source.c_str(), pos + start) << ende;
					return false;
				}
				DEBUG_LOG << "line : " << _getLineNumber(_source.c_str(), pos + start) << " " << objname << " " << p->GetDefaultValue() << endi;
				ss << p->GetDefaultValue();

				if (INCafterUsed)
				{
					char buf[64];
					sprintf(buf, "%ld", atol(p->GetDefaultValue().c_str()) + 1);
					p->SetDefaultValue(buf);
				}
			}

			pos2 = pos2 + 1;
		}
		ss << source.substr(pos2);
		DEBUG_LOG << "-------------------" << endi;
		return true;
	}

二、处理表达式

	//处理表达式,双引号引导为纯文本,单引号引导为脚本,没有引号先判断是不是对象再当作脚本,如果是对象则p有效
	string _ProcessExpression(CCTObject& O, CCTStack& S, string const& expression, CCTObject*& p)
	{
		//thelog << expression << endi;
		p = nullptr;
		if (expression.size() >= 2 && '\"' == expression[0] && '\"' == expression[expression.size() - 1])
		{
			//thelog << varname<<" "<< objname.substr(1, objname.size() - 2) <<endi;
			return expression.substr(1, expression.size() - 2);
		}
		stringstream tmp_ss;
		if (expression.size() >= 2 && '\'' == expression[0] && '\'' == expression[expression.size() - 1])
		{
			//thelog << expression << endi;
			if (_ProcessBlock(expression.substr(1, expression.size() - 2), 0, expression.size() - 2, tmp_ss, O, S))
			{
				//thelog << tmp_ss.str() << endi;
				return tmp_ss.str();
			}
			else
			{
				return expression + " 对象不存在或脚本出错 ";
			}
		}
		else
		{
			p = _tryFindObject(expression, O, S);
			if (NULL != p)
			{
				return "";
			}
			if (_ProcessBlock(expression, 0, expression.size(), tmp_ss, O, S))
			{
				return tmp_ss.str();
			}
			else
			{
				return expression + " 对象不存在或脚本出错 ";
			}
		}
	}

        处理表达式只在dim和set中使用。

三、寻找块结束

	//寻找块结束,end1 end2返回扩展后的结束标签
	bool _findBlockEnd(string const& source, size_t start, size_t end, size_t& end1, size_t& end2, char const* labelBegin, char const* labelEnd)
	{
		return __findBlockEnd(source, start, end, end1, end2, labelBegin, labelEnd, false);
	}
	bool _TryFindBlockEnd(string const& source, size_t start, size_t end, size_t& end1, size_t& end2, char const* labelBegin, char const* labelEnd)
	{
		return __findBlockEnd(source, start, end, end1, end2, labelBegin, labelEnd, true);
	}
	bool __findBlockEnd(string const& source, size_t start, size_t end, size_t& end1, size_t& end2, char const* labelBegin, char const* labelEnd, bool isTry)
	{
		long level = 1;
		string matchlable;
		end1 = start;
		end2 = start;
		while (level > 0)
		{
			end1 = source.find("<%", end2);
			if (string::npos == end1 || end1 >= end)
			{
				if (!isTry)thelog << "控制块不匹配 level " << level << " " << labelBegin << " " << labelEnd << " 行 " << _getLineNumber(source.c_str(), start) << ende;
				//exit(0);
				return false;
			}
			end2 = source.find("%>", end1 + 2);
			if (string::npos == end2 || end2 >= end)
			{
				thelog << "没找到匹配的 %> : " << source.substr(end1) << ende;
				return false;
			}
			string blockcode = source.substr(end1 + 2, end2 - (end1 + 2));
			StringTokenizer st(blockcode, " ");
			DEBUG_LOG << "level " << level << " " << st[0] << " 行:" << _getLineNumber(source.c_str(), end1) << endi;
			if (st.size() > 0)
			{
				if ((string)"else" == labelEnd)
				{
					if ((string)"else" == st[0] && 1 == level)
					{//找else只能在最后一层时降级
						DEBUG_LOG << "level=1时找到else" << endi;
						matchlable = st[0];
						--level;
					}
					if ((string)"endif" == st[0])
					{
						DEBUG_LOG << "找else时遇到endif" << endi;
						matchlable = st[0];
						--level;
					}
				}
				else if (labelEnd == st[0])
				{
					DEBUG_LOG << "找到结束标记" << endi;
					matchlable = st[0];
					--level;
				}
				if (labelBegin == st[0])
				{
					DEBUG_LOG << "找到开始标记" << endi;
					matchlable = st[0];
					++level;
				}
			}
			end2 += 2;
		}
		if (0 == level && labelEnd == matchlable)
		{
			_extendToLine(source.c_str(), end1, end2);
			DEBUG_LOG << "找到块 " << labelBegin << " " << labelEnd << " 行 " << _getLineNumber(source.c_str(), end1) << " " << source.substr(end1, end2 - end1) << endi;
			return true;
		}
		else
		{
			if (labelEnd != (string)"else")thelog << "控制块不匹配" << labelBegin << " " << labelEnd << " 行 " << _getLineNumber(source.c_str(), start) << ende;
			return false;
		}
	}

四、查找对象

	CCTObject* _FindObject(string _objname, CCTObject& O, CCTStack& S)
	{
		return __FindObject(_objname, O, S, false);
	}
	CCTObject* _tryFindObject(string _objname, CCTObject& O, CCTStack& S)
	{
		return __FindObject(_objname, O, S, true);
	}
	CCTObject* __FindObject(string _objname, CCTObject& O, CCTStack& S, bool isTry)
	{
		//G_IS_DEBUG = true;
		string objname = _makeobjname(_objname);//脱壳
		CCTObject* ret = NULL;
		DEBUG_LOG << "查找 " << objname << " " << S.size() << endi;
		for (long i = S.size() - 1; i >= 0; --i)
		{
			DEBUG_LOG << "S... " << endi;
			ret = S[i].FindObject(objname);
			if (ret != NULL)
			{
				DEBUG_LOG << "找到 " << endi;
				return ret;
			}
		}
		DEBUG_LOG << "O... " << endi;
		ret = O.FindObject(objname);
		if (NULL == ret)
		{
			if (!isTry)thelog << "对象不存在 " << objname << endw;
			//string str;
			//thelog << endl << O.toString(str) << endi;
			//for (CCTStack::reverse_iterator it = S.rbegin(); it != S.rend(); ++it)
			//{
			//	thelog << endl << it->toString(str) << endi;
			//}
		}
		return ret;
	}


(这里是结束但不是整个系列的结束)

上一篇:Node.js常用命令详解


下一篇:C++:数据类型-int(6)