view boost-spirit/Compiler-boost-spirit/EUC/node.cpp @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
line wrap: on
line source

#include "stdafx.h"
#include <iostream>
#include "node.h"
#include "compiler.h"

// 変数ノードを生成
cnode_t cnode::make_node(int op, const std::string &str)
{
	if (op == OP_IDENTIFIER)
		return cnode_t(new cvalue_node(str));

	if (op == OP_STRING) {
		size_t pos = str.rfind('\"');
		if (pos != std::string::npos)
			return cnode_t(new cnode(op, str.substr(0, pos)));
	}
	return cnode_t(new cnode(op, str));
}

// 単項演算子のノードを生成
cnode_t cnode::make_node(int op, cnode_t left)
{
	switch (op) {
	  case OP_NEG:
		if (left->op_ == OP_NUMBER) {			// 定数演算を計算する
			left->number_ = -left->number_;
			return left;
		}
		break;
	}
	return cnode_t(new cnode(op, left));
}

// 二項演算子のノードを生成
cnode_t cnode::make_node(int op, cnode_t left, cnode_t right)
{
	// 配列ノードは、leftノードのleft_メンバに加える
	if (op == OP_ARRAY) {
		left->left_ = right;
		return left;
	}

	// 定数演算を計算する
	if (left->op_ == OP_NUMBER && right->op_ == OP_NUMBER) {
		switch (op) {
		  case OP_LOGAND:
			left->number_ = (left->number_ && right->number_)? 1: 0;
			break;

		  case OP_LOGOR:
			left->number_ = (left->number_ || right->number_)? 1: 0;
			break;

		  case OP_EQ:
			left->number_ = (left->number_ == right->number_)? 1: 0;
			break;

		  case OP_NE:
			left->number_ = (left->number_ != right->number_)? 1: 0;
			break;

		  case OP_GT:
			left->number_ = (left->number_ > right->number_)? 1: 0;
			break;

		  case OP_GE:
			left->number_ = (left->number_ >= right->number_)? 1: 0;
			break;

		  case OP_LT:
			left->number_ = (left->number_ < right->number_)? 1: 0;
			break;

		  case OP_LE:
			left->number_ = (left->number_ <= right->number_)? 1: 0;
			break;

		  case OP_AND:
			left->number_ &= right->number_;
			break;

		  case OP_OR:
			left->number_ |= right->number_;
			break;

		  case OP_LSHIFT:
			left->number_ <<= right->number_;
			break;

		  case OP_RSHIFT:
			left->number_ >>= right->number_;
			break;

		  case OP_SUB:
			left->number_ -= right->number_;
			break;

		  case OP_ADD:
			left->number_ += right->number_;
			break;

		  case OP_MUL:
			left->number_ *= right->number_;
			break;

		  case OP_DIV:
			if (right->number_ == 0) {
				std::cerr << "定数計算を0で除算しました。" << std::endl;
			}
			else {
				left->number_ /= right->number_;
			}
			break;

		  case OP_MOD:
			if (right->number_ == 0) {
				std::cerr << "定数計算を0で除算しました。" << std::endl;
			}
			else {
				left->number_ %= right->number_;
			}
			break;

		  default:
			return cnode_t(new cnode(op, left, right));
		}
		return left;
	}

	// 文字列同士の定数計算
	if (left->op_ == OP_STRING && right->op_ == OP_STRING) {
		if (op == OP_ADD) {
			left->string_ += right->string_;
			return left;
		}

		int value = 0;
		switch (op) {
		  case OP_EQ:
			if (left->string_ == right->string_)
				value = 1;
			break;

		  case OP_NE:
			if (left->string_ != right->string_)
				value = 1;
			break;

		  case OP_GT:
			if (left->string_ > right->string_)
				value = 1;
			break;

		  case OP_GE:
			if (left->string_ >= right->string_)
				value = 1;
			break;

		  case OP_LT:
			if (left->string_ < right->string_)
				value = 1;
			break;

		  case OP_LE:
			if (left->string_ <= right->string_)
				value = 1;
			break;

		  default:
			std::cerr << "文字列同士ではできない計算です。" << std::endl;
			break;
		}
		return cnode_t(new cnode(OP_NUMBER, value));
	}
	return cnode_t(new cnode(op, left, right));
}

// 関数ノードの生成
cnode_t cnode::make_node(int op, cnode_t left, cnode_list_t right)
{
	return cnode_t(new cfunction_node(op, left, right));
}

// ノードのpush処理
int cnode::push(compiler *c) const
{
	switch (op_) {
	  case OP_NEG:
		if (left_->push(c) == TYPE_STRING)
			c->error("文字列には許されない計算です。");
		c->OpNeg();
		return TYPE_INTEGER;

	  case OP_NUMBER:
		c->PushConst(number_);
		return TYPE_INTEGER;

	  case OP_STRING:
		c->PushString(string_);
		return TYPE_STRING;

	  case OP_FUNCTION:
		return call(c, string_, NULL);
	}

	int left_type = left_->push(c);
	int right_type = right_->push(c);

	if (left_type != right_type)
		c->error("文字列と整数間で計算できません。");

	// 整数計算ノードの処理
	if (left_type == TYPE_INTEGER) {
		switch (op_) {
		  case OP_LOGAND:
			c->OpLogAnd();
			break;

		  case OP_LOGOR:
			c->OpLogOr();
			break;

		  case OP_EQ:
			c->OpEq();
			break;

		  case OP_NE:
			c->OpNe();
			break;

		  case OP_GT:
			c->OpGt();
			break;

		  case OP_GE:
			c->OpGe();
			break;

		  case OP_LT:
			c->OpLt();
			break;

		  case OP_LE:
			c->OpLe();
			break;

		  case OP_AND:
			c->OpAnd();
			break;

		  case OP_OR:
			c->OpOr();
			break;

		  case OP_LSHIFT:
			c->OpLeftShift();
			break;

		  case OP_RSHIFT:
			c->OpRightShift();
			break;

		  case OP_SUB:
			c->OpSub();
			break;

		  case OP_ADD:
			c->OpAdd();
			break;

		  case OP_MUL:
			c->OpMul();
			break;

		  case OP_DIV:
			c->OpDiv();
			break;

		  case OP_MOD:
			c->OpMod();
			break;

		  default:
			c->error("内部エラー:処理できない計算ノードがありました。");
			break;
		}
		return TYPE_INTEGER;
	}

	// 文字列計算ノードの処理
	switch (op_) {
	  case OP_EQ:
		c->OpStrEq();
		return TYPE_INTEGER;

	  case OP_NE:
		c->OpStrNe();
		return TYPE_INTEGER;

	  case OP_GT:
		c->OpStrGt();
		return TYPE_INTEGER;

	  case OP_GE:
		c->OpStrGe();
		return TYPE_INTEGER;

	  case OP_LT:
		c->OpStrLt();
		return TYPE_INTEGER;

	  case OP_LE:
		c->OpStrLe();
		return TYPE_INTEGER;

	  case OP_ADD:
		c->OpStrAdd();
		break;

	  default:
		c->error("文字列では計算できない式です。");
		break;
	}
	return TYPE_STRING;
}

// ノードのpop
// 計算ノードはpopできない

int cnode::pop(compiler *c) const
{
	c->error("内部エラー:計算ノードをpopしています。");
	return TYPE_INTEGER;
}

// 代入文

void cnode::assign(compiler *c) const
{
	if (op_ != OP_ASSIGN)
		left_->push(c);

	if (right_->push(c) == TYPE_INTEGER) {
		switch (op_) {
		  case OP_ADD_ASSIGN:
			c->OpAdd();
			break;

		  case OP_SUB_ASSIGN:
			c->OpSub();
			break;

		  case OP_MUL_ASSIGN:
			c->OpMul();
			break;

		  case OP_DIV_ASSIGN:
			c->OpDiv();
			break;

		  case OP_MOD_ASSIGN:
			c->OpMod();
			break;

		  case OP_AND_ASSIGN:
			c->OpAnd();
			break;

		  case OP_OR_ASSIGN:
			c->OpOr();
			break;

		  case OP_LSHIFT_ASSIGN:
			c->OpLeftShift();
			break;

		  case OP_RSHIFT_ASSIGN:
			c->OpRightShift();
			break;
		}
		if (left_->pop(c) != TYPE_INTEGER)
			c->error("文字列型に整数を代入しています。");
		return;
	}

	switch (op_) {
	  case OP_ADD_ASSIGN:
		c->OpStrAdd();
		break;

	  case OP_ASSIGN:
		break;

	  default:
		c->error("文字列では許されない計算です。");
		break;
	}
	if (left_->pop(c) != TYPE_STRING)
		c->error("整数型に文字列を代入しています。");
}

// 変数ノードのpush
int cvalue_node::push(compiler *c) const
{
	if (op_ != OP_IDENTIFIER) {
		c->error("内部エラー:変数ノードに変数以外が登録されています。");
	}
	else {
		const CValueTag *tag = c->GetValueTag(string_);
		if (tag == 0) {
			c->error("変数 " + string_ + " は定義されていません。");
		}
		else {
			// 参照型変数は、引数にしか存在しない
			if ((tag->type_ & TYPE_REF) != 0) {
				if (left_) {		// 配列
					left_->push(c);
					c->PushLocalArrayRef(tag->addr_);
				}
				else {
					c->PushLocalRef(tag->addr_);
				}
				return tag->type_ & ~TYPE_REF;
			}
			if (tag->global_) {		// 外部変数
				if (left_) {		// 配列
					left_->push(c);
					c->PushArray(tag->addr_);
				}
				else {
					c->PushValue(tag->addr_);
				}
			}
			else {					// ローカル変数
				if (left_) {		// 配列
					left_->push(c);
					c->PushLocalArray(tag->addr_);
				}
				else {
					c->PushLocal(tag->addr_);
				}
			}
			return tag->type_;
		}
	}
	return TYPE_INTEGER;
}

// 変数ノードのpop
int cvalue_node::pop(compiler *c) const
{
	if (op_ != OP_IDENTIFIER) {
		c->error("内部エラー:変数ノードに変数以外が登録されています。");
	}
	else {
		const CValueTag *tag = c->GetValueTag(string_);
		if (tag == 0) {
			c->error("変数 " + string_ + " は定義されていません。");
		}
		else {
			// 参照型変数は、引数にしか存在しない
			if ((tag->type_ & TYPE_REF) != 0) {
				if (left_) {		// 配列
					left_->push(c);
					c->PopLocalArrayRef(tag->addr_);
				}
				else {
					c->PopLocalRef(tag->addr_);
				}
				return tag->type_ & ~TYPE_REF;
			}
			if (tag->global_) {		// 外部変数
				if (left_) {		// 配列
					left_->push(c);
					c->PopArray(tag->addr_);
				}
				else {
					c->PopValue(tag->addr_);
				}
			}
			else {					// ローカル変数
				if (left_) {		// 配列
					left_->push(c);
					c->PopLocalArray(tag->addr_);
				}
				else {
					c->PopLocal(tag->addr_);
				}
			}
			return tag->type_;
		}
	}
	return TYPE_INTEGER;
}

// 関数呼び出し
struct set_arg {
	compiler *comp_;
	const CFunctionTag *func_;
	mutable int index_;
	set_arg(compiler *comp, const CFunctionTag *func): comp_(comp), func_(func), index_(0)
	{
	}

	void operator()(cnode_t node) const
	{
		int type = func_->GetArg(index_++);
		if ((type & TYPE_REF) != 0) {		// 参照
			if (node->op() != OP_IDENTIFIER) {
				comp_->error("参照型引数に、変数以外は指定できません。");
			}
			else {
				const CValueTag *tag = comp_->GetValueTag(node->string());
				if (tag == 0) {
					comp_->error("変数 " + node->string() + " は定義されていません。");
				}
				else if (tag->type_ >= TYPE_INTEGER_REF) {		// 参照
					// 参照型変数は、ローカルしかない
					if (node->left()) {
						node->left()->push(comp_);
						comp_->PushLocal(tag->addr_);
						comp_->OpAdd();
					}
					else {
						comp_->PushLocal(tag->addr_);
					}
				}
				else {
					if ((tag->type_ | TYPE_REF) != type) {
						comp_->error("引数の型が合いません。");
					}
					int addr = tag->addr_;
					if (tag->global_)			// 外部変数
						addr |= vm::vcpu::global_flag;
					// アドレスをpush
					if (node->left()) {			// 配列
						if (node->left()->op() == OP_NUMBER) {
							comp_->PushAddr(addr + node->left()->number());
						}
						else {
							node->left()->push(comp_);
							comp_->PushArrayAddr(addr);
						}
					}
					else {
						comp_->PushAddr(addr);
					}
				}
			}
		}
		else {
			if (node->push(comp_) != type) {
				comp_->error("引数の型が合いません。");
			}
		}
	}
} ;

// 関数呼び出し
int cnode::call(compiler *c, const std::string &name, const std::vector<cnode_t> *args) const
{
	const CFunctionTag *tag = c->GetFunctionTag(name);
	if (tag == NULL) {
		c->error("関数 " + name + "は、定義されていません。");
		return TYPE_INTEGER;
	}

	int arg_size = (args)? (int)args->size(): 0;
	if (tag->ArgSize() != arg_size) {
		c->error("引数の数が合いません。");
	}

	// 引数をpush
	if (args && tag->ArgSize() == arg_size) {
		std::for_each(args->begin(), args->end(), set_arg(c, tag));
	}

	// 引数の数をpush
	c->PushConst(arg_size);

	if (tag->IsSystem()) {
		c->OpSysCall(tag->GetIndex());		// システムコール
	}
	else {
		c->OpCall(tag->GetIndex());			// スクリプト上の関数
	}

	return tag->type_;
}

int cfunction_node::push(compiler *c) const
{
	return call(c, left_->string(), &node_list_->args_);
}

// 関数にpopはできないのでエラーメッセージを出す
int cfunction_node::pop(compiler *c) const
{
	c->error("内部エラー:関数ノードをpopした");
	return TYPE_INTEGER;
}

// 文ノード生成
cstatement_t cstatement::make_statement(int state)
{
	switch (state) {
	case NOP_STATE:
		return cstatement_t(new cnop_statement());

	case DEFAULT_STATE:
		return cstatement_t(new cdefault_statement());

	case BREAK_STATE:
		return cstatement_t(new cbreak_statement());

	case RETURN_STATE:
		return cstatement_t(new creturn_statement());

	case IF_STATE:
		return cstatement_t(new cif_statement());

	case FOR_STATE:
		return cstatement_t(new cfor_statement());

	case WHILE_STATE:
		return cstatement_t(new cwhile_statement());
	}

	std::cerr << "内部エラー:文ノードミス" << std::endl;
	return cstatement_t(new cnop_statement());
}

cstatement_t cstatement::make_statement(int state, cnode_t node)
{
	switch (state) {
	case ASSIGN_STATE:
		return cstatement_t(new cassign_statement(node));

	case CASE_STATE:
		return cstatement_t(new ccase_statement(node));

	case SWITCH_STATE:
		return cstatement_t(new cswitch_statement(node));

	case CALL_STATE:
		return cstatement_t(new ccall_statement(node));
	}

	std::cerr << "内部エラー:文ノードミス" << std::endl;
	return cstatement_t(new cnop_statement());
}

cstatement_t cstatement::make_statement(int state, cblock_t block)
{
	switch (state) {
	case BLOCK_STATE:
		return cstatement_t(new cblock_statement(block));
	}

	std::cerr << "内部エラー:文ノードミス" << std::endl;
	return cstatement_t(new cnop_statement());
}

// nop文
void cnop_statement::analyze(compiler *c) const
{
}

// 代入文
void cassign_statement::analyze(compiler *c) const
{
	node_->assign(c);
}

// 関数呼び出し文
void ccall_statement::analyze(compiler *c) const
{
	int type = node_->push(c);
	if (type != TYPE_VOID)
		c->OpPop();			// 戻り値を捨てるためのpop
}

// case文
void ccase_statement::analyze(compiler *c) const
{
	c->SetLabel(label_);
}

// case文の前処理
void ccase_statement::case_analyze(compiler *c, int *default_label)
{
	label_ = c->MakeLabel();
	if (node_->op() != OP_NUMBER)
		c->error("case 文には定数のみ指定できます。");
	node_->push(c);
	c->OpTest(label_);
}

// default文
void cdefault_statement::analyze(compiler *c) const
{
	c->SetLabel(label_);
}

// default文の前処理
void cdefault_statement::case_analyze(compiler *c, int *default_label)
{
	label_ = c->MakeLabel();
	*default_label = label_;
}

// break文
void cbreak_statement::analyze(compiler *c) const
{
	if (!c->JmpBreakLabel()) {
		c->error("breakがswitch/for/while外に有ります");
	}
}

// return文
void creturn_statement::analyze(compiler *c) const
{
	if (c->GetFunctionType() == TYPE_VOID) {	// 戻り値無し
		if (node_ != 0) {
			c->error("void関数に戻り値が設定されています");
		}
		c->OpReturn();
	}
	else {
		if (node_ == 0) {
			c->error("関数の戻り値がありません");
		}
		else {
			int node_type = node_->push(c);		// 戻り値をpush
			if (node_type != c->GetFunctionType()) {
				c->error("戻り値の型が合いません");
			}
		}
		c->OpReturnV();
	}
}

// if文
void cif_statement::analyze(compiler *c) const
{
	node_->push(c);
	int label1 = c->MakeLabel();
	c->OpJmpNC(label1);
	statement_[0]->analyze(c);

	if (statement_[1]) {
		int label2 = c->MakeLabel();
		c->OpJmp(label2);
		c->SetLabel(label1);
		statement_[1]->analyze(c);
		c->SetLabel(label2);
	}
	else {
		c->SetLabel(label1);
	}
}

// for文
void cfor_statement::analyze(compiler *c) const
{
	int label1 = c->MakeLabel();
	int label2 = c->MakeLabel();

	int break_label = c->SetBreakLabel(label2);

	node_[0]->assign(c);
	c->SetLabel(label1);
	node_[1]->push(c);
	c->OpJmpNC(label2);
	statement_->analyze(c);
	node_[2]->assign(c);
	c->OpJmp(label1);
	c->SetLabel(label2);

	c->SetBreakLabel(break_label);
}

// while文
void cwhile_statement::analyze(compiler *c) const
{
	int label1 = c->MakeLabel();
	int label2 = c->MakeLabel();

	int break_label = c->SetBreakLabel(label2);

	c->SetLabel(label1);
	node_->push(c);
	c->OpJmpNC(label2);
	statement_->analyze(c);
	c->OpJmp(label1);
	c->SetLabel(label2);

	c->SetBreakLabel(break_label);
}

// switch文
void cswitch_statement::analyze(compiler *c) const
{
	if (!statement_.empty()) {
		node_->push(c);

		int label = c->MakeLabel();		// L0ラベル作成
		int break_label = c->SetBreakLabel(label);
		int default_label = label;

		std::for_each(statement_.begin(), statement_.end(),
			boost::bind(&cstatement::case_analyze, _1, c, &default_label));

		c->OpPop();
		c->OpJmp(default_label);

		std::for_each(statement_.begin(), statement_.end(), boost::bind(&cstatement::analyze, _1, c));
		c->SetLabel(label);

		c->SetBreakLabel(break_label);
	}
}

// block文
void cblock_statement::analyze(compiler *c) const
{
	c->BlockIn();
	block_->analyze(c);
	c->BlockOut();
}

// 文ブロック
void cblock::analyze(compiler *c) const
{
	std::for_each(decl_.begin(), decl_.end(), boost::bind(&cdeclaration::analyze, _1, c));
	if (!decl_.empty())
		c->AllocStack();	// スタックフレーム確保
	std::for_each(state_.begin(), state_.end(), boost::bind(&cstatement::analyze, _1, c));
}

// 宣言の解析
void cdeclaration::analyze(compiler *c) const
{
	if (is_func_) {		// 関数
		c->DefineFunction(type_, name_, arg_);
	}
	else {
		c->DefineValue(type_, node_);
	}
}

// 関数の解析
void cfunction::analyze(compiler *c) const
{
	c->AddFunction(type_, name_, args_, block_);
}