本来准备来实现一个简单的python的shell交互器,现在只完成了python中几个数据结构的实现,目前正在啃编译原理,等编译原理啃完了再继续回来实现pytyon的shell。
写的有点乱哈~~
Github有详细的代码:achievePythonShell
实现的思想:
Python中的列表是个神奇的数据结构,也是Python中最学用的一个数据结构(个人认为),它能存放各个类型的数据,lst1=[1,2,2.3,”string”];它的数据元素还能是列表,lst2=[1,2,2.3,”string”,[2,3,’sdf’]],这个也是我在实现的时候最难的一点,因为它能放列表,列表的列表,列表的列表的列表……
所以我先定义了一个Type类,把列表中的元素都放到Type类中,这样列表就可以用vector来进行操作。
class Type
{
public:
float value;//用来存放int或float类型的数据
string val_str;//用来存放字符串类型数据
int type;//用来表示数据的类型,因为python中没有类型,0代表整形,1代表浮点型,2代表字符串类型
Type(float v=0,string vs="", int t=0) :value(v), type(t) {//在python中把字符串都加上‘’,在构造函数里实现
if (t == STRING)
{
vs = "'" + vs + "'";
val_str = vs;
}
}
那如果元素要是一个列表,即[1,2,[3,4]]中的[3,4]用什么来表示呢?想了很久 ,最后把这个[3,4]看成是一个字符串”[3,4]”存放在Type中的val_str里,同时type的值为2(字符串类型)+括号的层数。
比如:元素[3,4]可以表达为Type(0,”[3,4]”,2+1),其中type=2+1;
元素[[3,4],5]可以表达为Type(0,”[[3,4],3]”,2+2),其中type=2+2;
如果要访问里的元素怎么办呢?要访问上面的
Type(0,”[[3,4],3]”,4);中的元素3怎么访问呢?我的解决方法就在Type里面重载operatro[]访问“[[3,4],3]”里面的元素.
Type Type::operator[](int index)//不能返回引用
{
if (type < 2)//int float and string has no operator[]
{
cout << "\tthis type has no attritute" << endl;
exit(-1);
}
if (type == 2)
{
string temp_s = "";
temp_s = "'" + val_str[index];
temp_s += "'";
Type ty = Type(0.0, temp_s, STRING);
ty.plast = &val_str;
}
//type>=3时,val_str不为空
vector<char>bracket;//括号栈,当括号栈为空时索引才加1
int i = 1;//从第一个中括号开始
bool flag = true;//判断是否有语法错误
int cur_index = -1;//当前索引
string ele = "";//记录当前的元素
int bracket_maxnum = 0;//括号层数
while (flag&&i < val_str.size() && cur_index<index)
{
char ch = val_str[i];
if (i == val_str.size() - 1)
ch = ',';
switch (ch)
{
case '[':
bracket.push_back('[');
if (bracket.size() > bracket_maxnum)
bracket_maxnum = bracket.size();
ele += '[';
break;
case ']':
if (!bracket.empty() && bracket.back() == '[')
bracket.pop_back();
else
flag = false;
ele += ']';
break;
case ',':
if (ele == "")
{
flag = false;
break;
}
if (bracket.empty())
{
cur_index++;
if (cur_index < index)
{
bracket_maxnum = 0;
ele = "";
}
}
else
ele += ',';
break;
default:
ele += ch;
break;
}
i++;
}
if (!flag)//出现语法错误
{
cout << "\terror syntax!" << endl;
exit(-1);
}
else if (cur_index == index)//找到指定索引元素
{
Type temp_t;
temp_t.plast = &val_str;
if (judgeValueType(ele) == INTEGER || judgeValueType(ele) == FLOAT)
{
stringstream ss(ele);
ss >> temp_t.value;
temp_t.type = judgeValueType(ele);
}
else if (judgeValueType(ele) == STRING)
{
//removeSymbol(ele,"\"");
//removeSymbol(ele,"'");
temp_t.val_str = ele;
temp_t.type = STRING;
}
else
{
temp_t.val_str = ele;
temp_t.type = OFFSET + bracket_maxnum;
}
return temp_t;
}
else
{
cout << "\terror index!" << endl;
exit(-1);
}
}
里面用到了judgeValueType()函数,这个函数是自己定义的判断数据类型的函数,因为Python中的数据类型要自己判断
这样:Type ty=Type(0,”[[3,4],3]”);我就能通过ty[1]来访问其中的元素3了。
接下来又有个问题,我重写的operator[]只是单纯返回了一个值,没有返回引用!就实现不了ty[1]=3;来改变值了,那怎么解决呢?
因为整个列表元素在一个字符串类型,而要改变可能要改变它的字串,改变字串的同时还要改变整个列表中对应的元素。于是我在Type类中添加了一个成员,是保存上原来Type中的val_str的指针,通过它就能有返回引用的效果了。
class Type//Python中的所有函数都用这个类型
{
private:
string *plast;//用在operator[]中达到引用的效果,指向父串的内存;是opertor[]返回则非空,否则返回空
public:
string val_str;//存放string类型
float value;//存放float和int类型
int type;
Type(float v=0,string vs="", int t=0) :value(v), type(t) {//在python中把字符串都加上‘’,在构造函数里实现
if (t == STRING)
{
vs = "'" + vs + "'";
val_str = vs;
}
plast = NULL;
}
}