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