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

猜你喜欢

转载自blog.csdn.net/weixin_41374099/article/details/104971906