前言
上一篇增加了一个 assert 关键字,这一篇增加两个关键字,break,continue。有了这两个关键字后,循环就方便多了。
将assert/break/continue修改成语句
之前这个三个关键字后面是不跟分号的,但是为了语句的统一,现在修改成都加分号了。
但是assert; break; continue; 这三个【语句】不属于语句,不在语句容器中,只在语义树中!
- 每次的项目都比前面的变化一部分,但是很多变化都没写出来,所以需要用后面的文章、项目来对着前面的内容看看!!!
打印语义树
//Resolver.cpp
/*
suatin->code
>>>>>>
sum=0;
for(i=0;i<10;i=i+1)
if(i==0 or i==2 or i==4 or i==6 or (i-1+1)==8)
sum=sum+i;
else
sum=sum-1;
end
assert;
end
suatin->sematic tree
>>>>>>
block
├── [0]
└── for
├── init
│ └── [1]
├── cond
│ └── [2]
├── add
│ └── [3]
└── block
├── if
│ ├── cond
│ │ └── [4]
│ ├── block
│ │ └── [5]
│ └── last
│ └── else
│ └── block
│ └── [6]
└── assert
*/
void Resolver::print_st() {
if (semantic_tree == NULL)return;
try {
_fact_print_st(semantic_tree);//默认_num=0
}
catch (SuatinExcept& e) {
PrintException(e.what());
}
}
void Resolver::_fact_print_st(Cmd* _node, int _num) {
//返回条件
if (_node == NULL)return;
//打印分支装饰
auto print_decoration = [this](int _num) {
if (_num > 0) {
//1.打印每行前的空格和竖线
for (int i = 0; i < _num - 1; ++i) {
std::cout << ((v_forDisplaySemaTree[i] == 1) ? "│ " : " ");//1:竖线 0:空格
}
//2.打印每行终点的分叉
std::cout << ((v_forDisplaySemaTree[_num - 1] == 1) ? "├── " : "└── ");//1:T型线 0:τ型线
}
};
//语句块的迭代
auto block_iter = [this](BlockCmd* _node,int _num) {
std::cout << "block\n";
int i = 0;
for(auto it : _node->GetBlockVector()){
if (_node->GetBlockVector().size() == 1 || i + 1 == _node->GetBlockVector().size()) {
v_forDisplaySemaTree[_num] = 0; //"└── "
}
else {
v_forDisplaySemaTree[_num] = 1;// "├── "
}
_fact_print_st(it, 1 + _num);
v_forDisplaySemaTree[_num] = 0;
++i;
}
};
print_decoration(_num);
//打印节点
if (_node->GetClassType() == SuatinCmdClassType_SingleCmd) {
SingleCmd* tmp = dynamic_cast<SingleCmd*>(_node);
std::cout << "["<<tmp->GetIndex()<<"]\n";
}
else if (_node->GetClassType() == SuatinCmdClassType_BlockCmd) {
BlockCmd* tmp = dynamic_cast<BlockCmd*>(_node);
block_iter(tmp,_num);
}
else if (_node->GetClassType() == SuatinCmdClassType_IfCmd) {
IfCmd* tmp = dynamic_cast<IfCmd*>(_node);
std::cout << "if\n";
//if_cond
v_forDisplaySemaTree[_num] = 1;// "├── "
print_decoration(1 + _num);
std::cout << "cond\n";
v_forDisplaySemaTree[1 + _num] = 0;//"└── "
_fact_print_st(tmp->GetCondition(), 2 + _num);//condition只有一句话
if (tmp->last != NULL) {
//if_block
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
//if_last
v_forDisplaySemaTree[ _num] = 0; //"└── "
print_decoration(1 + _num);
std::cout << "last\n";
v_forDisplaySemaTree[1 + _num] = 0; //"└── "
_fact_print_st(tmp->last, 2 + _num);
v_forDisplaySemaTree[1 + _num] = 0;
}
else {
//if_block
v_forDisplaySemaTree[_num] = 0; //"└── "
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
}
}
else if (_node->GetClassType() == SuatinCmdClassType_ElifCmd) {
ElifCmd* tmp = dynamic_cast<ElifCmd*>(_node);
std::cout << "elif\n";
//elif_cond
v_forDisplaySemaTree[_num] = 1;// "├── "
print_decoration(1 + _num);
std::cout << "cond\n";
v_forDisplaySemaTree[1 + _num] = 0;//"└── "
_fact_print_st(tmp->GetCondition(), 2 + _num);//condition只有一句话
if (tmp->last != NULL) {
//elif_block
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
//elif_last
v_forDisplaySemaTree[ _num] = 0; //"└── "
print_decoration(1 + _num);
std::cout << "last\n";
v_forDisplaySemaTree[1 + _num] = 0; //"└── "
_fact_print_st(tmp->last, 2 + _num);
v_forDisplaySemaTree[1 + _num] = 0;
}
else {
//elif_block
v_forDisplaySemaTree[_num] = 0; //"└── "
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
}
}
else if (_node->GetClassType() == SuatinCmdClassType_ElseCmd) {
ElseCmd* tmp = dynamic_cast<ElseCmd*>(_node);
std::cout << "else\n";
//else_block
v_forDisplaySemaTree[_num] = 0; //"└── "
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
}
else if (_node->GetClassType() == SuatinCmdClassType_WhileCmd) {
WhileCmd* tmp = dynamic_cast<WhileCmd*>(_node);
std::cout << "while\n";
//while_cond
v_forDisplaySemaTree[_num] = 1;// "├── "
print_decoration(1 + _num );
std::cout << "cond\n";
v_forDisplaySemaTree[1 + _num] = 0;//"└── "
_fact_print_st(tmp->GetCondition(), 2 + _num);//condition只有一句话
//while_block
v_forDisplaySemaTree[_num] = 0; //"└── "
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
}
else if (_node->GetClassType() == SuatinCmdClassType_DoUntilCmd) {
DoUntilCmd* tmp = dynamic_cast<DoUntilCmd*>(_node);
std::cout << "do-until\n";
//do_until_block
v_forDisplaySemaTree[_num] = 1;// "├── "
print_decoration(1 + _num);
block_iter(tmp, _num + 1);
//do_until_cond
v_forDisplaySemaTree[_num] = 0; //"└── "
print_decoration(1 + _num);
std::cout << "cond\n";
v_forDisplaySemaTree[1 + _num] = 0;//"└── "
_fact_print_st(tmp->GetCondition(), 2 + _num);//condition只有一句话
}
else if (_node->GetClassType() == SuatinCmdClassType_ForCmd) {
ForCmd* tmp = dynamic_cast<ForCmd*>(_node);
std::cout << "for\n";
//for_init
v_forDisplaySemaTree[_num] = 1;// "├── "
print_decoration(1 + _num);
std::cout << "init\n";
v_forDisplaySemaTree[1 + _num] = 0;//"└── "
_fact_print_st(tmp->GetInit(), 2 + _num);//init只有一句话
//for_cond
print_decoration(1 + _num);
std::cout << "cond\n";
_fact_print_st(tmp->GetCondition(), 2 + _num);//condition只有一句话
//for_add
print_decoration(1 + _num);
std::cout << "add\n";
_fact_print_st(tmp->GetAdd(), 2 + _num);//add只有一句话
//for_block
v_forDisplaySemaTree[_num] = 0;//"└── "
print_decoration(1 + _num);
block_iter(tmp, _num+1);
}
else if (_node->GetClassType() == SuatinCmdClassType_AssertCmd) {
AssertCmd* tmp = dynamic_cast<AssertCmd*>(_node);
std::cout << "assert\n";
}
else if (_node->GetClassType() == SuatinCmdClassType_BreakCmd) {
BreakCmd* tmp = dynamic_cast<BreakCmd*>(_node);
std::cout << "break\n";
}
else if (_node->GetClassType() == SuatinCmdClassType_ContinueCmd) {
ContinueCmd* tmp = dynamic_cast<ContinueCmd*>(_node);
std::cout << "continue\n";
}
}
break&continue
上一篇调试机制中加入的 assert 很简单,只要创建一个AssertCmd节点,并把这个节点加入semantic_tree 或者,加入v_UnCompletedBlock 栈栈顶节点的block当中!!!
但是,我经过一个小时研究了一下,我发现这件事情并不简单,我有意向创建一个新的机制,有助于break和continue关键字或其他关键字,对循环节点的控制(狗头)
实现break,continue要注意的问题
- break&continue关键字只能放在循环的语句块下面,可以是循环节点的语句块的语句块下面,也可以的其语句块下的语句块下面
- break&continue关键字作用于最近的循环
- 解释break关键字时,将跳出本次循环——即最近的循环节点
- 解释continue关键字时,将跳出本次循环的BlockCmd::interpret,不会马上跳出本次循环
suatin语言的伪代码
while(?)
if(?)
do
if(?)
break
end
until(?)
end
end
suatin语义树
semantic_tree
-block
-while
-block
-if
-block
-do-until
-block
-if
-block
-break
break会退出最近的循环,就是退出do-until,但是不会退出外面的while,
这个信息会传递给最近的循环,通知其该采取别的解释顺序。
并且信息在使用后就失活了!!!不会传递给高一层的循环。
但是。。。。除了退出do-until外,break要先退出if,然后再退出do-until。。。。。
信号跳转机制
为语句块增加了一个属性jumpWhat,一个跳转信息枚举。当语句块解释的某条语句是break;或者continue;时,会设置这个属性为对应的信息,并退出当前语句块。
如果是if-elif-else链条,无论是链条上哪个块执行了(并且其中有一个break;或者continue;),都会把信息向上传递至if节点,
所以在解释语句块时,除了遇到break;或者continue;外,如果遇到了if节点,也要判断该节点的跳转信息!
//Cmd.cpp
void BlockCmd::interpret() {
for (std::vector<Cmd*>::iterator it = block.begin(); it != block.end(); ++it) {
//1.先解释
(*it)->interpret();
//2.语句块中出现break/continue节点
if ((*it)->GetClassType() == SuatinCmdClassType_BreakCmd) {
jumpWhat = SuatinJumpSignalType_Break;
return;
}
else if ((*it)->GetClassType() == SuatinCmdClassType_ContinueCmd) {
jumpWhat = SuatinJumpSignalType_Continue;
return;
}
//3.语句块中的if-elif-else链条中出现break/continue信号
if ((*it)->GetClassType() == SuatinCmdClassType_IfCmd) {
IfCmd* tmp = dynamic_cast<IfCmd*>(*it);
if (tmp->GetJumpSignal() == SuatinJumpSignalType_Break) {
jumpWhat = SuatinJumpSignalType_Break;
return;
}
else if (tmp->GetJumpSignal() == SuatinJumpSignalType_Continue) {
jumpWhat = SuatinJumpSignalType_Continue;
return;
}
}
}
}
void IfCmd::interpret() {
//if
if (IsTrue()) {
BlockCmd::interpret();
if (jumpWhat == SuatinJumpSignalType_Break || jumpWhat == SuatinJumpSignalType_Continue)return;
}
else {
//elif or else
if (last) {
last->interpret();
//将if-elif-else链条下的跳转信息传递上来
BlockCmd* tmp = dynamic_cast<BlockCmd*>(last);
jumpWhat = tmp->GetJumpSignal();
}
}
}
void WhileCmd::interpret() {
while (IsTrue()) {
BlockCmd::interpret();
if (jumpWhat == SuatinJumpSignalType_Break) {
jumpWhat = SuatinJumpSignalType_None;
return;
}
}
}
...
解释器的类
项目案例
//main.suatin
sum=7;
while(sum>0)
if(sum==2)
continue;
end
sum=sum-1;
end
[0]普通语句>sum=7;
[1]括号内语句>sum>0
[2]括号内语句>sum==2
[2]普通语句>continue;
[3]普通语句>sum=sum-1;
[0][result]7
[1][result]true
[2][result]false
[3][result]6
[1][result]true
[2][result]false
[3][result]5
[1][result]true
[2][result]false
[3][result]4
[1][result]true
[2][result]false
[3][result]3
[1][result]true
[2][result]false
[3][result]2
[1][result]true
[2][result]true
[1][result]true
[2][result]true
[1][result]true
[2][result]true
[1][result]true
...
...
...
项目代码地址CSDN
https://download.csdn.net/download/weixin_41374099/12273513
项目代码地址BDWP
链接:https://pan.baidu.com/s/1mmAfefo4LzKWOpDQx-rSHg
提取码:ko39