编译原理 词法分析 C++实现

编程入门 行业动态 更新时间:2024-10-10 15:27:53

编译原理 <a href=https://www.elefans.com/category/jswz/34/1764964.html style=词法分析 C++实现"/>

编译原理 词法分析 C++实现

词法分析实验

【文法定义】:

<标识符>::=<字母>{<字母>|<数字>}//标识符和关键字都不区分大小写,比如if和IF均为关键字,不允许出现与关键字相同的标识符

<字母>::=_|a|...|z|A|...|Z  

<数字>::=0|1|...|9  

<整数>::=[+|-]<无符号整数>

<无符号整数>::=<数字>{<数字>}

<字符>::='<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'  

<加法运算符>::=+|- 

<乘法运算符>::=*|/ 

<字符串>::="{十进制编码为32,33,35-126的ASCII字符}"  //字符串中要求至少有一个字符

【问题描述】

请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下:

  1. 数据结构和与语法分析程序的接口请自行定义;类别码需按下表格式统一定义;
  2. 为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt;输出的结果文件统一命名为output.txt,输入输出文件路径为相对路径,不要写成绝对路径。
  3. 结果文件中每行按如下方式组织:

单词类别码 单词的字符/字符串形式(中间仅用一个空格间隔)

单词的类别码请统一按如下形式定义:

 

【输入形式】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++实现

本文发布于:2024-02-06 05:51:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1746523.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:词法   原理

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!