📄 compiler.cpp
字号:
/****************************************************/
/* 文件 compiler.cpp */
/* 说明 类compiler的内部实现实现 */
/* 主题 编译器结构:原理和实例 */
/****************************************************/
/************ 该代码文件所包含的头文件 **************/
#include "globals.h" /* 该头文件globals.h定义了全局类与变量 */
#include "string.h"
#include "ctype.h" /* 用到了该库中的isalnum,isalpha,isdigit函数 */
#include "func.h" /* 该头文件func.h定义了相关功能函数 */
#include "math.h" /* 用到了这个库里的取模运算 */
#include "compiler.h"
#include "stdio.h"
#include<iostream.h>
/************************************************************/
/* 成员函数名 compiler */
/* 功 能 构造函数 */
/* 说 明 */
/************************************************************/
compiler::compiler()
{
tokenlist=NULL;
Tree=NULL;
}
/*=========================词法分析==================================*/
/************************************************************/
/* 函数名 getTokenlist */
/* 功 能 取得单词函数 */
/* 说 明 函数从源文件字符串序列中获取所有Token序列 */
/* 使用确定性有限自动机DFA,采用直接转向法 */
/* 超前读字符,对保留字采用查表方式识别 */
/* 产生词法错误时候,仅仅略过产生错误的字符,不加改正 */
/************************************************************/
ChainNodeType * compiler::getTokenlist(FILE * source)
{
ChainNodeType *chainHead; /*链表的表头指针*/
ChainNodeType *currentNode; /*指向处理当前Token的当前结点*/
ChainNodeType *preNode; /*指向当前结点的前驱结点*/
TokenType currentToken; /*存放当前的Token*/
/*产生链表的第一个结点*/
chainHead=preNode=currentNode=(ChainNodeType *)malloc(CHAINNODELEN);
/*初始化当前结点中,指向下一个结点的指针为空*/
(*currentNode).nextToken=NULL;
do
{ /* tokenStringIndex用于记录当前正在识别单词的词元存储区 *
* tokenString中的当前正在识别字符位置,初始为0 */
int tokenStringIndex = 0;
/* 当前状态标志state,始终都是以START作为开始 */
StateType state = START;
/* tokenString的存储标志save,整数类型 *
* 决定当前识别字符是否存入当前识别单词词元存储区tokenString */
int save;
/* 当前确定性有限自动机DFA状态state不是完成状态DONE */
while (state != DONE)
{
/* 从源代码文件中获取下一个字符,送入变量c作为当前字符 */
int c = scanner::getNextChar(source);
/* 当前正识别字符的存储标志save初始为TRUE */
save = TRUE;
switch (state)
{
/* 当前DFA状态state为开始状态START,DFA处于当前单词开始位置 */
case START:
/* 当前字符c为数字,当前DFA状态state设置为数字状态INNUM *
* 确定性有限自动机DFA处于数字类型单词中 */
if (isdigit(c))
state = INNUM;
/* 当前字符c为字母,当前DFA状态state设置为标识符状态INID *
* 确定性有限自动机DFA处于标识符类型单词中 */
else if (isalpha(c))
state = INID;
/* 当前字符c为冒号,当前DFA状态state设置为赋值状态INASSIGN *
* 确定性有限自动机DFA处于赋值类型单词中 */
else if (c == ':')
state = INASSIGN;
/* 当前字符c为.,当前DFA状态state设置为数组下标界限状态*/
/* INRANGE,确定性有限自动机DFA处于数组下标界限类型单词中*/
else if (c == '.')
state = INRANGE;
/* 当前字符c为',当前DFA状态state设置为字符标志状态*/
/* INCHAR,确定性有限自动机DFA处于字符标志类型单词中*/
else if (c == '\'')
{
save = FALSE;
state = INCHAR;
}
/* 当前字符c为空白(空格,制表符,换行符),字符存储标志save设置为FALSE *
* 当前字符为分隔符,不需要产生单词,无须存储 */
else if ((c == ' ') || (c == '\t') || (c == '\n'))
save = FALSE;
/* 当前字符c为左括号,字符存储标志save设置为FALSE *
* 当前DFA状态state设置为注释状态INCOMMENT *
* 确定性有限自动机DFA处于注释中,不生成单词,无需存储 */
else if (c == '{')
{
save = FALSE;
state = INCOMMENT;
}
/* 当前字符c为其它字符,当前DFA状态state设置为完成状态DONE *
* 确定性有限自动机DFA处于单词的结束位置,需进一步分类处理 */
else
{
state = DONE;
switch (c)
{
/* 当前字符c为EOF,字符存储标志save设置为FALSE,无需存储 *
* 当前识别单词返回值currentToken设置为文件结束单词ENDFILE */
case EOF:
save = FALSE;
currentToken.Lex = ENDFILE;
break;
/* 当前字符c为"=",当前识别单词返回值currentToken设置为等号单词EQ */
case '=':
currentToken.Lex = EQ;
break;
/* 当前字符c为"<",当前识别单词返回值currentToken设置为小于单词LT */
case '<':
currentToken.Lex = LT;
break;
/* 当前字符c为"+",当前识别单词返回值currentToken设置为加号单词PLUS */
case '+':
currentToken.Lex = PLUS;
break;
/* 当前字符c为"-",当前识别单词返回值currentToken设置为减号单词MINUS */
case '-':
currentToken.Lex = MINUS;
break;
/* 当前字符c为"*",当前识别单词返回值currentToken设置为乘号单词TIMES */
case '*':
currentToken.Lex = TIMES;
break;
/* 当前字符c为"/",当前识别单词返回值currentToken设置为除号单词OVER */
case '/':
currentToken.Lex = OVER;
break;
/* 当前字符c为"(",当前识别单词返回值currentToken设置为左括号单词LPAREN */
case '(':
currentToken.Lex = LPAREN;
break;
/* 当前字符c为")",当前识别单词返回值currentToken设置为右括号单词RPAREN */
case ')':
currentToken.Lex = RPAREN;
break;
/* 当前字符c为";",当前识别单词返回值currentToken设置为分号单词SEMI */
case ';':
currentToken.Lex = SEMI;
break;
/* 当前字符c为",",当前识别单词返回值currentToken设置为逗号单词COMMA */
case ',':
currentToken.Lex = COMMA;
break;
/* 当前字符c为"[",当前识别单词返回值currentToken设置为左中括号单词LMIDPAREN */
case '[':
currentToken.Lex = LMIDPAREN;
break;
/* 当前字符c为"]",当前识别单词返回值currentToken设置为右中括号单词RMIDPAREN */
case ']':
currentToken.Lex = RMIDPAREN;
break;
/* 当前字符c为其它字符,当前识别单词返回值currentToken设置为错误单词ERROR */
default:
currentToken.Lex = ERROR;
Error = TRUE;
break;
}
}
break;
/********** 当前状态为开始状态START的处理结束 **********/
/* 当前DFA状态state为注释状态INCOMMENT,确定性有限自动机DFA处于注释位置 */
case INCOMMENT:
/* 当前字符存储状态save设置为FALSE,注释中内容不生成单词,无需存储 */
save = FALSE;
/* 当前字符c为EOF,当前DFA状态state设置为完成状态DONE,当前单词识别结束 *
* 当前识别单词返回值currentToken设置为文件结束单词ENDFILE */
if (c == EOF)
{ state = DONE;
currentToken.Lex = ENDFILE;
}
/* 当前字符c为"}",注释结束.当前DFA状态state设置为开始状态START */
else if (c == '}') state = START;
break;
/* 当前DFA状态state为赋值状态INASSIGN,确定性有限自动机DFA处于赋值单词位置 */
case INASSIGN:
/* 当前DFA状态state设置为完成状态DONE,赋值单词结束 */
state = DONE;
/* 当前字符c为"=",当前识别单词返回值currentToken设置为赋值单词ASSIGN */
if (c == '=')
currentToken.Lex = ASSIGN;
/* 当前字符c为其它字符,即":"后不是"=",在输入行缓冲区中回退一个字符 *
* 字符存储状态save设置为FALSE,当前识别单词返回值currentToken设置为ERROR */
else
{
scanner::ungetNextChar();
save = FALSE;
currentToken.Lex = ERROR;
Error = TRUE;
}
break;
case INRANGE:
/* 当前DFA状态state设置为完成状态DONE,赋值单词结束 */
state = DONE;
/* 当前字符c为".",当前识别单词返回值currentToken设置为下标界UNDERANGE */
if (c == '.')
currentToken.Lex = UNDERANGE;
/* 当前字符c为其它字符,即"."后不是".",在输入行缓冲区中回退一个字符 *
* 字符存储状态save设置为FALSE,当前识别单词返回值currentToken设置为ERROR */
else
{
scanner::ungetNextChar();
save = FALSE;
currentToken.Lex = DOT;
}
break;
/* 当前DFA状态state为数字状态INNUM,确定性有限自动机处于数字单词位置 */
case INNUM:
/* 当前字符c不是数字,则在输入行缓冲区源中回退一个字符 *
* 字符存储标志设置为FALSE,当前DFA状态state设置为DONE,数字单词识别完成 *
* 当前识别单词返回值currentToken设置为数字单词NUM */
if (!isdigit(c))
{
scanner::ungetNextChar();
save = FALSE;
state = DONE;
currentToken.Lex = INTC;
}
break;
/*当前DFA状态state为字符标志状态INCHAR,确定有限自动机处于字符标志状态*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -