前言
上一篇增加了一個 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