Mercurial > hg > Members > nobuyasu > SampleSource
diff boost-spirit/Compiler-boost-spirit/compiler.h @ 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/boost-spirit/Compiler-boost-spirit/compiler.h Mon May 09 03:11:59 2011 +0900 @@ -0,0 +1,391 @@ +#ifndef __COMPILER_H__ +#define __COMPILER_H__ + +#include "vm.h" +#include "node.h" + +// 仮想マシンコード生成用 + +class CVMCode { + public: + CVMCode(unsigned char op) + : size_(1), op_(op), arg1_(0) + { + } + CVMCode(unsigned char op, int arg1) + : size_(5), op_(op), arg1_(arg1) + { + } + + unsigned char *Get(unsigned char *p) const + { + if (op_ != VM_MAXCOMMAND) { // ラベルのダミーコマンド + *p++ = op_; + if (size_ > 1) { + *(int *)p = arg1_; + p += 4; + } + } + return p; + } + + public: + unsigned char size_; + unsigned char op_; + int arg1_; +} ; + +// ラベル + +class CLabel { + public: + CLabel(int index) + : index_(index), pos_(0) + { + } + ~CLabel() + { + } + + public: + int index_; + int pos_; +} ; + +// 変数テーブル + +class CValueTag { + public: + CValueTag(): addr_(-1), type_(TYPE_INTEGER), size_(1), global_(false) + { + } + CValueTag(int addr, int type, int size, bool global) + : addr_(addr), type_(type), size_(size), global_(global) + { + } + + public: + int addr_; + int type_; + int size_; + bool global_; +} ; + +class CValueTable { + private: + typedef std::map<std::string, CValueTag>::iterator iter; + typedef std::map<std::string, CValueTag>::const_iterator const_iter; + + public: + CValueTable(int start_addr=0): addr_(start_addr), global_(false) + { + } + + void set_global() + { + global_ = true; + } + + bool add(int type, const std::string &name, int size=1) + { + std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr_, type, size, global_))); + if (result.second) { + addr_ += size; + return true; + } + return false; + } + + const CValueTag *find(const std::string &name) const + { + const_iter it = variables_.find(name); + if (it != variables_.end()) + return &it->second; + return NULL; + } + + bool add_arg(int type, const std::string &name, int addr) + { + std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr, type, 1, false))); + return result.second; + } + + int size() const { return addr_; } + void clear() + { + variables_.clear(); + addr_ = 0; + } + +#ifdef _DEBUG + struct dump_action { + void operator()(const std::pair<std::string, CValueTag> &it) + { + std::cout << it.first << ", addr = " << it.second.addr_ << ", type = " << it.second.type_ << ", size = " << it.second.size_ << ", global = " << it.second.global_ << std::endl; + } + } ; + + void dump() const + { + std::cout << "-------- value --------" << std::endl; + std::for_each(variables_.begin(), variables_.end(), dump_action()); + } +#endif + + private: + std::map<std::string, CValueTag> variables_; + int addr_; + bool global_; +} ; + +// 関数定義用 + +class CFunctionTag { + private: + enum { + flag_declaration = 1 << 0, + flag_definition = 1 << 1, + flag_system = 1 << 2, + } ; + + public: + CFunctionTag() + { + } + CFunctionTag(int type) + : type_(type), flags_(0), index_(0) + { + } + + void SetArg(int type) + { + args_.push_back((unsigned char)type); + } + + void SetArgs(const std::vector<cargdef> &args) + { + size_t size = args.size(); + for (size_t i=0; i < size; i++) { + args_.push_back((unsigned char)args[i].type()); + } + } + + void SetArgs(const std::vector<int> &args) + { + size_t size = args.size(); + for (size_t i=0; i < size; i++) { + args_.push_back((unsigned char)args[i]); + } + } + + bool SetArgs(const char *args) + { + if (args) { + for (int i=0; args[i] != 0; i++) { + switch (args[i]) { + case 'I': case 'i': + args_.push_back(TYPE_INTEGER); + break; + + case 'S': case 's': + args_.push_back(TYPE_STRING); + break; + + default: + return false; + } + } + } + return true; + } + + bool ChkArgList(const std::vector<cargdef> &args) const + { + // 引数が無い場合 + if (args.empty()) + return args_.empty(); + + // 引数の個数が異なる + if (args.size() != args_.size()) + return false; + + // 全引数の型をチェック + size_t size = args_.size(); + for (size_t i=0; i < size; i++) { + if (args[i].type() != (int)args_[i]) + return false; + } + return true; + } + + bool ChkArgList(const std::vector<int> &args) const + { + // 引数が無い場合 + if (args.empty()) + return args_.empty(); + + // 引数の個数が異なる + if (args.size() != args_.size()) + return false; + + // 全引数の型をチェック + size_t size = args_.size(); + for (size_t i=0; i < size; i++) { + if (args[i] != (int)args_[i]) + return false; + } + return true; + } + + // 指定の引数の型を得る + + int GetArg(int index) const + { + return args_[index]; + } + + int ArgSize() const { return (int)args_.size(); } + + void SetIndex(int index) { index_ = index; } + void SetDeclaration() { flags_ |= flag_declaration; } // 宣言 + void SetDefinition() { flags_ |= flag_definition; } // 定義 + void SetSystem() { flags_ |= flag_system; } + + int GetIndex() const { return index_; } + bool IsDeclaration() const { return (flags_ & flag_declaration) != 0; } + bool IsDefinition() const { return (flags_ & flag_definition) != 0; } + bool IsSystem() const { return (flags_ & flag_system) != 0; } + + public: + int type_; + int flags_; + int index_; + std::vector<unsigned char> args_; +} ; + +class CFunctionTable { + private: + typedef std::map<std::string, CFunctionTag>::iterator iter; + typedef std::map<std::string, CFunctionTag>::const_iterator const_iter; + + public: + CFunctionTable() + { + } + + CFunctionTag *add(const std::string &name, const CFunctionTag &tag) + { + std::pair<iter, bool> result = functions_.insert(make_pair(name, tag)); + if (result.second) + return &result.first->second; + return NULL; + } + + const CFunctionTag *find(const std::string &name) const + { + const_iter it = functions_.find(name); + if (it != functions_.end()) + return &it->second; + return NULL; + } + + CFunctionTag *find(const std::string &name) + { + iter it = functions_.find(name); + if (it != functions_.end()) + return &it->second; + return NULL; + } + + void clear() + { + functions_.clear(); + } + + private: + std::map<std::string, CFunctionTag> functions_; +} ; + +// コンパイラ + +class compiler { +public: + compiler(); + virtual ~compiler(); + + bool compile(const std::string &file, vm::data &data); + +#ifdef _DEBUG + void debug_dump(); +#endif + + bool add_function(int index, int type, const char *name, const char *args); + + void DefineValue(int type, const std::vector<cnode_t> &node); + void DefineFunction(int type, const std::string &name, const std::vector<int> &args); + void AddFunction(int type, const std::string &name, const std::vector<cargdef> &args, cblock_t block); + + // 変数の検索、内側のブロックから検索する。 + const CValueTag *GetValueTag(const std::string &name) const + { + int size = (int)variables.size(); + for (int i=size-1; i>=0; i--) { + const CValueTag *tag = variables[i].find(name); + if (tag) + return tag; + } + return NULL; + } + + // 関数の検索 + const CFunctionTag *GetFunctionTag(const std::string &name) const + { + return functions.find(name); + } + + // for code generator. +#define VM_CREATE +#include "vm_code.h" +#undef VM_CREATE + + void BlockIn(); + void BlockOut(); + void AllocStack(); + int LabelSetting(); + + int SetBreakLabel(int label) + { + int old_index = break_index; + break_index = label; + return old_index; + } + bool JmpBreakLabel(); + + int MakeLabel(); + + void AddValue(int type, const std::string &name, cnode_t node); + + void SetLabel(int label); + + void PushString(const std::string &name); + int GetFunctionType() const { return current_function_type; } + bool CraeteData(vm::data &data, int code_size); + + // Error handling. + void error(const std::string& m); + + private: + CFunctionTable functions; + std::vector<CValueTable> variables; + std::vector<CVMCode> statement; + std::vector<CLabel> labels; + std::vector<char> text_table; + + int break_index; + int error_count; + + std::string current_function_name; + int current_function_type; +} ; + +#endif