词法分析 C++实现"/>
编译原理 词法分析 C++实现
词法分析实验
【文法定义】:
<标识符>::=<字母>{<字母>|<数字>}//标识符和关键字都不区分大小写,比如if和IF均为关键字,不允许出现与关键字相同的标识符
<字母>::=_|a|...|z|A|...|Z
<数字>::=0|1|...|9
<整数>::=[+|-]<无符号整数>
<无符号整数>::=<数字>{<数字>}
<字符>::='<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'
<加法运算符>::=+|-
<乘法运算符>::=*|/
<字符串>::="{十进制编码为32,33,35-126的ASCII字符}" //字符串中要求至少有一个字符
【问题描述】
请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下:
- 数据结构和与语法分析程序的接口请自行定义;类别码需按下表格式统一定义;
- 为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt;输出的结果文件统一命名为output.txt,输入输出文件路径为相对路径,不要写成绝对路径。
- 结果文件中每行按如下方式组织:
单词类别码 单词的字符/字符串形式(中间仅用一个空格间隔)
单词的类别码请统一按如下形式定义:
【输入形式】testfile.txt中的符合文法要求的测试程序。
【输出形式】要求将词法分析结果输出至output.txt中。
【样例输入】
const int const1 = 1, const2 = -100;
const char const3 = '_';
int change1;
char change3;
int gets1(int var1,int var2){
change1 = var1 + var2;
return (change1);
}
void main(){
printf("Hello World");
printf(gets1(10, 20));
}
【样例输出】
CONSTTK const
INTTK int
IDENFR const1
ASSIGN =
INTCON 1
COMMA ,
IDENFR const2
ASSIGN =
MINU -
INTCON 100
SEMICN ;
CONSTTK const
CHARTK char
IDENFR const3
ASSIGN =
CHARCON _
SEMICN ;
INTTK int
IDENFR change1
SEMICN ;
CHARTK char
IDENFR change3
SEMICN ;
INTTK int
IDENFR gets1
LPARENT (
INTTK int
IDENFR var1
COMMA ,
INTTK int
IDENFR var2
RPARENT )
LBRACE {
IDENFR change1
ASSIGN =
IDENFR var1
PLUS +
IDENFR var2
SEMICN ;
RETURNTK return
LPARENT (
IDENFR change1
RPARENT )
SEMICN ;
RBRACE }
VOIDTK void
MAINTK main
LPARENT (
RPARENT )
LBRACE {
PRINTFTK printf
LPARENT (
STRCON Hello World
RPARENT )
SEMICN ;
PRINTFTK printf
LPARENT (
IDENFR gets1
LPARENT (
INTCON 10
COMMA ,
INTCON 20
RPARENT )
RPARENT )
SEMICN ;
RBRACE }
代码:
#include<stdio.h>
#include<string.h>
struct Symbol
{char name[10];//名字char real[3];//真实的符号
} ;
char c;
int i;
FILE *inFile,*outFile;
int split();
char buffer[1024];
int result=0;
char CONSTTKS[][7]= {"CONST","INT","CHAR","RETURN","VOID","MAIN","PRINTF"};struct Symbol symbols[]= {{"COMMA",","},{"SEMICN",";"},{"MINU","-"},{"PLUS","+"},{"DIV","/"},{"LSS","<"},{"GRE",">"},{"ASSIGN","="},{"LPARENT","("},{"RPARENT",")"},{"LBRACK","["},{"RBRACK","]"},{"LBRACE","{"},{"RBRACE","}"}
};int comp(char* a,char* b)
{int i;for(i=0; a[i]!='\0'&&b[i]!='\0'; i++){if(a[i]!=b[i]&&a[i]-b[i]!=32&&a[i]-b[i]!=-32)return 1;}if(a[i]==b[i]&&a[i]=='\0')return 0;else return 1;}
int isConsttks(char* c)
{int i;for(i=0; i<7; i++){if(comp(CONSTTKS[i],c)==0){return i;}}return -1;
}//判断一个字母是否是字母:a-zA-Z_,
//返回1代表是,0 代表不是
int isAlpheBelta(char c)
{return (c>='A'&&c<='Z')||(c>='a'&&c<='z')||c=='_';
}int isDigit(char c)
{return c>='0'&&c<='9';
}/**
* 分割单词的时候,通过;空格 ,‘’“”(){}进行分割
*/
int main()
{int toFile=1;int kind;int temp2;inFile=fopen("testfile.txt","r");outFile=fopen("output.txt","w");if(inFile==NULL){printf("打开文件失败!程序退出!");return -1;}if(outFile==NULL){printf("创建输出文件失败!程序退出!");return -1;}else{while((kind=split())!=-1){if(buffer[0]!='\0'){if(kind==15)//如果是char类型{if(toFile)fprintf(outFile,"CHARCON %c\n",buffer[0]);elseprintf("CHARCON %c\n",buffer[0]);buffer[0]='\0';result=0;}else if(kind==16){if(toFile)fprintf(outFile,"STRCON %s\n",buffer);else printf("STRCON %s\n",buffer);buffer[0]='\0';result=0;}else{temp2=isConsttks(buffer);if(temp2>=0){if(toFile)fprintf(outFile,"%sTK %s\n",CONSTTKS[temp2],buffer);else printf("%sTK %s\n",CONSTTKS[temp2],buffer);}else if(toFile)fprintf(outFile,"IDENFR %s\n",buffer);else printf("IDENFR %s\n",buffer);if(kind==111){if(toFile)fprintf(outFile,"LEQ <=\n");else printf("LEQ <=\n");}else if(kind==112){if(toFile)fprintf(outFile,"GEQ >=\n");else printf("GEQ >=\n");}else if(kind==113){if(toFile)fprintf(outFile,"EQL ==\n");else printf("EQL ==\n");}else if(kind==114){if(toFile){fprintf(outFile,"NEQ !=\n");}else printf("NEQ !=\n");}}}if(kind>0&&kind<=14){if(toFile)fprintf(outFile,"%s %s\n",symbols[kind-1].name,symbols[kind-1].real);else printf("%s %s\n",symbols[kind-1].name,symbols[kind-1].real);}}}printf("分析完成!");return 0;
}//分词程序,返回值用来控制下一个输出
int split()
{int count=0;int flag=0;while(!feof(inFile)&&!flag){i=fgetc(inFile);c=(char)i;if(result==16){if(i==32||i==33||(i>=35&&i<=126))buffer[count++]=c;else if(i==34){buffer[count]='\0';flag=1;}}else if(result==15){if(i==32||i==33||(i>=35&&i<=126)){buffer[count++]=c;buffer[count]='\0';flag=1;}}else{if(isAlpheBelta(i)) //如果是字母{result=0;buffer[count++]=c;}else if(isDigit(c)){result=0;//如果是数字buffer[count++]=c;}else{flag=1;buffer[count]='\0';switch(c){case ' ':case '\t':case '\n':if(result==16){result=16;flag=0;buffer[count++]=c;}else if(result==15){result=15;buffer[count++]=c;buffer[count]='\0';}else result=0;break;case ',':result=1;//break;case ';':result=2;break;case '-':result=3;break;case '+':result=4;break;case '/':result=5;break;case '<':result=6;if((char)fgetc(inFile)=='='){result=111;}else{fseek(inFile,-1,SEEK_CUR);}break;case '>':result=7;if((char)fgetc(inFile)=='='){result=112;}else{fseek(inFile,-1,SEEK_CUR);}break;case '=':result=8;if((char)fgetc(inFile)=='='){result=113;}else{fseek(inFile,-1,SEEK_CUR);}break;case '(':result=9;break;case ')':result=10;break;case '[':result=11;break;case ']':result=12;break;case '{':result=13;break;case '}':result=14;break;case '\'':result=15;break;case '\"':result=16;break;case '!':c=(char)fgetc(inFile);if(c=='='){result=114;}else{fseek(inFile,-1,SEEK_CUR);}break;}}}}if(feof(inFile))return -1;if (flag==1){return result;}return -1;}
运行效果:
更多推荐
编译原理 词法分析 C++实现
发布评论