Mercurial > hg > Members > nobuyasu > SampleSource
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); +}