📄 accidenceanalysis.cpp
字号:
/* =========================================================================== *\
Author : skyang
Date : 11 - 23 - 2007
Description: Accidence Analysis,which is used to analyse a subset of PASCAL(PL/0),
input the source code in a file named "test.in" and output the words and
their properties in a file named "res.out", besides, this software also
indicate the position of accidence error in the source file.
The size of source code can't be larger than 100000 words.
Warning : Copyright (c) skyang 2007 All rights reserved.
\* =========================================================================== */
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define N 100000
char ch; //单个字符缓冲
char strToken[128];//字符串缓冲区,标识符不得超过127个字符
struct{
int flag;//1表示符号串在key表中;0表示符号串是标识符,在idList中;-1表示符号串是整数,在intList中
int id;//表示在不同表中的下标
}Word[N]; //记录源程序单词符号串及其属性码
int idListlen,intListLen;//标识符表和常数表的长度
char idList[N][128];//标识符表
int intList[N];//常数表
int error;//记录错误个数
int row;//记录行号,用来指明出错位置
char property[30][20]={//属性表
"$PROGRAM","$CONST","$VAR","$PROC",
"$BEG", "$END", "$IF","$THEN",
"$ELSE","$WHILE","$DO", "$CALL","$READ","$WRITE",
"$ID", "$INT", "$ASSIGN", "$SEMICOLON",
"$EQUAL","$PLUS","$SUBTRCT","$STAR",
"$DIVIDE", "$GREATER", "$LESS",
"$NONGREATER","$NONLESS","$UNEQUAL","$LPAR","$RPAR",
};
char _key[30][20]={//关键字及符号表
"program","const","var","procedure","begin","end",
"if","then","else","while","do","call","read","write",
"标识符","整数",":=",";","=","+","-","*","/",">","<",
">=","<=","<>","(",")",
};
void getCH(){//将下一个字符读入到ch中
ch=getchar();
if(ch=='\n') row++;
}
void getBC(){//如果ch中是空格换行,继续读入
while(ch==' ' || ch=='\n' || ch=='\t'){
getCH();
}
}
void contact(){//将ch中的字符连接到strToken中
int tmp=strlen(strToken);
strToken[tmp]=ch;
strToken[tmp+1]=0;
}
void clear(){//将strToken中的字符清零
strToken[0]=0;
}
int letterkind(){//数字返回1,字母返回0,"><="返回-1,'\n''\r'返回-2,其他字符返回-3
if(ch>='0' && ch<='9') return 1;
else if((ch>='A' && ch<='Z') ||(ch>='a' && ch<='z')) return 0;
else if(ch=='<' || ch=='>' || ch=='=') return -1;
else if(ch=='\n' || ch=='\r') return -2;
else return -3;
}
int checKey(){//如果strToken中的字符全是字母送入此函数中查找对应的关键字id,找不到返回-1
for(int i=0;i<=13;i++){
if(strcmp(strToken,_key[i])==0) return i;
}
return -1;
}
int checkToken(){//如果strToken中出现非数字和字母送入此函数中查找id,为了检测>=,<=,:=等字符,
//这里需要超前一位搜索
getCH();
if(letterkind()==-1){//letterkind()返回-1是比较符,-2是换行,-3是其他字符,
//如果下一位是"><="就连接上
contact();
getCH();
}
for(int i=16;i<=29;i++){
if(strcmp(strToken,_key[i])==0) return i;
}
return -1;
}
int InsertInt(){//将字符串变成整数插入到数字表中,返回下标
int num,i;
num=0;
for(i=0;i<(int)strlen(strToken);i++){
num*=10;
num+=(strToken[i]-'0');
}
intList[intListLen]=num;
intListLen++;
return intListLen-1;
}
void errorAction(){//处理出错的情况
//标识符以非字母开头或者出现无法识别的字符
char te=strToken[0];
if(!(te>='A' && te<='Z') && !(te>='a' && te<='z')){
while(letterkind()==1 || letterkind()==0){
contact();
getCH();
}
printf("error%d:(%d) \"%s\" is not legal.\n",error,row,strToken);//指出错误的行号和单词
}
clear();//将strToken中的字符清空继续处理后续的代码
error++;
}
int main(){
freopen("test.in","r",stdin);//文件输入,重定向
// freopen("res.out","w",stdout);//结果输出到中间文件
int count;//记录Word串的大小
int tmp;
count=0; error=1; row=1;
getCH();
getBC();
while(ch!=EOF){//判断文件末尾
if(letterkind()==0){//首字符是字母
while(letterkind()==1 || letterkind()==0){
contact();
getCH();
}
tmp=checKey();
if(tmp==-1){//标识符id
Word[count].flag=0;
Word[count].id=idListlen;
strcpy(idList[idListlen],strToken);//标识符插入到idList表中
idListlen++; count++;
}
else{//关键字
Word[count].flag=1;
Word[count].id=tmp;
count++;
}
}
else if(letterkind()==1){//首字符是数字
while(letterkind()==1){
contact();
getCH();
}
if(letterkind()==0){//数字后跟字母,调用出错处理
errorAction();
}
else{
Word[count].flag=-1;//-1表示整数,存在数字表中
Word[count].id=InsertInt();//整数插入数字表
count++;
}
}
else {//其他字符,调用checkToken()
contact();
tmp=checkToken();
if(tmp==-1){//_key表中找不到对应项,调用出错处理
errorAction();
}
else{
Word[count].flag=1;//其他字符也在_key表中
Word[count].id=tmp;
count++;
}
}
clear();//清空strToken
getBC();
}
//打印结果
printf("*****Analysis Result*****\n");
printf("Token\tProperty\n");
for(int i=0;i<count;i++){
tmp=Word[i].id;
if(Word[i].flag==1){//_key表
printf("%s\t%s\n",_key[tmp],property[tmp]);
}
else if(Word[i].flag==0){//idList表
printf("%s\t%s\n",idList[tmp],property[14]);
}
else {//intList表
printf("%d\t%s\n",intList[tmp],property[15]);
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -