diff Bison-Flex/BasicCompiler-StackBase/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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bison-Flex/BasicCompiler-StackBase/EUC/node.cpp	Mon May 09 03:11:59 2011 +0900
@@ -0,0 +1,213 @@
+#include <functional>
+#include <iostream>
+#include <iomanip>
+#include "node.h"
+#include "compiler.h"
+#include "script-parser.hh"
+
+// ノード生成
+//	ただし、定数同士の計算は、leftノードに結果を代入し、それを返す
+
+CNode *CNode::MakeNode(compiler &c, const yy::location& l, int op, CNode *left, CNode *right)
+{
+	if (right == 0) {
+		switch (op) {
+		  case OP_NEG:
+			if (left->op_ == OP_CONST) {				// 定数演算を計算する
+				left->value_ = -left->value_;
+				return left;
+			}
+			break;
+		}
+		return new CNode(l, op, left);
+	}
+
+	// 定数演算を計算する
+	if (left->op_ == OP_CONST && right->op_ == OP_CONST) {
+		switch (op) {
+		  case OP_EQ:
+			left->value_ = (left->value_ == right->value_)? 1: 0;
+			break;
+
+		  case OP_NE:
+			left->value_ = (left->value_ != right->value_)? 1: 0;
+			break;
+
+		  case OP_GT:
+			left->value_ = (left->value_ > right->value_)? 1: 0;
+			break;
+
+		  case OP_GE:
+			left->value_ = (left->value_ >= right->value_)? 1: 0;
+			break;
+
+		  case OP_LT:
+			left->value_ = (left->value_ < right->value_)? 1: 0;
+			break;
+
+		  case OP_LE:
+			left->value_ = (left->value_ <= right->value_)? 1: 0;
+			break;
+
+		  case OP_MINUS:
+			left->value_ -= right->value_;
+			break;
+
+		  case OP_PLUS:
+			left->value_ += right->value_;
+			break;
+
+		  case OP_TIMES:
+			left->value_ *= right->value_;
+			break;
+
+		  case OP_DIVIDE:
+			if (right->value_ == 0) {
+				c.error(l, "定数計算を0で除算しました。");
+			}
+			else {
+				left->value_ /= right->value_;
+			}
+			break;
+
+		  case OP_MOD:
+			if (right->value_ == 0) {
+				c.error(l, "定数計算を0で除算しました。");
+			}
+			else {
+				left->value_ %= right->value_;
+			}
+			break;
+
+		  default:
+			return new CNode(l, op, left, right);
+		}
+		delete right;
+		return left;
+	}
+	return new CNode(l, op, left, right);
+}
+
+void CNode::push(compiler *c) const
+{
+	switch (op_) {
+	  case OP_NEG:
+		left_->push(c);
+		c->OpNeg();
+		return;
+
+	  case OP_RANDFUNC:
+		left_->push(c);
+		c->OpRand();
+		return;
+
+	  case OP_CONST:
+		c->PushConst(value_);
+		return;
+	}
+
+	left_->push(c);
+	right_->push(c);
+
+	// 整数計算ノードの処理
+	switch (op_) {
+	  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_MINUS:
+		c->OpSub();
+		break;
+
+	  case OP_PLUS:
+		c->OpAdd();
+		break;
+
+	  case OP_TIMES:
+		c->OpMul();
+		break;
+
+	  case OP_DIVIDE:
+		c->OpDiv();
+		break;
+
+	  case OP_MOD:
+		c->OpMod();
+		break;
+
+	  default:
+		c->error(l_, "内部エラー:処理できない計算ノードがありました。");
+		break;
+	}
+}
+
+void CNode::pop(compiler *c) const
+{
+	c->error(l_, "内部エラー:計算ノードをpopしています。");
+}
+
+void CValueNode::push(compiler *c) const
+{
+	if (op_ != OP_VALUE) {
+		c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
+	}
+	else {
+		const CValueTag *tag = c->GetValueTag(*string_);
+		if (tag == 0) {
+			c->error(l_, "変数 " + *string_ + " は定義されていません。");
+		}
+		else {
+			c->PushValue(tag->addr_);
+		}
+	}
+}
+
+void CValueNode::pop(compiler *c) const
+{
+	if (op_ != OP_VALUE) {
+		c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
+	}
+	else {
+		const CValueTag *tag = c->GetValueTag(*string_);
+		if (tag == 0) {
+			tag = c->AddValue(*string_);
+		}
+		if (tag == 0) {
+			c->error(l_, "変数 " + *string_ + " が定義できません。");
+		}
+		else {
+			c->PopValue(tag->addr_);
+		}
+	}
+}
+
+// 代入命令を生成
+//
+//	>	push b
+//	>	pop a
+//
+void CAssign::analyze(compiler *c)
+{
+	expr_->push(c);
+	value_->pop(c);
+}