//词法分析器
#include<iostream>
#include<ctype.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define ID 6
#define INT 7
#define LT 8
#define LE 9
#define EQ 10
#define NE 11
#define GT 12
#define GE 13
#define FZ 14
#define DEV 15
using namespace std;
struct KeyWord //关键字结构
{
char *word;
int id;
};
KeyWord keyword[]={ //关键字数组
{"begin",1},
{"end",2},
{"if",3},
{"then",4},
{"else",5},
{"integer",16},
{"float",17},
{"double",18}
};
char TOKEN[20];
int graphnum=1; //记录错误所在的位置(行数)
int lookup(char *string);//给定字符串得到对应的ID
void out(int id ,char *string);//输出ID和字符串
void report_error(char ERR_CH);//输出错误的位置
bool isalpha(char c) ; //合法字符的判断(字母)
bool isdigit(char c);//合法字符的判断(数字)
bool isalnum(char c);//合法字符的判断
void scanner_example(FILE *fp);//主分析程序
int lookup(char *string)//给定字符串得到对应的ID
{
for(int i=0;i<(sizeof(keyword)/sizeof(KeyWord));i++)
{
if(strcmp(string,keyword[i].word)==0)
return keyword[i].id;
}
return 0;
}
void out(int id ,char *string)//输出ID和字符串
{
printf("(%d,%s)\n",id,string);
}
void report_error(char ERR_CH) //错误处理程序
{
printf("undeclared identifler %c int %d line!\n",ERR_CH,graphnum);
}
bool isalpha(char c) //合法字符的判断(字母)
{
if( (c>='a'&&c<='z') || (c>='A'&&c<='Z') )
return true;
else
return false;
}
bool isdigit(char c) //合法字符的判断(数字)
{
if(c>='0'&&c<='9')
return true;
else
return false;
}
bool isalnum(char c)//合法字符的判断
{
if( isalpha(c) || isdigit(c) )
return true;
else
return false;
}
void scanner_example(FILE *fp)//主分析程序
{
char ch;
int i,c;
while(!feof(fp))
{
ch=fgetc(fp);
if(isalpha(ch))//首字符是字母
{
TOKEN[0]=ch;
ch=fgetc(fp);
i=1;
//连续读取只到出现非法字符
while(isalnum(ch)) //注意!TOKEN只有20长,若不加检测可能使程序崩溃
{
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
fseek(fp,-1,1);
c=lookup(TOKEN);//得到ID
//输出词法分析的结果
if(c==0)
out (ID,TOKEN);
else
out (c,"");
}
else if(isdigit(ch))//首字符是数字
{
TOKEN[0]=ch;
ch=fgetc(fp);
i=1;
while(isdigit(ch))
{
TOKEN[i]=ch;
i++;
ch=fgetc(fp);
}
TOKEN[i]='\0';
fseek(fp,-1,1);
out(INT,TOKEN);
}
else//特殊字符
switch(ch)
{
case '<': ch=fgetc(fp);
if(ch=='=')
out(LE," ");
else if(ch=='>')
out(NE," ");
else
{
fseek(fp,-1,1);
out(LT," ");
}
break;
case '=': out(EQ, " ");
break;
case '>': ch=fgetc(fp);
if(ch=='=')
out(GE," ");
else
{
fseek(fp,-1,1);
out(GT," ");
}
break;
case ':': ch=fgetc(fp);
if(ch=='=') // := 为赋值语句
out(FZ," ");
else
{
fseek(fp,-1,1);
report_error(ch);
}
break;
case '/': ch=fgetc(fp); //删除程序中的注释
if(ch=='/')
{
do
{
ch=fgetc(fp);
}while(ch!='\n');
graphnum++;
}
else
{
fseek(fp,-1,1);
out(DEV," ");
}
break;
case ' ' : break; //删除程序中的空格
case '\n': graphnum++; break; //删除程序中的回车,并记录程序编译到第几行
case '\t': break; //删除程序中的横向制表符
case -1 : break; //删除文件尾符号
default : report_error(ch);
break;
}
}
return;
}
void main(int argc,char *argv[])
{
FILE *fp;
//采用标准的C++错误处理
try
{
if(argc!=2)
throw argc;
fp=fopen(argv[1],"r");
if(!fp)
throw argv[1];
}
catch(char *str)
{
cout<<"打开文件 : "<<str<<" 时发生错误!"<<endl;
exit(1);
}
catch(int)
{
cout<<"请输入一个文件名!"<<endl;
exit(1);
}
scanner_example(fp);
fclose (fp);
}
评论