⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit1.~cpp

📁 编译原理源码(包括语法分析
💻 ~CPP
📖 第 1 页 / 共 3 页
字号:
/*** PL0 COMPILER WITH CODE GENERATION ***/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
int COD=1;//0为词法分析
int choice=1;//0为IF未改
const  AL    =  10;  /*标示符的长度为10*/
const  NORW  =  19;  /*保留字的个数为19*/
const  TXMAX = 100;  /* 标示符表的最大长度为100*/
const  NMAX  =  14;  /* 数字最大位数为14*/
const  AMAX  =2047;  /* 最大寻址为2047*/
const  LEVMAX=   3;  /* 嵌套最大层数为3*/
const  CXMAX = 200;  /* 代码数组最大为200*/
const  NumOfSybol=43;//定义关键保留字43个

typedef int *ERRORPOINT;

typedef enum  { NUL, IDENT, NUMBER, PLUS, MINUS, TIMES,
	            SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ,
	            LPAREN, RPAREN,
                    QUOT,//单引号
                    COMMA, SEMICOLON, PERIOD,
	            BECOMES,
                    PLUSBECOMES,//+=
                    MINUSBECOMES,//-=
                    DOUBLEPLUS,  //++
                    DOUBLEMINUS,  //--
                    BEGINSYM, ENDSYM, IFSYM, THENSYM,
	            WHILESYM, WRITESYM, READSYM, DOSYM, CALLSYM,
	            CONSTSYM, VARSYM, PROCSYM, PROGSYM,CHARSYM,//字符类型
                    ELSESYM,//在此加了ELSE
                    FORSYM, //加了FOR
                    TOSYM,  //加了TO
                    DOWNTOSYM //加了DOWMTO

        } SYMBOL; /*词汇表,其中控制程序结构的保留字14个*/
char *SYMOUT[] = {"NUL", "IDENT", "NUMBER", "PLUS", "MINUS", "TIMES",
	    "SLASH", "ODDSYM", "EQL", "NEQ", "LSS", "LEQ", "GTR", "GEQ",
	    "LPAREN", "RPAREN",
            "QUOT",//单引号
            "COMMA", "SEMICOLON", "PERIOD",
	    "BECOMES",
            "PLUSBECOMES", //+=
            "MINUSBECOMES", //-=
            "DOUBLEPLUS",   //++
            "DOUBLEMINUS",   //--
            "BEGINSYM", "ENDSYM", "IFSYM", "THENSYM",
	    "WHILESYM", "WRITESYM", "READSYM", "DOSYM", "CALLSYM",
	    "CONSTSYM", "VARSYM", "PROCSYM", "PROGSYM",  "CHARSYM", //字符类型
            "ELSESYM", //在此加了ELSE
            "FORSYM",//加了FOR
            "TOSYM",//加了TO
            "DOWNTOSYM"//加了DOWMTO
             };
typedef  int *SYMSET; //字符集;
typedef  char ALFA[11];
typedef  enum { CONSTANT, VARIABLE, PROCEDUR,CHARACTOR } OBJECTS ;
typedef  enum { LIT, OPR, LOD, STO, CAL, INI, JMP, JPC } FCT;
typedef struct {
	 FCT F;     /*函数命令*/
	 int L; 	/*0..LEVMAX  LEVEL*/
	 int A;     /*0..AMAX    DISPLACEMENT ADDR*/
} INSTRUCTION;
/*
LIT   0   A  将常数值取到栈顶,A为常数值
LOD  L   A  将变量值取到栈顶,A为偏移量,L为层差
STO  L   A  将栈顶内容送入某一变量单元中,A为偏移量,L为层差
CAL  L   A  调用过程,A为过程地址,L为层差
INT  0   A  在运行栈中为被调用的过程开辟A个单元的数据区
JMP  0   A  无条件跳转到A地址
JPC  0   A  条件跳转,当栈顶布尔值非真则跳转到A地址,否则顺序执行
OPR  0   0  过程调用结束后,返回调用点并退栈
OPR  0   1  栈顶元素取反
OPR  0   2  次栈顶与栈顶相加,退两个栈元素,结果值进栈
OPR  0   3  次栈顶减去栈顶,退两个栈元素,结果值进栈
OPR  0   4  次栈顶乘以栈顶,退两个栈元素,结果值进栈
OPR  0   5  次栈顶除以栈顶,退两个栈元素,结果值进栈
OPR  0   6  栈顶元素的奇偶判断,结果值在栈顶
OPR  0   7  
OPR  0   8  次栈顶与栈顶是否相等,退两上栈元素,结果值进栈
OPR  0   9  次栈顶与栈顶是否不等,退两个栈元素,结果值进栈
OPR  0   10 次栈顶是否小于栈顶,退两个栈元素,结果值进栈
OPR  0   11 次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈
OPR  0   12 次栈顶是否大于栈顶,退两个栈元素,结果值进栈
OPR  0   13 次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈
OPR  0   14 栈顶值输出到屏幕
OPR  0   15 屏幕输出换行
OPR  0   16 从命令行读入一个输入置于栈顶

*/

char   CH;  /*最近读进的字符*/
SYMBOL SYM; /*存放每个单词的类别,用内部编码形式表示*/
ALFA   ID;  /*存放用户所定义的标识符的值,即字符串的机内表示*/
int    NUM; /*用户所定义的数*/
int    CC;  /*CHARACTER COUNT*/
int    LL;  /*缓冲器的长度*/
int    CX;  /*CODE数组的下标索引*/
char   LINE[81];
INSTRUCTION  CODE[CXMAX];
ALFA    KWORD[NORW+1];
SYMBOL  WSYM[NORW+1];  //存放保留字
SYMBOL  SSYM['^'+1]; //在' '到'^'才是可用
ALFA    MNEMONIC[9];
SYMSET  DECLBEGSYS, STATBEGSYS, FACBEGSYS;

struct {
  ALFA NAME; //名称
  OBJECTS KIND;  //类型
  union {
    int VAL;   /*常量*/
    struct {
        int LEVEL,ADR,SIZE;
        } vp;  /*变量或者过程*/
  };
} TABLE[TXMAX]; //即TABLE[100]

FILE *FIN,*FOUT;  //输入输出文件的指针
int ERR;          //错误个数统计
String ERRORKIND[34] = {"",
        "常数说明中的'='写成':='",                      //1
        "常数说明中的'='后应是数字",                    //2
        "常数说明中的标识符后应是=号",                  //3
        "CHAR,CONST,VAR,PROCEDURE 后应为标识符",             //4
        "漏掉了','或';'",                               //5
        "过程说明后的符号不正确",                       //6
        "应是语句开始符",                               //7
        "程序体内语句部分的后跟符不正确",               //8
        "程序结尾丢了句号'.'",                          //9
        "语句之间漏了';'",                              //10
        "标识符未说明",                                 //11
        "赋值语句中,赋值号左部标识符属性应是变量",      //12
        "赋值语句左部标识符后应是赋值号':='",           //13
        "CALL后应为标识符",                             //14
        "CALL后标识符属性应为过程",                     //15
        "条件语句中丢了'THEN'或'ELSE'",                 //16
        "丢了'END'或';'",                               //17
        "WHILE型循环语句中丢了'DO'",                    //18
        "语句后的符号不正确",                           //19
        "应为关系运算符",                               //20
        "表达式内标识符属性不能是过程",                 //21
        "表达式中漏掉右括号')'",                        //22
        "因子后的非法符号",                             //23
        "表达式的开始符不能是此符号",                   //24
        "FOR 语句后应有TO或DOWN",                       //25
        "字符类型不符",                                 //26
        "字符类型漏了'''单引号",                         //27
        "READ 函数内的标识符没定义",                    //28
        "NUL",            //~30
        "数越界",                                       //31
        "READ语句括号中的标识符不是变量"               //32
        "NUL"                                          //33
        "NUL"                                          //34
         };
void EXPRESSION(SYMSET FSYS, int LEV, int &TX);
void TERM(SYMSET FSYS, int LEV, int &TX);
//---------------------------------------------------------------------------
int SymIn(SYMBOL SYM, SYMSET S1) {
  return S1[SYM];
}
//---------------------------------------------------------------------------
SYMSET SymSetUnion(SYMSET S1, SYMSET S2) {
  SYMSET S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (int i=0; i<NumOfSybol; i++)
	if (S1[i] || S2[i]) S[i]=1;
	else S[i]=0;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetAdd(SYMBOL SY, SYMSET S) {
  SYMSET S1;
  S1=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (int i=0; i<NumOfSybol; i++) S1[i]=S[i];
  S1[SY]=1;
  return S1;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a, SYMBOL b) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;  S[b]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;  S[b]=1; S[c]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c, SYMBOL d) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;  S[b]=1; S[c]=1; S[d]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c, SYMBOL d,SYMBOL e) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;  S[b]=1; S[c]=1; S[d]=1; S[e]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNew(SYMBOL a, SYMBOL b, SYMBOL c, SYMBOL d,SYMBOL e, SYMBOL f) {
  SYMSET S; int i,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  S[a]=1;  S[b]=1; S[c]=1; S[d]=1; S[e]=1; S[f]=1;
  return S;
}
//---------------------------------------------------------------------------
SYMSET SymSetNULL() {
  SYMSET S; int i,n,k;
  S=(SYMSET)malloc(sizeof(int)*NumOfSybol);
  for (i=0; i<NumOfSybol; i++) S[i]=0;
  return S;
}
//---------------------------------------------------------------------------
/* 错误处理:  打印出错位置和错误编码

*/
void Error(int n) {
  String s = "***"+AnsiString::StringOfChar(' ', CC-1)+"^";
  s=s+n+ERRORKIND[n];
   Form1->printfs(s.c_str());
 // Form1->printls(s.c_str(),n);
  //Form1->printls(
  fprintf(FOUT,"%s%d\n", s.c_str(), n);
  ERR++;
} /*Error*/
//---------------------------------------------------------------------------
void GetCh() { /*漏掉空格,读取一个字符*/
	/*
	CH:存放当前读取的字符,初始值为空
	LINE:为一维数组,其数组元素是字符,界对为1:800.用于读入一行的缓冲区.
	LL:计数器,初始值为0.
	CC:计数器,初始值为0.
	*/

  if (CC==LL) {   //缓冲区是否结束?
                  //是则执行下边
    if (feof(FIN)) {//判断文件是否结束
	  Form1->printfs("PROGRAM INCOMPLETE");
	  fprintf(FOUT,"PROGRAM INCOMPLETE\n");
	  fclose(FOUT);
	  exit(0);  //goto 199;出口
	}
	LL=0; CC=0;
	CH=' ';
	while (!feof(FIN) && CH!=10)  //ASCII码 换行符
      { CH=fgetc(FIN);  LINE[LL++]=CH; }   //逐个放到LINE缓冲区啊
	LINE[LL-1]=' ';  LINE[LL]=0;
    String s=IntToStr(CX);
    while(s.Length()<3) s=" "+s;
    s=s+" "+LINE;
	Form1->printfs(s.c_str());
    fprintf(FOUT,"%s\n",s);
  }
  CH=LINE[CC++];  //否
} /*GetCh()*/
//---------------------------------------------------------------------------
void GetSym() {/*词法分析,读取一个单词*/
	/*完成的任务:
	(1)滤空格:
	(2)识别保留字:设有一张保留字表,对每个字母打头的字母,数字字符串要查此表
	   若查着则为保留字,将对应的类别放在SYM中,若查不着,则认为是用户定义的标识符
	(3)识别标识符:对用户定义的标识符将IDENT放在SYM中,标识符本身的值放在ID中;
	(4)拼数:当所取的单词是数字时,将数的类别NUMBER放在SYM中,数值本身的值存放的NUM中.
	(5)拼复用词:对两处字符组成的算符识别后将类别送SYM中;
	(6)输出源程序:为边读入字符边输出(可输出在文件中).
	A:一维数组.数组元素为字符,界对[1:10],存放读进的标识符.
	ID:同A.
	WORD:保留字表,一维数组.数组元素是以字符为元素的一维数组.界对为[1:13].
	查表方式采用二分法.
	*/
  int i,J,K;   ALFA  A; //存放读进的标识符.
  while (CH<=' ') GetCh();  //滤空格并滤掉控制字符,因为' '之前的都是控制字符
  if (CH>='A' && CH<='Z') { /*如果是标识符*/
    K=0;
	do {
	  if (K<AL) A[K++]=CH;
	  GetCh();
	}while((CH>='A' && CH<='Z')||(CH>='0' && CH<='9'));
	A[K]='\0';
	strcpy(ID,A);  //将A的内容COPY给ID
        i=1; J=NORW;//NORW是关键保留字的个数初始时为14
	do {                      //以下为 查表方式采用二分法方式查表方式.
	  K=(i+J) / 2;
	  if (strcmp(ID,KWORD[K])<=0) J=K-1;
	  if (strcmp(ID,KWORD[K])>=0) i=K+1;
	}while(i<=J);
	if (i-1 > J) SYM=WSYM[K]; //若查找到,则是关键保留字
	else SYM=IDENT;          //否则为用户定义的标识符
  }
  else if (CH>='0' && CH<='9') { /*数字处理*/
      K=0; NUM=0;  //值放在NUM中
       SYM=NUMBER; //类型为数字
	  do {
	    NUM=10*NUM+(CH-'0');
		K++; GetCh();
      }while(CH>='0' && CH<='9');
	  if (K>NMAX) Error(30);  //若K大于数值的最大位数NMAX14位时则出错
    }
    else if (CH==':') {
	    GetCh();
		if (CH=='=') { SYM=BECOMES; GetCh(); }
		else SYM=NUL;
          }
	  else if (CH=='<') {  /* 处理<, <=,> */
		  GetCh();
		  if (CH=='=') { SYM=LEQ; GetCh(); }
                  else if(CH=='>') { SYM=NEQ; GetCh(); }
		  else SYM=LSS;
		}
		else if (CH=='>') {/* 处理> ,>=的关系 */
		    GetCh();
			if (CH=='=') { SYM=GEQ; GetCh(); }
			else SYM=GTR;
                  }
                  else if(CH=='+'){//处理以'+'开头的
                          GetCh();
		          if (CH=='=') { SYM=PLUSBECOMES; GetCh(); }
		          else if(CH=='+') { SYM=DOUBLEPLUS; GetCh(); }
                                else  { SYM=PLUS;  }
                    }
                    else if(CH=='-'){//处理以'-'开头的
                          GetCh();
		          if (CH=='=') { SYM=MINUSBECOMES; GetCh(); }
		          else if(CH=='-') { SYM=DOUBLEMINUS; GetCh(); }
                               else  { SYM=MINUS;}
                          }
                          else if(CH=='\''){SYM=QUOT;GetCh();}
		          else { SYM=SSYM[CH]; GetCh(); }
} /*GetSym()*/
//---------------------------------------------------------------------------
void GEN(FCT X, int Y, int Z) {
/*  完成任务:生成目标代码,并送入目标程序区
   FCT:功能代码
       Y:层差
       Z:位移量

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -