view Bison-Flex/BasicCompiler-StackBase/UTF8/compiler.h @ 3:3cea2e8a0e4b

add function goto
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 10 May 2011 10:48:02 +0900
parents fbe42292d479
children
line wrap: on
line source

#ifndef __COMPILER_H__
#define	__COMPILER_H__

#include <stack>
#include "script-parser.hh"
#include "vm.h"
#include "node.h"

// Forward declarations.
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)
		: 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), size_(1)
	{
	}
	CValueTag(int addr, int size)
		: addr_(addr), size_(size)
	{
	}

  public:
	int		addr_;
	int		size_;
} ;

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)
	{
	}

	bool add(const std::string &name, int size=1)
	{
		std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr_, size)));
		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(const std::string &name, int addr)
	{
		std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr, 1)));
		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_ << ", size = " << it.second.size_ << std::endl;
		}
	} ;

	void dump() const
	{
		std::for_each(variables_.begin(), variables_.end(), dump_action());
	}
#endif

  private:
	std::map<std::string, CValueTag> variables_;
	int		addr_;
} ;

// コンパイラ

class compiler {
  private:
	enum STACK_STATE {
		STATE_IF,
		STATE_FOR,
		STATE_WHILE,
	} ;

	class CState {
	  public:
		CState(const yy::location& l, int state, int label)
			: l_(l), state_(state), label1_(label), label2_(0), start_(0), end_(0), step_(0)
		{
		}
		CState(const yy::location& l, int state, int label1, int label2)
			: l_(l), state_(state), label1_(label1), label2_(label2), start_(0), end_(0), step_(0)
		{
		}
		CState(const yy::location& l, int state, int label, CAssign *start, CNode *end, CNode *step)
			: l_(l), state_(state), label1_(label), label2_(0), start_(start), end_(end), step_(step)
		{
		}

	  public:
		yy::location l_;
		int state_;
		int label1_;
		int label2_;
		CAssign *start_;
		CNode *end_;
		CNode *step_;
	} ;

  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

	// 文
	// 代入文
	void AssignStatement(const yy::location& l, CAssign *assign);
	// if文
	void IfStatement(const yy::location& l, CNode *expr);
	void ElseStatement(const yy::location& l);
	void EndifStatement(const yy::location& l);
	// for文
	void ForStatement(const yy::location& l, CAssign *start, CNode *end, CNode *step);
	void NextStatement(const yy::location& l);
	// while文
	void WhileStatement(const yy::location& l, CNode *expr);
	void WendStatement(const yy::location& l);
	// end文
	void EndStatement(const yy::location& l);
	// print文
	void PrintStatement(const yy::location& l, CArgs *args);

	// make label for goto
	void MakeGotoLabel(const yy::location& l, std::string *string);
	// goto
	void GotoLabel(const yy::location& l, std::string *string);


	const CValueTag *GetValueTag(const std::string &name) const
	{
		return variables.find(name);
	}

	const CValueTag *AddValue(const std::string &name)
	{
		if (variables.add(name, 1)) {
			return variables.find(name);
		}
		return NULL;
	}

	// for code generator.
#define	VM_CREATE
#include "vm_code.h"
#undef	VM_CREATE

	int LabelSetting();

	int MakeLabel();

	void SetLabel(int label);

	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:
	CValueTable variables;
	std::vector<CVMCode> statement;
	std::vector<CLabel> labels;
	std::stack<CState> state_stack;

	std::map<std::string, int> gototable;

	int error_count;

	std::string file;
} ;

#endif