view 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 source

#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);
}