📄 parse.c
字号:
/*
20031401008 褚超
实验一 词法分析程序
简易TC词法分析程序的实现
测试源文件:parse.c (即使用本程序的源文件即可)
可在程序输出文件output.TXT中查看程序运行结果
*/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "symbol.h"
#define TRUE 1
#define FALSE 0
/* BUFLEN定义源文件行中的最大字符数 */
#define BUFLEN 256
#define TAB 8
/* 一个记号的最大的长度 */
#define MAXTOKENLEN 40
/* tokenString数组用来存储每个记号 */
char tokenString[MAXTOKENLEN+1];
/* 当前单词的类型 */
int tokenType;
FILE *fin,*fout;
/* 词法分析程序初始化函数,完成各种符号表的构建 */
void init();
/* 扫描下一个字符:从输入缓冲区中获取字符,要注意维护当前字符所在的位置信息
void scanChar()
{
}
*/
/*系统保留字判断函数
该函数用于判断当前输入单词是否是系统保留字*/
int iskeyword();
int isOperator();
int isSpecial(char ch);
/* 扫描下一个符号:根据当前字符ch来判断下一个符号可能是什么,调用相应的函数进行处理 */
void nextToken();
/*
1.当前如果是空白符,则进行过滤
2.当前是'_'或字母,则是标识符
3.当前是'.',若其后紧接着数字,则应该是一个小数,否则是一个普通符号DOT
4.当前是',',':'等单独的分界符。它们不是多个单词符号公有的字符,所以它们直接对应其所表示的单词符号
5.当前是/,情况较复杂
1)后面紧跟一个/,单行注释
2)后面是/*,多行注释
3)后面紧跟'=',是除法赋值
4)否则是一个简单的除法运算符
(注意此种情况下如果是注释,则需要进行过滤)
6.当前是" ' "或者" " ",后面应该是字符常量和字符串常量,分别调用相应的函数进行处理
*/
/* 若是标识符,调用此函数对其余部分进行扫描 */
void scanIdent();
/* 若是数字,调用此函数继续扫描 */
void scanNum(int base);
/* 过滤源程序中的注释 */
void skipComment();
void scanOperator();
/*
出错处理函数
*/
void error_manage(char error,int row,int col)
{
printf("\nerror: %c ,row %d col %d",error,row,col); /*报告出错符号和所在行数,列数*/
}
/* 当前处理的字符 */
char ch;
static char lineBuf[BUFLEN]; /* 保留当前行 */
static int linepos = 0; /* 保存LineBuf中的当前位置 */
static int lineno = 0;
static int row=0,col=0; /* 保存当前处理字符所在的行和列 */
static int bufsize = 0; /* 当前缓存中保存的字符数 */
static int EOF_flag = FALSE; /* 当遇到EOF(文件结束符)调整ungetNextChar的操作 */
/*
getNextCharlineBuf取得下一个非空格的字符。如果读完了缓存中的全部字符,
就把新的一行读入缓存
*/
static int getNextChar()
{
if (!(linepos < bufsize))
{
lineno++;
if (fgets(lineBuf,BUFLEN-1,fin))
{
bufsize = strlen(lineBuf);
linepos = 0;
return lineBuf[linepos++];
}
else
{
EOF_flag = TRUE;
return EOF;
}
}
else return lineBuf[linepos++];
}
/* ungetNextChar把一个字符退回到lineBuf缓存中 */
static void ungetNextChar(void)
{
if (!EOF_flag)
linepos-- ;
}
FILE *fin,*fout;
void main()
{
nextToken();
}
void nextToken()
{
//FILE *fin,*fout;
char filename[20];
int count;
printf("Please input the source file:");
scanf("%s",filename);
if((fin=fopen(filename,"r"))==NULL)
{
printf("\nCan't open the source file!\n");
exit(1);
}
fout=fopen("output.txt","w");
while( (ch=getNextChar())!= EOF )
{
switch(ch)
{
case ' ':
col++;
//ch=getNextChar();
break;
case '\t':
col=(col/TAB*TAB)+TAB;
//ch=getNextChar();
break;
case '\r':
col=0;
row++;
//ch=getNextChar();
break;
case '\n':
col=0;
row++;
//ch=getNextChar();
break; /* 过滤空白符号 */
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 '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 '_':
scanIdent();
break;
case '0':
ch=getNextChar();
if(ch=='x' || ch=='X')
{
ch=getNextChar();
if( !((ch>='0' && ch<='9') || ( ch>='a' && ch<='f') || (ch>='A' && ch<='F')) )
error_manage(ch,lineno,col);
tokenString[0]='0';
tokenString[1]='x';
scanNum(16);
} else {
/*回退前一个字符*/
tokenString[0]='0';
scanNum(8);
}
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
scanNum(10);
break;
case '.':
fprintf(fout,"DOT\t.\n");
break;
case ',':
fprintf(fout,"COMMA\t,\n");
break;
case ';':
fprintf(fout,"SEMI\t;\n");
break;
case '(':
fprintf(fout,"LPAREN\t(\n");
break;
case ')':
fprintf(fout,"RPAREN\t)\n");
break;
case '[':
fprintf(fout,"LBRACE\t[\n");
break;
case ']':
fprintf(fout,"RBRACE\t]\n");
break;
case '{':
fprintf(fout,"LBRACKET\t{\n");
break;
case '}':
fprintf(fout,"RBRACKET\t}\n");
break;
case '/':
/* 消除注释部分 */
ch=getNextChar();
if (ch == '/') {
do {
ch=getNextChar();
} while(ch != '\n');
}
else if (ch == '*') {
count=0;
ch=getNextChar();
while(count!=2)
{ /*当扫描到‘*’且紧接着下一个字符为‘/’才是注释的结束*/
count=0;
while(ch!='*')
ch=getNextChar();
count++;
ch=getNextChar();
if(ch=='/')
count++;
else
ch=getNextChar();
}
}
else if (ch == '=') {
fprintf(fout,"SLASHEQ\t/=\n");
}
else
{
/*仅为一个单独的'/' */
ungetNextChar();
fprintf(fout,"SLASH\t/\n");
}
break;
case '\'':
break;
case '"':
break;
default:
if (isSpecial(ch)) {
scanOperator();
}else if (ch==EOF) {
fprintf(fout,"EOF");
}
}
}
fclose(fin);
fclose(fout);
}
/*系统保留字判断函数
该函数用于判断当前输入单词是否是系统保留字*/
int iskeyword()
{
int i;
for(i=0;i<33;i++)
{
if(strcmp(tokenString,keywords[i])==0)
return(keytype[i]);
}
if(i==ID)
return(ID);
else
return -1;
}
int isOperator()
{
int i;
for(i=0;i<32;i++)
{
if (strcmp(tokenString,operators[i])==0) {
return(optype[i]-50);
}
}
return -1;
}
/*是否是特殊字符*/
int isSpecial(char ch) {
switch (ch) {
case '!': case '%': case '&': case '*': case '?':
case '+': case '-': case ':': case '<': case '=':
case '>': case '^': case '|': case '~':
return TRUE;
default:
return FALSE;
}
}
void scanIdent()
{
//char ch;
int i=0,t;
do {
tokenString[i++]=ch;
ch=getNextChar();
} while(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_')||((ch>='0')&&(ch<='9')));
tokenString[i]='\0';
if (ch!='\n') {
ungetNextChar();
}
t=iskeyword(); /*判断是否是系统保留字*/
if (t<33 && t>0) {
/*输出关键字*/
fprintf(fout,"KEYWORDS\t%s\n",tokenString);
}
/* 是标识符 */
if (t==ID) {
fprintf(fout,"IDEN\t%s\n",tokenString);
}
}
void scanNum(int base)
{
int i=0;
switch(base) {
case 8:
i=1;
do {
tokenString[i++]=ch;
ch=getNextChar();
} while(ch>='0'&&ch<='7');
tokenString[i]='\0';
if (ch!='\n') {
ungetNextChar();
}
fprintf(fout,"OCT\t%s\n",tokenString);
break;
case 16:
i=2;
do {
tokenString[i++]=ch;
ch=getNextChar();
} while((ch>='0' && ch<='9') || ( ch>='a' && ch<='f') || (ch>='A' && ch<='F'));
tokenString[i]='\0';
if (ch!='\n') {
ungetNextChar();
}
fprintf(fout,"HEX\t%s\n",tokenString);
break;
default:
do {
tokenString[i++]=ch;
ch=getNextChar();
} while(ch>='0' && ch<='9');
tokenString[i]='\0';
if (ch!='\n') {
ungetNextChar();
}
fprintf(fout,"INT\t%s\n",tokenString);
}
}
void scanOperator()
{
int i=0,t;
do {
tokenString[i++]=ch;
ch=getNextChar();
} while(isSpecial(ch));
tokenString[i]='\0';
if (ch!='\n') {
ungetNextChar();
}
t=isOperator();
if (t>=0 && t<32) {
fprintf(fout,"OPERATOR\t%s\n",tokenString);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -