---内容开始---

这是一份编译原理实验报告,分析表是手动造的,可以作为借鉴。

基于  SLR(1) 分析法的语法制导翻译及中间代码生成程序设计原理与实现
1 、理论传授
语法制导的基本概念,目标代码结构分析的基本方法,赋值语句语法制导生成四元式的
基本原理和方法,该过程包括语法分析和语义分析过程。

2 、目标任务
[ 实验 项目] 完成以下描述赋值语句 SLR(1)文法语法制导生成中间代码四元式的过程。
G[A]:A→V=E
E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
V→i
 [ 设计说明 ] 终结符号 i 为用户定义的简单变量,即标识符的定义。
 [ 设计要求]

(1)构造文法的 SLR(1)分析表,设计语法制导翻译过程,给出每一产生式
对应的语义动作;

(2)设计中间代码四元式的结构;

(3)输入串应是词法分析的输出二元式序列,即某赋值语句“专题 1”的输出结果,输出为赋值语句的四元式序列中间文件;

(4)设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。

3、 程序功能描述

在第一次实验词法分析输出结果的基础上设计SLR1文法分析过程,并了解四元式的形成:

  1. 输入串为实验一的二元式序列
  2. 输出为对输入串的SLR(1)文法的判断结果
  3. 输出有针对输入串的SLR(1)文法的具体分析过程
  4. 有对输入串的四元式输出序列

4、 主要数据结构描述

二元组结构体,用来存储词法分析程序输出的二元组对 <类别,单词>:

int count;

struct eryuanzu

{

int a;

char temp[COUNT];

}m[COUNT];

void out(int a,char* temp){// 打印二元组

printf("< %d %s >\n",a,temp);

m[count].a=a;

strcpy(m[count].temp,temp);  //

count++;

}

SLR1分析过程中所要用到的状态栈、符号栈等:

stack<int> state;           //状态栈

stack<char> sign;           //符号栈

char st; //规约弹出时,状态栈顶元素

int flag=0; //标志是否是SLR

stack<string> place;        //变量地址栈

ACTION表,二维数组表示:

/* i  ( ) + - * / =  #

以1开头的百位数为s移进项,0为error,-1为accept,其余的一位两位数是r规约项*/

int ACTION[20][9]={{103,0,0,0,0,0,0,0,0},//0

{0,0,0,0,0,0,0,0,-1},

{0,0,0,0,0,0,0,104,0},

{0,0,0,0,0,0,0,10,0},

{109,108,0,0,0,0,0,0},

{0,0,0,110,111,0,0,0,1},//5 mnl;;huhyhjhjio

{0,0,4,4,4,112,113,0,4},

{0,0,7,7,7,7,7,0,7},

{109,108,0,0,0,0,0,0,0},

{0,0,9,9,9,9,9,0,9},

{109,108,0,0,0,0,0,0,0},//10

{109,108,0,0,0,0,0,0,0},

{109,108,0,0,0,0,0,0,0},

{109,108,0,0,0,0,0,0,0},

{0,0,119,110,111,0,0,0,0},

{0,0,2,2,2,112,113,0,2},//

{0,0,3,3,3,112,113,0,3},

{0,0,5,5,5,5,5,0,5},

{0,0,6,6,6,6,6,0,6},

{0,0,8,8,8,8,8,0,8}};//19

·GOTO表,二维数组表示:

//A V E T F

int GOTO[20][5]={{1,2,0,0,0},

{0,0,0,0,0},//1

{0,0,0,0,0},

{0,0,0,0,0},

{0,0,5,6,7},

{0,0,0,0,0},//5

{0,0,0,0,0},

{0,0,0,0,0},

{0,0,14,6,7},

{0,0,0,15,7},

{0,0,0,16,7},//10

{0,0,0,0,17},

{0,0,0,0,18},

{0,0,0,0,0},

{0,0,0,0,0},

{0,0,0,0,0},//15

{0,0,0,0,0},

{0,0,0,0,0},

{0,0,0,0,0},

{0,0,0,0,0}};//19

规约时所用到的函数,分别对应每一条规则:

void R1();          //A→V=E

void R2();          //E→E+T

void R3();          //E→E-T

void R4();          //E→T

void R5();          //T→T*F

void R6();          //T→T/F

void R7();          //T→F

void R8();          //F→(E)

void R9();          //F→i

void R10();         //V→i

void R1() {

sign.pop(); sign.pop(); sign.pop();       //弹出符号栈

state.pop(); state.pop(); state.pop();    //弹出状态栈

sign.push('A');                         //符号'A'入栈

st=state.top();

printf("r1\t");

}

void R2() {

sign.pop(); sign.pop(); sign.pop();       //弹出符号栈

state.pop(); state.pop(); state.pop();    //弹出状态栈

sign.push('E'); st=state.top();                        //符号'E'入栈

printf("r2\t\t");

}

void R3() {

sign.pop(); sign.pop(); sign.pop();

state.pop(); state.pop(); state.pop();

sign.push('E');st=state.top();

printf("r3\t\t");

}

void R4() {

sign.pop();

state.pop();

sign.push('E');st=state.top();

printf("r4\t\t");

}

void R5() {

sign.pop(); sign.pop(); sign.pop();

state.pop(); state.pop(); state.pop();

sign.push('T');st=state.top();

printf("r5\t\t");

}

void R6() {

sign.pop(); sign.pop(); sign.pop();

state.pop(); state.pop(); state.pop();

sign.push('T');st=state.top();

printf("r6\t\t");

}

void R7() {

sign.pop();

state.pop();

sign.push('T');st=state.top();

printf("r7\t\t");

}

void R8() {

sign.pop(); sign.pop(); sign.pop();

state.pop(); state.pop(); state.pop();

sign.push('F');st=state.top();

printf("r8\t\t");

}

void R9() {

sign.pop();

state.pop();

sign.push('F');st=state.top();

printf("r9\t\t");

}

void R10() {

sign.pop();

state.pop();

sign.push('V');st=state.top();

printf("r10\t\t");

}

SLR1分析处理函数:

void SLR()

{

printf("输入串\t\t状态栈\t\t符号栈\t\tACTION\t\tGOTO   ");

int i,j,k=1;

state.push(0); //初始化

sign.push('#');

int which;  //对应表项内容

char c; //输入符号串首

int a; //坐标

int b;

do{

printf("\n");

c=m[k-1].temp[0]; //输入符号串首

cout<<c<<' ';

for(int j=k;j<=count;j++)

printf("%s",m[j].temp);

printf("\t\t");

displayStack(state);

displayStack1(sign);

a=state.top(); //坐标

b=isVt(c);

/*if(isOp(c)!=-1)

temp1=c;

place.push(temp1);*/

if(b!=-1)  //输入串首c是终结符

{

which=ACTION[a][b];

if(which==-1)

{

printf(" acc,分析成功!\n");

flag=1;

break;

}

else if(which==0)

{ printf("error项1\n ");break; }

else if(which>=100) //移进

{

which=s_r(which);

printf("s%d\t\t",which);

sign.push(c);

state.push(which);

k++;

}

else

{

switch(which) //which整型,case不要加''

{

case 1:R1();break;

case 2:R2();break;

case 3:R3();break;

case 4:R4();break;

case 5:R5();break;

case 6:R6();break;

case 7:R7();break;

case 8:R8();break;

case 9:R9();break;

case 10:R10();break;

default:printf("which=%derror项2\n ");break;

}

//状态转移 Vn

int e=isVn(sign.top());

if(e!=-1)

{

int convert=GOTO[st][e];

state.push(convert);

printf("GOTO[%d,%c]=%d",st,sign.top(),convert);

}

}

}

else

{ printf("error_b ");break; }

}while(which!=-1);//while

}

5、实验测试

1.测试用例:i=(i-i*i)#,输入file.txt直接从文件读取输入串,得到结果如下:

四元式结果输出:

由于图片无法上传便罢

6、 实验总结

本次实验是对理论课上所学知识的应用,重点是理解分析栈和符号栈,这里我采用自行造ACTION和GOTO表,这样SLR分析表就出来了,自动造表还是比较复杂。而且在造表的过程中经常出错,最后在大家的讨论中解决了。造完表后的分析过程并不复杂,按部就班分情况来处理。

本次实验加深了我对SLR1的分析过程的理解,也加深了对四元式的认识。

7、源代码

分为两个CPP

Siyuanshi.cpp   

  1. #include "stdafx.h"
  2. #include<stdlib.h>
  3. #include<fstream>
  4. #include<iostream>
  5. #include<stdio.h>
  6. using namespace std;
  7.  
  8. #define MAX 100
  9. int mm=,sum=;//sum用于计算运算符的个数
  10. //mm用于标输入表达式中字符的个数
  11. char JG='A';
  12. char str[MAX];//用于存输入表达式
  13. int token=;//左括号的标志
  14.  
  15. /***********用于更改计算后数组中的值**************/
  16. void change(int e)
  17. {
  18. int f=e+;
  19. char ch=str[f];
  20. if(ch>='A'&&ch<='Z')
  21. {
  22. for(int l=;l<mm+;l++)
  23. {
  24. if(str[l]==ch)
  25. str[l]=JG;
  26. }
  27. }
  28.  
  29. if(str[e]>='A'&&str[e]<='Z')
  30. {
  31. for(int i=;i<mm;i++)
  32. {
  33. if(str[i]==str[e])
  34. str[i]=JG;
  35. }
  36. }
  37. }
  38.  
  39. void chengchuchuli(int i,int mm)
  40. {
  41.  
  42. i++;
  43. for( ;i<=mm-;i++)//处理乘除运算
  44. {
  45. if(str[i]=='*'||str[i]=='/')
  46. {
  47.  
  48. cout<<"("<<str[i]<<" "<<str[i-]<<" "<<str[i+]<<" "<<JG<<")"<<endl;
  49. change(i-);
  50. str[i-]=str[i]=str[i+]=JG;
  51. sum--;
  52. JG=(char)(int)JG++;
  53. }
  54. }
  55. }
  56.  
  57. void jiajianchuli(int j,int mm)
  58. {
  59. j++;
  60. for( ;j<=mm-;j++)//处理加减运算
  61. {
  62. if(str[j]=='+'||str[j]=='-')
  63. {
  64. cout<<"("<<str[j]<<" "<<str[j-]<<" "<<str[j+]<<" "<<JG<<")"<<endl;
  65. change(j-);
  66. str[j-]=str[j]=str[j+]=JG;
  67. sum--;
  68. JG=(char)(int)JG++;
  69. }
  70. }
  71. }
  72.  
  73. /*扫描遍从文件中读入表达式*/
  74. void scan(FILE *fin)
  75. {
  76. int p[MAX];
  77. char ch='a';
  78. int c=-,q=;
  79. while(ch!=EOF)
  80. {
  81. ch=getc(fin);
  82.  
  83. while(ch==' '||ch=='\n'||ch=='\t')
  84. ch=getc(fin);//消除空格和换行符
  85.  
  86. str[mm++]=ch;
  87. if(ch=='='||ch=='+'||ch=='-'||ch=='*'||ch=='/')
  88. sum++;
  89. else if(ch=='(')
  90. {
  91. p[++c]=mm-;
  92. }
  93. else if(ch==')')
  94. {
  95. q=mm-;
  96. chengchuchuli(p[c],q);//从左括号处理到又括号
  97. jiajianchuli(p[c],q);
  98. JG=(char)(int)JG--;
  99. str[p[c]]=str[mm-]=JG;
  100. c--;
  101. JG=(char)(int)JG++;
  102. }
  103. }
  104. }
  105.  
  106. void siyuanshi()
  107. {
  108.  
  109. for(int i=;i<=mm-;i++)//处理乘除运算
  110. {
  111. if(str[i]=='*'||str[i]=='/')
  112. {
  113.  
  114. cout<<"("<<str[i]<<" "<<str[i-]<<" "<<str[i+]<<" "<<JG<<")"<<endl;
  115. change(i-);
  116. str[i-]=str[i]=str[i+]=JG;
  117. sum--;
  118. JG=(char)(int)JG++;
  119. }
  120.  
  121. }
  122.  
  123. for(int j=;j<=mm-;j++)//处理加减运算
  124. {
  125. if(str[j]=='+'||str[j]=='-')
  126. {
  127.  
  128. cout<<"("<<str[j]<<" "<<str[j-]<<" "<<str[j+]<<" "<<JG<<")"<<endl;
  129. change(j-);
  130. str[j-]=str[j]=str[j+]=JG;
  131. sum--;
  132. JG=(char)(int)JG++;
  133. }
  134.  
  135. }
  136.  
  137. for(int k=;k<=mm-;k++)//处理赋值运算
  138. {
  139. if(str[k]=='=')
  140. {
  141.  
  142. JG=(char)(int)--JG;
  143. cout<<"("<<str[k]<<" "<<str[k+]<<" "<<" "<<" "<<str[k-]<<")"<<endl;
  144. sum--;
  145. change(k+);
  146. str[k-]=JG;
  147. }
  148. }
  149.  
  150. }
  151.  
  152. extern void MAIN(){
  153. char in[MAX]; //用于接收输入输出文件名
  154. FILE *fin;
  155. cout<<"请输入源文件名(包括后缀名)"<<endl;
  156. cin>>in;;
  157. if ((fin=fopen(in,"r"))==NULL)
  158. {
  159. cout<<"error"<<endl;
  160. }
  161. cout<<"*********四元式如下*********"<<endl;
  162. scan(fin);//调用函数从文件中读入表达式
  163. siyuanshi();
  164. if(sum==) printf("成功?");
  165. else printf("有错误");
  166. //关闭文件
  167. fclose(fin);
  168. system("pause");
  169. }

Bianyi_5.cpp

  1. // bianyi_5.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include <iostream>
  6. #include <string>
  7. #include <stack>
  8. #include <map>
  9. #include <string>
  10. #include <cstring>
  11. #include <iomanip>
  12.  
  13. using namespace std;
  14. extern void MAIN();
  15. #define ADD 1
  16. #define SUB 2
  17. #define MUL 3
  18. #define FH 4
  19. #define SG 5
  20. #define ID 6
  21. #define INT 7
  22. #define LT 8
  23. #define LE 9
  24. #define EQ 10
  25. #define NE 11
  26. #define GT 12
  27. #define GE 13
  28. #define MHEQ 14
  29. #define XGMUL 15
  30. #define ZKH 16
  31. #define YKH 17
  32. #define DIV 18
  33. #define EQ 19//=
  34. #define blz 00
  35.  
  36. #define COUNT 40
  37. char* keyword[]={"begin","end","if","then","else","for","do","and","or","not"};//保留字
  38.  
  39. int count;
  40. struct eryuanzu
  41. {
  42. int a;
  43. char temp[COUNT];
  44. }m[COUNT];
  45.  
  46. void out(int a,char* temp){// 打印二元组
  47.  
  48. printf("< %d %s >\n",a,temp);
  49. m[count].a=a;
  50. strcpy(m[count].temp,temp); //
  51. count++;
  52. }
  53.  
  54. stack<int> state; //状态栈
  55. stack<char> sign; //符号栈
  56. char st; //规约弹出时,状态栈顶元素
  57. int flag=; //标志是否是SLR
  58. stack<string> place; //变量地址栈
  59.  
  60. /* i ( ) + - * / = #
  61. 以1开头的百位数为s移进项,0为error,-1为accept,其余的一位或两位数是r规约项*/
  62. int ACTION[][]={{,,,,,,,,},//
  63. {,,,,,,,,-},
  64. {,,,,,,,,},
  65. {,,,,,,,,},
  66. {,,,,,,,},
  67. {,,,,,,,,},//5
  68. {,,,,,,,,},
  69. {,,,,,,,,},
  70. {,,,,,,,,},
  71. {,,,,,,,,},
  72. {,,,,,,,,},//
  73. {,,,,,,,,},
  74. {,,,,,,,,},
  75. {,,,,,,,,},
  76. {,,,,,,,,},
  77. {,,,,,,,,},//
  78. {,,,,,,,,},
  79. {,,,,,,,,},
  80. {,,,,,,,,},
  81. {,,,,,,,,}};//19
  82. //A V E T F
  83. int GOTO[][]={{,,,,},
  84. {,,,,},//
  85. {,,,,},
  86. {,,,,},
  87. {,,,,},
  88. {,,,,},//
  89. {,,,,},
  90. {,,,,},
  91. {,,,,},
  92. {,,,,},
  93. {,,,,},//
  94. {,,,,},
  95. {,,,,},
  96. {,,,,},
  97. {,,,,},
  98. {,,,,},//
  99. {,,,,},
  100. {,,,,},
  101. {,,,,},
  102. {,,,,}};//
  103.  
  104. void R1(); //A→V=E
  105. void R2(); //E→E+T
  106. void R3(); //E→E-T
  107. void R4(); //E→T
  108. void R5(); //T→T*F
  109. void R6(); //T→T/F
  110. void R7(); //T→F
  111. void R8(); //F→(E)
  112. void R9(); //F→i
  113. void R10(); //V→i
  114.  
  115. int isOp(char a) //判断二元运算符及二元运算符的优先级
  116. {
  117. int i;
  118. switch(a)
  119. {
  120. case '=':i=;break;
  121. case '+':i=;break;
  122. case '-':i=;break;
  123. case '*':i=;break;
  124. case '/':i=;break;
  125. default:i=-;break;
  126. }
  127. return i;
  128. }
  129. int isVt(char a)
  130. {
  131. int i;
  132. switch(a)
  133. {
  134. case 'i':i=;break;
  135. case '(':i=;break;
  136. case ')':i=;break;
  137. case '+':i=;break;
  138. case '-':i=;break;
  139. case '*':i=;break;
  140. case '/':i=;break;
  141. case '=':i=;break;
  142. case '#':i=;break;
  143. default:i=-;break;
  144. }
  145. return i;
  146. }
  147. int isVn(char a)
  148. {
  149. int i;
  150. switch(a)
  151. {
  152. case 'A':i=;break;
  153. case 'V':i=;break;
  154. case 'E':i=;break;
  155. case 'T':i=;break;
  156. case 'F':i=;break;
  157. default:i=-;break;
  158. }
  159. return i;
  160. }
  161. int s_r(int i) //移进或者其他
  162. {
  163. int result;
  164. if(i/==) //移进
  165. result=i-;
  166. else
  167. result=i;
  168. return result;
  169. }
  170.  
  171. bool invertStack(stack<int> &one_stack)
  172. {
  173. if (one_stack.empty())//if the stack is null,then don't invert it
  174. {
  175. return false;
  176. }
  177. else
  178. {
  179. //init a stack to save the inverted stack
  180. stack<int> invert;
  181. while (!one_stack.empty())
  182. {
  183. invert.push(one_stack.top());
  184. one_stack.pop();
  185. }
  186. //this moment the stack's inverted state is the stack invert ,so get it back
  187. one_stack = invert;
  188. return true;
  189. }
  190. }
  191.  
  192. void displayStack(stack<int> one_stack) //打印输出
  193. {
  194. invertStack(one_stack);
  195. while (!one_stack.empty())
  196. {
  197. cout << one_stack.top();
  198. one_stack.pop();
  199. }
  200. cout << '\t' << '\t' ;
  201. }
  202.  
  203. bool invertStack1(stack<char> &one_stack)
  204. {
  205. if (one_stack.empty())//if the stack is null,then don't invert it
  206. {
  207. return false;
  208. }
  209. else
  210. {
  211. //init a stack to save the inverted stack
  212. stack<char> invert;
  213. while (!one_stack.empty())
  214. {
  215. invert.push(one_stack.top());
  216. one_stack.pop();
  217. }
  218. //this moment the stack's inverted state is the stack invert ,so get it back
  219. one_stack = invert;
  220. return true;
  221. }
  222. }
  223.  
  224. void displayStack1(stack<char> one_stack)
  225. {
  226. invertStack1(one_stack);
  227. while (!one_stack.empty())
  228. {
  229. cout << one_stack.top();
  230. one_stack.pop();
  231. }
  232. cout << '\t' << '\t';
  233. }
  234.  
  235. void SLR()
  236. {
  237. printf("输入串\t\t状态栈\t\t符号栈\t\tACTION\t\tGOTO ");
  238. int i,j,k=;
  239. state.push(); //初始化
  240. sign.push('#');
  241. int which; //对应表项内容
  242. char c; //输入符号串首
  243. int a; //坐标
  244. int b;
  245. do{
  246. printf("\n");
  247. c=m[k-].temp[]; //输入符号串首
  248. cout<<c<<' ';
  249. for(int j=k;j<=count;j++)
  250. printf("%s",m[j].temp);
  251. printf("\t\t");
  252. displayStack(state);
  253.  
  254. displayStack1(sign);
  255. a=state.top(); //坐标
  256. b=isVt(c);
  257. /*if(isOp(c)!=-1)
  258. temp1=c;
  259. place.push(temp1);*/
  260. if(b!=-) //输入串首c是终结符
  261. {
  262.  
  263. which=ACTION[a][b];
  264. if(which==-)
  265. {
  266. printf(" acc,分析成功!\n");
  267. flag=;
  268. break;
  269. }
  270. else if(which==)
  271. { printf("error项1\n ");break; }
  272. else if(which>=) //移进
  273. {
  274. which=s_r(which);
  275. printf("s%d\t\t",which);
  276. sign.push(c);
  277. state.push(which);
  278. k++;
  279. }
  280. else
  281. {
  282. switch(which) //which整型,case不要加''
  283. {
  284. case :R1();break;
  285. case :R2();break;
  286. case :R3();break;
  287. case :R4();break;
  288. case :R5();break;
  289. case :R6();break;
  290. case :R7();break;
  291. case :R8();break;
  292. case :R9();break;
  293. case :R10();break;
  294. default:printf("which=%derror项2\n ");break;
  295. }
  296. //状态转移 Vn
  297. int e=isVn(sign.top());
  298. if(e!=-)
  299. {
  300. int convert=GOTO[st][e];
  301. state.push(convert);
  302. printf("GOTO[%d,%c]=%d",st,sign.top(),convert);
  303. }
  304. }
  305. }
  306. else
  307. { printf("error_b ");break; }
  308.  
  309. }while(which!=-);//while
  310. }
  311.  
  312. void R1() {
  313.  
  314. sign.pop(); sign.pop(); sign.pop(); //弹出符号栈
  315. state.pop(); state.pop(); state.pop(); //弹出状态栈
  316. sign.push('A'); //符号'A'入栈
  317. st=state.top();
  318. printf("r1\t");
  319. }
  320. void R2() {
  321.  
  322. sign.pop(); sign.pop(); sign.pop(); //弹出符号栈
  323. state.pop(); state.pop(); state.pop(); //弹出状态栈
  324. sign.push('E'); st=state.top(); //符号'E'入栈
  325. printf("r2\t\t");
  326. }
  327. void R3() {
  328.  
  329. sign.pop(); sign.pop(); sign.pop();
  330. state.pop(); state.pop(); state.pop();
  331. sign.push('E');st=state.top();
  332. printf("r3\t\t");
  333. }
  334. void R4() {
  335. sign.pop();
  336. state.pop();
  337. sign.push('E');st=state.top();
  338. printf("r4\t\t");
  339. }
  340. void R5() {
  341.  
  342. sign.pop(); sign.pop(); sign.pop();
  343. state.pop(); state.pop(); state.pop();
  344. sign.push('T');st=state.top();
  345. printf("r5\t\t");
  346. }
  347. void R6() {
  348.  
  349. sign.pop(); sign.pop(); sign.pop();
  350. state.pop(); state.pop(); state.pop();
  351. sign.push('T');st=state.top();
  352. printf("r6\t\t");
  353. }
  354. void R7() {
  355. sign.pop();
  356. state.pop();
  357. sign.push('T');st=state.top();
  358. printf("r7\t\t");
  359. }
  360. void R8() {
  361. sign.pop(); sign.pop(); sign.pop();
  362. state.pop(); state.pop(); state.pop();
  363. sign.push('F');st=state.top();
  364. printf("r8\t\t");
  365. }
  366. void R9() {
  367. sign.pop();
  368. state.pop();
  369. sign.push('F');st=state.top();
  370. printf("r9\t\t");
  371. }
  372. void R10() {
  373. sign.pop();
  374. state.pop();
  375. sign.push('V');st=state.top();
  376. printf("r10\t\t");
  377. }
  378.  
  379. ///////////////////////////////////////////////
  380. void scanner(FILE *p)
  381. {
  382. char filein[],fileout[]; //文件名
  383. printf("请输入要打开的源文件名(包括路径)\n");
  384. scanf("%s",filein);
  385. //printf("请输入要输出的目标文件名(包括路径)\n");
  386. //scanf("%s",fileout);
  387. if((p=fopen(filein,"r"))==NULL) {printf("输入文件打开有错!\n");return;}
  388. // if((q=fopen("fileout","rw"))==NULL) {printf("输出文件打开有错!\n");return;}
  389.  
  390. char token[COUNT]; //输出数组
  391. int r=,i=;
  392. char ch;
  393. ch=fgetc(p);
  394. while(!feof(p)) //没有读到文件末尾
  395. {
  396. if(isdigit(ch))
  397. {
  398. i=;
  399. token[i]=ch;
  400. while(isdigit(ch=fgetc(p)))
  401. {
  402. i++;
  403. token[i]=ch;
  404. }
  405. token[i+]='\0'; //整数结束。不要忘结束标志!
  406. fseek(p,-,); //重定向到当前位置的前一个!
  407. out(INT,token);
  408. //fprintf(q,"%d %s\n",INT,token);
  409. }
  410. else if(isalpha(ch))
  411. {
  412. i=;
  413. int flag=; //标志是否是保留字,默认不是
  414. token[i]=tolower(ch);
  415. while(isalpha(ch=fgetc(p)))
  416. {
  417. i++;
  418. token[i]=tolower(ch);
  419. }
  420. token[i+]='\0';
  421. fseek(p,-,);
  422. for(r=;r<;r++)
  423. {
  424. if(!strcmp(token,keyword[r]))
  425. {
  426. printf("<blz %s>\n",token);
  427. // fprintf(q,"%d %s\n","保留字",token);
  428. flag=;
  429. break;
  430. }
  431. }
  432. if(!flag)
  433. { out(ID,token);
  434. // fprintf(q,"%d %s\n",ID,token);
  435. }
  436. }
  437. else
  438. {
  439. i=;
  440. switch(ch)
  441. {
  442. case '+':{ token[i]=ch;
  443. token[i+]='\0';
  444. out(ADD,token);
  445. }break;
  446. case '-':{ token[i]=ch;
  447. token[i+]='\0';
  448. out(SUB,token);}break;
  449. case '*':{ token[i]=ch;
  450. token[i+]='\0';
  451. out(MUL,token);}break;
  452. case ';':{ token[i]=ch;
  453. token[i+]='\0';
  454. out(FH,token);}break;
  455. case '|':{ token[i]=ch;
  456. token[i+]='\0';
  457. out(SG,token);}break;
  458. case '(':{ token[i]=ch;
  459. token[i+]='\0';
  460. out(ZKH,token);}break;
  461. case ')':{ token[i]=ch;
  462. token[i+]='\0';
  463. out(YKH,token);}break;
  464. case '=':{ token[i]=ch;
  465. token[i+]='\0';
  466. out(EQ,token);}break;
  467. case ' ':{ break;} //空格直接跳
  468. case '#':{ break;} //井号用作结尾
  469. case '<':{token[i]=ch;
  470. ch=fgetc(p);
  471. if(ch=='='){
  472. token[i+]='=';
  473. token[i+]='\0';
  474. out(LE,token);
  475. }
  476. else if(ch=='>'){
  477. token[i+]='>';
  478. token[i+]='\0';
  479. out(NE,token);
  480. }
  481. else
  482. { printf(" error \n");
  483. fseek(p,-,); //多读的要回退一个字符
  484. }
  485. }break;
  486.  
  487. case '>':{token[i]=ch;
  488. ch=fgetc(p);
  489. if(ch=='=')
  490. {
  491. token[i+]='=';
  492. token[i+]='\0';
  493. out(GE,token);
  494. }
  495. else
  496. { printf(" error \n");
  497. fseek(p,-,); //多读的要回退一个字符
  498. }
  499. }break;
  500. case ':':{token[i]=ch;
  501. ch=fgetc(p);
  502. if(ch=='='){
  503. token[i+]='=';
  504. token[i+]='\0';
  505. out(MHEQ,token);
  506. }
  507. else
  508. { printf(" error \n");
  509. fseek(p,-,); //多读的要回退一个字符
  510. }
  511. }break;
  512. case '/':{token[i]=ch;
  513. ch=fgetc(p);
  514. if(ch=='*')
  515. {
  516. token[i+]='*';
  517. token[i+]='\0';
  518. out(XGMUL,token);
  519. while() //注释部分的处理!
  520. {
  521. ch=fgetc(p);
  522. if(ch=='*')
  523. {
  524. if((ch=fgetc(p))=='/')
  525. break;
  526. }
  527. }
  528. }
  529. else // 除号,修改第一次程序部分
  530. { /*printf(" error \n");
  531. fseek(p,-1,1); */
  532. out(DIV,token);
  533. fseek(p,-,);//多读的要回退一个字符
  534. }
  535. }break;
  536. default:{
  537. printf(" error\n ");
  538. }break;
  539.  
  540. }
  541. }
  542. ch=fgetc(p);
  543. }
  544. fclose(p);
  545. }
  546. int main(int argc, char* argv[])
  547. {
  548. printf("编译原理实验_5:SLR分析程序(待分析内容在文件file.txt中,以#结尾)\n");
  549. FILE *fin,*q;
  550. scanner(fin);
  551. strcpy(m[count].temp,"#");//!
  552. count=count+;
  553. //scanner(p,q);
  554. SLR();
  555. MAIN();
  556. return ;
  557. }

---内容结束---

编译原理实验之SLR1文法分析的更多相关文章

  1. 《编译原理》构造 LL(1) 分析表的步骤 - 例题解析

    <编译原理>构造 LL(1) 分析表的步骤 - 例题解析 易错点及扩展: 1.求每个产生式的 SELECT 集 2.注意区分是对谁 FIRST 集 FOLLOW 集 3.开始符号的 FOL ...

  2. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  3. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  4. 编译原理:LL(1)文法的判断,递归下降分析程序

    1. 文法 G(S): (1)S -> AB (2)A ->Da|ε (3)B -> cC (4)C -> aADC |ε (5)D -> b|ε 验证文法 G(S)是不 ...

  5. 编译原理之LL(1)文法的判断,递归下降分析程序

    1. 文法 G(S): (1)S -> AB (2)A ->Da|ε (3)B -> cC (4)C -> aADC |ε (5)D -> b|ε 验证文法 G(S)是不 ...

  6. 编译原理 算法3.8 LR分析 c++11实现

    LR分析简介 LR分析是应用最广泛的一类分析方法,它是实用的编译器功能中最强的分析器,其特点是: 1,采用最一般的无回溯移进-规约方法. 2,可分析的文法是LL文法的真超集. 3,能够及时发现错误,及 ...

  7. 编译原理 #02# 简易递归下降分析程序(js实现)

    // 实验存档 截图: 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...

  8. 编译原理实习(应用预测分析法LL(1)实现语法分析)

    #include<iostream> #include<fstream> #include<iomanip> #include<cstdio> #inc ...

  9. 编译原理实验 NFA子集法构造DFA,DFA的识别 c++11实现

    实验内容 将非确定性有限状态自动机通过子集法构造确定性有限状态自动机. 实验步骤 1,读入NFA状态.注意最后需要设置终止状态. 2,初始态取空,构造DFA的l0状态,将l0加入未标记状态队列que ...

随机推荐

  1. ILSpy反编译工具之C#反汇编

    1.下载ILspy工具 https://github.com/icsharpcode/ILSpy#ilspy------- 注意: ILspy需要在电脑上安装.NET Framework 4.0.   ...

  2. .Net Core使用分布式缓存Redis:Lua脚本

    一.前言 运行环境window,redis版本3.2.1.此处暂不对Lua进行详细讲解,只从Redis的方面讲解. 二.Redis的Lua脚本 在Redis的2.6版本推出了脚本功能,允许开发者使用L ...

  3. 1、Vue 实战-入门篇

    先决条件:需要 Node.js . npm 基础. 如果没有基础看先看下面简单的两点介绍. 1.npm 命令介绍. 1.所有命令  -h 可以查看.也可以从官网查 docs,结果如下. --help ...

  4. ubuntu16.04 docker kubernetes(k8s) istio 安装

    版本: docker: 19.03.5 kubernetes: 1.17.0 istio: 1.4.3 步骤一:给ubuntu换源 https://www.cnblogs.com/lfri/p/106 ...

  5. wannafly camp day4

    2088: 电音之王 描述 题目描述: 终于活成了自己讨厌的样子. 听说多听电音能加快程序运行的速度. 定义一个数列,告诉你a0,a1,m0,m1,ca\_0,a\_1,m\_0,m\_1,ca0​, ...

  6. sg函数的变形 - 可以将一堆石子分开

    Nim is a two-player mathematic game of strategy in which players take turns removing objects from di ...

  7. Ubuntu阿里镜像

    ubuntu 14.04: http://mirrors.aliyun.com/ubuntu-releases/14.04/ ubuntu 16.04: http://mirrors.aliyun.c ...

  8. Django AJAX csrf

    1.原始 a.在HTML中添加 {% csrf_token %} b.在data中添加csrf_token对应input的 键值对 "csrfmiddlewaretoken" : ...

  9. .net core appsetting/获取配置文件

    修改appsetting 最近用Identity4所以需要做一个配置项项目 { "Logging": { "IncludeScopes": false, &qu ...

  10. 安装anaconda python时只能安装到默认文件夹&& 安装提示文件夹以存在问题

    这个问题困扰了两次,网上说可以,我就是不行,查了半天没找到解决方法, 后来装在C盘里, 之后在百度知道(ID:幸福999快乐)发现解决办法后来才发现问题. 在安装的时候,要安装的目标文件夹不需要先在安 ...