我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
专题:一个自制代码生成器(嵌入式脚本语言)之总述-CSDN博客
专题:一个自制代码生成器(嵌入式脚本语言)之对象模型-CSDN博客
专题:一个自制代码生成器(嵌入式脚本语言)之堆栈结构和总入口-CSDN博客 (本篇)
专题:一个自制代码生成器(嵌入式脚本语言)之核心逻辑-CSDN博客
专题:一个自制代码生成器(嵌入式脚本语言)之辅助逻辑-CSDN博客
专题:一个自制代码生成器(嵌入式脚本语言)之应用实例-CSDN博客
专题:一个自制代码生成器(嵌入式脚本语言)之模型开发-CSDN博客
目录
一、堆栈概述
此处“堆栈”指的是“栈”。栈是用来实现上下文关系的基本数据结构,最熟悉的场景就是函数调用。
函数调用时函数参数被放在栈里面,函数返回后栈被清理。
栈一般被描述为后进先出的结构,适合于表达上下文关系。
作为脚本语言,自然要处理上下文关系,各种嵌套、循环都涉及到变量的覆盖问题。
代码其实相当的简单,用vector就可以实现栈,要点是在每个正确的地方入栈和出栈。
二、代码
栈结构用vector实现,每层是一个对象,为了方便,提供了三个直接操作栈顶的方法。
struct CCTStack : public vector<CCTObject >
{
void Push()
{
CCTObject o;
this->push_back(o);
}
void Pop()
{
this->pop_back();
}
bool AddRef(string const& objname, CCTObject * pObj)
{
if (0 == this->size())return false;
this->rbegin()->SetObjectAddRef(objname, pObj);
return true;
}
bool Add(string const& objname, CCTObject const& obj)
{
if (0 == this->size())return false;
this->rbegin()->SetObjectAdd(objname, obj);
return true;
}
bool AddProperty(string const& objname, string const& obj)
{
if (0 == this->size())return false;
this->rbegin()->SetObjectAddProperty(objname, obj);
return true;
}
string& toString(string& ret)const
{
string str;
stringstream ss;
for (const_iterator it = begin(); it != end(); ++it)
{
ss << "===============================" << endl;
ss << it->toString(str) << endl;
}
return ret = ss.str();
}
};
三、总入口
总入口如下:
//处理模板文件,输出到ss中
bool ProcessTemplate(char const* templatefile, stringstream& ss, CCTObject& O, CCTStack& S)
{
m_functions.clear();
CEasyFile file;
string filedata;
if (!file.ReadFile(templatefile, filedata))
{
thelog << "未能打开模板文件 " << templatefile << ende;
return false;
}
long end = filedata.size();
bool ret = _ProcessBlock(filedata, 0, end, ss, O, S);
if (!ret)
{
thelog << "操作失败 " << templatefile << " 输出文件在出错处中止 " << ende;
}
//thelog << endl << ss.str() << endi;
return ret;
}
bool ProcessFile(char const* infile, char const* outfile, CCTObject& O, CCTStack& S)
{
thelog << "开始处理 " << infile << " 输出到 " << outfile << endi;
stringstream ss;
bool ret = ProcessTemplate(infile, ss, O, S);
//thelog << endl << ss.str() << endi;
CEasyFile file;
if (!file.WriteFile(outfile, ss.str().c_str()))
{
thelog << "写文件出错 " << outfile << ende;
return false;
}
return ret;
}
前两个参数为输入文件和输出,输入文件是模板,输出是文本。两个接口的区别是一个输出到stringstream对象,一个输出到文件(其实调用了另一个)。
第三个参数是对象模型,相当于预设的全局变量,可以在脚本任何地方引用。
第四个参数是栈对象,一般不需要预设数据,不过如果有环境变量之类可以设置进去。
脚本里面搜索对象时优先从堆栈搜索,堆栈里没有才从对象模型里搜索。
调用示例:
CCodeTemplate ct;
CCTObject O;
CCTStack S;
stringstream ss;
O.SetObjectAddProperty("sys", "aaaaaaaaaaaaa\n");
if (!ct.ProcessTemplate("simplesample.ct", ss, O, S))
{
thelog << "执行失败" << ende;
}
thelog <<"========================="<< endl << ss.str() << endi;
实际的处理逻辑从_ProcessBlock()开始,下一篇将详细解释。
(这里是结束,但不是整个系列的结束)