view Bison-Flex/Compiler-StackBase/EUC/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 source

//
// コンパイラドライバ
//
//		(c)2008 Chihiro.SAKAMOTO HyperWorks
//
#ifndef __COMPILER_H__
#define	__COMPILER_H__

#include "script-parser.hh"
#include "vm.h"
#include "node.h"

// 前方宣言
class compiler;

// flexの関数宣言
#define	YY_DECL											\
	yy::script_parser::token_type						\
	yylex(yy::script_parser::semantic_type* yylval,		\
		 yy::script_parser::location_type* yylloc,		\
		 compiler& driver)

YY_DECL;

// 仮想マシンコード生成用

class CVMCode {
  public:
	CVMCode(unsigned char op)			// 引数なし命令
		: size_(1), op_(op), arg1_(0)
	{
	}
	CVMCode(unsigned char op, int arg1)	// 引数1つの命令
		: 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((char)type);
	}

	void SetArgs(const CArgList *args)
	{
		if (args) {
			size_t size = args->size();
			for (size_t i=0; i < size; i++) {
				args_.push_back((char)args->get(i)->type());
			}
		}
	}

	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 CArgList *args) const
	{
		// 引数が無い場合
		if (args == 0)
			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->get(i)->type() != (int)args_[i])
				return false;
		}
		return true;
	}

	// 指定の引数の型を得る

	int GetArg(int index) const
	{
		return args_[index];
	}

	int ArgSize() const { return 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<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();

	std::string &get_filename() { return file; }
	bool compile(const std::string &f, vm::data &data);
#ifdef	_DEBUG
	void debug_dump();
#endif

	bool add_function(int index, int type, const char *name, const char *args);

	void DefineValue(const yy::location& l, int type, CValueList *value_list);
	void DefineFunction(const yy::location& l, int type, const std::string *name, CArgList *args);
	void AddFunction(const yy::location& l, int type, const std::string *name, CArgList *args, CStateBlock *states);

	// 変数の検索、内側のブロックから検索する。
	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(const yy::location& l, int type, const std::string &name, const CNode *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 yy::location& l, const std::string& m);
	void error(const std::string& m);

  private:
	void scan_begin();
	void scan_end();

  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;

	std::string file;
} ;

#endif