Mercurial > hg > Members > nobuyasu > myCompiler
view Bison-Flex/BasicCompiler-StackBase/UTF8/#compiler.cpp# @ 4:805d39d28230
add Compiler-stackbase
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 17 May 2011 08:00:38 +0900 |
parents | |
children |
line wrap: on
line source
#include <iostream> #include <iomanip> #include "script-parser.hh" #include "compiler.h" #ifdef _MSC_VER #pragma warning(disable: 4996) #endif // ’¥³’¥ó’¥¹’¥È’¥é’¥¯’¥¿ compiler::compiler() : error_count(0) { } // ’¥Ç’¥¹’¥È’¥é’¥¯’¥¿ compiler::~compiler() { } // ’¥³’¥ó’¥Ñ’¥¤’¥ë bool compiler::compile(const std::string &f, vm::data &data) { // ’¥·’¥¹’¥Æ’¥à’¥³’¡¼’¥ë’¤Î’Àß’Äê file = f; scan_begin(); // ’¥¹’¥’¥ã’¥Ê’¡¼’½é’´ü’²½ yy::script_parser parser(*this); // ’¥Ñ’¡¼’¥µ’¡¼’¹½’ÃÛ int result = parser.parse(); // ’¹½’ʸ’²ò’ÀÏ scan_end(); // ’¥¹’¥’¥ã’¥Ê’¡¼’½ª’λ if (result != 0) return false; // ’¥Ñ’¡¼’¥µ’¡¼’¥¨’¥é’¡¼ // ’¥¹’¥Æ’¡¼’¥È’¥¹’¥¿’¥Ã’¥¯’¤¬’¶õ’¤Ç’¤Ï’¤Ê’¤¤’¤Ê’¤é’¤Ð’¡¢if, for, while’¤¬ // ’ÊÄ’¤¸’¤Æ’¤¤’¤Ê’¤¤ while (!state_stack.empty()) { CState &state = state_stack.top(); switch (state.state_) { case STATE_IF: error(state.l_, "if’¤Ë’ÂÐ’±þ’¤¹’¤ëendif’¤¬’Í’¤ê’¤Þ’¤»’¤ó"); break; case STATE_FOR: error(state.l_, "for’¤Ë’ÂÐ’±þ’¤¹’¤ënext’¤¬’Í’¤ê’¤Þ’¤»’¤ó"); delete state.start_; delete state.end_; delete state.step_; break; case STATE_WHILE: error(state.l_, "while’¤Ë’ÂÐ’±þ’¤¹’¤ëwend’¤¬’Í’¤ê’¤Þ’¤»’¤ó"); break; } state_stack.pop(); } // ’È֒ʼ’ÍÑHALT’¥³’¥Þ’¥ó’¥É’¤ò’ÄÉ’²Ã const CVMCode &code = statement.back(); if (code.op_ != VM_HALT) // halt’¤¬’̵’¤¤’¤Ê’¤é’¤Ð OpHalt(); // halt’¤ò’ÄÉ’²Ã int code_size = LabelSetting(); // ’¥é’¥Ù’¥ë’¤Ë’¥¢’¥É’¥ì’¥¹’¤ò’Àß’Äê CraeteData(data, code_size); // ’¥Ð’¥¤’¥Ê’¥ê’À¸’À® return error_count == 0; } // ’¥¨’¥é’¡¼’¥á’¥Ã’¥»’¡¼’¥¸’¤ò’½Ð’ÎÏ void compiler::error(const yy::location& l, const std::string& m) { std::cerr << l << ": " << m << std::endl; error_count++; } // ’¥¨’¥é’¡¼’¥á’¥Ã’¥»’¡¼’¥¸’¤ò’½Ð’ÎÏ void compiler::error(const std::string& m) { std::cerr << m << std::endl; error_count++; } // ’Ì¿’Îá’ʸ’¤Î’ÅÐ’Ï¿ // ’Âå’Æþ’ʸ void compiler::AssignStatement(const yy::location& l, CAssign *assign) { assign->analyze(this); delete assign; } // if’ʸ // // if expr then // A // endif // // > push expr // > jmp_nc L1 // > A // > L1: // // if expr then // A // else // B // endif // // > push expr // > jmp_nc L1 // > A // > jmp L2 // > L1: // > B // > L2: // void compiler::IfStatement(const yy::location& l, CNode *expr) expr->push(this); int label = MakeLabel(); OpJmpNC(label); // ’µ¶’¤Î’»þ’¤Î’Èô’¤Ó’Àè state_stack.push(CState(l, STATE_IF, label)); delete expr; } void compiler::ElseStatement(const yy::location& l) { if (state_stack.empty() || state_stack.top().state_ != STATE_IF) { error(l, "if’ʸ’¤È’ÂÐ’±þ’¤·’¤Æ’¤¤’¤Ê’¤¤else’ʸ’¤¬’Í’¤ê’¤Þ’¤·’¤¿’¡£"); } else { CState &state = state_stack.top(); int label = MakeLabel(); OpJmp(label); SetLabel(state.label1_); // ’µ¶’¤Î’»þ’¤Î’Èô’¤Ó’Àè’¤ò’¤³’¤³’¤Ë’¤¹’¤ë state.label1_ = label; // endif’¤Î’Èô’¤Ó’Àè’¤ò’ºÆ’Àß’Äê } } void compiler::EndifStatement(const yy::location& l) { if (state_stack.empty() || state_stack.top().state_ != STATE_IF) { error(l, "if’ʸ’¤È’ÂÐ’±þ’¤·’¤Æ’¤¤’¤Ê’¤¤endif’ʸ’¤¬’Í’¤ê’¤Þ’¤·’¤¿’¡£"); } else { CState &state = state_stack.top(); SetLabel(state.label1_); // endif’¤Î’Èô’¤Ó’Àè’¤ò’¤³’¤³’¤Ë’¤¹’¤ë state_stack.pop(); // ’¥¹’¥Æ’¡¼’¥È’¥¹’¥¿’¥Ã’¥¯’¤òpop } } // FOR’ʸ // // for value=X to Y step Z // A // next // // > push X : value = X // > pop value // > L1: // > A // > push value : if (value == Y) goto L2 // > push Y // > eq // > jmp_c L2 // > push value : value = value + Z // > push Z // > add // > pop value // > jmp L1 // > L2: // void compiler::ForStatement(const yy::location& l, CAssign *start, CNode *end, CNode *step) { int label = MakeLabel(); start->analyze(this); SetLabel(label); state_stack.push(CState(l, STATE_FOR, label, start, end, step)); } void compiler::NextStatement(const yy::location& l) { if (state_stack.empty() || state_stack.top().state_ != STATE_FOR) { error(l, "for’ʸ’¤È’ÂÐ’±þ’¤·’¤Æ’¤¤’¤Ê’¤¤next’ʸ’¤¬’Í’¤ê’¤Þ’¤·’¤¿’¡£"); } else { CState &state = state_stack.top(); int label = MakeLabel(); // ’¥ë’¡¼’¥×’½ª’λ’¤Î’¥Á’¥§’¥Ã’¥¯ state.start_->push_value(this); state.end_->push(this); OpEq(); OpJmpC(label); // ’½ª’λ’»þ’Èô’¤Ó’Àè // ’¥«’¥¦’¥ó’¥¿’¡¼’Áý’ʬ state.start_->push_value(this); if (state.step_) state.step_->push(this); else PushConst(1); OpAdd(); state.start_->pop_value(this); // ’¥ë’¡¼’¥× OpJmp(state.label1_); // ’¥ë’¡¼’¥×’½ª’λ SetLabel(label); // ’¸å’»Ï’Ëö delete state.start_; delete state.end_; delete state.step_; state_stack.pop(); } } // while’ʸ // // while (expr) A // > L1: // > push expr // > jmp_nc L2 // > A // > jmp L1 // > L2: // void compiler::WhileStatement(const yy::location& l, CNode *expr) { int label1 = MakeLabel(); int label2 = MakeLabel(); SetLabel(label1); expr->push(this); OpJmpNC(label2); state_stack.push(CState(l, STATE_WHILE, label1, label2)); delete expr; } void compiler::WendStatement(const yy::location& l) { if (state_stack.empty() || state_stack.top().state_ != STATE_WHILE) { error(l, "while’ʸ’¤È’ÂÐ’±þ’¤·’¤Æ’¤¤’¤Ê’¤¤wend’ʸ’¤¬’Í’¤ê’¤Þ’¤·’¤¿’¡£"); } else { CState &state = state_stack.top(); OpJmp(state.label1_); SetLabel(state.label2_); state_stack.pop(); } } // end’ʸ // // > halt // void compiler::EndStatement(const yy::location& l) { OpHalt(); } // print’ʸ // // print a, b, c // // > push c // > push b // > push a // > print 3 // void compiler::PrintStatement(const yy::location& l, CArgs *args) { int arg_count = 0; if (args) { args->for_each_rev(std::bind2nd(std::mem_fun(&CNode::push), this)); arg_count = args->size(); } OpPrint(arg_count); delete args; } void compiler::MakeGotoLabel(const yy::location& l, std::string *value) { int label = MakeLabel(); SetLabel(label); gototable.insert( std::map<std::string, int>::value_type( *value, label) ); } void compiler::GotoLabel(const yy::location& l, std::string *value) { OpJmp(gototable[*value]); } // ’¥é’¥Ù’¥ë’À¸’À® int compiler::MakeLabel() { int index = (int)labels.size(); labels.push_back(CLabel(index)); return index; } // ’¥é’¥Ù’¥ë’¤Î’¥À’¥ß’¡¼’¥³’¥Þ’¥ó’¥É’¤ò’¥¹’¥Æ’¡¼’¥È’¥á’¥ó’¥È’¥ê’¥¹’¥È’¤Ë’ÅÐ’Ï¿’¤¹’¤ë void compiler::SetLabel(int label) { statement.push_back(CVMCode(VM_MAXCOMMAND, label)); } // ’¥é’¥Ù’¥ë’²ò’·è // // ’£±’¡¥’¥¢’¥É’¥ì’¥¹’¤ò’À¸’À®’¤¹’¤ë // ’£²’¡¥’¥À’¥ß’¡¼’¤Î’¥é’¥Ù’¥ë’¥³’¥Þ’¥ó’¥É’¤¬’Í’¤Ã’¤¿’¥¢’¥É’¥ì’¥¹’¤ò’¡¢’¥é’¥Ù’¥ë’¥Æ’¡¼’¥Ö’¥ë’¤Ë’ÅÐ’Ï¿’¤¹’¤ë // ’£³’¡¥Jmp’¥³’¥Þ’¥ó’¥É’¤Î’Èô’¤Ó’Àè’¤ò’¥é’¥Ù’¥ë’¥Æ’¡¼’¥Ö’¥ë’¤Ë’ÅÐ’Ï¿’¤µ’¤ì’¤¿’¥¢’¥É’¥ì’¥¹’¤Ë’¤¹’¤ë // note: // GCC’¤Ç’¤Ï’¡¢’´Ø’¿ô’¥ª’¥Ö’¥¸’¥§’¥¯’¥È’¤ò’´Ø’¿ô’Æ⒤˒½ñ’¤±’¤Ê’¤¤’¤Î’¤Ç’¡¢’¤³’¤³’¤Ë’µ’½Ò’¤¹’¤ë’¡£ // VC++9.0(VS2008)’¤Ç’¤Ï’´Ø’¿ô’Æ⒤˒½ñ’¤¯’¤³’¤È’¤Ç’¡¢’¥¹’¥³’¡¼’¥×’¤ò’Éõ’¤¸’¹þ’¤á’¤ë’»ö’¤¬’²Ä’ǽ’¡£ // ’¥¢’¥É’¥ì’¥¹’·×’»»’´Ø’¿ô’¥ª’¥Ö’¥¸’¥§’¥¯’¥È struct calc_addr { std::vector<CLabel> &labels_; int &pos_; calc_addr(std::vector<CLabel> &labels, int &pos): labels_(labels), pos_(pos) { } void operator()(const CVMCode &code) { if (code.op_ == VM_MAXCOMMAND) { // ’¥é’¥Ù’¥ë’¤Î’¥À’¥ß’¡¼’¥³’¥Þ’¥ó’¥É labels_[code.arg1_].pos_ = pos_; } else { pos_ += code.size_; } } } ; // ’¥¸’¥ã’¥ó’¥×’¥¢’¥É’¥ì’¥¹’Àß’Äê’´Ø’¿ô’¥ª’¥Ö’¥¸’¥§’¥¯’¥È struct set_addr { std::vector<CLabel> &labels_; set_addr(std::vector<CLabel> &labels): labels_(labels) { } void operator()(CVMCode &code) { switch (code.op_) { case VM_JMP: case VM_JMPC: case VM_JMPNC: code.arg1_ = labels_[code.arg1_].pos_; break; } } } ; int compiler::LabelSetting() { // ’¥¢’¥É’¥ì’¥¹’·×’»» int pos = 0; std::for_each(statement.begin(), statement.end(), calc_addr(labels, pos)); // ’¥¸’¥ã’¥ó’¥×’¥¢’¥É’¥ì’¥¹’Àß’Äê std::for_each(statement.begin(), statement.end(), set_addr(labels)); return pos; } // ’¥Ð’¥¤’¥Ê’¥ê’¥Ç’¡¼’¥¿’À¸’À® // ’´Ø’¿ô’¥ª’¥Ö’¥¸’¥§’¥¯’¥È struct copy_code { unsigned char *p; copy_code(unsigned char *code): p(code) { } void operator()(const CVMCode &code) { p = code.Get(p); } } ; bool compiler::CraeteData(vm::data &data, int code_size) { data.command_ = new unsigned char[code_size]; data.command_size_ = code_size; data.value_size_ = (int)variables.size(); std::for_each(statement.begin(), statement.end(), copy_code(data.command_)); return true; } // ’¥Ç’¥Ð’¥Ã’¥°’¥À’¥ó’¥× #ifdef _DEBUG void compiler::debug_dump() { std::cout << "---variables---" << std::endl; variables.dump(); static const char *op_name[] = { #define VM_NAMETABLE #include "vm_code.h" #undef VM_NAMETABLE "LABEL", } ; std::cout << "---code---" << std::endl; int pos = 0; size_t size = statement.size(); for (size_t i=0; i < size; i++) { std::cout << std::setw(6) << pos << ": " << op_name[statement[i].op_]; if (statement[i].size_ > 1) { std::cout << ", " << statement[i].arg1_; } std::cout << std::endl; if (statement[i].op_ != VM_MAXCOMMAND) { pos += statement[i].size_; } } std::cout << "---" << std::endl; } #endif