做商务网站要多少钱制作网站要找什么公司
初级代码游戏的专栏介绍与文章目录-CSDN博客
我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
系列入口:
编程实战:类C语法的编译型脚本解释器(系列)-CSDN博客
本文介绍语句,主要是控制语句,if、else、for之类。
目录
一、语句概览
二、CheckSentence
三、ExecSentence
一、语句概览
//语句//EXPRESSION RETURN:expressions[0]//BLOCK:senetnces//IF:if(expressions[0])sentences[0] else sentences[1]//FOR:for(expressions[0];expressions[1];expressions[2])sentences[0]//DO:do sentences[0] while(expressions[0]);//WHILE:while(expressions[0])sentences[0]struct Sentence{enum types { NULLSENTENCE = 0, DECLARE, EXPRESSION, BLOCK, RETURN, IF, FOR, BREAK, CONTINUE, DO, WHILE };types type;size_t source_start;//起始位置size_t source_end;//结束位置vector<Expression > expressions;vector<Sentence > sentences;Sentence() { clear(); }void clear(){type = NULLSENTENCE;source_start = 0;source_end = 0;expressions.clear();sentences.clear();}bool isLoop()const { return FOR == type || DO == type || WHILE == type; }//inloop=true表示处于循环体内,可能从上层带入bool CheckSentence(string& source, T_VARIABLE_S& vars, bool _inloop);//若为return语句则设置bFinishbool ExecSentence(CZBScript const& script, T_VARIABLE_S& vars, bool& bFinish, bool& bBreak, bool& bContinue, Variable& ret, void* pe)const;string ToString(string const& source, T_VARIABLE_S const& vars, long level = 0)const;
};
语句比表达式简单多了。语句的类型更容易理解,大部分语句类型都是控制语句,有特殊的关键字对应,其余几个需要特别理解:
- 声明语句 声明并定义变量
- 表达式语句 整个语句就是一个表达式
- 块语句 就是用大括号包裹的一组语句
从表达式和语句的分析可以看出来,语言结构就是一系列递归。
语句对象除了类型和辅助调试的开始位置、结束位置外,只有子语句和表达式两个成员变量。块语句包含一组语句,for语句则包含三个表达式和一个语句:
//for语句的逻辑结构
for(表达式1;表达式2;表达式3)语句
for语句的第二个表达式的结果必须是逻辑值。
if语句则包含一个逻辑表达式和一个或两个子语句:
if(逻辑表达式)语句;
或者:
if(逻辑表达式)语句1;else 语句2;
单语句和大括号困扰了很多人,C语法中所有控制结构都是基于“语句”的,也就是单语句,为了多塞几个语句,就要用大括号括起来,变成块语句、复合语句或者别的叫法,总之就是可以当成一个“语句”的东西。
二、CheckSentence
编译后检查语法:
//inloop=true表示处于循环体内,可能从上层带入bool CheckSentence(string& source, T_VARIABLE_S& vars, bool _inloop){bool inloop = (_inloop || isLoop());size_t i;if (FOR == type){vars.PushLevel();//只有for语句的表达式可以定义变量if (sentences.size() != 2)CException::Throw(__FILE__, __LINE__, source, source_start, "for语句子语句必须有2个");if (!sentences[0].CheckSentence(source, vars, inloop))return false;}for (i = 0; i < expressions.size(); ++i){set<string > setpp;if (!expressions[i].CheckExpression(source, vars, 0, setpp))return false;}switch (type){case NULLSENTENCE:if (expressions.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "空语句不能有表达式");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "空语句不能有子语句");break;case DECLARE:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "变量定义语句有且只能有一个表达式");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "变量定义语句语句不能有子语句");if (expressions[0].type != Expression::DEFINE)CException::Throw(__FILE__, __LINE__, source, source_start, "变量定义语句表达式必须是DEFINE类型");if (0 == expressions[0].VariableName.size())CException::Throw(__FILE__, __LINE__, source, source_start, "变量定义语句表达式必须有变量名");break;case EXPRESSION:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "简单语句表达式只能有一个");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "简单语句不能有子语句");break;case BLOCK:if (expressions.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "块语句不能有表达式");break;case RETURN:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "return语句表达式只能有一个");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "return语句不能有子语句");break;case IF:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "if语句表达式只能有一个");if (sentences.size() != 1 && sentences.size() != 2)CException::Throw(__FILE__, __LINE__, source, source_start, "if语句子语句只能有1或2个");if (expressions[0].result_type != Variable::LONG && expressions[0].result_type != Variable::DOUBLE)CException::Throw(__FILE__, __LINE__, source, source_start, "if语句判断表达式必须是数值类型");break;case DO:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "do语句表达式只能有一个");if (sentences.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "do语句子语句只能有1个");if (expressions[0].result_type != Variable::LONG && expressions[0].result_type != Variable::DOUBLE)CException::Throw(__FILE__, __LINE__, source, source_start, "do语句判断表达式必须是数值类型");break;case WHILE:if (expressions.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "while语句表达式只能有一个");if (sentences.size() != 1)CException::Throw(__FILE__, __LINE__, source, source_start, "while语句子语句只能有1个");if (expressions[0].result_type != Variable::LONG && expressions[0].result_type != Variable::DOUBLE)CSException::Throw(__FILE__, __LINE__, source, source_start, "while语句判断表达式必须是数值类型");break;case FOR:if (expressions.size() != 2)CException::Throw(__FILE__, __LINE__, source, source_start, "for语句表达式必须有2个");if (sentences.size() != 2)CException::Throw(__FILE__, __LINE__, source, source_start, "for语句子语句必须有2个");if (expressions[1].result_type != Variable::LONG && expressions[1].result_type != Variable::DOUBLE)CException::Throw(__FILE__, __LINE__, source, source_start, "for语句判断表达式必须是数值类型");break;case BREAK:if (expressions.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "break语句不能有表达式");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "break语句不能有子语句");break;case CONTINUE:if (expressions.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "break语句不能有表达式");if (sentences.size() != 0)CException::Throw(__FILE__, __LINE__, source, source_start, "break语句不能有子语句");break;default:CException::Throw(__FILE__, __LINE__, source, source_start, "暂不支持");return false;break;}if (BLOCK == type)vars.PushLevel();for (i = 0; i < sentences.size(); ++i){if (BLOCK != type)vars.PushLevel();//每个子语句都是一个层次,if有1或2个子语句,do\while\for有1个子语句(for的第一个语句已经提前检查)if ((FOR == type && 0 != i) || FOR != type)if (!sentences[i].CheckSentence(source, vars, inloop))return false;if (!inloop){if (BREAK == sentences[i].type)CException::Throw(__FILE__, __LINE__, source, source_start, "非期待的break语句");if (CONTINUE == sentences[i].type)CException::Throw(__FILE__, __LINE__, source, source_start, "非期待的continue语句");}if (BLOCK != type)vars.PopLevel();}if (BLOCK == type)vars.PopLevel();if (FOR == type)vars.PopLevel();return true;}
基本上就是针对每种类型检查特定的要求,然后递归对每个表达式和子语句做检查。检查每种类型对应的表达式和语句是否存在,检查break和continue是否出现在了非循环结构中。
部分语句类型导致新的变量层级,因此要在开始时调用vars.PushLevel()并在最后调用vars.PopLevel()。 PopLevel()将丢弃变量表的最后一级。
for循环的整体是一个层级,循环体又是一个层级。块语句整体是一个层级。
客观地讲,语句比表达式简单多了。
三、ExecSentence
执行语句:
//若为return语句则设置bFinishbool ExecSentence(CScript const& script, T_VARIABLE_S& vars, bool& bFinish, bool& bBreak, bool& bContinue, Variable& ret, void* pe)const{size_t i;if (bFinish)return true;if (bBreak)return true;if (bContinue)return true;ret.type = Variable::NULLVARIABLE;switch (type){case NULLSENTENCE:ret.type = Variable::NULLVARIABLE;break;case DECLARE:expressions[0].ExecExpression(script, vars, ret, pe);break;case EXPRESSION:expressions[0].ExecExpression(script, vars, ret, pe);break;case BLOCK:vars.PushLevel();for (i = 0; i < sentences.size(); ++i){sentences[i].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);if (bFinish)break;if (bBreak)break;if (bContinue)break;}vars.PopLevel();break;case RETURN:expressions[0].ExecExpression(script, vars, ret, pe);bFinish = true;break;case IF:expressions[0].ExecExpression(script, vars, ret, pe);vars.PushLevel();if (ret.GetBool()){sentences[0].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);}else{if (sentences.size() >= 2)sentences[1].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);else ret.type = Variable::NULLVARIABLE;}vars.PopLevel();break;case FOR:vars.PushLevel();sentences[0].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);while (true){expressions[0].ExecExpression(script, vars, ret, pe);if (!ret.GetBool())break;vars.PushLevel();sentences[1].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);vars.PopLevel();if (bFinish)break;if (bBreak){bBreak = false;break;}if (bContinue)bContinue = false;expressions[1].ExecExpression(script, vars, ret, pe);}vars.PopLevel();//ret.type=Variable::NULLVARIABLE;break;case DO:while (true){vars.PushLevel();sentences[0].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);vars.PopLevel();if (bFinish)break;if (bBreak){bBreak = false;break;}if (bContinue)bContinue = false;expressions[0].ExecExpression(script, vars, ret, pe);if (!ret.GetBool())break;}//ret.type=Variable::NULLVARIABLE;break;case WHILE:while (true){expressions[0].ExecExpression(script, vars, ret, pe);if (!ret.GetBool())break;vars.PushLevel();sentences[0].ExecSentence(script, vars, bFinish, bBreak, bContinue, ret, pe);vars.PopLevel();if (bFinish)break;if (bBreak){bBreak = false;break;}if (bContinue)bContinue = false;}//ret.type=Variable::NULLVARIABLE;break;case BREAK:bBreak = true;break;case CONTINUE:bContinue = true;break;default:script.ThrowN(__FILE__, __LINE__, "暂不支持的语句类型", type);return false;break;}return true;}
第一个参数script仅仅是用来在出错时报错。其余参数提供当前变量表并返回程序流程状态。语句没有返回值,这是语句和表达式的关键区别——尽管一个语句可能仅仅包含一个表达式。
执行和检查以同样的规则处理变量层级(变量生存期)。
(这里是结束,但不是整个系列的结束)