Compiler

Compiler

compiler.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdarg>

/*
** @ Name: Simplified C Compiler
** @ Auther: TBAALi
** @ Time: 2019-07-24
**
** @ Introduction:
**        SC 语言(源程序) -> SCC编译器 -> Intelx86机器语言(目标语言)
**        控制台程序的函数入口为:mainCRTStartup
**
**             源程序
**               |
**         预处理,词法分析 - 此法着色
**               |
**            语法分析     - 语法自动缩进
**               |
**            语义分析
**               |
**           Obj目标文件
**               |
**             链接器      - 库文件
**               |
**          exe可执行文件
**
**       形式语言:不考虑语义,只从语法这一方面来看待语言
**       巴克斯范式:是一种形式化符号类描述给定语言的语法,从一个符号开始然后给出替换前面符号的规则
**
		 EBNF:
		   元符号       表示含义        备注
			::=         定义为,推导为
			 |          或者
			< >         尖括号用于括起非终结符
			{ }         含0次在内任意多次重复
			[ ]         含0次或1次
			( )         括号内看做一项
			.           一条生成规则的结束
			“ ”         终结符
**
**       SC语言以C89为蓝本进行简化:
         1. 支持单字节、双字节、四字节的基本数据类型。
		 2. 支持数组、结构体
		 3. 支持字符串
		 4. 支持函数、局部变量、全局变量
		 5. 支持条件语句、循环语句
		 6. 支持基本的算术运算、关系运算
		 7. 能用多种方式实现的功能,只保留一种
		 
		 SC语言字符集由字母、数字、空格、标点和特殊字符组成
		 源码字符集:用于书写SC语言源文件的字符集
		 执行字符集:SC语言编译后在执行环境中解释的字符集

		 基本字符集:
		 1. 字母
		  * 英文26个小写字母
		   a 
		   b
		   c
		   d
		   e
		   f
		   g
		   h
		   i
		   j
		   k
		   l
		   m
		   n
		   o
		   p
		   q
		   r
		   s
		   t
		   u
		   v
		   w
		   x
		   y
		   z
		  * 英文26个大写字母
		   A
		   B
		   C
		   D
		   E
		   F
		   G
		   H
		   I
		   J
		   K
		   L
		   M
		   N
		   O
		   P
		   Q
		   R
		   S
		   T
		   U
		   V
		   W
		   X
		   Y
		   Z
		 2. 下滑线
		   _
		 3. 10个数字
		   0
		   1
		   2
		   3
		   4
		   5
		   6
		   7
		   8
		   9
		4. 标点和特殊符号
		   +
		   -
		   *
		   /
		   %
		   =
		   !
		   >
		   <
		   .
		   &
		   (
		   )
		   [
		   ]
		   {
		   }
		   ;
		   :
		   \
		   "
		   '
		5. 空白符
		  空格符、制表符、换行符。空白符只在字符常量和字符串常量中起作用
		6. 空字符
		  字节的所有位均置为0
		
	    SC语言词法定义
		 1. 关键字
		  * 定义:
		  <char关键字>::="char"
		  <short关键字>::="short"
		  <int关键字>::="int"
		  <void关键字>::="void"
		  <struct关键字>::="struct"
		  <if关键字>::="if"
		  <else关键字>::="else"
		  <for关键字>::="for"
		  <continue关键字>::="continue"
		  <break关键字>::="break"
		  <return关键字>::="return"
		  <sizeof关键字>::="sizeof"
		  <__cdecl关键字>::="__cdecl"
		  <__stdcall关键字>::="__stacall"
		  <__align关键字>::="__align"
		  * 语义
		  ...
		  __cdecl : 函数调用约定关键字 __cdecl调用约定
		  __stdcall : 函数调用约定关键字 __stdcall调用约定
		  __align : 结构成员对齐函数 __align(n)强制结构成员对齐到n
		2. 标识符
		 * 定义
		 <标识符>::=<非数字>{<数字>|<非数字>}
		 <非数字>::=
			"_"
			|"a"
			|"b"
			|"c"
			|"d"
			|"e"
			|"f"
			|"h"
			|"i"
			|"j"
			|"k"
			|"l"
			|"m"
			|"n"
			|"o"
			|"p"
			|"q"
			|"r"
			|"s"
			|"t"
			|"u"
			|"v"
			|"w"
			|"x"
			|"y"
			|"z"
			|"A"
			|"B"
			|"C"
			|"D"
			|"E"
			|"F"
			|"G"
			|"H"
			|"I"
			|"J"
			|"K"
			|"L"
			|"M"
			|"N"
			|"O"
			|"P"
			|"Q"
			|"R"
			|"S"
			|"T"
			|"U"
			|"V"
			|"W"
			|"X"
			|"Y"
			|"Z"
          <数字>::=
			 "0"
			|"1"
			|"2"
			|"3"
			|"4"
			|"5"
			|"6"
			|"7"
			|"8"
			|"9"
          * 语义
		    标识符可以代表很多实体:函数、变量、结构体名称、结构体成员名、数组名
		3. 整数常量
		   * 定义
		   <整数常量>::=<数字>{<数字>}
		   <数字>::=
		    "0"
			|"1"
			|"2"
			|"3"
			|"4"
			|"5"
			|"6"
			|"7"
			|"8"
			|"9"
            * 语义
			整数常量的值以10为基计算,语法上的第一个数字是最高有效位
         4. 字符常量
		    * 定义
			<字符常量>::='<C-字符>'
			<C-字符>::=<转义序列>|源字符集中除单引号', 反斜杠\, 新行字符外的任何字符
			<转义序列>为下列序列之一
			 \' 
			 \"
			 \\
			 \a
			 \b
			 \f
			 \n
			 \r
			 \t
			 \v
			 * 语义
			 整型字符常量的类型是int
		  5. 字符串常量
		     * 定义
			 <字符串常量>::="{<串字符>}"
			 <串字符>::=<转义字符>|源字符集中除双引号", 反斜杠\, 新行字符外的任何字符。
			 * 语义
			 字符串常量实际是字节数组,该数组的元素类型为char,用该多字节符序列中的各个字节初始化数组的各个元素。
          6. 运算符及分隔符
		     * 定义
			 <加号>::="+"
			 <减号>::="-"
			 <星号>::="*"
			 <除号>::="\"
			 <取余号>::="%"
			 <等于号>::="=="
			 <不等于号>::="!="
			 <小于号>::="<"
			 <小于等于号>::="<="
			 <大于号>::=">"
			 <大于等于号>::=">="
			 <赋值等号>::="="
			 <箭头>::="->"
			 <点号>::="."
			 <与号>::="&"
			 <左小括号>::="("
			 <右小括号>::=")"
			 <左中括号>::="["
			 <右中括号>::="]"
			 <左大括号>::="{"
			 <右大括号>::="}"
			 <分号>::=";"
			 <逗号>::=","
			 <省略号>::="..."
			 * 语义
			 算符说明要执行的运算
			 分隔符是具有独立的语法和语义含义的符号
			 [] () {} 应成对出现
          7. 注释
		     \*  *\  中间的部分

        SC语言语法定义
		外部声明
		  1. 外部声明
		   * 定义
		   <翻译单元>::={<外部声明>}<文件结束符>
		   <外部声明>::=<函数定义>|<声明>
		   * 语义
		   每个SC源文件就是一个翻译单元,由一系列外部声明构成,出现在任何函数之外,
		   因而具有全局作用域。
		 2. 函数定义
		   * 定义
		   <函数定义>::=<类型区分符><声明符><函数体>
		   <函数体>::=<符合语句>
		   * 语义
		   函数定义中的声明符指定要定义的函数名以及形参列表
         3. 声明
		   * 定义
		   <声明>::=<类型区分符>[<初始值声明符号>]<分号>
		   <初始值声明符表>::=<初始值声明符>{<逗号><初始值声符>}
		   <初始值声明符>::=<声明符>|<声明符><赋值运算符><初始值符>
		   * 语义
		   声明规定了一组标识符的解释和属性,而同时还导致为标识符所代表的对象或函数保留存储空间的声明
		   类型区分符指示声明符所代表实体的部分。
         4. 类型区分符
		   * 定义
		   <类型区分符>::=<void关键字>
		    |<char关键字>
			|<int关键字>
			|<short关键字>
			|<结构区分符>
           <结构区分符>::=<struct关键字>
		    <标识符>
		    <左大括号>
		    <结构声明表>
		    <右大括号>
		    |<struct关键字>
		    <标识符>
		   <结构声明表>::=<结构声明>{<结构声明>}
		   <结构声明>::=<类型区分符>{<结构声明符表>}<分号>
		   <结构声明符表>::=<声明符>{<逗号><声明符>}
         5. 声明符
		   * 定义
		   <声明符>::={<指针>}[<调用约定>][<结构成员对齐>]<直接声明符>
		   <调用约定>::=<__cdecl关键字>|<__stdcall关键字>
           <结构成员对齐>::=<__align关键字><左小括号><整数常量><右小括号>
		   <指针>::=<星号>
		   <直接声明符>::=<标识符><直接声明符后缀>
		   <直接声明符后缀>::={<左中括号><右中括号>}
		    |<左中括号><整数常量><右中括号>
			|<左小括号><右小括号>
			|<左小括号><形参表><右小括号>}
           <参数声明>::=<类型区分符><声明符>
		   * 语义
		   每个声明符声明一个标识符,并表明当某个表达式中出现于该声明符形式相同的操作数时
		   则该操作数指示一个函数或对象,他们具有声明区分符所指出的作用域、存储期及类型。
		6. 初始值符
		   * 定义
		   <初始值符>::=<赋值表达式>、
		   * 语义
		   初值符规定存储在对象中的初始值,若未显示的初始化一个自动存储期的对象,则其值不确定
       
	   语句
	     1. 语句
		 * 定义
		 <语句>::={<符合语句>
		   |<if语句>
		   |<for语句>
		   |<break语句>
		   |<continue语句>
		   |<return语句>
		   |<表达式语句>}
         * 语义
		 语句规定了要执行的动作,除非特别规定外,语句均按顺序执行
		 2. 复合语句
		 * 定义
		 <复合语句>::=<左大括号>{<声明>}{<语句>}<右大括号>
		 * 语义
		 复合语句允许将一系列语句组合成一个语法单位。
		 3. 表达式语句与空语句
		 * 定义
		 <表达式语句>::=[<expression>]<分号>
		 * 语义
		 表达式语句中的表达式将按void表达式求值以获得其副作用
		 4. 选择语句
		 * 定义
		 <if语句>::=<if关键字><左小括号><表达式><右小括号><语句>[<else关键字><语句>]
		 5. 循环语句
		 * 定义
		 <for语句>::=<for关键字><左小括号><表达式语句><表达式语句><表达式><右小括号><语句>
		 6. 跳转语句
		 * 定义
		 <continue语句>::=<continue关键字><分号>
		 <break语句>::=<break关键字><分号>
		 <return语句>::=<return关键字><expression><分号>
	  表达式
	     1. 表达式
		 * 定义
		 <表达式>::=<赋值表达式>{<逗号><赋值表达式>}
		 * 语义
		 表达式是由算符和操作数组成的序列,它规定了对一个值的计算,或产生一个副作用,或他们的组合。
		 2. 赋值表达式
		 * 定义
		 <赋值表达式>::=<相等类表达式>|<一元表达式><赋值等号><赋值表达式>
		 3. 相等类表达式
		 * 定义
		 <相等类表达式>::=<关系表达式>{<等于号><关系表达式>|<不等于号><关系表达式>}
		 4. 关系表达式
		 * 定义
		 <关系表达式>::=<加减类表达式>{<小于号><加减类表达式>
		   |<大于号><加减类表达式>
		   |<小于等于号><加减类表达式>
		   |<大于等于号><加减类表达式>}
         5. 加减类表达式
		 * 定义
		 <加减类表达式>::=<乘除类表达式>{<加号><乘除类表达式>
		  |<减号><乘除类表达式>}
		 6. 乘除类表达式
		 * 定义
		 <乘除类表达式>::=<一元表达式>{
		  <星号><一元表达式>
		  |<除号><一元表达式>
		  |<取余运算符><一元表达式>}
		 7. 一元表达式
		 * 定义
		 <一元表达式>::=<后缀表达式>
		  |<与号><一元表达式>
		  |<星号><一元表达式>
		  |<加号><一元表达式>
		  |<减号><一元表达式>
		  |<sizeof表达式>
		 <sizeof表达式>::=<sizeof关键字>(<类型区分符>)
		 8. 后缀表达式
		 * 定义
		 <后缀表达式>::=<初等表达式>{
		  <左中括号><expression><右中括号>
		  |<左小括号><右小括号>
		  |<左小括号><实参表达式><右小括号>
		  |<点号>IDENTIFIER
		  |<箭头>IDENTIFIER}
		 <实参表达式>::=<赋值表达式>{<逗号><赋值表达式>}
		 9. 初等表达式
		 <初等表达式>::=<标识符>|<整数常量>|<字符串常量>|<字符常量>|(<表达式>)


     SC语言词法分析
	   源程序是由字符序列构成的,此法分析器扫描源程序字符串,根据语言的此法规则分析并识别具有独立意识
	   的最小语法单元:单词码,并以某种编码形式输出。

**
*/
void ERROR(const char* error_msg)
{
	printf("ERROR: %s \n", error_msg);
}

/*
** 单词编码
*/
enum e_TokenCode
{
	/*运算符及分隔符*/
	TK_PLUS,    // + 
	TK_MINUS,   // -
	TK_STAR,    // *
	TK_DIVIDE,  // /
	TK_MOD,     // %
	TK_EQ,      // ==
	TK_NEQ,     // !=
	TK_LT,      // <
	TK_LEQ,     // <=
	TK_GT,      // >
	TK_GEQ,     // >=
	TK_ASSIGN,  // =
	TK_POINTSTO,// ->
	TK_DOT,     // .
	TK_AND,     // $
	TK_OPENPA,  // (
	TK_CLOSEPA, // )
	TK_OPENBR,  // [
	TK_CLOSEBR, // ]
	TK_BEGIN,   // {
	TK_END,     // }
	TK_SEMICOLON, // ;
	TK_COMMA,   // ,
	TK_ELLIPSIS,// ...
	TK_EOF,     // 文件结束符

	/*常量*/
	TK_CINT,    // 整型常量
	TK_CCHAR,   // 字符常量
	TK_CSTR,    // 字符串常量

	/*关键字*/
	KW_CHAR,    // char
	KW_SHORT,   // short
	KW_INT,     // int
	KW_VOID,    // void
	KW_STRUCT,  // struct
	KW_IF,      // if
	KW_ELSE,    // else
	KW_FOR,     // for
	KW_CONTINUE,// continue
	KW_BREAK,   // break
	KW_RETURN,  // return
	KW_SIZEOF,  // sizeof

	KW_ALIGN,   // __align
	KW_CDECL,   // __cdecl
	KW_STDCALL, // __stdcall

	/*标识符*/
	TK_IDENT,
};

/*C中字符串是以连续的字节流表示的 以  '\0' 结尾*/
/*动态字符串定义*/
typedef struct DynString
{
	int count;       // 字符串长度
	int capacity;    // 包含该字符串的缓冲区长度
	char* data;      // 指向字符串的指针
} DynString;

/*动态字符串操作函数*/
void dynstring_init(DynString* pstr, int initsize); 
void dynstring_free(DynString* pstr);
void dynstring_reset(DynString* pstr);
void dynstring_realloc(DynString* pstr, int new_size);
void dynstring_chcat(DynString* pstr, int ch);

/*动态数租定义*/
typedef struct DynArray
{
	int count;      // 动态数组元素个数
	int capacity;   // 动态数组缓存区长度
	void** data;    // 指向数据指针数组
} DynArray;

/*单词表*/
/*单词存储结构定义*/
e_TokenCode token;                                      // ++++++++++++++++ 得确定

typedef struct TkWord
{
	int tkcode;                       /*单词编码*/
	struct TkWord* next;              /*指向hash冲突的同义词*/
	char* spelling;                   /*单词字符串*/
	struct Symbol* sym_struct;        /*指向单词所表示的结构的定义*/
	struct Symbol* sym_identifier;    /*指向单词所表示的标识符*/
} TkWord;

/*动态数组操作*/
void dynarray_realloc(DynArray* parr, int new_size);
void dynarray_add(DynArray* parr, void* data);
void dynarray_init(DynArray* parr, int initsize);
void dynarray_free(DynArray* parr);
int dynarray_search(DynArray* parr, int key);

/*哈希表函数*/
#define MAXKEY 1024                   /*哈希表长度*/
TkWord* tk_hashtable[MAXKEY];         /*单词哈希表*/
DynArray tktable;                     /*单词表*/

int elf_hash(char* key);


/*单词表操作函数*/
TkWord* tkword_direct_insert(TkWord* tp);
TkWord* tkword_find(char* p, int keyno);
TkWord* tkword_insert(char* p);
void* mallocz(int size);

/*此法分析初始化*/
void init_lex();

/*错误处理*/
/*错误处理程序用到的枚举定义*/
/*错误级别*/
enum e_ErrorLevel
{
	LEVEL_WARNING,
	LEVEL_ERROR,
};

/*工作阶段*/
enum e_WorkStage
{
	STAGE_COMPILE,
	STAGE_LINK,
};

void handle_exception(int stage, int level, char* fmt, va_list ap);
void warning(char* fmt, ...);
void error(char* fmt, ...);
void except(char* msg);
void skip(int c);
char* get_tkstr(int v);
void link_error(char* fmt, ...);

char ch;
/*此法分析*/
void get_token();
void getch();

/*预处理*/
void preprocess();
void parse_comment();
void skip_white_space();

/*解析标识符*/
int is_nodigit(char c);
int is_digit(char c);
void parse_identifier();
void parse_num();
void parse_string(char sep);

/*此法着色*/
void color_token(int lex_state);

/*词法分析用到的全局变量*/
TkWord* tk_hashtable[MAXKEY];         // 单词哈希表
DynArray tktable;                                     // 单词表中放置标识符,包括变量名,函数名,数据结构定义名
DynString tkstr;                                      // 单词字符串
DynString sourcestr;                              // 单词源码字符串
int tkvalue;    											// 单词值,单词为整型常量
char ch;													// 当前取得的源码字符
int token; 												// 单词编码
int line_num;											// 行号                                                               

main.cpp

#include "compiler.h"
#include <iostream>

int main()
{
	std::cout << "Compiler" << std::endl;
	return 0;
}

void _entry()
{
	int ret;
	ret = main();
	exit(ret);
}

/* ===============================================
* 初始化动态字符串存储容量
* pstr: 动态字符换存储结构
* initsize: 字符串初始化分配空间
*/
void dynstring_init(DynString* pstr, int initsize)
{
	if (pstr != NULL)
	{
		pstr->data = (char*)malloc(sizeof(char) * initsize);
		pstr->count = 0;
		pstr->capacity = initsize;
	}
}

/* ================================================
* 释放动态字符串使用的内训空间
* pstr: 动态字符换存储结构
*/
void dynstring_free(DynString* pstr)
{
	if (pstr != NULL)
	{
		if (pstr->data)
		{
			free(pstr->data);
		}

		pstr->count = 0;
		pstr->capacity = 0;
	}
}

/* =================================================
* 重置动态字符串,先释放,重新初始化
* pstr: 动态字符串存储结构
*/
void dynstring_reset(DynString* pstr)
{
	dynstring_free(pstr);
	dynstring_init(pstr, 8);     /*字符串初始化分配空间8字节*/
}

/* ==================================================
* 重新分配字符换容量
* pstr: 动态字符串存储结构
* new_size: 字符串新长度
*/
void dynstring_realloc(DynString* pstr, int new_size)
{
	int capacity_;
	char* data_;

	capacity_ = pstr->capacity;
	while (capacity_ < new_size)
	{
		capacity_ = capacity_ * 2;
	}

	data_ = (char*)realloc(pstr->data, capacity_); /* 重新分配内存块大小, void* 指向之前已经分配内存块的指针, size_t 新大小 */
	if (!data_)
	{
		error("内存分配失败!");
	}

	pstr->capacity = capacity_;
	pstr->data = data_;
}

/* ==================================================
* 追加单个字符到动态字符串对象
* pstr: 动态字符串存储结构
* ch: 所要追加的字符
*/
void dynstring_chcat(DynString* pstr, int ch)
{
	int count_;
	count_ = pstr->count + 1;
	if (count_ > pstr->capacity)
	{
		dynstring_realloc(pstr, count_);
	}

	((char*)pstr->data)[count_ - 1] = ch;
	pstr->count = count_;
}

/* ==================================================
* 重新分配动态数组容量
* parr: 动态数组存储容量
* new_size: 动态数组最新元素个数
*/
void dynarray_realloc(DynArray* parr, int new_size)
{
	int capacity;
	void* data;

	capacity = parr->capacity;
	while (capacity < new_size)
	{
		capacity = capacity * 2;
	}

	data = realloc(parr->data, capacity);
	if (!data)
	{
		error("内存分配失败!");
	}

	parr->capacity = capacity;
	parr->data = (void**)data;  // TMD
}

/* ===============================================
* 追加动态数组元素
* parr: 动态数组存储结构
* data: 所要追加的新元素
*/
void dynarray_add(DynArray* parr, void* data)
{
	int count;
	count = parr->count + 1;
	if (count * sizeof(void*) > parr->capacity)
	{
		dynarray_realloc(parr, count * sizeof(void*));
	}

	parr->data[count - 1] = data;
	parr->count = count;
}

/* ===============================================
* 初始化动态数组存储容量
* parr: 动态数组存储结构
* initsize: 动态数组初始化分配空间
*/
void dynarray_init(DynArray* parr, int initsize)
{
	if (parr != NULL)
	{
		parr->data = (void**)malloc(sizeof(void*) * initsize);
		parr->count = 0;
		parr->capacity = initsize;
	}
}

/* ===============================================
* 释放动态数组使用的内存空间
* parr: 动态数组存储结构
*/
void dynarray_free(DynArray* parr)
{
	void** p;
	for (p = parr->data;
		parr->count;
		++p, --parr->count)
	{
		if (*p)
		{
			free(*p);
		}

		free(parr->data);
		parr->data = NULL;
	}
}

/* ==================================================
* 动态数组元素查找
* parr: 动态数组查找结构
* key: 要查找的元素
*/
int dynarray_search(DynArray* parr, int key)
{
	int i;
	int** p;
	p = (int**)parr->data;
	for (i = 0; i < parr->count; ++i, p++)
	{
		if (key == **p)
		{
			return i;
		}
	}

	return -1;
}

compiler.cpp


#include "Compiler.h"


int main()
{
	std::cout << "Heelo" << std::endl;
	return 0;

}

/* ===============================================
* 初始化动态字符串存储容量
* pstr: 动态字符换存储结构
* initsize: 字符串初始化分配空间
*/
void dynstring_init(DynString* pstr, int initsize)
{
	if (pstr != NULL)
	{
		pstr->data = (char*)malloc(sizeof(char) * initsize);
		pstr->count = 0;
		pstr->capacity = initsize;
	}
}

/* ================================================
* 释放动态字符串使用的内训空间
* pstr: 动态字符换存储结构
*/
void dynstring_free(DynString* pstr)
{
	if (pstr != NULL)
	{
		if (pstr->data)
		{
			free(pstr->data);
		}

		pstr->count = 0;
		pstr->capacity = 0;
	}
}

/* =================================================
* 重置动态字符串,先释放,重新初始化
* pstr: 动态字符串存储结构
*/
void dynstring_reset(DynString* pstr)
{
	dynstring_free(pstr);
	dynstring_init(pstr, 8);     /*字符串初始化分配空间8字节*/
}

/* ==================================================
* 重新分配字符换容量
* pstr: 动态字符串存储结构
* new_size: 字符串新长度
*/
void dynstring_realloc(DynString* pstr, int new_size)
{
	int capacity_;
	char* data_;

	capacity_ = pstr->capacity;
	while (capacity_ < new_size)
	{
		capacity_ = capacity_ * 2;
	}

	data_ = (char*)realloc(pstr->data, capacity_); /* 重新分配内存块大小, void* 指向之前已经分配内存块的指针, size_t 新大小 */
	if (!data_)
	{
		ERROR("内存分配失败!");
	}

	pstr->capacity = capacity_;
	pstr->data = data_;
}

/* ==================================================
* 追加单个字符到动态字符串对象
* pstr: 动态字符串存储结构
* ch: 所要追加的字符
*/
void dynstring_chcat(DynString* pstr, int ch)
{
	int count_;
	count_ = pstr->count + 1;
	if (count_ > pstr->capacity)
	{
		dynstring_realloc(pstr, count_);
	}

	((char*)pstr->data)[count_ - 1] = ch;
	pstr->count = count_;
}

/* ==================================================
* 重新分配动态数组容量
* parr: 动态数组存储容量
* new_size: 动态数组最新元素个数
*/
void dynarray_realloc(DynArray* parr, int new_size)
{
	int capacity;
	void* data;

	capacity = parr->capacity;
	while (capacity < new_size)
	{
		capacity = capacity * 2;
	}

	data = realloc(parr->data, capacity);
	if (!data)
	{
		ERROR("内存分配失败!");
	}

	parr->capacity = capacity;
	parr->data = (void**)data;  // TMD
}

/* ===============================================
* 追加动态数组元素
* parr: 动态数组存储结构
* data: 所要追加的新元素
*/
void dynarray_add(DynArray* parr, void* data)
{
	int count;
	count = parr->count + 1;
	if (count * sizeof(void*) > (unsigned int)parr->capacity)
	{
		dynarray_realloc(parr, count * sizeof(void*));
	}

	parr->data[count - 1] = data;
	parr->count = count;
}

/* ===============================================
* 初始化动态数组存储容量
* parr: 动态数组存储结构
* initsize: 动态数组初始化分配空间
*/
void dynarray_init(DynArray* parr, int initsize)
{
	if (parr != NULL)
	{
		parr->data = (void**)malloc(sizeof(void*) * initsize);
		parr->count = 0;
		parr->capacity = initsize;
	}
}

/* ===============================================
* 释放动态数组使用的内存空间
* parr: 动态数组存储结构
*/
void dynarray_free(DynArray* parr)
{
	void** p;
	for (p = parr->data;
		parr->count;
		++p, --parr->count)
	{
		if (*p)
		{
			free(*p);
		}

		free(parr->data);
		parr->data = NULL;
	}
}

/* ==================================================
* 动态数组元素查找
* parr: 动态数组查找结构
* key: 要查找的元素
*/
int dynarray_search(DynArray* parr, int key)
{
	int i;
	int** p;
	p = (int**)parr->data;
	for (i = 0; i < parr->count; ++i, p++)
	{
		if (key == **p)
		{
			return i;
		}
	}

	return -1;
}

/*2019-08-21 20:04*/
/* ==================================================
* 我们需要的哈希函数是以单词字符串为关键字进行哈希计算的
* 计算哈希地址
* key: 哈希关键字
* MAXKEY: 哈希表长度
*/
int elf_hash(char* key)
{
	int h = 0;
	int g;
	while (*key)
	{
		h = (h << 4) + *key++;
		g = h & 0xf0000000;
		if (g)
		{
			h ^= g >> 24;
		}

		h &= ~g;
	}

	return h % MAXKEY;
}

/*单词表操作函数: */
/* ======================================================
* 运算符,关键字,常量直接放入单词表
*/
TkWord* tkword_direct_insert(TkWord* tp)
{
	int keyno;
	dynarray_add(&tktable, tp);
	keyno = elf_hash(tp->spelling);
	tp->next = tk_hashtable[keyno];
	tk_hashtable[keyno] = tp;
	return tp;
}

/* ======================================================
* 在单词表中查找单词
* p: 要查找的单词
8 keyno: 要查找单词的哈希值
*/
TkWord* tkword_find(char* p, int keyno)
{
	TkWord* tp = NULL;
	TkWord* tp1;
	for (tp1 = tk_hashtable[keyno]; tp1; tp1 = tp1->next)
	{
		if (!strcmp(p, tp1->spelling))   // 比较字符串
		{
			token = (e_TokenCode)tp1->tkcode;           /* error token得确定*/
			tp = tp1;
		}
	}

	return tp;
}

/* ======================================================
* 标识符插入单词表,先查找,查找不到再插入单词表
*/
TkWord* tkword_insert(char* p)
{
	TkWord* tp;
	int keyno;
	char* s;
	char* end;
	int length;

	keyno = elf_hash(p);
	tp = tkword_find(p, keyno);

	if (tp == NULL)
	{
		length = strlen(p);
		tp = (TkWord*)mallocz(sizeof(TkWord) + length + 1);
		tp->next = tk_hashtable[keyno];
		tk_hashtable[keyno] = tp;
		dynarray_add(&tktable, tp);
		tp->tkcode = tktable.count - 1;
		s = (char*)tp + sizeof(TkWord);
		tp->spelling = (char*)s;
		for (end = p + length; p < end; )
		{
			*s++ = *p++;
		}

		*s = (char)'\0';
	}

	return tp;
}

/* ======================================================
* 分配堆内存,并将数据初始花化为0
* size: 分配内存大小
*/
void* mallocz(int size)
{
	void* ptr;
	ptr = malloc(size);
	if (!ptr && size)
	{
		ERROR("内存分配失败!");
	}

	memset(ptr, 0, size);
	return ptr;
}

/* ======================================================
* 此法分析初始化
* typedef struct TkWord
* {
*	int tkcode;                     /*单词编码
* struct TkWord* next;              /*指向hash冲突的同义词
* char* spelling;                   /*单词字符串
* struct Symbol* sym_struct;        /*指向单词所表示的结构的定义
* struct Symbol* sym_identifier;    /*指向单词所表示的标识符
* } TkWord;
*/
void init_lex()
{
	TkWord* tp;
	static TkWord keyword[] =
	{
		/*单词编码*/       /*指向hash冲突的同义词*/  /*单词字符串*/  /*指向单词所表示的结构的定义*/  /*指向单词所表示的标识符*/
		{TK_PLUS,         NULL,                    (char*)"+",            NULL,                        NULL},   // +
		{TK_MINUS,        NULL,                    (char*)"-",            NULL,                        NULL},   // -
		{TK_STAR,         NULL,                    (char*)"*",            NULL,                        NULL},   // *
		{TK_DIVIDE,       NULL,                    (char*)"/",            NULL,                        NULL},   // /
		{TK_MOD,          NULL,                    (char*)"%",            NULL,                        NULL},   // %
		{TK_EQ,           NULL,                    (char*)"==",           NULL,                        NULL},   // ==
		{TK_NEQ,          NULL,                    (char*)"~=",           NULL,                        NULL},   // !=
		{TK_LT,           NULL,                    (char*)"<",            NULL,                        NULL},   // <
		{TK_LEQ,          NULL,                    (char*)"<=",           NULL,                        NULL},   // <=
		{TK_GT,           NULL,                    (char*)">",            NULL,                        NULL},   // >
		{TK_GEQ,          NULL,                    (char*)">=",           NULL,                        NULL},   // >=
		{TK_ASSIGN,       NULL,                    (char*)"=",            NULL,                        NULL},   // =
		{TK_POINTSTO,     NULL,                    (char*)"->",           NULL,                        NULL},   // ->
		{TK_DOT,          NULL,                    (char*)".",            NULL,                        NULL},   // .
		{TK_AND,          NULL,                    (char*)"$",            NULL,                        NULL},   // $
		{TK_OPENPA,       NULL,                    (char*)"(",            NULL,                        NULL},   // (
		{TK_CLOSEPA,      NULL,                    (char*)")",            NULL,                        NULL},   // )
		{TK_OPENBR,       NULL,                    (char*)"[",            NULL,                        NULL},   // [
		{TK_CLOSEBR,      NULL,                    (char*)"]",            NULL,                        NULL},   // ]
		{TK_BEGIN,        NULL,                    (char*)"{",            NULL,                        NULL},   // {
		{TK_END,          NULL,                    (char*)"}",            NULL,                        NULL},   // }
		{TK_SEMICOLON,    NULL,                    (char*)";",            NULL,                        NULL},   // ;
		{TK_COMMA,        NULL,                    (char*)",",            NULL,                        NULL},   // ,
		{TK_ELLIPSIS,     NULL,                    (char*)"...",          NULL,                        NULL},   // ...
		{TK_EOF,          NULL,                    (char*)"End_Of_File",  NULL,                        NULL},   // 文件结束符

		/*常量*/
		{TK_CINT,         NULL,                    (char*)"整型常量",      NULL,                        NULL},   // 整型常量
		{TK_CCHAR,        NULL,                    (char*)"字符常量",      NULL,                        NULL},   // 字符常量
		{TK_CSTR,         NULL,                    (char*)"字符串常量",    NULL,                        NULL},   // 字符串常量

		/*关键字*/
		{KW_CHAR,         NULL,                    (char*)"char",         NULL,                        NULL},   // char
		{KW_SHORT,        NULL,                    (char*)"short",        NULL,                        NULL},   // short
		{KW_INT,          NULL,                    (char*)"int",          NULL,                        NULL},   // int
		{KW_VOID,         NULL,                    (char*)"void",         NULL,                        NULL},   // void
		{KW_STRUCT,       NULL,                    (char*)"struct",       NULL,                        NULL},   // struct
		{KW_IF,           NULL,                    (char*)"if",           NULL,                        NULL},   // if
		{KW_ELSE,         NULL,                    (char*)"else",         NULL,                        NULL},   // else
		{KW_FOR,          NULL,                    (char*)"for",          NULL,                        NULL},   // for
		{KW_CONTINUE,     NULL,                    (char*)"continue",     NULL,                        NULL},   // continue
		{KW_BREAK,        NULL,                    (char*)"break",        NULL,                        NULL},   // break
		{KW_RETURN,       NULL,                    (char*)"return",       NULL,                        NULL},   // return
		{KW_SIZEOF,       NULL,                    (char*)"sizeof",       NULL,                        NULL},   // sizeof

		{KW_ALIGN,        NULL,                    (char*)"__align",      NULL,                        NULL},   // __align
		{KW_CDECL,        NULL,                    (char*)"__cdecl",      NULL,                        NULL},   // __cdecl
		{KW_STDCALL,      NULL,                    (char*)"__stdcall",    NULL,                        NULL},   // __stdcall

		/*标识符*/
		{TK_IDENT,        NULL,                    (char*)"标识符",        NULL,                        NULL},

		{0,               NULL,                     NULL,                  NULL,                        NULL},
	};

	/*关键字,运算符优先进入单词表*/
	dynarray_init(&tktable, 8);
	for (tp = &keyword[0]; tp->spelling != NULL; tp++)
	{
		tkword_direct_insert(tp);
	}
}

/*错误处理*/
/*错误处理程序用到的枚举定义*/
/*错误级别*/
/* ======================================================
* 异常处理
* stage: 编译阶段还是链接阶段
* level: 错误级别
* fmt: 参数输出的格式
* ap: 可变参数列表
*/
void handle_exception(int stage, int level, char* fmt, va_list ap)
{
	char buf[1024];
	vsprintf(buf, fmt, ap); /*使用参数格式换输出*/
	if (stage == STAGE_COMPILE)
	{
		if (level == LEVEL_WARNING)
		{
			printf("%s(第%d行):编译警告:%s~\n", __FILE__, __LINE__, buf);
		}
		else
		{
			printf("%s(第%d行):编译错误:%s~\n", __FILE__, __LINE__, buf);
			exit(-1);
		}
	}
	else
	{
		printf("链接错误:%s\n!", buf);
	}
}

/* ======================================================
* 编译警告处理
* fmt: 参数输出格式
* ap: 可变参数列表
*/
void warning(char* fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	handle_exception(STAGE_COMPILE, LEVEL_WARNING, fmt, ap);
	va_end(ap);
}

/* ============================================================
* 编译致命错误处理
* fmt: 参数输出格式
* ap: 可变参数列表
*/
void error(char* fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	handle_exception(STAGE_COMPILE, LEVEL_ERROR, fmt, ap);
	va_end(ap);
}

/* ============================================================
* 错误提示,此处缺少某个语法成分
* msg: 需要什么语法成分
*/
void except(char* msg)
{
	error((char*)"缺少%s", msg);
}

/* ============================================================
* 跳过单词c,取下一个单词,如果当前单词不是c,提示错误
* c: 要跳过的单词
*/
void skip(int c)
{
	if (token != c)
	{
		error((char*)"缺少 '%s' ", get_tkstr(c));
	}

	// get_token();
}

/* ============================================================
* 取得单词v所代表的源码字符串
* V: 单词编号
*/
char* get_tkstr(int v)
{
	if (v > tktable.count)
	{
		return NULL;
	}
	else if (v >= TK_CINT && v <= TK_CSTR)
	{
		// return sourcestr.data;
	}
	else
	{
		return ((TkWord*)tktable.data[v])->spelling;
	}
}

/* ============================================================
* 链接错误处理
* fmt: 参数输出格式
* ap: 可变参数列表
*/
void link_error(char* fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	handle_exception(STAGE_LINK, LEVEL_ERROR, fmt, ap);
	va_end(ap);
}

/*此法分析过程*/
/* ============================================================
* 取单词
*/
/*此法分析*/
void get_token()
{
	preprocess();
	switch (ch)
	{
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
		case 'g':
		case 'h':
		case 'i':
		case 'j':
		case 'k':
		case 'l':
		case 'm':
		case 'n':
		case 'o':
		case 'p':
		case 'q':
		case 'r':
		case 's':
		case 't':
		case 'u':
		case 'v':
		case 'w':
		case 'x':
		case 'y':
		case 'z':
		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
		case 'G':
		case 'H':
		case 'I':
		case 'J':
		case 'L':
		case 'M':
		case 'N':
		case 'O':
		case 'P':
		case 'Q':
		case 'R':
		case 'S':
		case 'T':
		case 'U':
		case 'V':
		case 'W':
		case 'X':
		case 'Y':
		case 'Z':
		case '_':
		{
			TkWord* tp;
			parse_identifier();
			tp = tkword_insert(tkstr.data);
			token = (e_TokenCode)(tp->tkcode);
		}

		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		{
			parse_num();
			token = TK_CINT;
			break;
		}

		case'+':
			getch();
			token = TK_PLUS;
			break;

			
		case'-':
			getch();
			if (ch == '>')
			{
				token = TK_POINTSTO;
				getch();
			}
			else
			{
				token = TK_MINUS;
			}

			break;

		case'/':
			token = TK_DIVIDE;
			getch();
			break;

		case'%':
			token = TK_MOD;
			getch();
			break;

		case'=':
			getch();
			if (ch == '=')
			{
				token = TK_EQ;
				getch();
			}
			else
				token = TK_ASSIGN;
			break;

		case'!':
			getch();
			if (ch == '=')
			{
				token = TK_NEQ;
				getch();
			}
			else
				error((char*)"暂不支持");
			break;

		case'<':
			getch();
			if (ch == '=')
			{
				token = TK_LEQ;
				getch();
			}
			else
				token = TK_LT;
			break;

		case'>':
			getch();
			if (ch == '=')
			{
				token = TK_GEQ;
				getch();
			}
			else
				token = TK_GT;
			break;

		case'.':
			getch();
			if (ch == '.')
			{
				getch();
				if (ch != '.')
				{
					error((char*)"...拼写错误!");
				}
				else
				{
					token = TK_ELLIPSIS;
				}

				getch();
			}
			else
			{
				token = TK_DOT;
			}
			break;

		case'&':
			token = TK_AND;
			getch();
			break;

		case';':
			token = TK_SEMICOLON;
			getch();
			break;

		case']':
			token = TK_CLOSEBR;
			getch();
			break;

		case'}':
			token = TK_END;
			getch();
			break;

		case')':
			token = TK_CLOSEPA;
			getch();
			break;

		case'[':
			token = TK_OPENBR;
			getch();
			break;

		case'{':
			token = TK_BEGIN;
			getch();
			break;

		case',':
			token = TK_COMMA;
			getch();
			break;

		case'(':
			token = TK_OPENPA;
			getch();
			break;

		case'*':
			token = TK_STAR;
			getch();
			break;

		case'\'':
			parse_string(ch);
			token = TK_CCHAR;
			// tkvalue = *(char*)tkstr.data;
			break;

		case'\"':
			parse_string(ch);
			token = TK_CSTR;
			break;

		case EOF:
			token = TK_EOF;
			break;

		default:
			error((char*)"不认识的字符:\\x%02x ", ch);
			getch();
			break;
	}
}

/* ============================================================
* 从SC源文件中读取一个字符
*/
void getch()
{
	ch = getc(fin);           // 文件尾返回EOF,其他返回实际字符值
}

/*预处理*/
/* ============================================================
* 预处理,忽略空白字符及注释
*/
void preprocess()
{
	while (1)
	{
		if (ch == ' '
			|| ch == '\t'
			|| ch == '\r')
			skip_white_space();
		else if (ch == '/')
		{
			// 向前再读一个字节看是否是注释开始,猜错了把多读的字符放回去
			getch();
			if (ch == '*')
			{
				parse_comment();
			}
			else
			{
				ungetc(ch, fin);       // 把一个字符退回到输入流中
				ch = '/';
				break;
			}
		}
		else
			break;
	}
}

/* ============================================================
* 解释注释
*/
void parse_comment()
{
	getch();
	do
	{
		if (ch == '\n' 
		 || ch == '*'
		 || ch == CH_EOF)
		 break;
		 else
			 getch();
	}while(1);
	
	if (ch == '\n')
	{
		line_num++;
		getch();
	}
	else if (ch == '*')
	{
		getch();
		if (ch == '/')
		{
			getch();
			return;
		}
	}
	else
	{
		error("一直到文件末尾未看到配对的注释结束符!");
		return;
	}
		
}

/* ==================================================
* 空白字符处理,忽略空格,Tab,回车
*/
void skip_white_space()
{
	while (ch == ' ' 
	    || ch == '\t'
		|| ch == '\r')
		{
			if (ch == '\r')
			{
				getch();
				if (ch != '\n')
					return;
				lint_num++;
			}
			
			printf("%c", ch);
			getch();
		}
}

/*解析标识符*/
/* ==================================================
* 判断c是否为字母或下划线
* c: 字符值
*/
int is_nodigit(char c)
{
	return (c >= 'a'
	     && c <= 'z')
		 || (c >= 'A'
		 && c <= 'Z')
		 || c == '+';
}

/* ==================================================
* 判断c是否为数字
* c: 字符值
*/	
int is_digit(char c)
{
	return c >= '0' && c <= '9';
}

/* ===================================================
* 解析标识符
*/
void parse_identifier()
{
	dynstring_reset(&tkstr);
	dynstring_chcat(&tkstr, ch);
	getch();
	while(is_nodigit(ch)
		|| is_digit(ch))
		{
			dynstring_chcat(&tkstr, ch);
			getch();
		}
		
		dynstring_chcat(&tkstr, '\0');
}

/* ==================================================
* 解析整型常量
*/
void parse_num()
{
	
}
void parse_string(char sep);

/*此法着色*/
void color_token(int lex_state);
``
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值