lang:自制編程語言15——break&continue

前言

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章