2020年寒假?(不)認真學習《自制編程語言,基於C語言》第一個Demo,詞法分析

前言

這本書的sparrow(麻雀)語言,基於wren(鷦鷯)語言,是一門面向對象語言!——至於其他特點我忘了,還記得的就是Demo中部分函數命名很簡單、簡單到與其他庫函數產生衝突了。。。。

幾個月前寫(抄)的項目,後面的語法分析、製作C語言的面向對象、設計虛擬機等等內容沒時間看下去了,只能講講廢話了——

加前綴

C語言做的,因爲沒有前綴,所以一是不好看,二是容易衝突。只有一個解決辦法,就是用專有的前綴。所以,我在每個函數、每個結構體、每個枚舉、許多個宏的前面,都加上相同的前綴 hj

詞法分析的Demo

頭文件

//hj_common.h
/*
hj_common.h文件是整個項目的最底層的文件,這個文件裏只有宏

整個項目是C寫的,沒有命名空間,所以很容易發生重命名!
規定:
		1.變量、結構體、枚舉、函數等,所有的非宏標識符前都要有前綴 hj
		2.特殊宏前後都有兩個下劃線。特殊宏就是那些特別簡單,分不清是枚舉還是宏的
		3.所有的前綴都是hj,把整個項目所有的hj都刪除了基本不影響理解
			可能影響執行。畢竟不能避免衝突和重命名了!!!


*/
#define _CRT_SECURE_NO_WARNINGS
#ifndef _hj_common_h
#define _hj_common_h
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h> //uint32_t
#include<string.h>
#include<math.h>
#include<ctype.h>
#include<Windows.h>
#include<time.h>
#include<sys/stat.h> //stat 求文件大小
#include<stdarg.h>





#define hjBOOL char
#define hjTRUE 1
#define hjFALSE 0
#define hjPUBLIC
#define hjPRIVATE static
#define UNUSED __attribute__((unused))




/*hjDEBUG 的定義會寫在makefile裏*/
#ifdef hjDEBUG
	#define hjASSERT(condition,errMsg)\
	{\
		if(!condition){\
			fprintf(stderr,"hjASSERT failed! %s:%d   IN FUNCTION %s(): %s\n",__FILE__,__LINE__,__func__,errMsg);\
			abort();\
		}\
	}
#else
	#define hjASSERT(condition,errMsg) ((void)0)
#endif


/*hjNOT_REACHED放在不能抵達的地方*/
#define hjNOT_REACHED \
{\
fprintf(stderr,"hjNOT_REACHED :%s:%d   IN FUNCTION %s()\n",__FILE__,__LINE__,__func__);\
abort();\
}




typedef struct hjVM hjVM;
typedef struct hjLexer hjLexer;
typedef struct hjParser hjParser;
typedef struct hjClass hjClass;


#endif
//hj_core.h
/*
hj_core.h文件是整個項目的最核心的文件
		1.幾乎所有底層的結構體、枚舉都定義在這裏
		2.只有結構體和枚舉和全局變量,沒有函數

*/
#ifndef _hj_core_h
#define _hj_core_h
#include"hj_common.h"


//虛擬機
typedef struct hjVM {
	uint32_t allocatedByte;		//累加已經分配的字節數
	hjLexer* curLexer;					//當前詞法分析器
}hjVM;





//單詞類型
typedef enum hjTokenType {
	/*未知單詞*/
	hjTOKEN_UNKNOWN,

	/*數據類型*/
	hjTOKEN_NUM,					//數字
	hjTOKEN_STR,					//字符串
	hjTOKEN_ID,						//標識符
	hjTOKEN_EXPR,					//內嵌表達式

	/*關鍵字*/
	hjTOKEN_LET,					//let
	hjTOKEN_FUNCTION,		//function
	hjTOKEN_IF,						//if
	hjTOKEN_ELSE,					//else
	hjTOKEN_TRUE,					//True
	hjTOKEN_FALSE,				//False
	hjTOKEN_WHILE,				//while
	hjTOKEN_FOR,					//for
	hjTOKEN_BREAK,				//break
	hjTOKEN_CONTINUE,		//continue
	hjTOKEN_RETURN,			//return
	hjTOKEN_NIL,						//Nil
	/*關於類及模塊導入*/
	hjTOKEN_CLASS,				//class
	hjTOKEN_SELF,					//self
	hjTOKEN_STATIC,				//static
	hjTOKEN_IS,						//is
	hjTOKEN_SUPER,				//super
	hjTOKEN_IMPORT,			//import
	

	/*分隔符*/
	hjTOKEN_AT,						//@
	hjTOKEN_WELL,					//#
	hjTOKEN_ACCENT,			//'      重音
	hjTOKEN_SEMI,					//;      分號
	hjTOKEN_BASKSLASH,		// \     反斜槓
	hjTOKEN_COLON,				//:      冒號
	hjTOKEN_COMMA,				//,      逗號
	hjTOKEN_DOT,					//.      一個點
	hjTOKEN_DOT_DOT,			//..     兩個連續的點
	hjTOKEN_LEFT_PAREN,	//(   
	hjTOKEN_RIGHT_PAREN,	//)   
	hjTOKEN_LEFT_BRACKET,	//[   
	hjTOKEN_RIGHT_BRACKET,	//]   
	hjTOKEN_LEFT_BRACE,	//{   
	hjTOKEN_RIGHT_BRACE,	//}   


	//賦值號
	hjTOKEN_ASSIGN,				//=

	/*簡單的二元運算符*/
	hjTOKEN_ADD,					//+
	hjTOKEN_SUB,					//-
	hjTOKEN_MUL,					//*
	hjTOKEN_DIV,					// /
	hjTOKEN_MOD,					//%
	hjTOKEN_POW,					//^			上面幾個都是左結合的,乘方是右結合的!

	/*位運算符*/
	hjTOKEN_BIT_AND,			//&
	hjTOKEN_BIT_OR,				//|
	hjTOKEN_BIT_NOT,			//~
	hjTOKEN_BIT_SHIFT_LEFT,			//<<
	hjTOKEN_BIT_SHIFT_RIGHT,			//>>



	/*邏輯運算符*/
	hjTOKEN_LOGIC_AND,		//&&
	hjTOKEN_LOGIC_OR,		//||
	hjTOKEN_LOGIC_NOT,		//!



	/*關係運算符*/
	hjTOKEN_EQ,						//==
	hjTOKEN_NEQ,					//!=
	hjTOKEN_GT,						//>
	hjTOKEN_GE,						//>=
	hjTOKEN_LT,						//<
	hjTOKEN_LE,						//<=


	/*問號,可能是?:三元運算符的一部分*/
	hjTOKEN_QUE,					//?


	hjTOKEN_EOL,					//end of line = newline = line feed = line break = line ending =  \n = 換行符 ,EOL = LF
	hjTOKEN_EOF					//end of file = 文件結束符   ,  EOF = LE

}hjTokenType;




//單詞
typedef struct hjToken {
	hjTokenType type;			 //單詞類型
	const char* start;				 //指向單詞字符串的開始
	uint32_t len;						 //單詞字符串的長度
	uint32_t lineNo;				 //單詞所在的文件行號
}hjToken;





//詞法分析器
typedef struct hjLexer {
	const char* file;				//文件
	const char* srcCode;		//源碼
	const char* next;				//指向下一個字符
	char curChar;					//當前字符
	hjToken preToken;			//先前單詞
	hjToken curToken;			//當前單詞
	hjVM* vm;						//虛擬機
	int Lcounter;						//記錄小括號的嵌套,也就是記錄內嵌表達式
}hjLexer;








//字符串
//這個類型的數據將作爲符號表的元素
typedef struct hjString {
	uint32_t len;						//字符串長度,不包含\0
	char* str;							//字符串內容
}hjString;



/*
字符串緩衝區
用於存儲字符串對象中的字符串

*/
typedef struct hjCharValue {
	uint32_t len;						//除\0之外的字符個數!!!
	char start[0];					//柔性數組
}hjCharValue;







/*--------------------定義幾種類型的動態數組--------------------*/
//字符串數組
typedef struct  hjStringArray {
	uint32_t count;					//數據個數
	uint32_t capacity;			//容量
	hjString* data;					//字符串數據緩衝區
}hjStringArray;



//字節數組
typedef struct  hjByteArray {
	uint32_t count;					//數據個數
	uint32_t capacity;			//容量
	uint8_t* data;					//字節數據緩衝區
}hjByteArray;


//字符數組
typedef struct  hjCharArray {
	uint32_t count;					//數據個數
	uint32_t capacity;			//容量
	char* data;						//字符數據緩衝區
}hjCharArray;

//int數組
typedef struct  hjIntArray {
	uint32_t count;					//數據個數
	uint32_t capacity;			//容量
	int* data;							//int數據緩衝區
}hjIntArray;



//符號表類型就是字符串數組類型
#define hjSymbolTable hjStringArray






#endif
//hj_error.h
/*
hj_error.h文件是錯誤處理模塊
*/
#ifndef _hj_error_h
#define _hj_error_h
#include"hj_core.h"



//錯誤類型
typedef enum hjErrorType {
	hjERROR_IO,
	hjERROR_MEM,
	hjERROR_LEX,
	hjERROR_PARSE,
	hjERROR_COMPILE,
	hjERROR_RUNTIME
}hjErrorType;



//打印錯誤信息
hjPUBLIC void hjError(void* _lexer, hjErrorType _errType, char* _errMsg);
hjPUBLIC void hjError_(void* _lexer, hjErrorType _errType, const char* _format,...);



#define __hjERROR_IO__(...)  hjError_(NULL,hjERROR_IO,__VA_ARGS__)
#define __hjERROR_MEM__(...)  hjError_(NULL,hjERROR_MEM,__VA_ARGS__)
#define __hjERROR_LEX__(lexer,...)  hjError_(lexer,hjERROR_LEX,__VA_ARGS__)
#define __hjERROR_PARSE__(lexer,...)  hjError_(lexer,hjERROR_PARSE,__VA_ARGS__)
#define __hjERROR_COMPILE__(lexer,...)  hjError_(lexer,hjERROR_COMPILE,__VA_ARGS__)
#define __hjERROR_RUNTIME__(...)  hjError_(NULL,hjERROR_RUNTIME,__VA_ARGS__)






#endif
//hj_mem.h
/*
hj_mem.h文件是內存管理模塊
內存管理模塊的功能:
			1.申請內存
			2.修改空間大小
			3.釋放內存

*/
#ifndef _hj_mem_h
#define _hj_mem_h
#include"hj_error.h"





//申請內存
hjPUBLIC void* hjMemManager(hjVM* _vm, void* _ptr, uint32_t _oldSize, uint32_t _newSize);
//找出大於等於_v的最近的2次冪
hjPUBLIC uint32_t hjNumOf2Pow_GE_v(uint32_t _v);
//清理符號表
hjPUBLIC void hjClear_SymbolTable(hjVM* _vm, hjSymbolTable* _table);




/*一組內存管理的宏*/
#define ALLOCATE(vm,type)  (type*)hjMemManager(vm,NULL,0,sizeof(type))																//給type類型申請type類型大小的內存
#define ALLOCATE_EXTRA(vm,type,extraSize)  (type*)hjMemManager(vm,NULL,0,sizeof(type) + extraSize)			//給type類型申請type類型大小+額外大小的內存
#define ALLOCATE_ARRAY(vm,type,count)  (type*)hjMemManager(vm,NULL,0,sizeof(type) * count)							//申請若干個type類型大小的內存
#define DEALLOCATE(vm,mem)  MemManager(vm,mem,0,0)																						//釋放mem的內存
#define DEALLOCATE_ARRAY(vm,arr,count)  MemManager(vm,arr,sizeof(arr[0]) * count,0)										 //釋放arr數組的內存










/*--------------------字符串數組方法--------------------*/
hjPUBLIC void hjInit_StringArray(hjStringArray* _arr);
hjPUBLIC void hjWrite_StringArray(hjVM* _vm, hjStringArray* _arr, hjString _data, uint32_t _fillCount);
hjPUBLIC void hjAdd_StringArray(hjVM* _vm, hjStringArray* _arr, hjString _data);
hjPUBLIC void hjClear_StringArray(hjVM* _vm, hjStringArray* _arr);


/*--------------------字節數組方法--------------------*/
hjPUBLIC void hjInit_ByteArray(hjByteArray* _arr);
hjPUBLIC void hjWrite_ByteArray(hjVM* _vm, hjByteArray* _arr, uint8_t _data, uint32_t _fillCount);
hjPUBLIC void hjAdd_ByteArray(hjVM* _vm, hjByteArray* _arr, uint8_t _data);
hjPUBLIC void hjClear_ByteArray(hjVM* _vm, hjByteArray* _arr);

/*--------------------字符數組方法--------------------*/
hjPUBLIC void hjInit_CharArray(hjCharArray* _arr);
hjPUBLIC void hjWrite_CharArray(hjVM* _vm, hjCharArray* _arr, char _data, uint32_t _fillCount);
hjPUBLIC void hjAdd_CharArray(hjVM* _vm, hjCharArray* _arr, char _data);
hjPUBLIC void hjClear_CharArray(hjVM* _vm, hjCharArray* _arr);


/*--------------------int數組方法--------------------*/
hjPUBLIC void hjInit_IntArray(hjIntArray* _arr);
hjPUBLIC void hjWrite_IntArray(hjVM* _vm, hjIntArray* _arr, int _data, uint32_t _fillCount);
hjPUBLIC void hjAdd_IntArray(hjVM* _vm, hjIntArray* _arr, int _data);
hjPUBLIC void hjClear_IntgArray(hjVM* _vm, hjIntArray* _arr);





#endif
//hj_lexer.h
/*
hj_lexer.h文件是詞法分析器

*/
#ifndef _hj_lexer_h
#define _hj_lexer_h
#include"hj_vm.h"
#include"hj_mem.h"
#include"hj_utf8.h"






/*定義全局變量*/
//文件根目錄
extern char* hj_rootDir;




//讀取腳本
hjPUBLIC char* hjReadScript(const char* _path);






//初始化詞法分析器
hjPUBLIC hjInit_Lexer(hjVM* _vm, hjLexer* _lexer, const char* _file, const char* _srcCode);
//查看下一個字符
hjPUBLIC char hjPeek_NextChar(hjLexer* _lexer);
//獲取下一個單詞
hjPUBLIC void hjGet_NextToken(hjLexer* _lexer);
//匹配單詞
hjPUBLIC hjBOOL hjMatch_Token(hjLexer* _lexer, hjTokenType _expectedToken);
//吸收當前單詞
hjPUBLIC void hjConsume_CurToken(hjLexer* _lexer, hjTokenType _expectedToken, const char* _errMsg);
//吸收下一個單詞
hjPUBLIC void hjConsume_NextToken(hjLexer* _lexer, hjTokenType _expectedToken, const char* _errMsg);










//判斷是否是數字
hjPRIVATE hjBOOL hjJudge_Num(char _c);
//判斷是否是字母
hjPRIVATE hjBOOL hjJudge_Alpha(char _c);

//判斷是標識符還是關鍵字
hjPRIVATE hjTokenType hjJudge_IdOrKey(const char* _start, uint32_t _len);
//獲取下一個字符
hjPRIVATE void hjGet_NextChar(hjLexer* _lexer);
//匹配下一個字符
hjPRIVATE hjBOOL hjMatch_NextChar(hjLexer* _lexer, char _expectedChar);


//跳過連續的空字符
hjPRIVATE void hjSkip_Blanks(hjLexer* _lexer);
//跳過單行註釋
hjPRIVATE void hjSkip_CommentALine(hjLexer* _lexer);
//跳過多行註釋
hjPRIVATE void hjSkip_Comment(hjLexer* _lexer);
//跳過一行
hjPRIVATE void hjSkip_ALine(hjLexer* _lexer);


//解析標識符
hjPRIVATE void hjLex_Id(hjLexer* _lexer, hjTokenType _token);
//解析字符串
hjPRIVATE void hjLex_Str(hjLexer* _lexer);
//解析UTF8碼點
hjPRIVATE void hjLex_CodePointOfUTF8(hjLexer* _lexer, hjByteArray* _buf);






#endif
//hj_utf8.h
/*
hj_utf8.h文件是unicode utf8編碼模塊
*/
#ifndef _hj_utf8_h
#define _hj_utf8_h
#include"hj_common.h"



//獲取編碼UTF8後的字節數
hjPUBLIC uint32_t hjGet_ByteNumOfEncodedUTF8(int _value);
//獲取解碼UTF8後的字節數
hjPUBLIC uint32_t hjGet_ByteNumOfDecodedUTF8(uint8_t _byte);
//編碼UTF8
hjPUBLIC uint8_t hjEncodeUTF8(uint8_t* _buf, int _value);
//解碼UTF8
hjPUBLIC int hjDecodeUTF8(const uint8_t* _bytePtr, uint32_t _len);


#endif
//hj_vm.h
/*
hj_vm.h文件是虛擬機

*/
#ifndef _hj_vm_h
#define _hj_vm_h
#include"hj_error.h"







//初始化虛擬機
hjPUBLIC void hjInit_VM(hjVM* _vm);
//創建虛擬機
hjPUBLIC hjVM* hjNew_VM();



#endif

  \;
  \;
  \;
  \;
  \;

源文件

//hj_error.h
#include "hj_error.h"

/*
打印錯誤信息
*/
hjPUBLIC void hjError(void* _lexer, hjErrorType _errType, char* _errMsg) {

	//設置異常信息的字體顏色
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED); //高亮紅色

	switch (_errType) {
	case hjERROR_IO:
		printf("[Error_io]");
		break;
	case hjERROR_MEM:
		printf("[Error_mem]");
		break;
	case hjERROR_LEX:
		printf("[Error_lex]");
		break;
	case hjERROR_PARSE:
		printf("[Error_parse]");
		break;
	case hjERROR_RUNTIME:
		printf("[Error_runtime]");
		break;
	case hjERROR_COMPILE:
		printf("[Error_compile]");
		break;	
	default:
		break;
	}

	if (_lexer != NULL) { 
		hjLexer* myLexer = (hjLexer*)_lexer;
		printf("file \"%s\",line %d,at \"%s\"=>", myLexer->file, myLexer->curToken.lineNo, myLexer->curToken.start);
	}
	printf("%s\n", _errMsg);

	//恢復字體顏色
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);//白色

}

/*
打印錯誤信息
*/
hjPUBLIC void hjError_(void* _lexer, hjErrorType _errType, const char* _format, ...) {

	char buf[512] = { '\0' };
	va_list  myVa;
	va_start(myVa, _format);
	vsnprintf(buf, 512, _format, myVa);   //把可變參數列表按照_format的格式放入buf中
	va_end(myVa);


	//設置異常信息的字體顏色
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED); //高亮紅色

	switch (_errType) {
	case hjERROR_IO:
	case hjERROR_MEM:
		fprintf(stderr, "%s:%d IN FUNCTION %s():%s\n", __FILE__, __LINE__, __func__, buf);
		break;
	case hjERROR_LEX:
	case hjERROR_PARSE:
	case hjERROR_COMPILE:
		hjASSERT(_lexer != NULL, "lexer is null");
		fprintf(stderr, "%s:%d \"%s\"\n",
			((hjLexer*)_lexer)->file,
			((hjLexer*)_lexer)->preToken.lineNo,
			buf
		);
		break;
	case hjERROR_RUNTIME:
		fprintf(stderr, "%s\n", buf);
		break;	
	default:
		hjNOT_REACHED;
		break;
	}

	//恢復字體顏色
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);//白色

	//退出程序
	exit(1);
}
//hj_mem.cpp
#include"hj_mem.h"





//申請內存
hjPUBLIC void* hjMemManager(hjVM* _vm, void* _ptr, uint32_t _oldSize, uint32_t _newSize) {
	if (_newSize < 0 || _oldSize < 0)return NULL;//做個檢查

	//累計系統分配的總內存
	_vm->allocatedByte += _newSize - _oldSize;

	/*
	避免realloc(NULL,0)定義的新地址,此地址不能被釋放
	realloc(NULL,0)會返回無法使用,也無法置空的非空指針
	*/
	if(_newSize==0){
		free(_ptr);   
		_ptr = NULL;
		return NULL;
	}
	//p變量是爲了避免返回空指針,把原來不爲空的指針置空了
	void* p = realloc(_ptr, _newSize);
	if (p == NULL) {
		__hjERROR_MEM__("memory allocate failed!");
	}
	return p;
}



/*
找出大於等於_v的最近的2次冪
1U<<(log(v-1)+1)
向下找離2最近的2的次冪,然後再乘以一個2


*/
hjPUBLIC uint32_t hjNumOf2Pow_GE_v(uint32_t _v) {

	//修復_v==0時結果爲0的情況,在_v==0時給_v設置爲1
	_v += (_v == 0);
	

	--_v;
	//給_v開31次方
	_v |= (_v >> 1);//除以2
	_v |= (_v >> 2);//除以4
	_v |= (_v >> 4);//除以16
	_v |= (_v >>8);//除以64
	_v |= (_v >> 16);//除以2^16
	//
	++_v;
	return _v;

}


//清理符號表
hjPUBLIC void hjClear_SymbolTable(hjVM* _vm, hjSymbolTable* _table) {

	uint32_t i = 0;
	for (; i < _table->count;++i) {
		hjMemManager(_vm, _table->data[i].str, 0, 0);
	}
	hjClear_StringArray(_vm, _table);
}








/*--------------------字符串數組方法--------------------*/
hjPUBLIC void hjInit_StringArray(hjStringArray* _arr) {
	_arr->data = NULL;
	_arr->capacity = _arr->count = 0;
}

hjPUBLIC void hjWrite_StringArray(hjVM* _vm, hjStringArray* _arr, hjString _data, uint32_t _fillCount) {

	//當前已經存在的元素個數加上要添加的元素個數
	uint32_t newCount = _arr->count + _fillCount;

	if (newCount > _arr->capacity) { //要擴容了
		size_t oldSize = _arr->capacity * sizeof(hjString);
		_arr->capacity = hjNumOf2Pow_GE_v(newCount);//找出大於newCount的2次冪,做新的容量
		size_t newSize = _arr->capacity * sizeof(hjString);

		//新的尺寸還不如舊的尺寸的話,就報錯!
		hjASSERT(newSize > oldSize, "faint ... memory allocate!");

		//申請新的內存空間
		_arr->data = (hjString*)hjMemManager(_vm, _arr->data, oldSize, newSize);

	}

	//添加數據
	uint32_t i = 0;
	for (; i < _fillCount; ++i, ++_arr->count) {
		_arr->data[_arr->count] = _data;
	}
}

hjPUBLIC void hjAdd_StringArray(hjVM* _vm, hjStringArray* _arr, hjString _data) {
	hjWrite_StringArray(_vm, _arr, _data, 1);
}

hjPUBLIC void hjClear_StringArray(hjVM* _vm, hjStringArray* _arr) {
	uint32_t size = _arr->capacity * sizeof(_arr->data[0]);
	hjMemManager(_vm, _arr->data, size, 0);//size => 0
	hjInit_StringArray(_arr);
}




/*--------------------字節數組方法--------------------*/
hjPUBLIC void hjInit_ByteArray(hjByteArray* _arr) {
	_arr->data = NULL;
	_arr->capacity = _arr->count = 0;
}

hjPUBLIC void hjWrite_ByteArray(hjVM* _vm, hjByteArray* _arr, uint8_t _data, uint32_t _fillCount) {

	//當前已經存在的元素個數加上要添加的元素個數
	uint32_t newCount = _arr->count + _fillCount;

	if (newCount > _arr->capacity) { //要擴容了
		size_t oldSize = _arr->capacity * sizeof(uint8_t);
		_arr->capacity = hjNumOf2Pow_GE_v(newCount);//找出大於等於newCount的2次冪,做新的容量
		size_t newSize = _arr->capacity * sizeof(uint8_t);

		//新的尺寸還不如舊的尺寸的話,就報錯!
		hjASSERT(newSize > oldSize, "faint ... memory allocate!");

		//申請新的內存空間
		_arr->data = (uint8_t*)hjMemManager(_vm, _arr->data, oldSize, newSize);

	}

	//添加數據
	uint32_t i = 0;
	for (; i < _fillCount; ++i, ++_arr->count) {
		_arr->data[_arr->count] = _data;
	}

}

hjPUBLIC void hjAdd_ByteArray(hjVM* _vm, hjByteArray* _arr, uint8_t _data) {
	hjWrite_ByteArray(_vm, _arr, _data, 1);
}

hjPUBLIC void hjClear_ByteArray(hjVM* _vm, hjByteArray* _arr) {
	uint32_t size = _arr->capacity * sizeof(_arr->data[0]);
	hjMemManager(_vm, _arr->data, size, 0);//size => 0
	hjInit_ByteArray(_arr);
}




/*--------------------字符數組方法--------------------*/
hjPUBLIC void hjInit_CharArray(hjCharArray* _arr) {
	_arr->data = NULL;
	_arr->capacity = _arr->count = 0;
}

hjPUBLIC void hjWrite_CharArray(hjVM* _vm, hjCharArray* _arr, char _data, uint32_t _fillCount) {

	//當前已經存在的元素個數加上要添加的元素個數
	uint32_t newCount = _arr->count + _fillCount;

	if (newCount > _arr->capacity) { //要擴容了
		size_t oldSize = _arr->capacity * sizeof(char);
		_arr->capacity = hjNumOf2Pow_GE_v(newCount);//找出大於newCount的2次冪,做新的容量
		size_t newSize = _arr->capacity * sizeof(char);

		//新的尺寸還不如舊的尺寸的話,就報錯!
		hjASSERT(newSize > oldSize, "faint ... memory allocate!");

		//申請新的內存空間
		_arr->data = (char*)hjMemManager(_vm, _arr->data, oldSize, newSize);

	}

	//添加數據
	uint32_t i = 0;
	for (; i < _fillCount; ++i, ++_arr->count) {
		_arr->data[_arr->count] = _data;
	}

}

hjPUBLIC void hjAdd_CharArray(hjVM* _vm, hjCharArray* _arr, char _data) {
	hjWrite_CharArray(_vm, _arr, _data, 1);
}

hjPUBLIC void hjClear_CharArray(hjVM* _vm, hjCharArray* _arr) {
	uint32_t size = _arr->capacity * sizeof(_arr->data[0]);
	hjMemManager(_vm, _arr->data, size, 0);//size => 0
	hjInit_CharArray(_arr);
}





/*--------------------int數組方法--------------------*/
hjPUBLIC void hjInit_IntArray(hjIntArray* _arr) {
	_arr->data = NULL;
	_arr->capacity = _arr->count = 0;
}

hjPUBLIC void hjWrite_IntArray(hjVM* _vm, hjIntArray* _arr, int _data, uint32_t _fillCount) {

	//當前已經存在的元素個數加上要添加的元素個數
	uint32_t newCount = _arr->count + _fillCount;

	if (newCount > _arr->capacity) { //要擴容了
		size_t oldSize = _arr->capacity * sizeof(int);
		_arr->capacity = hjNumOf2Pow_GE_v(newCount);//找出大於newCount的2次冪,做新的容量
		size_t newSize = _arr->capacity * sizeof(int);

		//新的尺寸還不如舊的尺寸的話,就報錯!
		hjASSERT(newSize > oldSize, "faint ... memory allocate!");

		//申請新的內存空間
		_arr->data = (int*)hjMemManager(_vm, _arr->data, oldSize, newSize);

	}

	//添加數據
	uint32_t i = 0;
	for (; i < _fillCount; ++i, ++_arr->count) {
		_arr->data[_arr->count] = _data;
	}

}

hjPUBLIC void hjAdd_IntArray(hjVM* _vm, hjIntArray* _arr, int _data) {
	hjWrite_IntArray(_vm, _arr, _data, 1);
}

hjPUBLIC void hjClear_IntgArray(hjVM* _vm, hjIntArray* _arr) {
	uint32_t size = _arr->capacity * sizeof(_arr->data[0]);
	hjMemManager(_vm, _arr->data, size, 0);//size => 0
	hjInit_IntArray(_arr);

}


//hj_utf8.cpp
#include"hj_utf8.h"




//獲取編碼UTF8後的字節數
hjPUBLIC uint32_t hjGet_ByteNumOfEncodedUTF8(int _value) {
	hjASSERT(_value > 0, "can't encode negative value!");

	//單個ASCII一個字節
	if (_value <= 0x7f)return 1;
	//此範圍內數值編碼爲UTF8需要2字節
	if (_value <= 0x7ff)return 2;
	//此範圍內數值編碼爲UTF8需要3字節
	if (_value <= 0xffff)return 3;
	//此範圍內數值編碼爲UTF8需要4字節
	if (_value <= 0x10ffff)return 4;


	//超過範圍返回0
	return 0;

}


//獲取解碼UTF8後的字節數
hjPUBLIC uint32_t hjGet_ByteNumOfDecodedUTF8(uint8_t _byte) {

	//_byte應該是UTF8的最高一字節,如果指定了UTF8編碼後面的低字節部分則返回0
	
	if ((_byte & 0xc0) == 0x80)return 0;
	if ((_byte & 0xf8) == 0xf0)return 4;
	if ((_byte & 0xf0) == 0xe0)return 3;
	if ((_byte & 0xe0) == 0xc0)return 2;

	//ASCII碼
	return 1;
}


//編碼UTF8
hjPUBLIC uint8_t hjEncodeUTF8(uint8_t* _buf, int _value) {

	hjASSERT(_value > 0, "can't encode negative value!");

	/*按照大端模式寫入緩衝區*/

	//單個ASCII一個字節
	if (_value <= 0x7f) {
		*_buf = _value & 0x7f;
		return 1;
	}
	//此範圍內數值編碼爲UTF8需要2字節
	if (_value <= 0x7ff) {
		//先寫入高字節
		*_buf++ = 0xc0 | ((_value & 0x7c0) >> 6);
		//再寫入低字節
		*_buf = 0x80 | (_value & 0x3f);
		return 2;
	}
	//此範圍內數值編碼爲UTF8需要3字節
	if (_value <= 0xffff) {
		//先寫入高字節
		*_buf++ = 0xe0 | ((_value & 0xf000) >> 12);
		//再寫入中字節
		*_buf++ = 0x80 | ((_value & 0xfc0) >> 6);
		//再寫入低字節
		*_buf = 0x80 | (_value & 0x3f);
		return 3;
	}
	//此範圍內數值編碼爲UTF8需要4字節
	if (_value <= 0x10ffff){
		*_buf++ = 0xf0 | ((_value & 0x1c0000) >> 18);
		*_buf++ = 0x80 | ((_value & 0x3f000) >> 12);
		*_buf++ = 0x80 | ((_value & 0xfc0) >> 6);
		*_buf = 0x80 | (_value & 0x3f);
		return 4;
	}

	hjNOT_REACHED;
	//超過範圍返回0
	return 0;
}


//解碼UTF8
hjPUBLIC int hjDecodeUTF8(const uint8_t* _bytePtr, uint32_t _len) {

	//如果是一字節的ASCII碼:0xxx'xxxx
	if (*_bytePtr <= 0x7f)return *_bytePtr;


	int value;
	uint32_t remainingBytes;



	/*先讀取高字節*/
	if ((*_bytePtr & 0xe0) == 0xc0) {  //如果是2字節的UTF8
		value = *_bytePtr & 0x1f;
		remainingBytes = 1;
	}
	else if ((*_bytePtr & 0xf0) == 0xe0) {  //如果是3字節的UTF8
		value = *_bytePtr & 0x0f;
		remainingBytes = 2;
	}
	else if ((*_bytePtr & 0xf8) == 0xf0) {  //如果是4字節的UTF8
		value = *_bytePtr & 0x07;
		remainingBytes = 3;
	}
	else { //非法編碼
		return -1;
	}


	/*如果UTF8被折斷就不再讀過去了*/
	if (remainingBytes > _len - 1)return -1;


	/*再讀取低字節*/
	
	for (; remainingBytes > 0;) {
		++_bytePtr;
		--remainingBytes;

		//高2位必須是10
		if ((*_bytePtr & 0xc0) != 0x80)return -1;

		//從次高序往低字節讀,不斷累加各字節的低6位
		value = value << 6 | (*_bytePtr & 0x3f);

	}

	return value;
}

//hj_lexer.cpp
#include"hj_lexer.h"



/*初始化全局變量*/
char* hj_rootDir="";




/*定義私有化結構體和映射表*/
//關鍵字
typedef struct hjKeyToken {
	char* keyword;					//關鍵字字符串
	uint8_t len;						//字符串長度
	hjTokenType type;			//關鍵字類型
}hjKeyToken;


//關鍵字映射表
hjKeyToken hjMap_KeyToken[] = {
	{"let",3,hjTOKEN_LET},
	{"function",8,hjTOKEN_FUNCTION},
	{"if",2,hjTOKEN_IF},
	{"else",4,hjTOKEN_ELSE},
	{"hjTRUE",4,hjTOKEN_TRUE},
	{"hjFALSE",5,hjTOKEN_FALSE},
	{"while",5,hjTOKEN_WHILE},
	{"for",3,hjTOKEN_FOR},
	{"break",5,hjTOKEN_BREAK},
	{"continue",8,hjTOKEN_CONTINUE},
	{"return",6,hjTOKEN_RETURN},
	{"Nil",3,hjTOKEN_NIL},
	{"class",5,hjTOKEN_CLASS},
	{"self",4,hjTOKEN_SELF},
	{"static",6,hjTOKEN_STATIC},
	{"is",2,hjTOKEN_IS},
	{"super",5,hjTOKEN_SUPER},
	{"import",6,hjTOKEN_IMPORT}
};









//讀取腳本
hjPUBLIC char* hjReadScript(const char* _path) {
	FILE* file = fopen(_path, "r");
	if (file == NULL) {
		__hjERROR_IO__("Couldn't open file \"%s\".", _path);
	}


	//獲取文件大小
	struct stat myStat;
	stat(_path, &myStat);
	size_t fileSize = myStat.st_size;
	char* fileContent = (char*)malloc(1 + fileSize);
	if (fileContent == NULL) {
		__hjERROR_MEM__("Couldn't allocate memory for reading file \"%s\".\n", _path);
	}

	
	//將文件中的內容按char的步長讀取進fileContent內
	if (fread(fileContent, sizeof(char), fileSize, file) == 0) {
		__hjERROR_IO__("Couldn't read file \"%s\".", _path);
	}
	fileContent[fileSize] = '\0';
	fclose(file);
	return fileContent;
}








//初始化詞法分析器
hjPUBLIC hjInit_Lexer(hjVM* _vm, hjLexer* _lexer, const char* _file, const char* _srcCode) {

	//設置文件路徑
	_lexer->file = _file;
	//設置源碼字符串
	_lexer->srcCode = _srcCode;
	//設置當前字符
	_lexer->curChar = *_srcCode;
	//設置下一個字符指針
	_lexer->next = _lexer->srcCode + 1;
	//初始化當前單詞
	_lexer->curToken.lineNo = 1;
	_lexer->curToken.len = 0;
	_lexer->curToken.start = NULL;
	_lexer->curToken.type = hjTOKEN_UNKNOWN;
	//初始先前單詞
	_lexer->preToken = _lexer->curToken;
	//初始化(計數器
	_lexer->Lcounter = 0;
	//初始化虛擬機
	_lexer->vm = _vm;


}


//查看下一個字符
hjPUBLIC char hjPeek_NextChar(hjLexer* _lexer) {
	return *(_lexer->next);
}




//獲取下一個單詞
hjPUBLIC void hjGet_NextToken(hjLexer* _lexer) {

	/*當前單詞指針後移*/
	_lexer->preToken = _lexer->curToken;
	//跳過待識別單詞之間的空格
	hjSkip_Blanks(_lexer);
	//初始化當前單詞
	_lexer->curToken.type = hjTOKEN_EOF;
	_lexer->curToken.len = 0;
	_lexer->curToken.start = _lexer->next - 1;



	for (;_lexer->curChar!='\0';) {

		switch (_lexer->curChar) {
		/*
		case '@':
			_lexer->curToken.type = hjTOKEN_AT;
			break;
		case '#':
			_lexer->curToken.type = hjTOKEN_WELL;
			break;
		case '`':	//重音
			_lexer->curToken.type = hjTOKEN_ACCENT;
			break;
		case ';':		//分號
			_lexer->curToken.type = hjTOKEN_SEMI;
			break;
		case '\\':     反斜槓
			_lexer->curToken.type = hjTOKEN_SEMI;
			break;
			*/

		case ':':		//冒號
			_lexer->curToken.type = hjTOKEN_COLON;
			break;
		case ',':		//逗號
			_lexer->curToken.type = hjTOKEN_COMMA;
			break;
		case '.':		//點     
			if (hjMatch_NextChar(_lexer, '.')) {//兩個連續的點
				_lexer->curToken.type = hjTOKEN_DOT_DOT;
			}
			else {//一個點
				_lexer->curToken.type = hjTOKEN_DOT;
			}
			break;
		case '(':
			if (_lexer->Lcounter > 0) {
				++_lexer->Lcounter;//遇到(加一
			}
			_lexer->curToken.type = hjTOKEN_LEFT_PAREN;
			break;
		case ')':
			if (_lexer->Lcounter > 0) {
				--_lexer->Lcounter;//遇到)減一
				
				if (_lexer->Lcounter == 0) {
					hjLex_Str(_lexer);
					break;
				}

			}
			_lexer->curToken.type = hjTOKEN_RIGHT_PAREN;
			break;
		case '[':
			_lexer->curToken.type = hjTOKEN_LEFT_BRACKET;
			break;
		case ']':
			_lexer->curToken.type = hjTOKEN_RIGHT_BRACKET;
			break;
		case '{':
			_lexer->curToken.type = hjTOKEN_LEFT_BRACE;
			break;
		case '}':
			_lexer->curToken.type = hjTOKEN_RIGHT_BRACE;
			break;
		case '=':
			if (hjMatch_NextChar(_lexer, '=')) {//判斷等於
				_lexer->curToken.type = hjTOKEN_EQ;
			}
			else {//賦值
				_lexer->curToken.type = hjTOKEN_ASSIGN;
			}
			break;
		case '+':
			_lexer->curToken.type = hjTOKEN_ADD;
			break;
		case '-':
			_lexer->curToken.type = hjTOKEN_SUB;
			break;
		case '*':
			_lexer->curToken.type = hjTOKEN_MUL;
			break;
		case '/':
			if (hjMatch_NextChar(_lexer,'/') ) { //單行註釋
				hjSkip_CommentALine(_lexer);
				_lexer->curToken.start = _lexer->next - 1;
				continue;
			}
			else if (hjMatch_NextChar(_lexer, '*')) {  //多行註釋
				hjSkip_Comment(_lexer);
				_lexer->curToken.start = _lexer->next - 1;
				continue;
			}
			else { //除號
				_lexer->curToken.type = hjTOKEN_DIV;
			}
			break;
		case '%':
			_lexer->curToken.type = hjTOKEN_MOD;
			break;
		case '^':
			_lexer->curToken.type = hjTOKEN_POW;
			break;
		case '&':
			if (hjMatch_NextChar(_lexer, '&')) {//邏輯與
				_lexer->curToken.type = hjTOKEN_LOGIC_AND;
			}
			else {//位運算與
				_lexer->curToken.type = hjTOKEN_BIT_AND;
			}
			break;
		case '|':
			if (hjMatch_NextChar(_lexer, '|')) {//邏輯或
				_lexer->curToken.type = hjTOKEN_LOGIC_OR;
			}
			else {//位運算或
				_lexer->curToken.type = hjTOKEN_BIT_OR;
			}
			break;	
		case '!':
			if (hjMatch_NextChar(_lexer, '=')) {//不等於
				_lexer->curToken.type = hjTOKEN_NEQ;
			}
			else {//邏輯非
				_lexer->curToken.type = hjTOKEN_LOGIC_NOT;
			}
			break;
		case '~':
			_lexer->curToken.type = hjTOKEN_BIT_NOT;
			break;
		case '<':
			if (hjMatch_NextChar(_lexer, '=')) {//<=
				_lexer->curToken.type = hjTOKEN_LE;
			}
			else {//<
				_lexer->curToken.type = hjTOKEN_LT;
			}
			break;
		case '>':
			if (hjMatch_NextChar(_lexer, '=')) {//>=
				_lexer->curToken.type = hjTOKEN_GE;
			}
			else {//>
				_lexer->curToken.type = hjTOKEN_GT;
			}
			break;
		case '?':
			_lexer->curToken.type = hjTOKEN_QUE;
			break;
		case '"':	//雙引號
			hjLex_Str(_lexer);
			break;	
		/*eol、eof 沒有處理。eof沒辦法處理,但是eol之後可以想法處理一下	*/
		default:
			//如果首字符是字母或下劃線
			if (hjJudge_Alpha(_lexer->curChar) || _lexer->curChar == '_') {
				hjLex_Id(_lexer,hjTOKEN_UNKNOWN);
			}
			//不處理#!及其後面的內容
			else 	if (_lexer->curChar == '#' && hjMatch_NextChar(_lexer, '!')) {
				hjSkip_ALine(_lexer);

				_lexer->curToken.start = _lexer->next - 1;
				continue;
			}
			else{
				///__hjERROR_LEX__(_lexer, "unsupport char : \"%c\" , quit.", _lexer->curChar);
			}
			return;
		}


		/*默認執行上面操作一次就退出了,但是可能遇到continue,那樣就可能循環幾遍*/
		_lexer->curToken.len = (uint32_t)(_lexer->next - _lexer->curToken.start);
		hjGet_NextChar(_lexer);
		return;
	}
}




/*
匹配單詞
如果當前token是所期望的話,就讀入下一個token並返回true,否則返回false
*/
hjPUBLIC hjBOOL hjMatch_Token(hjLexer* _lexer, hjTokenType _expectedToken) {

	if (_lexer->curToken.type == _expectedToken) {
		hjGet_NextToken(_lexer);
		return hjTRUE;
	}
	return hjFALSE;
}


/*
吸收當前單詞
斷言當前token爲所期望的話,就讀入下一個token,否則報錯
*/
hjPUBLIC void hjConsume_CurToken(hjLexer* _lexer, hjTokenType _expectedToken, const char* _errMsg) {
	if (_lexer->curToken.type == _expectedToken) {
		hjGet_NextToken(_lexer);
	}	
	else {
		__hjERROR_COMPILE__(_lexer, _errMsg);
	}
}


/*
吸收下一個單詞
斷言當前token爲所期望的,否則報錯
*/
hjPUBLIC void hjConsume_NextToken(hjLexer* _lexer, hjTokenType _expectedToken, const char* _errMsg) {
	hjGet_NextToken(_lexer);
	if (_lexer->curToken.type != _expectedToken) {
		__hjERROR_COMPILE__(_lexer, _errMsg);
	}
}









//判斷是否是數字
hjPRIVATE hjBOOL hjJudge_Num(char _c) {
	if (_c <= 57 && _c >= 48)return hjTRUE;
	return hjFALSE;
}
//判斷是否是字母
hjPRIVATE hjBOOL hjJudge_Alpha(char _c) {
	if ((_c <= 90 && _c >= 65 )|| (_c<= 122&& _c>= 97) )return hjTRUE;
	return hjFALSE;
}


/*
判斷是標識符還是關鍵字
輸入的字符串肯定是標識符或者是關鍵字,這個函數就是具體區分一下到底是哪種
關鍵字,還是標識符!
*/
hjPRIVATE hjTokenType hjJudge_IdOrKey(const char* _start, uint32_t _len) {
	
	uint32_t i ;
	for (i=0; hjMap_KeyToken[i].keyword != NULL;++i) {
		if (hjMap_KeyToken[i].len == _len && \
			memcmp(hjMap_KeyToken[i].keyword ,_start,_len ) == 0) {
			return hjMap_KeyToken[i].type;//返回具體的關鍵字類型
		}
	}
	
	//如果不是關鍵字那就是標識符了
	return hjTOKEN_ID;
}


//獲取下一個字符
hjPRIVATE void hjGet_NextChar(hjLexer* _lexer) {
	_lexer->curChar = *(_lexer->next);//下一個字符當做是當前字符
	++_lexer->next;//下一個字符後(這個指針的移動應該是在srcCode上移動的)
}


/*
匹配下一個字符
如果匹配上了,就後移當前字符指針,否則就不移動!
*/
hjPRIVATE hjBOOL hjMatch_NextChar(hjLexer* _lexer,char _expectedChar) {
	if ( hjPeek_NextChar(_lexer)== _expectedChar ) {//如果下一個字符是我所希望的字符的話,就獲取該字符
		hjGet_NextChar(_lexer);
		return hjTRUE;
	}
	return hjFALSE;
}





//跳過連續的空字符
hjPRIVATE void hjSkip_Blanks(hjLexer* _lexer) {
	for (;_lexer->curChar == ' '||_lexer->curChar=='\n'||_lexer->curChar=='\t'||_lexer->curChar=='\r';) {
		if (_lexer->curChar == '\n') {
			++_lexer->curToken.lineNo;//行數加一
		}
		hjGet_NextChar(_lexer);
	}
}



//跳過單行註釋
hjPRIVATE void hjSkip_CommentALine(hjLexer* _lexer) {
	//跳過一行
	hjSkip_ALine(_lexer);
	//註釋之後有可能會有空白字符
	hjSkip_Blanks(_lexer);
}


//跳過多行註釋
hjPRIVATE void hjSkip_Comment(hjLexer* _lexer) {

	char nextChar = hjPeek_NextChar(_lexer);
	//吸收註釋內的字符
	for (; nextChar != '*' && nextChar != '\0';) {
		hjGet_NextChar(_lexer);
		if (_lexer->curChar == '\n') {
			++_lexer->curToken.lineNo;//行數加一
		}
		nextChar = hjPeek_NextChar(_lexer);
	}

	//匹配 */
	if (hjMatch_NextChar(_lexer, '*')) {
		if (!hjMatch_NextChar(_lexer, '/')) {
			__hjERROR_LEX__(_lexer, "expect \"/\" after \"*\"!");
		}
		hjGet_NextChar(_lexer);
	}
	else {
		__hjERROR_LEX__(_lexer, "expect \"*/\" before file end!");
	}


	//註釋之後有可能會有空白字符
	hjSkip_Blanks(_lexer);
}


//跳過一行
hjPRIVATE void hjSkip_ALine(hjLexer* _lexer) {
	
	hjGet_NextChar(_lexer);
	for (;_lexer->curChar!='\0';) {
		if (_lexer->curChar=='\n') {
			++_lexer->curToken.lineNo;//行數加一
			hjGet_NextChar(_lexer);
			break;
		}
		hjGet_NextChar(_lexer);
	}
}







//解析標識符
hjPRIVATE void hjLex_Id(hjLexer* _lexer, hjTokenType _token) {

	//標識符是字母或下劃線開頭的,後面是連續的字母或數字或下劃線
	for (;hjJudge_Num(_lexer->curChar)|| hjJudge_Alpha(_lexer->curChar) || _lexer->curChar == '_';) {
		hjGet_NextChar(_lexer);
	}

	//next指向第一個不合法字符的下一個字符,因此要-1
	uint32_t len = (uint32_t)(_lexer->next - _lexer->curToken.start - 1);

	if (_token != hjTOKEN_UNKNOWN) {
		_lexer->curToken.type = _token;
	}
	else { //是關鍵字或者是標識符
		_lexer->curToken.type = hjJudge_IdOrKey(_lexer->curToken.start, len);
	}

	_lexer->curToken.len = len;
	
}


//解析字符串
hjPRIVATE void hjLex_Str(hjLexer* _lexer) {

	hjByteArray str;
	hjInit_ByteArray(&str);
	
	for (;1;) {
		hjGet_NextChar(_lexer);

		if (_lexer->curChar == '\0') {
			__hjERROR_LEX__(_lexer, "unterminated string!");
		}
		else if (_lexer->curChar == '"') {  //雙引號
			_lexer->curToken.type = hjTOKEN_STR;
			break;
		}
		else if (_lexer->curChar == '%') {  
			if (!hjMatch_NextChar(_lexer, '(')) { //%後面沒有跟着(
				__hjERROR_LEX__(_lexer, "\"%\" should followed by \"(\"!");
			}
			
			if(_lexer->Lcounter>0){ //
				__hjERROR_COMPILE__(_lexer, "not support nest interpolate expression");
			}

			_lexer->Lcounter = 1;
			_lexer->curToken.type = hjTOKEN_EXPR;
			break;
		}


		/*處理轉移字符*/
		if (_lexer->curChar == '\\') {
			hjGet_NextChar(_lexer);

			switch (_lexer->curChar) {
			case '0':
				hjAdd_ByteArray(_lexer->vm, &str, '\0');
				break;
			case 'a':
				hjAdd_ByteArray(_lexer->vm, &str, '\a');
				break;
			case 'b':
				hjAdd_ByteArray(_lexer->vm, &str, '\b');
				break;
			case 'f':
				hjAdd_ByteArray(_lexer->vm, &str, '\f');
				break;
			case 'n':
				hjAdd_ByteArray(_lexer->vm, &str, '\n');
				break;
			case 'r':
				hjAdd_ByteArray(_lexer->vm, &str, '\r');
				break;
			case 't':
				hjAdd_ByteArray(_lexer->vm, &str, '\t');
				break;
			case 'u':
				hjLex_CodePointOfUTF8(_lexer, &str);
				break;
			case '"':	//雙引號
				hjAdd_ByteArray(_lexer->vm, &str, '"');
				break;
			case '\\':
				hjAdd_ByteArray(_lexer->vm, &str, '\\');
				break;
			default:
				__hjERROR_LEX__(_lexer, "unsupport escape \\%c", _lexer->curChar);
				break;
			}
		}
		else {
			hjAdd_ByteArray(_lexer->vm, &str, _lexer->curChar);
		}


	}


	hjClear_ByteArray(_lexer->vm, &str);

}


//解析UTF8碼點
hjPRIVATE void hjLex_CodePointOfUTF8(hjLexer* _lexer, hjByteArray* _buf) {


	uint32_t i;
	int value = 0;
	uint8_t digit = 0;
	//獲得數值,u後面跟着4位16進制數字
	for (i=0;i<4;) {
		++i;
		hjGet_NextChar(_lexer);
		if (_lexer->curChar == '\0') {
			__hjERROR_LEX__(_lexer, "unterminated unicode!");
		}
		else if (_lexer->curChar >= '0' && _lexer->curChar <= '9') {
			digit = _lexer->curChar - '0';
		}
		else if (_lexer->curChar >= 'a' && _lexer->curChar <= 'f') {
			digit = _lexer->curChar - 'a'+10;
		}
		else if (_lexer->curChar >= 'A' && _lexer->curChar <= 'F') {
			digit = _lexer->curChar - 'A' + 10;
		}
		else{
			__hjERROR_LEX__(_lexer, "invalid unicode!");
		}

		value = (value * 16) | digit;
	}


	uint32_t byteNum = hjGet_ByteNumOfEncodedUTF8(value);
	hjASSERT(byteNum != 0, "utf8 encode bytes should be between 1 and 4 ");


	/*
	爲了代碼通用,下面會直接寫 _buf->data ,在此先寫入byteNum個0,
	以保證事先有byteNum個空間
	*/
	hjWrite_ByteArray(_lexer->vm, _buf, 0, byteNum);
	//把value編碼成utf8後寫入緩衝區
	hjEncodeUTF8(_buf->data + _buf->count - byteNum, value);
}




//hj_vm.cpp
#include"hj_vm.h"



//初始化虛擬機
hjPUBLIC void hjInit_VM(hjVM* _vm) {
	_vm->allocatedByte = 0;
	_vm->curLexer = NULL;
}
//創建虛擬機
hjPUBLIC hjVM* hjNew_VM() {
	hjVM* vm = (hjVM*)malloc(sizeof(hjVM));
	if (vm == NULL) {

	}
	hjInit_VM(vm);
	return vm;
}

主函數的文件hj.cpp

//hj.cpp
#include"hj_lexer.h"

/*
項目文件引用關係——下次做個打印文件引用關係的工具!!!
common 
|————core
|				|————error 
|				|				|————vm
|				|								|————lexer
|		        |
|				|————mem
|				|				|————lexer
|				|				|				|
|				|				|
|
|
|
|————utf8
|				|————lexer

*/

void test_error() {
	hjLexer* myLexer = (hjLexer*)malloc(sizeof(hjLexer));


	hjToken* myToken = (hjToken*)malloc(sizeof(hjToken));
	myToken->lineNo = 50;
	myToken->start = "function";
	myToken->type = hjTOKEN_FUNCTION;

	myLexer->curToken = *myToken;
	myLexer->file = "E:\\C\\hjRun.hj";


	hjError(myLexer, hjERROR_MEM, "出錯了!!!");

}





//執行腳本文件
hjPRIVATE void hjRunScript(const char* _path) {
	const char* lastSlash = strrchr(_path, '/');

	if (lastSlash != NULL) {
		char* root = (char*)malloc(lastSlash - _path + 2);
		memcpy(root, _path, lastSlash - _path + 1);
		root[lastSlash - _path + 1] = '\0';
		hj_rootDir = root;
	}

	
	//創建虛擬機
	hjVM* vm = hjNew_VM();

	//讀取腳本
	const char* srcCode = hjReadScript(_path);

	//創建詞法分析器
	hjLexer  myLexer;
	hjInit_Lexer(vm, &myLexer, _path, srcCode);

	//導入單詞表
#include "token.list"

	uint32_t i = 0;
	for (; myLexer.curToken.type != hjTOKEN_EOF;) {
		hjGet_NextToken(&myLexer);
		//打印行號和單詞類型
		printf("%d:%s[", myLexer.curToken.lineNo, hjTokenArr[myLexer.curToken.type]);
		
		//打印單詞
		for (i=0; i < myLexer.curToken.len;++i) {
			printf("%c", *(myLexer.curToken.start+i));
		}

		printf("]\n");
	}

}



int main(int argc,const char** argv) {

	argc = 2;
	argv[1] = "test.hj";

	//test_error();
	if (argc < 2) {
		printf("參數不夠");
		return 0;
	}


	hjRunScript(argv[1]);

	system("pause");
	return 0;
}


token.list

這個無所謂,把數組放在其他文件也一樣!

char* hjTokenArr[] = {
	"UNKNOWN",
	"NUM",				
	"STR",				
	"ID",					
	"EXPR",				
	"LET",				
	"FUNCTION",	
	"IF",					
	"ELSE",				
	"TRUE",				
	"FALSE",			
	"WHILE",			
	"FOR",				
	"BREAK",			
	"CONTINUE",	
	"RETURN",		
	"NIL",					
	"CLASS",			
	"SELF",				
	"STATIC",			
	"IS",					
	"SUPER",			
	"IMPORT",		
	"AT",					
	"WELL",				
	"ACCENT",		
	"SEMI",	
	"BACKSLASH",
    "COLON",			
    "COMMA",			
    "DOT",				
    "DOT_DOT",		
    "LEFT_PAREN",
    "RIGHT_PAREN",
    "LEFT_BRACKET",
    "RIGHT_BRACKET",
    "LEFT_BRACE",
    "RIGHT_BRACE",
	"ASSIGN",
    "ADD",				
    "SUB",				
    "MUL",				
    "DIV",				
    "MOD",				
    "POW",				
    "BIT_AND",		
    "BIT_OR",			
    "BIT_NOT",		
    "BIT_SHIFT_LEFT",
    "BIT_SHIFT_RRIGHT",
    "LOGIC_AND",	
    "LOGIC_OR",	
    "LOGIC_NOT",	 
    "EQ",					
    "NEQ",				
    "GT",					
    "GE",					
    "LT",					
    "LE",					
    "QUE",				
    "EOL",				
    "EOF"				
};

  \;
  \;
  \;
  \;

測試文件test.hj

//   單行註釋
/*
	多
	行
	注
	釋
*/
import people for People
function func(){
	print("hello word")
	let p = People.new("demllie","turtle")
	p.run()
}


class Family : People{
	let father
	let mother
	let child
	new(f,m,c){
		father = f
		mother = m
		child = c

		super("Kiana","wife")
	}
}


let f = Family.new("Kiana","female","shine")
f.run()

func()


運行結果

8:IMPORT[import]
8:ID[people]
8:FOR[for]
8:ID[People]
9:FUNCTION[function]
9:ID[func]
9:LEFT_PAREN[(]
9:RIGHT_PAREN[)]
9:LEFT_BRACE[{]
10:ID[print]
10:LEFT_PAREN[(]
10:STR["hello word"]
10:RIGHT_PAREN[)]
11:LET[let]
11:ID[p]
11:ASSIGN[=]
11:ID[People]
11:DOT[.]
11:ID[new]
11:LEFT_PAREN[(]
11:STR["demllie"]
11:COMMA[,]
11:STR["turtle"]
11:RIGHT_PAREN[)]
12:ID[p]
12:DOT[.]
12:ID[run]
12:LEFT_PAREN[(]
12:RIGHT_PAREN[)]
13:RIGHT_BRACE[}]
16:CLASS[class]
16:ID[Family]
16:COLON[:]
16:ID[People]
16:LEFT_BRACE[{]
17:LET[let]
17:ID[father]
18:LET[let]
18:ID[mother]
19:LET[let]
19:ID[child]
20:ID[new]
20:LEFT_PAREN[(]
20:ID[f]
20:COMMA[,]
20:ID[m]
20:COMMA[,]
20:ID[c]
20:RIGHT_PAREN[)]
20:LEFT_BRACE[{]
21:ID[father]
21:ASSIGN[=]
21:ID[f]
22:ID[mother]
22:ASSIGN[=]
22:ID[m]
23:ID[child]
23:ASSIGN[=]
23:ID[c]
25:SUPER[super]
25:LEFT_PAREN[(]
25:STR["Kiana"]
25:COMMA[,]
25:STR["wife"]
25:RIGHT_PAREN[)]
26:RIGHT_BRACE[}]
27:RIGHT_BRACE[}]
30:LET[let]
30:ID[f]
30:ASSIGN[=]
30:ID[Family]
30:DOT[.]
30:ID[new]
30:LEFT_PAREN[(]
30:STR["Kiana"]
30:COMMA[,]
30:STR["female"]
30:COMMA[,]
30:STR["shine"]
30:RIGHT_PAREN[)]
31:ID[f]
31:DOT[.]
31:ID[run]
31:LEFT_PAREN[(]
31:RIGHT_PAREN[)]
33:ID[func]
33:LEFT_PAREN[(]
33:RIGHT_PAREN[)]
35:EOF[]

最後

除了編碼風格外,文件依賴關係也變了,增加了幾種token類型,更改了關鍵字!

hj=happy joy

參考:《自制編程語言,基於C語言》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章