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