四川大学Cminus语法分析器纯代码
C-Minus词法分析和语法分析设计编译器编译原理课程设计

编译原理课程设计报告课题名称:C- Minus词法分析和语法分析设计1.课程设计目标实验建立C-编译器。
只含有扫描程序(scanner)和语法分析(parser)部分。
2.分析与设计C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。
打开源代码文件source.txt扫描处理(词法分析)记号语法分析程序语法树语义分析程序错误处理器注释树记号表源代码优化程序文字表中间代码代码生成器目标代码目标代码优化程序目标代码2.1 、扫描程序scanner部分2.1.1系统设计思想设计思想:根据DFA图用switch-case结构实现状态转换。
惯用词法:① 语言的关键字:else if int return void while② 专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③ 其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter* NUM = digit digit*letter = a|..|z|A|..|Z digit = 0|..|9大写和小写字母是有区别的④ 空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
⑤ 注释用通常的C语言符号/ * . . . * /围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。
注释不能嵌套scanner的DFA/+ - * <= >= == != ; , ( ) [] { }INASSIGNWhite space >,<,=,!=digit\t \n[other]NUMdigit[other]STARTDONEletter[other]letterINID[other]ZHU*/[other]INCOMMENT*[other]ZZHU*说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。
语法分析器源代码

语法分析器源代码#include<stdio.h>#include<stdlib.h>#include<string.h>#define HIGHER 1#define LOWER -1#define EQUAL 0#define TRUE 1#define FALSE 0#define OPER_NUM 50 //默认算符数目 #define VN_NUM 50 //默认非终结符数目 #define MAX_BUFFER 128 //每行输入行最大长度#define MAX_GRA_NUM 20 //最大文法数目 #define EMPTY -2 //算符优先表初始值,表示这对算符没有优先关系fine STACK_SIZE 64 #detypedef struct{char c; //非终极符符号int firstvt[OPER_NUM]; //firstvt集,保存算符在oper_list中的下标int fir_n,last_n;int lastvt[OPER_NUM];}vn_t;int prior_table[OPER_NUM][OPER_NUM]; char oper_list[OPER_NUM];int oper_num = 0;vn_t vn_list[VN_NUM];int vn_num = 0;char *grammar[MAX_GRA_NUM][2]; int gra_num = 0;char start_vn;char stack[STACK_SIZE];int top = 0;void get_input(char *buf);int buf_deal(char* buf); void get_FIRVT_LASTVT(int vn_n);int create_table(); void init_table();int analyze(char *sentence); void display_table();void display_fir_lastvt(); int get_oper(char c); //得到算符c的数组下标没有返回-1int get_vn(char c); //得到非终结符c的数组下标,没有返回-1int is_vn(char a){return (('A'<=a&&a<='Z')?1:0); }int get_oper(char c){int i;for(i = 0; i < oper_num; ++i)if(oper_list[i] == c)return i;return -1;}int get_vn(char c){int i;for(i = 0; i < vn_num; ++i)if(vn_list[i].c == c)return i;return -1;}char reduce(int start, int end, int size) //规约{char *tar, *g, t1, t2, left;int i, j =0, gi, ti, cn = 0;int same;tar = (char *)malloc(sizeof(char)*MAX_BUFFER);if(!tar){printf("Allocation fails.\n");exit(-1);}for(i = start; i <= end; ++i) //将此最左素短语的终结符存入tar字符串{if(!is_vn(stack[i]))tar[j++] = stack[i];}tar[j++] = '\0';for(i = 0; i < gra_num; ++i) {g = grammar[i][1];gi = 0;ti = 0;same = FALSE;t1 = g[gi];t2 = tar[ti];while (t1 != '\0'){if(t2 == '\0' && !is_vn(t1)) {same = FALSE;break;}if(!is_vn(t1)){if(t1 != t2){same = FALSE;break;}t2 = tar[++ti];same = TRUE;}t1= g[++gi];}if(same && t2 == '\0')break;}if(i == gra_num){printf("无法找到相应文法~\n");return FALSE;}left = grammar[i][0][0];return vn_list[get_vn(left)].c; }int analyze(char *sentence) {char r, c,new_vn;int i = 0, k = 0, j, pi, printi = 1, cou = 1; //i是sentence[]和stack[]的索引int r_index, s_index, pre_index;printf("\n\n规约过程如下表所示:\n");printf("--------------------------------------\n");stack[top++] = '#';printf("序号\t符号栈\t最左素短语\t规约\t\n");do{r = sentence[i++];if((r_index = get_oper(r)) == -1){printf("Error : 您输入的字符不在文法定义中~\n"); flushall();c = getchar();flushall();return FALSE;}if(!is_vn(stack[k])){j = k;s_index = get_oper(stack[j]);}else{j = k - 1;s_index = get_oper(stack[j]);}while(prior_table[s_index][r_index] == HIGHER) {do{pre_index = s_index;if(!is_vn(stack[j-1])){j--;s_index = get_oper(stack[j]);}else{j -= 2;s_index = get_oper(stack[j]);}}while(prior_table[s_index][pre_index] != LOWER); printf(" %d\t", cou++);for(pi = 0; pi < top; ++pi){printf("%c",stack[pi]);}printf(" \t");for(pi = j + 1; pi <= k; ++pi){if (pi == j+1)printf(" %c",stack[pi]);elseprintf("%c",stack[pi]);}if((new_vn = reduce(j + 1, k, k - j)) == 0){return FALSE;}printf("\t\t %c\n",new_vn);k = j + 1; //规约最左素短语stack[k] = new_vn;top = k + 1;}if(prior_table[s_index][r_index] == LOWER ||prior_table[s_index][r_index] ==EQUAL){stack[++k] = r;top++;}else{printf("Error : 您输入的句型有错误~\n");return FALSE;}}while(r != '#');printf("--------------------------------------\n");return TRUE;}int buf_deal(char *buf){int i = 2,count = 0;char pre = buf[0], now;char *left_g, *right_g, *new_buf;left_g = (char *)malloc(sizeof(char)*2);right_g = (char *)malloc(sizeof(char)*(MAX_BUFFER-2)); if(!left_g || !right_g){printf("Allocation fails.\n");exit(-2);}if(is_vn(pre)){if(get_vn(pre) == -1){vn_list[vn_num].c = pre;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}left_g[count] = pre;count++;left_g[count] = '\0';}elsereturn FALSE;if(buf[1] != '-' || buf[2] != '>') return FALSE;pre = buf[2];count = 0;while((now = buf[++i]) != '\0') {if(now != '|'){right_g[count] = now;count++;if(is_vn(now) && is_vn(pre))return FALSE;if(is_vn(now)){if(get_vn(now) == -1){vn_list[vn_num].c = now;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}elsecontinue;}else{if(get_oper(now) == -1){oper_list[oper_num] = now; oper_num++;}elsecontinue;}pre = now;}else{right_g[count] = '\0'; grammar[gra_num][0] = left_g; grammar[gra_num][1] = right_g; gra_num++;break;}}if(buf[i] == '\0'){right_g[count] = '\0';grammar[gra_num][0] = left_g;grammar[gra_num][1] = right_g;gra_num++;}else{new_buf = (char *)malloc(sizeof(char)*MAX_BUFFER); new_buf[0] = left_g[0];new_buf[1] = '-';new_buf[2] = '>';strcpy(&new_buf[3],&buf[++i]);return buf_deal(new_buf);}return TRUE;}int create_table(){int gi = 0, ti, ni, fi, li, i;char *ng, t,next, next1;int t_index,n_index, n_index1, n_vn, t_vn;vn_t temp;for(gi = 0; gi < gra_num; ++gi ){ng = grammar[gi][1];t = ng[0];ti = 0;t_index = get_oper(t);next = ng[1];ni = 1;n_index = get_oper(next);while(next != '\0'){if(t_index != -1 && n_index != -1){if (prior_table[t_index][n_index] == EMPTY)prior_table[t_index][n_index] = EQUAL;else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[n_index]);return FALSE;}}else if(t_index != -1 && n_index == -1 && ng[ni+1] != '\0'){next1 = ng[ni+1];n_index1 = get_oper(next1);if(prior_table[t_index][n_index1] == EMPTY)prior_table[t_index][n_index1] = EQUAL;else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[n_index1]);return FALSE;}prior_table[t_index][oper_num - 1] = -3;prior_table[oper_num - 1][n_index1] = -3;}if (t_index != -1 && n_index == -1){n_vn = get_vn(next);temp = vn_list[n_vn];for(fi = 0; fi < temp.fir_n; fi++){if(prior_table[t_index][temp.firstvt[fi]] == EMPTY) prior_table[t_index][temp.firstvt[fi]] = LOWER; else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[temp.firstvt[fi]]); return FALSE;}}}else if(t_index == -1 && n_index != -1){n_vn = get_vn(t);temp = vn_list[n_vn];for(fi = 0; fi < st_n; fi++){if(prior_table[stvt[fi]][n_index] == EMPTY) prior_table[stvt[fi]][n_index] = HIGHER;else{printf("%c与%c有多种优先关系~\n",oper_list[fi],oper_list[n_index]);return FALSE;}}}t = ng[++ti];next = ng[++ni];t_index = get_oper(t);n_index = get_oper(next);}}for(i = 0; i < oper_num - 1; ++i){if(prior_table[oper_num - 1][i] != -3)prior_table[oper_num - 1][i] = LOWER;}for(i = 0; i < oper_num - 1; ++i){if(prior_table[i][oper_num - 1] != -3)prior_table[i][oper_num - 1] = HIGHER;}prior_table[oper_num - 1][oper_num - 1] = EQUAL; return TRUE;}void display_fir_lastvt(){int i, j;for (i = 0; i < vn_num; ++i){printf("FIRSTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].fir_n; ++j){if (j == vn_list[i].fir_n - 1)printf(" %c ",oper_list[vn_list[i].firstvt[j]]); elseprintf(" %c ,",oper_list[vn_list[i].firstvt[j]]); }printf("}\n");printf("LASTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].last_n; ++j){if (j == vn_list[i].last_n - 1)printf(" %c ",oper_list[vn_list[i].lastvt[j]]); elseprintf(" %c ,",oper_list[vn_list[i].lastvt[j]]); }printf("}\n\n");}}void display_table(){int i,j;printf("\n\t算符");for(i = 0; i < oper_num; ++i)printf("\t%c",oper_list[i]);printf("\n");for(i = 0; i < oper_num; ++i){printf("\t%c",oper_list[i]);for(j = 0; j <oper_num; ++j){if(prior_table[i][j] == 1)printf("\t>");else if(prior_table[i][j] == -1)printf("\t<");else if(prior_table[i][j] == 0)printf("\t=");elseprintf("\tNO");}printf("\n");}}void firstvt(int vn){int i, j, t, c_index, v_i, orin, pre = -1; char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];c = ng[0];if((c_index = get_oper(c)) != -1){vn_list[vn].firstvt[vn_list[vn].fir_n++] = c_index; continue;}else{v_i = get_vn(c);if(v_i != vn && v_i != pre){if(vn_list[v_i].fir_n == 0 )firstvt(v_i);orin = vn_list[vn].fir_n;vn_list[vn].fir_n += vn_list[v_i].fir_n;t = 0;for(j = orin; j < vn_list[vn].fir_n; ++j ){vn_list[vn].firstvt[j] = vn_list[v_i].firstvt[t++]; }}pre = v_i;if(ng[1] != '\0'){vn_list[vn].firstvt[vn_list[vn].fir_n++] = get_oper(ng[1]); }}}}}void lastvt(int vn){int i, j, t, c_index, v_i, orin, ni = 0, pre = -1;char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];ni = 0; //每次对新语法搜索时初始化位置。
C-Minus词法分析报告四川大学编译原理

内层CASE判断getNextChar()获取的下一个字符使当前状态转换为其他状态。
关键代码分析
TokenType getToken(void)
} TokenType;
//定义状态类型
typedef enum { START,LBUFFER,RBUFFER,INCOMMENT,INNUM,INID,INEQ,INLE,INGE,INNEQ,DONE }StateType;
//结构定义
static struct
{ char *str;
TokenType tok;
}
实验结果截图
总结
词法分析程序的输出和输入:词法分析程序的功能是读入源程序,输出单词符号。单词符号是程序设计语言的本语法符号,程序设计语言的单词符号一般分为如下几种:关键字,标示符,常数,运算符,界符,单词的输出是二元式的形式,需要知道二元式的表示方法,把得到的二元式写入输出文件。
实验注意事项:
1.试验中在设计注释部分的解析时,因为C-Minus的注释符是四个字符组成,设计DFA时设计了两个中间态,用来判断状态转换;在代码中,如果由中间态转换为INCOMMENT状态,注意字符回退和save置false
currentToken=ENDFILE;
}
else
state=INCOMMENT;
break;
}
case INNUM:{
if(!isdigit(c))
{
ungetNextChar();
save=FALSE;
语法分析器源代码

语法分析程序的源代码#include<stdio.h>#include<string.h>char prog[80],token[6];char ch;int syn,p,m,n,sum,kk=0;char * rwtab[6]={"begin","if","then","while","do","end"};main(){p=0;printf("\nplease intput string:");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}/*词法扫描程序:*/scaner(){for(n=0;n<8;n++)token[n]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')){while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';ch=prog[--p];syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}elseif((ch<='9'&&ch>='0')){sum=0;while((ch<='9'&&ch>='0')){sum=sum*10+ch-'0';ch=prog[p++];}ch=prog[--p];syn=11;}elseswitch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}elseif(ch=='='){syn=22;token[m++]=ch;}else{syn=20;ch=prog[--p];}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;ch=prog[--p];}break;case ':':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;ch=prog[--p];}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ':=':syn=18;token[0]=ch;break;case '<>':syn=21;token[0]=ch;break;case '<=':syn=22;token[0]=ch;break;case '>=':syn=24;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}lrparser(){if(syn==1){scaner();if(syn==6){scaner();if((syn==0)&&(kk==0))printf("sucess");}else{if(kk!=1) printf("lost end error!");kk=1;}}else{printf("output of begin is error!");kk=1;}return;}yucu(){statement();while(syn==26){scaner();statement();}return;}statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}{printf("output of equal is error!");kk=1;}}else{printf("input of sentence is error!");kk=1;}return;}expression(){term();while(syn==13||syn==14){scaner();term();}return;}term(){factor();while(syn==15||syn==16){scaner();factor();}return;}factor(){if(syn==10||syn==11)scaner();elseif(syn==27){scaner();expression();if(syn==28)scaner();else{printf("output ')' is error!");kk=1;}}else{printf("output expression is error!");kk=1;}return;}。
C_minus语言词法分析器的设计

实验一:词法分析程序的设计与实现姓名:专业班级:学号:一、实验目的设计一个简单的词法分析器,从而进一步加深对词法分析器工作原理的理解。
二.、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求根据PL/0语言文法,编制词法分析程序GETSYM完成以下功能:1)从键盘读入数据,分析出一个单词。
2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。
四.、实验步骤1. 采用C语言,设计GETSYM ,实现该算法2. 编制测试程序(主函数main)。
3. 调试程序:输入一组单词,检查输出结果。
五.、实验设计分析1.词法的正规式描述S=aA|aA=(aA|dA)}(a|d)2.变换后的正规文法S→aAS→aA→aAA→dAA→aA→d3.词法分析程序的程序代码#include "stdafx.h"#include <iostream>#include<string>using namespace std;#define MAX 17char ch =' ';stringkey[17]={"const","long","float","double","void","main","if","else","then","break","int","char","in clude","for","while","printf","scanf"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++){if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c){ //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsLetter1(char c){ //判断是否为a~f字母if(((c<='f')&&(c>='a'))||((c<='F')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void scan(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF){arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)||ch=='_'){arr=arr+ch;ch=fgetc(fpin);while(IsLetter(ch)||IsDigit(ch)){if((ch<='Z')&&(ch>='A')) ch=ch+32;arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t关键字"<<endl;}else cout<<arr<<"\t普通标识符"<<endl;}else if(IsDigit(ch)){int flag=0;if(ch=='0'){arr=arr+ch;ch=fgetc(fpin);if(ch>='0'&&ch<='7'){while(ch>='0'&&ch<='7'){flag=1;arr=arr+ch;ch=fgetc(fpin);}}else if(ch=='x'||ch=='X'){flag=2;arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)||IsLetter1(ch)){arr=arr+ch;ch=fgetc(fpin);}}else if(ch==' '||ch==','||ch==';' ){cout<<arr<<"\t整数0"<<endl;}fseek(fpin,-1L,SEEK_CUR);if(flag==1) cout<<arr<<"\t八进制整数"<<endl;else if(flag==2) cout<<arr<<"\t十六进制整数"<<endl;}else{arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t十进制整数"<<endl;}}else switch(ch){case'+':case'-' :case'*' :case'=' :case'|' :case'/' :cout<<ch<<"\t运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t运算符"<<endl;else{cout<<"::"<<"\t界符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t运算符"<<endl;if(ch=='>')cout<<">>"<<"\t输入控制符"<<endl;else {cout<<">"<<"\t运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t输出控制符"<<endl;else if(ch=='>') cout<<"<>"<<"\t运算符"<<endl;else{cout<<"<"<<"\t运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n分析如下:\n"<<endl;scan(fpin);fclose(fpin);}七.实验测试:输入数据及运行结果:int a=3;double b=4;int c;if(a>b)c=a;elsec=b;。
C语言词法分析器-内容说明注释完整-可运行代码

1.实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C 语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windowsxp软件:visual c++6。
02.实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4。
测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确.通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
3.实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void$关键字流程图、程序流程图:程序:#include〈string。
h〉#include〈stdio。
h〉#include〈stdlib。
h>#include<ctype。
h>//定义关键字char *Key[10]={”main”,”void”,"int","char",”printf",”scanf”,"else”,"if”,"return”};char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z’)&&(c〉=’a'))||((c〈='Z’)&&(c〉=’A'))) return 1; ﻩelse return 0;}int IsNum(char c){ //判断是否为数字ﻩif(c>='0’&&c<='9’) return 1;ﻩelse return0;}int IsKey(char *Word){//识别关键字函数ﻩintm,i;ﻩfor(i=0;i〈9;i++){ﻩif((m=strcmp(Word,Key[i]))==0){ﻩﻩif(i==0)ﻩﻩreturn 2;return 1;}}ﻩ return 0;}void scanner(FILE *fp){ //扫描函数ﻩcharWord[20]={'\0’};char ch;ﻩint i,c;ﻩch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ﻩch=fgetc(fp);i=1;ﻩwhile(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字ﻩWord[i]=ch;ﻩﻩi++;ﻩch=fgetc(fp);ﻩ}ﻩWord[i]='\0'; //’\0' 代表字符结束(空格)ﻩfseek(fp,—1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字ﻩﻩif(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字ﻩelseif(c==2) printf(”%s\t$主函数\n\n”,Word);ﻩelse printf(”%s\t$关键字\n\n",Word); //输出关键字}else //开始判断的字符不是字母ﻩ if(IsNum(ch)){ //判断是否是数字ﻩWord[0]=ch;ﻩﻩ ch=fgetc(fp);ﻩﻩﻩ i=1;ﻩﻩ while(IsNum(ch)){ﻩﻩWord[i]=ch;ﻩﻩﻩﻩi++;ﻩﻩﻩﻩﻩch=fgetc(fp);ﻩﻩﻩ}ﻩﻩWord[i]='\0';ﻩﻩﻩfseek(fp,—1,1); //回退ﻩﻩprintf("%s\t$无符号实数\n\n”,Word);ﻩ }ﻩ else //开始判断的字符不是字母也不是数字ﻩ {ﻩﻩ Word[0]=ch;ﻩﻩ switch(ch){ﻩﻩ case'[’:ﻩcase’]’:ﻩﻩcase’(’:ﻩﻩﻩcase’)’:ﻩﻩcase’{':ﻩﻩcase’}':ﻩﻩcase’,’:case’"’:ﻩ case’;’:printf(”%s\t$界符\n\n",Word); break;ﻩcase'+’:ch=fgetc(fp);ﻩﻩﻩﻩWord[1]=ch;ﻩif(ch=='='){ﻩﻩﻩ printf("%s\t$运算符\n\n",Word);//运算符“+=”ﻩﻩ}ﻩﻩ elseif(ch=='+’){ﻩprintf("%s\t$运算符\n\n”,Word); //判断结果为“++"ﻩﻩﻩ}ﻩﻩelse {fseek(fp,-1,1);printf(”%s\t$运算符\n\n",Word); //判断结果为“+”ﻩﻩﻩ }ﻩﻩ break;ﻩﻩ case'-':ch=fgetc(fp);Word[1]=ch;ﻩﻩﻩ if(ch=='='){ﻩﻩﻩprintf(”%s\t$运算符\n\n",Word); ﻩﻩ}ﻩ else if(ch=='-’){ﻩprintf(”%s\t$运算符\n\n",Word); //判断结果为“-—" ﻩﻩﻩﻩ}ﻩﻩﻩelse{ﻩﻩfseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”ﻩ}ﻩﻩﻩ break;ﻩcase'*’:ﻩﻩcase’/':case'!':ﻩﻩcase’=':ch=fgetc(fp);ﻩﻩ if(ch=='=’){ﻩﻩ printf("%s\t$运算符\n\n",Word);ﻩﻩﻩﻩ }ﻩﻩﻩ else {ﻩﻩﻩ fseek(fp,—1,1);ﻩﻩﻩﻩﻩ printf(”%s\t$运算符\n\n”,Word);ﻩﻩﻩ }ﻩﻩﻩﻩ break;ﻩcase'〈’:ch=fgetc(fp);ﻩﻩWord[1]=ch;ﻩﻩﻩﻩ if(ch==’=’){ﻩﻩﻩﻩﻩprintf("%s\t$运算符\n\n",Word);//判断结果为运算符“<=”ﻩﻩ }ﻩﻩﻩﻩ else if(ch==’<'){ﻩﻩﻩprintf(”%s\t$运算符\n\n”,Word); //判断结果为“〈〈"ﻩﻩﻩ}ﻩﻩﻩ else{ﻩﻩ fseek(fp,-1,1);ﻩﻩ printf(”%s\t$运算符\n\n”,Word); //判断结果为“<”ﻩﻩﻩﻩﻩ}ﻩﻩﻩ break;case’〉’:ch=fgetc(fp);ﻩ Word[1]=ch;ﻩif(ch==’=’) printf("%s\t$运算符\n\n”,Word);ﻩelse {ﻩﻩﻩfseek(fp,-1,1);ﻩprintf(”%s\t$运算符\n\n",Word);ﻩﻩﻩ }ﻩﻩ break;ﻩﻩ case’%':ch=fgetc(fp);ﻩﻩﻩﻩWord[1]=ch;ﻩﻩif(ch==’=’){printf("%s\t$运算符\n\n”,Word);} ﻩﻩ if(IsAlpha(ch))printf(”%s\t$类型标识符\n\n”,Word);ﻩﻩelse {ﻩﻩﻩfseek(fp,-1,1);ﻩﻩﻩﻩﻩ printf(”%s\t$取余运算符\n\n”,Word);ﻩﻩﻩ}break;default:printf(”无法识别字符!\n\n");break;ﻩﻩ }ﻩ}}main(){ﻩchar in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):”);while(1){gets(in_fn);ﻩ//scanf("%s”,in_fn);if((fp=fopen(in_fn,"r”))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:”);ﻩ}printf("\n*******************词法分析结果如下*******************\n");do{ﻩ ch=fgetc(fp);if(ch==’#’) break; //文件以#结尾,作为扫描结束条件ﻩ else if(ch==’ '||ch==’\t'||ch==’\n’){} //忽略空格,空白,和换行ﻩelse{ﻩﻩ fseek(fp,—1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!=’#’);return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
C_minus语言词法分析器实验报告

, 睡河心孕IIIIII 编译原理实验报告IIII! 题目: Cminus语言词法分析器I装订线I 学院计算机科学与技术II 专业xxxxxxxxxxxxxxxxI| 学号xxxxxxxxxxxxI 姓名xxxxI ---------------------------- ! 指导教师xxxxIIII20xx年xx月xx日C_minus语言词法分析器一、 实验目的1. 理解词法分析器的设计方法:利用DFA 编写相应的程序。
2. 掌握手工编写词法分析程序的方法。
3. 复习熟悉以前学过的编程语言4. 通过实验了解编译器词法分析的工作原理 二、 实验原理1. 文法的概念,DFA 的表示方法。
2. 词法分析程序的输出和输入:词法分析程序的功能是读入源程序, 输出单词符号。
单 词符号是程序设计语言的比本语法符号, 程序设计语言的单词符号一般分为如下几种: 关键 字,标示符,常数,运算符,界符,单词的输出是二元式的形式,需要知道二元式的表示方法,把得到的二元式写入输出文件。
转化图如下:3.熟悉单词的描述工具, 及他们之间的互相转化。
熟悉把正规文法转化为正规式,把正规式转化为 转为相应的DFA 最后再把DFA 简化, 器4.C 语言的基本语法。
、实验要求1、该个词法分析器要求至少能够识别以下几类单词:关键字: else if int return void while 共 6 个, 是小写;标识符:识别与 C 语言词法规定相一致的标识符,通过下列正则表达式定义:ID = letter (letter | digit)* 常数:NUM= digitletter = a|..|z|A|..|Z| 学计数法表示的常数,如专用符号:+-如正规文法,正规式,以及知道正规文法和正规式的等价性以NFA 以及把NFADFA 的状态转化为相应的子程序,最后得到词法分析 鸟式kr NFA 正规文法尸 DFA 状态最小 DFA ► 词法 分析器 所有的关键字都是保留字,并且必须 digit*(.digit digit* | & )(e(+ | - | & ) digit digit* | & ), ,digit =0|..|9 ,包括整数,如123等;小数,如123.45等;科 1.23e3 , 2.3e-9 等;*/<<=>>===!==,()[]{}/* */ ;2、分析器的输入为由上述几类单词构成的程序,输出为该段程序的机内表示形式,即关键字、运算符、界限符变为其对应的机内符,常数使用二进制形式,标识符使用相应的标识符表指针表示。
C-Minus词法分析四川大学编译原理

四川大学计算机学院、软件学院实验报告学号姓名:专业:DFA数据类型数据结构设计//定义数据类型TokenTypetypedef enum{ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,EQ,LT,LE,GT,GE,NEQ,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,LBRACKET,RBRACKET,LBRACE,RBRACE,COMMA,SEMI} TokenType;//定义状态类型typedef enum{ START,LBUFFER,RBUFFER,INCOMMENT,INNUM,INID,INEQ,INLE,INGE,INNEQ,DO NE }StateType;//结构定义实验结果截图总结词法分析程序的输出和输入:词法分析程序的功能是读入源程序,输出单词符号。
单词符号是程序设计语言的本语法符号,程序设计语言的单词符号一般分为如下几种:关键字,标示符,常数,运算符,界符,单词的输出是二元式的形式,需要知道二元式的表示方法,把得到的二元式写入输出文件。
实验注意事项:1.试验中在设计注释部分的解析时,因为C-Minus的注释符是四个字符组成,设计DFA时设计了两个中间态,用来判断状态转换;在代码中,如果由中间态转换为INCOMMENT状态,注意字符回退和save置false2.在判断运算符<,<=,>,>=,!=时,第二字符是’=’可成功识别出运算符,第二字符是其他字符时也可能是合法符号,注意字符回退与token判断。
参考资料:《编译原理及实践/编译器设计方案》。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<fstream>#include<iostream>#include<string>#include<strstream>using namespace std;#define BUFLEN 256#define MAXLEN 256#define MAXTOKENLEN 40#define MAXCHILDREN 4static int lineno;static int linepos = 0;//读取的字符在lineBuf的位置static int EOF_FLAG = false;static int bufsize = 0;//lineBuf的长度static char lineBuf[BUFLEN];FILE * source;char tokenString[MAXTOKENLEN+1];string output;//输出文件enum TokenType{ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI,LBRACKET,RBRA CKET,LBRACE,RBRACE,COMMA,GT,GEQ,NEQ,LEQ};enum StateType{START,INASSIGN,INCOMMENT,INNUM,INID,DONE,PRECOMMENT,AFTERCOMMENT };struct{char* str;TokenType tok;}ReserverWords[6]= { {"if",IF},{"else",ELSE},{"int",INT},{"return",RETURN},{"void",VOID},{"w hile",WHILE} };void UnGetNextChar(){if (!EOF_FLAG)linepos--;}int GetNextChar(){if(!(linepos<bufsize)){lineno++;if(fgets(lineBuf,BUFLEN-1,source)){bufsize=strlen(lineBuf);linepos=0;return lineBuf[linepos++];}else{EOF_FLAG=true;return EOF;}}else{return lineBuf[linepos++];}}TokenType ReservedLookUp(char * s){int i;for (i = 0; i < 6; i++){if(!strcmp(s,ReserverWords[i].str)){return ReserverWords[i].tok;}}return ID;}TokenType GetToken(){StateType state = START;//初始状态为startbool save;TokenType CurrentToken;int tokenStringIndex=0;string assign="";while(state!=DONE){int c=GetNextChar();save = true;switch (state){case START:if (isdigit(c)){state = INNUM;}else if (isalpha(c)){state = INID;}else if ((c == '<')||(c=='>')||(c=='=')||(c=='!')){state = INASSIGN;assign+=char(c);}else if ((c == ' ') || (c == '\t') || (c == '\n'))save = false;else if (c == '/'){save = false;state = PRECOMMENT;}else{state = DONE;switch (c){case EOF:save = false;CurrentToken = ENDFILE;break;case'+':CurrentToken = PLUS;break;case'-':CurrentToken = MINUS;break;case'*':CurrentToken = TIMES;break;case'(':CurrentToken = LPAREN;break;case')':CurrentToken = RPAREN;break;case';':CurrentToken = SEMI;break;case'[':CurrentToken = LBRACKET;break;case']':CurrentToken = RBRACKET;break;case'{':CurrentToken = LBRACE;break;case'}':CurrentToken = RBRACE;break;case',':CurrentToken = COMMA;break;default:CurrentToken = ERROR;break;}}break;case INCOMMENT:save = false;if (c == EOF){state = DONE;CurrentToken = ENDFILE;}else if (c == '*')state = AFTERCOMMENT;else{state=INCOMMENT;}break;case INASSIGN:if (c == '='){CurrentToken = EQ;state=DONE;}else if(assign=="!"){UnGetNextChar();save = false;CurrentToken = ERROR;state=DONE;}else if(assign=="="){UnGetNextChar();save = false;CurrentToken =ASSIGN ;state=DONE;}else if(assign=="<"){UnGetNextChar();save = false;CurrentToken =LT ;state=DONE;}else{UnGetNextChar();save = false;CurrentToken =GT ;state=DONE;}break;case INNUM:if (!isdigit(c)){UnGetNextChar();save = false;state = DONE;CurrentToken = NUM;}break;case INID:if (!isalpha(c)){UnGetNextChar();save = false;state = DONE;CurrentToken = ID;}break;case PRECOMMENT:if(c=='*'){state=INCOMMENT;save=false;}else{UnGetNextChar();CurrentToken=OVER;state=DONE;}break;case AFTERCOMMENT:save=false;if(c=='/'){state=START;}else if(c=='*'){state=AFTERCOMMENT;}else{state=INCOMMENT;}break;case DONE:default:state = DONE;CurrentToken = ERROR;break;}if((save)&&(tokenStringIndex<=MAXTOKENLEN)){tokenString[tokenStringIndex++]=(char)c;}if(state==DONE){tokenString[tokenStringIndex]='\0';if(CurrentToken==ID){CurrentToken=ReservedLookUp(tokenString);}}}return CurrentToken;}enum NodeKind//节点类型{FuncK,IntK,IdK,ParamsK,ParamK,CompK,ConstK,CallK,ArgsK,VoidK,Var_De clK,Arry_DeclK,Arry_ElemK,AssignK/*,WhileK*/,OpK,Selection_StmtK,Iteration_StmtK,Return_StmtK};struct//节点类型和字符串关系{string str;NodeKind nk;}nodekind[18]= { {"Funck",FuncK},{"IntK",IntK},{"IdK",IdK},{"ParamsK",ParamsK},{"ParamK" ,ParamK},{"CompK",CompK},{"ConstK",ConstK},{"CallK",CallK},{"ArgsK",ArgsK},{"VoidK",VoidK},{"Var_DeclK",Var_DeclK},{"Arry_DeclK",Arry_ DeclK},{"Arry_ElemK",Arry_ElemK},{"AssignK",AssignK},/*{"WhileK",WhileK},*/{"OpK",OpK},{"Selection_StmtK",Selection_StmtK},{"Ite ration_StmtK",Iteration_StmtK},{"Return_StmtK",Return_StmtK}};struct//符号与字符串关系{string str;TokenType tk;}Ope[11]= { {"=",ASSIGN},{"==",EQ},{"<",LT},{"+",PLUS},{"-",MINUS},{"*",TIMES},{"/" ,OVER},{">",GT},{">=",GEQ},{"!=",NEQ},{"<=",LEQ}};string OpeLookUp(TokenType tk)//操作符转换为字符串{int i;for(i=0;i<11;i++){if(tk==Ope[i].tk){return Ope[i].str;}}}string Change(NodeKind nk)//节点类型转换为字符串{int i;for(i=0;i<19;i++){if(nk==nodekind[i].nk){return nodekind[i].str;break;}}}TokenType token;struct TreeNode{struct TreeNode * child[4];struct TreeNode * sibling;int lineno;NodeKind nodekind;union { TokenType op; int val; const char * name;} attr;};TreeNode * declaration_list(void);TreeNode * declaration(void);TreeNode * params(void);TreeNode * param_list(TreeNode * p);TreeNode * param(TreeNode * p);TreeNode * compound_stmt(void);TreeNode * local_declaration(void);TreeNode * statement_list(void);TreeNode * statement(void);TreeNode * expression_stmt(void);TreeNode * selection_stmt(void);TreeNode * iteration_stmt(void);TreeNode * return_stmt(void);TreeNode * expression(void);TreeNode * var(void);TreeNode * simple_expression(TreeNode * p); TreeNode * additive_expression(TreeNode * p); TreeNode * term(TreeNode * p);TreeNode * factor(TreeNode * p);TreeNode * call(TreeNode * p);TreeNode * args(void);char * copyString(char *s){int n;char * t;if (s==NULL){return NULL;}n=strlen(s)+1;t=(char*)malloc(n);if (t==NULL){}else{strcpy(t,s);}return t;}void match(TokenType expected){if(token==expected)token=GetToken();else{cout<<"unexpected token"<<endl;}}TreeNode * newNode(NodeKind kind){TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));int i;if (t==NULL){;}else {for (i=0;i<4;i++){t->child[i] = NULL;}t->sibling = NULL;t->nodekind = kind;t->lineno = lineno;if (kind==OpK||kind==IntK||kind==IdK){if(kind==IdK)t-> = "";}if(kind==ConstK)t->attr.val = 0;}return t;}TreeNode * declaration_list(void)//declaration_list->declaration_list decla ration | declaration{TreeNode * t = declaration();TreeNode * p =t;while((token!=INT)&&(token!=VOID)&&(token!=ENDFILE)){token = GetToken();if(token==ENDFILE)break;}while(token==INT||token==VOID){TreeNode * q;q = declaration();if (q!=NULL){if (t==NULL){t=p=q;}else{p->sibling=q;p=q;}}}match(ENDFILE);return t;}TreeNode * declaration(void){TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;TreeNode * s = NULL;TreeNode * a = NULL;if (token==INT){p=newNode(IntK);match(INT);}else//(token==VOID){p=newNode(VoidK);match(VOID);}if(p!=NULL&&token==ID){q = newNode(IdK);q-> = copyString(tokenString);match(ID);if (token==LPAREN){t = newNode(FuncK);t->child[0] = p; //p是t子节点t->child[1] = q;match(LPAREN);t->child[2] = params();match(RPAREN);t->child[3] = compound_stmt();}else if (token==LBRACKET){t = newNode(Var_DeclK);a = newNode(Arry_DeclK);t->child[0] = p; //p是t子节点t->child[1] = a;match(LBRACKET);s = newNode(ConstK);s->attr.val = atoi(tokenString);match(NUM);a->child[0]=q;a->child[1]=s;match(RBRACKET);match(SEMI);}else if (token==SEMI){t = newNode(Var_DeclK);t->child[0] = p;t->child[1] = q;match(SEMI);}else{;}}else{;}return t;}TreeNode * params(void)//params_list | void{TreeNode * t = newNode(ParamsK);TreeNode * p = NULL;if (token==VOID){p = newNode(VoidK);match(VOID);if (token==RPAREN){if(t!=NULL)t->child[0] = p;}else//参数列表为(void id,[……]){t->child[0] = param_list(p);}}else//(token==INT){t->child[0] = param_list(p);}return t;}TreeNode * param_list(TreeNode * k)//params_list->params_list,param | param {TreeNode * t = param(k);TreeNode * p = t;k = NULL;//没有要传给param的VoidK,所以将k设为NULLwhile (token==COMMA){TreeNode * q = NULL;match(COMMA);q = param(k);if (q!=NULL){if (t==NULL){t=p=q;}else{p->sibling = q;p = q;}}}return t;}TreeNode * param(TreeNode * k){TreeNode * t = newNode(ParamK);TreeNode * p = NULL;TreeNode * q = NULL;if(k==NULL&&token==VOID){p = newNode(VoidK);match(VOID);}else if(k==NULL&&token==INT){p = newNode(IntK);match(INT);}else if (k!=NULL){p = k;}if(p!=NULL){t->child[0] = p;if (token==ID){q = newNode(IdK);q-> = copyString(tokenString);t->child[1] = q;match(ID);}if (token==LBRACKET&&(t->child[1]!=NULL))//@@@@@@@@@@@@{match(LBRACKET);t->child[2] = newNode(IdK);match(RBRACKET);}else{return t;}}else{;}return t;}TreeNode * compound_stmt(void){TreeNode * t = newNode(CompK);match(LBRACE);t->child[0] = local_declaration();t->child[1] = statement_list();match(RBRACE);return t;}TreeNode * local_declaration(void){TreeNode * t = NULL;TreeNode * q = NULL;TreeNode * p = NULL;while(token==INT || token==VOID){p = newNode(Var_DeclK);if(token==INT){TreeNode * q1 = newNode(IntK);p->child[0] = q1;match(INT);}else if(token==VOID){TreeNode * q1 = newNode(VoidK);p->child[0] = q1;match(INT);}if((p!=NULL)&&(token==ID)){TreeNode * q2 = newNode(IdK);q2-> = copyString(tokenString);p->child[1] = q2;match(ID);if(token==LBRACKET){TreeNode * q3 = newNode(Var_DeclK);p->child[3] = q3;match(LBRACKET);match(RBRACKET);match(SEMI);}else if(token==SEMI){match(SEMI);}else{match(SEMI);}}if(p!=NULL){if(t==NULL)t = q = p;else{q->sibling = p;q = p;}}}return t;}TreeNode * statement_list(void){TreeNode * t = statement();TreeNode * p = t;while (IF==token || LBRACKET==token || ID==token || WHILE==token || RETURN ==token || SEMI==token || LPAREN==token || NUM==token){TreeNode * q;q = statement();if(q!=NULL){if(t==NULL){t = p = q;}else{p->sibling = q;p = q;}}}return t;}TreeNode * statement(void){TreeNode * t = NULL;switch(token){case IF:t = selection_stmt();break;case WHILE:t = iteration_stmt();break;case RETURN:t = return_stmt();break;case LBRACE:t = compound_stmt();break;case ID: case SEMI: case LPAREN: case NUM:t = expression_stmt();break;default:token = GetToken();break;}return t;}TreeNode * selection_stmt(void){TreeNode * t = newNode(Selection_StmtK);match(IF);match(LPAREN);if(t!=NULL){t->child[0] = expression();}match(RPAREN);t->child[1] = statement();if(token==ELSE){match(ELSE);if(t!=NULL){t->child[2] = statement();}}return t;}TreeNode * iteration_stmt(void){TreeNode * t = newNode(Iteration_StmtK);match(WHILE);match(LPAREN);if(t!=NULL){t->child[0] = expression();}match(RPAREN);if(t!=NULL){t->child[1] = statement();}return t;}TreeNode * return_stmt(void){TreeNode * t = newNode(Return_StmtK);match(RETURN);if (token==SEMI){match(SEMI);return t;}else{if(t!=NULL){t->child[0] = expression();}}match(SEMI);return t;}TreeNode * expression_stmt(void){TreeNode * t = NULL;if(token==SEMI){match(SEMI);return t;}else{t = expression();match(SEMI);}return t;}TreeNode * expression(void){TreeNode * t = var();if(t==NULL)//不是以ID开头,只能是simple_expression情况{t = simple_expression(t);}else//以ID开头,可能是赋值语句,或simple_expression中的var和call类型的情况{TreeNode * p = NULL;if(token==ASSIGN)//赋值语句{p = newNode(AssignK);match(ASSIGN);p->child[0] = t;p->child[1] = expression();return p;}else//simple_expression中的var和call类型的情况{t = simple_expression(t);}}return t;}TreeNode * var(void){TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;if(token==ID){p = newNode(IdK);p-> = copyString(tokenString);match(ID);if(token==LBRACKET){match(LBRACKET);q = expression();match(RBRACKET);t = newNode(Arry_ElemK);t->child[0] = p;t->child[1] = q;}else{t = p;}}return t;}TreeNode * simple_expression(TreeNode * k){TreeNode * t = additive_expression(k);k = NULL;if(EQ==token || GT==token || GEQ==token || LT==token || LEQ==token || NEQ==token){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;t = q;match(token);t->child[1] = additive_expression(k);return t;}return t;}TreeNode * additive_expression(TreeNode * k){TreeNode * t = term(k);k = NULL;while((token==PLUS)||(token==MINUS)){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;match(token);q->child[1] = term(k);t = q;}return t;}TreeNode * term(TreeNode * k){TreeNode * t = factor(k);k = NULL;while((token==TIMES)||(token==OVER)){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;t = q;match(token);q->child[1] = factor(k);}return t;}TreeNode * factor(TreeNode * k){TreeNode * t = NULL;if(k!=NULL)//k为上面传下来的已经解析出来的以ID开头的var,可能为call或var{if(token==LPAREN && k->nodekind!=Arry_ElemK) //call{t = call(k);}else{t = k;}}else//没有从上面传下来的var{switch(token){case LPAREN:match(LPAREN);t = expression();match(RPAREN);break;case ID:k = var();if(LPAREN==token && k->nodekind!=Arry_ElemK){t = call(k);}else//如果是连续计算,进入这一步{t=k;}break;case NUM:t = newNode(ConstK);if((t!=NULL)&&(token==NUM)){t->attr.val = atoi(tokenString);}match(NUM);break;default:token = GetToken();break;}}return t;}TreeNode * call(TreeNode * k){TreeNode * t = newNode(CallK);if(k!=NULL)t->child[0] = k;match(LPAREN);if(token==RPAREN){match(RPAREN);return t;}else if(k!=NULL){t->child[1] = args();match(RPAREN);}return t;}TreeNode * args(void){TreeNode * t = newNode(ArgsK);TreeNode * s = NULL;TreeNode * p = NULL;if(token!=RPAREN){s = expression();p = s;while(token==COMMA){TreeNode * q;match(COMMA);q = expression();if(q!=NULL){if(s==NULL){s = p = q;}else{p->sibling = q;p = q;}}}}if(s!=NULL){t->child[0] = s;}return t;}int blank_number=0;void PreOrder(TreeNode* t){string blank=" ";int i;for(i=0;i<blank_number;i++){blank+=" ";}if(t!=NULL){if(t->nodekind==OpK){cout<<blank<<"Op: "<<OpeLookUp(t->attr.op)<<endl;output+=blank+"Op: "+OpeLookUp(t->attr.op)+"\n";}else if(t->nodekind==IdK){cout<<blank<<Change(t->nodekind)<<": "<<t-><<endl;output+=blank+Change(t->nodekind)+": "+t->+"\n";}else if(t->nodekind==ConstK){cout<<blank<<Change(t->nodekind)<<": "<<t->attr.val<<endl;int n=t->attr.val;strstream ss;string s;ss << n;ss >> s;output+=blank+Change(t->nodekind)+": "+s+"\n";}else if(t->nodekind==AssignK){cout<<blank<<"Assign"<<endl;output+=blank+"Assign"+"\n";}else if(t->nodekind==Selection_StmtK){cout<<blank<<"If"<<endl;output+=blank+"If"+"\n";}else if(t->nodekind==Iteration_StmtK){cout<<blank<<"While"<<endl;output+=blank+"While"+"\n";}else if(t->nodekind==Return_StmtK){cout<<blank<<"Return"<<endl;output+=blank+"Return"+"\n";}else{cout<<blank<<Change(t->nodekind)<<endl;output+=blank+Change(t->nodekind)+"\n";}}for(i=0;i<MAXCHILDREN;i++){if(t->child[i]!=NULL){blank_number+=2;PreOrder(t->child[i]);blank_number-=2;}}if(t->sibling!=NULL){PreOrder(t->sibling);}}void parse(void){TreeNode * t;cout<<"Syntax tree:"<<endl;token = GetToken();t = declaration_list();PreOrder(t);}void main(){char* file=(char *)malloc(100);//打开的文件名string result;//输出结果文件名cout<<"请输入文件名.例如:gcd.c-"<<endl;scanf("%s",file);while((source=fopen(file,"r"))==NULL){cout<<"文件名无效,请重新输入"<<endl;scanf("%s",file);}ofstream write;//输出文件result=string(file)+"-Result.txt";write.open(result);write<<"Syntax tree:"<<endl;parse();write<<output;write.close();system("PAUSE");}。