#include <iostream>
#include <ctype.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include<fstream>
using namespace std;
#define KEYWORD_LEN 32 //保留字个数
#define STR_MAX_LEN 300 //标识符最大长度
#define PRO_MAX_LEN 20480 //源程序最大长度
#define STB_MAX_LEN 1000 //符号表最大容量
#define CTB_MAX_LEN 1000 //常数表最大容量
#define ERROR 0 //错误
#define ID (KEYWORD_LEN+1) //标识符
#define CONST (KEYWORD_LEN+2) //常量
#define OPERAT (KEYWORD_LEN+3) //运算符
#define DIVIDE (KEYWORD_LEN+4) //界符
char proBuffer[PRO_MAX_LEN] = ""; //存储程序代码的全局缓冲区
char ch; //读出来的当前字符
char word[STR_MAX_LEN]; //标识符 或 常量
int point = 0; //源程序当前位置指针
char signTab[STB_MAX_LEN][STR_MAX_LEN]; //符号表
int pointSTB = 0; //符号表指针
char constTab[CTB_MAX_LEN][STR_MAX_LEN]; //常量表
int pointCTB = 0; //常数表指针
int Line=0;
char kwTab[KEYWORD_LEN][10]={ //保留字表 C语言一共有32个保留字[关键字]
"auto", "break", "case", "char", "const",
"continue", "default", "do", "double", "else",
"enum", "extern", "float", "for", "goto",
"if", "int", "long", "register", "return",
"short", "signed", "sizeof", "static", "struct",
"switch", "typedef", "union", "unsigned", "void",
"volatile", "while"};
typedef struct Duality
{
int kind;
int value;
int order;
}*pD, Dua;
//函数声明
bool Getchar(); //获得一个字符不包括结束标记
bool GetBC(); //获得一个非空白字符
void Concat(char *str); //将ch连接到str后
int Reserve(char *str); //对str字符串查找保留字表 若是一个保留字-返回其编码 否则返回0
void Retract(); //将搜索指示器回调一个字符位置
int InsertId(char *str);//将str串以标识符插入符号表,并返回符号表指针
int InsertConst(char *str); //将str串以常数插入符号表,并返回常数表指针
bool wordAnalyse(pD pDu); //词法分析 true正常
bool Getchar()//获得一个字符
{
if(point < PRO_MAX_LEN && proBuffer[point] != '\0')//如果当前下标合法且当前字符为结束标记则取字符增游标
{
ch = proBuffer[point++];
if (ch == '\n')
Line ++;
return true;
}
ch = '\0';
return false;
}
//获得一个非空白字符
bool GetBC()
{
do
{
if(!Getchar()) //获取字符失败
{
ch = '\0';
return false;
}
}while(isspace(ch)); //直到获得一个非空白字符
return true;
}
//将ch连接到str后
void Concat(char *str)
{
int i;
for(i=0; str[i]; ++i);
str[i] = ch;
str[i+1] = '\0';
}
//对str字符串查找保留字表 若是一个保留字-返回其编码 否则返回0
int Reserve(char *str)
{
int i;
for(i=0; i<KEYWORD_LEN; ++i) //从保留字表中查找str串
{
if(0 == strcmp(kwTab[i], str))
return i+1; //注意,这里加一原因是0值被错误标记占用
}
return 0;
}
//将搜索指示器回调一个字符位置
void Retract()///char *ch
{
if(proBuffer[point] == '\n' && Line > 0)
Line --;
point --;
}
//将str串以标识符插入符号表,并返回符号表指针
int InsertId(char *str)
{
int i;
for(i=0; i < pointSTB; ++i)
if(0 == strcmp(signTab[i], str))
return i;
strcpy(signTab[pointSTB++], str);
return (pointSTB-1);
}
//将str串以常数插入常量表,并返回常数表指针
/*int InsertConst(char *str)
{
int i;
for(i=0; i < pointCTB; ++i)
if(0 == strcmp(constTab[i], str))
return i;
strcpy(constTab[pointCTB++], str);
return (pointCTB-1);
}*/
//词法分析 false--分析结束
bool wordAnalyse(pD pDu)
{
int code, value;
char judge; //这里有个技巧 借用此变量巧妙的运用SWITCH结构
int i = 0; //辅助
GetBC();
judge = ch;
if (isalpha(ch) || ch == '_') judge='L';
if (isdigit(ch)) judge='D';
switch(judge)
{
case 'L':
while(isalnum(ch) || ch == '_')
{ //标识符
word[i++] = ch;
Getchar();
}
word[i] = '\0';
Retract(); //回退一个字符
code = Reserve(word);
if(code == 0)
{
value = InsertId(word);
pDu->kind = ID;
pDu->value = value;
}
else
{
pDu->kind = code;
pDu->value = -1;
}
return true;
case 'D':
while(isdigit(ch))
{
word[i++] = ch;
Getchar();
}
word[i] = '\0';
Retract();
// value = InsertConst(word);
pDu->kind = CONST;
// pDu->value= value;
return true;
case '"':
//字符串常量
do
{
word[i++] = ch;
Getchar();
}while(ch != '"' && ch != '\0');
word[i++] = ch;
word[i] = '\0';
if(ch == '\0')
{
// cout<<word;
pDu->kind = ERROR;
pDu->value = 0;
}
else
{
// value = InsertConst(word);
pDu->kind = CONST;
// pDu->value = value;
}
return true;
//字符常量
case '\'':
word[i++] = ch; // '
Getchar();
word[i++] = ch;
if(ch == '\\') // '\n'
{//如果是转义字符则要多接收一个字符
Getchar(); // ch = '
word[i++] = ch;
}
Getchar();
word[i++] = ch;
word[i] = '\0';
if(ch != '\'')
{//'\b'
cout<<word;
// ProcError(2);
pDu->kind = ERROR;
pDu->value = 0;
}
else
{
// value = InsertConst(word);
pDu->kind = CONST;
// pDu->value = value;
}
return true;
case '(':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=1;
return true;
case ')':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=2;
return true;
case '[':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=3;
return true;
case ']':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=4;
return true;
case '.':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=5;
return true;
case ',':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=6;
return true;
case '~':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=7;
return true;
case '?':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=8;
return true;
case ':':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=9;
return true;
case ';':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=10;
return true;
case '{':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=11;
return true;
case '}':
word[i++] = ch; word[i] = '\0';
pDu->kind = DIVIDE; //界符
pDu->value = -1;
pDu->order=12;
ret