Mercurial > hg > Members > nobuyasu > SampleSource
view Bison-Flex/Compiler-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
// // ノード // // (c)2008 Chihiro.SAKAMOTO HyperWorks // #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_LOGAND: left->value_ = (left->value_ && right->value_)? 1: 0; break; case OP_LOGOR: left->value_ = (left->value_ || right->value_)? 1: 0; break; 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_AND: left->value_ &= right->value_; break; case OP_OR: left->value_ |= right->value_; break; case OP_LSHIFT: left->value_ <<= right->value_; break; case OP_RSHIFT: left->value_ >>= right->value_; 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; } // 文字列同士の定数計算 if (left->op_ == OP_STRING && right->op_ == OP_STRING) { if (op == OP_PLUS) { *left->string_ += *right->string_; delete right; 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: c.error(l, "文字列同士ではできない計算です"); break; } delete left; delete right; return new CNode(l, OP_CONST, value); } return new CNode(l, op, left, right); } // ノードのpush処理 int CNode::push(compiler *c) const { switch (op_) { case OP_NEG: if (left_->push(c) == TYPE_STRING) c->error(l_, "文字列には許されない計算です。"); c->OpNeg(); return TYPE_INTEGER; case OP_CONST: c->PushConst(value_); return TYPE_INTEGER; case OP_STRING: c->PushString(*string_); return TYPE_STRING; } int left_type = left_->push(c); int right_type = right_->push(c); if (left_type != right_type) c->error(l_, "文字列と整数間で計算できません。"); // 整数計算ノードの処理 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_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; } 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_PLUS: c->OpStrAdd(); break; default: c->error(l_, "文字列では計算できない式です。"); break; } return TYPE_STRING; } // ノードのpop // 計算ノードはpopできない int CNode::pop(compiler *c) const { c->error(l_, "内部エラー:計算ノードをpopしています。"); return TYPE_INTEGER; } // 変数ノードのpush int 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 { // 参照型変数は、引数にしか存在しない if (tag->type_ >= TYPE_INTEGER_REF) { if (left_) { // 配列 left_->push(c); c->PushLocalArrayRef(tag->addr_); } else { c->PushLocalRef(tag->addr_); } return tag->type_ - TYPE_INTEGER_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 CValueNode::pop(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 { // 参照型変数は、引数にしか存在しない if (tag->type_ >= TYPE_INTEGER_REF) { if (left_) { // 配列 left_->push(c); c->PopLocalArrayRef(tag->addr_); } else { c->PopLocalRef(tag->addr_); } return tag->type_ - TYPE_INTEGER_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 *node) const { int type = func_->GetArg(index_++); if (type >= TYPE_INTEGER_REF) { // 参照 if (node->op() != OP_VALUE) { comp_->error(node->location(), "参照型引数に、変数以外は指定できません。"); } else { const CValueTag *tag = comp_->GetValueTag(node->string()); if (tag == 0) { comp_->error(node->location(), "変数 " + 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 (TypeToRef(tag->type_) != type) { comp_->error(node->location(), "引数の型が合いません。"); } int addr = tag->addr_; if (tag->global_) // 外部変数 addr |= vm::vcpu::global_flag; // アドレスをpush if (node->left()) { // 配列 if (node->left()->op() == OP_CONST) { comp_->PushAddr(addr + node->left()->value()); } else { node->left()->push(comp_); comp_->PushArrayAddr(addr); } } else { comp_->PushAddr(addr); } } } } else { if (node->push(comp_) != type) { comp_->error(node->location(), "引数の型が合いません。"); } } } } ; int CFunctionNode::push(compiler *c) const { const CFunctionTag *tag = c->GetFunctionTag(*string_); if (tag == NULL) { c->error(l_, "関数 " + *string_ + "は、定義されていません。"); return TYPE_INTEGER; } int arg_size = (args_)? args_->size(): 0; if (tag->ArgSize() != arg_size) { c->error(l_, "引数の数が合いません。"); } // 引数をpush if (args_ && tag->ArgSize() == arg_size) { args_->for_each(set_arg(c, tag)); } // 引数の数をpush c->PushConst(arg_size); if (tag->IsSystem()) { c->OpSysCall(tag->GetIndex()); // システムコール } else { c->OpCall(tag->GetIndex()); // スクリプト上の関数 } return tag->type_; } // 関数にpopはできないのでエラーメッセージを出す int CFunctionNode::pop(compiler *c) const { c->error(l_, "内部エラー:関数ノードをpopした"); return TYPE_INTEGER; } // 変数定義 struct add_value { compiler *comp_; int type_; add_value(compiler *comp, int type): comp_(comp), type_(type) { } void operator()(CValueNode *node) { comp_->AddValue(node->location(), type_, node->string(), node->left()); } } ; void CDecl::analyze(compiler *c) { list_->for_each(add_value(c, type_)); } // 代入命令を生成 // // a = b // > push b // > pop a // // a += b // > push a // > push b // > add // > pop a // void CAssign::analyze(compiler *c) { if (op_ != '=') value_->push(c); if (expr_->push(c) == TYPE_INTEGER) { switch (op_) { case '+': c->OpAdd(); break; case '-': c->OpSub(); break; case '*': c->OpMul(); break; case '/': c->OpDiv(); break; case '%': c->OpMod(); break; } if (value_->pop(c) != TYPE_INTEGER) c->error(l_, "文字列型に整数を代入しています。"); return; } switch (op_) { case '+': c->OpStrAdd(); break; case '=': break; default: c->error(l_, "文字列では許されない計算です。"); break; } if (value_->pop(c) != TYPE_STRING) c->error(l_, "整数型に文字列を代入しています。"); } // '{' '}' で囲まれた文の生成 void CStateBlock::analyze(compiler *c) { // ローカル変数の定義 if (decls_) { decls_->for_each(std::bind2nd(std::mem_fun(&CDecl::analyze), c)); c->AllocStack(); } // 文のコード生成 if (states_) { states_->for_each(std::bind2nd(std::mem_fun(&CStatement::analyze), c)); } } // NOP void CNopStatement::analyze(compiler *c) { // 何もしない } // 代入 void CAssignStatement::analyze(compiler *c) { assign_->analyze(c); } // 関数呼び出し void CFunctionStatement::analyze(compiler *c) { int type = node_.push(c); if (type != TYPE_VOID) c->OpPop(); // 戻り値を捨てるためのpop } // IF文 // // if (expr) A // > push expr // > jmp_nc L1 // > A // > L1: // // if (expr) A else B // > push expr // > jmp_nc L1 // > A // > jmp L2 // > L1: // > B // > L2: // void CIfStatement::analyze(compiler *c) { expr_->push(c); int label1 = c->MakeLabel(); c->OpJmpNC(label1); then_statement_->analyze(c); if (else_statement_) { int label2 = c->MakeLabel(); c->OpJmp(label2); c->SetLabel(label1); else_statement_->analyze(c); c->SetLabel(label2); } else { c->SetLabel(label1); } } // FOR文 // // for (init; expr; next) A // > init // > L1: // > push expr // > jmp_nc L2 // > A // > next // > jmp L1 // > L2: // void CForStatement::analyze(compiler *c) { int label1 = c->MakeLabel(); int label2 = c->MakeLabel(); int break_label = c->SetBreakLabel(label2); init_->analyze(c); c->SetLabel(label1); expr_->push(c); c->OpJmpNC(label2); statement_->analyze(c); next_->analyze(c); c->OpJmp(label1); c->SetLabel(label2); c->SetBreakLabel(break_label); } // WHILE文 // // while (expr) A // > L1: // > push expr // > jmp_nc L2 // > A // > jmp L1 // > L2: // void CWhileStatement::analyze(compiler *c) { int label1 = c->MakeLabel(); int label2 = c->MakeLabel(); int break_label = c->SetBreakLabel(label2); c->SetLabel(label1); expr_->push(c); c->OpJmpNC(label2); statement_->analyze(c); c->OpJmp(label1); c->SetLabel(label2); c->SetBreakLabel(break_label); } // SWITCH文 // // switch (expr) { // case A: // STATE_A // break; // case B: // STATE_B // break; // default: // STATE_C // break; // } // > push expr // > push A // > test L1 ; stack上の2値を比較し、等しければpopしてJmp // > push B // > test L2 // > pop // > jmp L3 // > L1: // > STATE_A // > jmp L0 ; break // > L2: // > STATE_B // > jmp L0 ; break // > L3: // > STATE_C // > jmp L0 ; break // > L0: // void CSwitchStatement::analyze(compiler *c) { expr_->push(c); if (list_) { int label = c->MakeLabel(); // L0ラベル作成 int break_label = c->SetBreakLabel(label); int default_label = label; case_action_param param(c, default_label); list_->for_each(std::bind2nd(std::mem_fun(&CStatement::case_analyze), ¶m)); c->OpPop(); c->OpJmp(default_label); list_->for_each(std::bind2nd(std::mem_fun(&CStatement::analyze), c)); c->SetLabel(label); c->SetBreakLabel(break_label); } } // CASE文 // // switch文の特殊処理 // void CCaseStatement::analyze(compiler *c) { c->SetLabel(label_); } void CCaseStatement::case_analyze(case_action_param *param) { compiler *c = param->comp_; label_ = c->MakeLabel(); if (expr_->op() != OP_CONST) c->error(l_, "case 文には定数のみ指定できます。"); expr_->push(c); c->OpTest(label_); } // DEFAULT文 // // switch文の特殊処理 // void CDefaultStatement::analyze(compiler *c) { c->SetLabel(label_); } void CDefaultStatement::case_analyze(case_action_param *param) { label_ = param->comp_->MakeLabel(); param->default_label = label_; } // BREAK文 // // 登録されているJump先へのJmp命令を生成 // void CBreakStatement::analyze(compiler *c) { if (!c->JmpBreakLabel()) { c->error(l_, "breakがswitch/for/while外に有ります"); } } // RETURN文 // // RETURNコマンドを生成 // void CReturnStatement::analyze(compiler *c) { if (c->GetFunctionType() == TYPE_VOID) { // 戻り値無し if (expr_ != 0) { c->error(l_, "void関数に戻り値が設定されています"); } c->OpReturn(); } else { if (expr_ == 0) { c->error(l_, "関数の戻り値がありません"); } else { int expr_type = expr_->push(c); // 戻り値をpush if (expr_type != c->GetFunctionType()) { c->error(l_, "戻り値の型が合いません"); } } c->OpReturnV(); } } // 文ブロック // // 再帰的にすべての文を解析 // void CBlockStatement::analyze(compiler *c) { c->BlockIn(); block_->analyze(c); c->BlockOut(); }