初级代码游戏的专栏介绍与文章目录-****博客
我的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;
}
(这里是结束但不是整个系列的结束)