lang:自制编程语言10——改进赋值

Freda ·
更新时间:2024-09-20
· 768 次阅读

前言

赋值节点的interpret接口、interpet_str接口、interpret_bool接口不是并列的关系……

这个自制编程语言的项目中,已经遇到太多的不对称的东西了,明明是相似的接口,相似的类型,但是实现却特别冗余!没办法把两个相似的函数放在一起比较,这说明一个问题,我的项目架构不好,有很多辣鸡代码!

现在来解决这个问题!

设置firstId_is_bool_flag标志

项目中的数据类型:int/number/nil/bool/string
底层数据类型:double/bool/string

项目中的Token有下面三种情况

数字、数字类型的id 字符串、字符串类型的id 布尔类型的id

之前为了将简单表达式从语句中抽离出来,就是用and , >= 之类的符号,分割简单表达式,将其作为判断式或逻辑式的单元!!!
为此引入了firstId_is_string_flag,因为要靠简单表达式开头的数据,区分简单表达式的模式,是否是字符串拼接模式!!!

a = TRUE; 这样的语句会调用到EqExpr的interpret接口,还会被当成计算式计算。也就是出现下面这张情况

a = 1 + TRUE; [result]1

所以,规定

如果表达式是简单表达式,并且第一个是bool类型的id,那么,就准备退出——此id后面如果不是分号,就报错!如果是分号就如愿退出! void Parser::CreateASTree() { //遍历全局中缀表达式 try { for (int it = start; it *funcMap[global_infix[it]->type])(it);//处理Token和keyword if (end_flag)break;//遇到分号跳出 if (firstId_is_bool_flag) {//表达式第一个id是bool类型的变量 if (global_infix[ ++ it]->type != SuatinTokenType_Sem) {//如果下一个不是分号 ThrowException(start,end,"boolean identifier cannot used for calculate"); return; } DealToken_Sem(it); break; } } if (root == NULL) ThrowException(start,end,"abstract syntax tree was none"); /* judgeRoot exprRoot logicRoot exprRoot exprRoot root 最后除了root外,其他指针都为空! */ CheckASTreeSyntax(); } catch (SuatinExcept& e) { std::cout << e.what(); } catch (...) { std::cout <name]->type == SuatinIDType_bool) { firstId_is_bool_flag = true; } } } void Parser::interpret() { try { if (m_exprType == ExprType_Simple) { //简单表达式 if (firstId_is_bool_flag) { //开头第一个是bool类型的id bool result = root == NULL ? true : root->interpret_bool(); std::cout << "[result]" << BOOL2STR(result) << std::endl; } else if (m_simpleExprType == SimpleExprType_NumCalc) { //五则计算式 ... ... 使EqExpr的三个解释接口并列

因为五则计算式中只有数字、字符串拼接式中只有字符串、开头bool或判断式或逻辑式的返回只有布尔,所以解释起来,清楚多了!
果然是自己辣鸡代码写多了!

//处理数字、数字类型的id-------------------- double EqExpr::interpret() { double rightValue = right->interpret();//递归进去 ////把右边的变量的值拷贝给左边的变量,因为是对符号表的操作,不改变指针,所以传入一级指针就好!!! //auto copyBlock = [](Expr* _left,Expr* _right) { // IDExpr* dst = dynamic_cast(_left); // IDExpr* src = dynamic_cast(_right); // CopyID(dst->GetName(), src->GetName()); //}; ////赋值右边的表达式只有单个Id //if (typeid(*(right->GetClassType())) == typeid(IDExpr)) { //右孩子只有个变量节点!!! // copyBlock(left, right); // return rightValue; //} //else if (typeid(*(right->GetClassType())) == typeid(EqExpr)) { //右孩子同样是个赋值节点!!! // SymbolExpr* node_tmp = dynamic_cast(right); // copyBlock(left, node_tmp->GetLeft()); // return rightValue; //} //赋值右边的表达式不是单个Id IDExpr* var = dynamic_cast(left); var->SetNumber(rightValue); return rightValue; } //处理字符串、字符串类型的id------------------ std::string EqExpr::interpret_str() { std::string rightValue = right->interpret_str();//递归进去 ////把右边的变量的值拷贝给左边的变量,因为是对符号表的操作,不改变指针,所以传入一级指针就好!!! //auto copyBlock = [](Expr* _left, Expr* _right) { // IDExpr* dst = dynamic_cast(_left); // IDExpr* src = dynamic_cast(_right); // CopyID(dst->GetName(), src->GetName()); //}; ////赋值右边的表达式只有单个Id //if (typeid(*(right->GetClassType())) == typeid(IDExpr)) { //右孩子只有个变量节点!!! // copyBlock(left, right); // return rightValue; //} //else if (typeid(*(right->GetClassType())) == typeid(EqExpr)) { //右孩子同样是个赋值节点!!! // SymbolExpr* node_tmp = dynamic_cast(right); // copyBlock(left, node_tmp->GetLeft()); // return rightValue; //} IDExpr* var = dynamic_cast(left); var->SetString(rightValue); return rightValue; } //bool类型的id-------------------- bool EqExpr::interpret_bool() { bool rightValue = right->interpret_bool();//递归进去 IDExpr* var = dynamic_cast(left); var->SetBool(rightValue); return rightValue; }

这样操作一番后,可以看出,开头bool、五则计算、字符串拼接这几个已经是并列的了,可以看做三个模式!

项目代码下载地址


作者:Demllie



lang 赋值 编程语言

需要 登录 后方可回复, 如果你还没有账号请 注册新账号