文章目录
- 实验
- 任务1
- 任务2
- 本次的实验是在前三次
TINYC
的基础上的一个测试,所以完成前三次的实验是基础
编译原理 之 实验一
编译原理实验 之 Tiny C语言编译程序实验 语法分析
编译原理实验 之 TINY 之 语义分析(第二次作业
- 首先将新的文件复制到先前的目录下面
需要复制的文件
整体的实验目录
实验要求
本次实验任务:
1、联调,给出sample.tny程序运行结果截图
2、自行编写Tiny C语言源程序,上交源代码,有运行结果的截图。
实验
任务1
直接对原本的那个
sample.tny
进行测试
其实那个
TM.c
我还修改了一下,应该是不用修改的,如果修改的话,可以直接复制我下面的代码
/****************************************************/
/* File: tm.c */
/* The TM ("Tiny Machine") computer */
/****************************************************/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif/******* const *******/
#define IADDR_SIZE 1024 /* increase for large programs */
#define DADDR_SIZE 1024 /* increase for large programs */
#define NO_REGS 8
#define PC_REG 7#define LINESIZE 121
#define WORDSIZE 20/******* type *******/typedef enum {opclRR, /* reg operands r,s,t */opclRM, /* reg r, mem d+s */opclRA /* reg r, int d+s */} OPCLASS;typedef enum {/* RR instructions */opHALT, /* RR halt, operands are ignored */opIN, /* RR read into reg(r); s and t are ignored */opOUT, /* RR write from reg(r), s and t are ignored */opADD, /* RR reg(r) = reg(s)+reg(t) */opSUB, /* RR reg(r) = reg(s)-reg(t) */opMUL, /* RR reg(r) = reg(s)*reg(t) */opDIV, /* RR reg(r) = reg(s)/reg(t) */opRRLim, /* limit of RR opcodes *//* RM instructions */opLD, /* RM reg(r) = mem(d+reg(s)) */opST, /* RM mem(d+reg(s)) = reg(r) */opRMLim, /* Limit of RM opcodes *//* RA instructions */opLDA, /* RA reg(r) = d+reg(s) */opLDC, /* RA reg(r) = d ; reg(s) is ignored */opJLT, /* RA if reg(r)<0 then reg(7) = d+reg(s) */opJLE, /* RA if reg(r)<=0 then reg(7) = d+reg(s) */opJGT, /* RA if reg(r)>0 then reg(7) = d+reg(s) */opJGE, /* RA if reg(r)>=0 then reg(7) = d+reg(s) */opJEQ, /* RA if reg(r)==0 then reg(7) = d+reg(s) */opJNE, /* RA if reg(r)!=0 then reg(7) = d+reg(s) */opRALim /* Limit of RA opcodes */} OPCODE;typedef enum {srOKAY,srHALT,srIMEM_ERR,srDMEM_ERR,srZERODIVIDE} STEPRESULT;typedef struct {int iop ;int iarg1 ;int iarg2 ;int iarg3 ;} INSTRUCTION;/******** vars ********/
int iloc = 0 ;
int dloc = 0 ;
int traceflag = FALSE;
int icountflag = FALSE;INSTRUCTION iMem [IADDR_SIZE];
int dMem [DADDR_SIZE];
int reg [NO_REGS];char * opCodeTab[]= {"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",/* RR opcodes */"LD","ST","????", /* RM opcodes */"LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"/* RA opcodes */};char * stepResultTab[]= {"OK","Halted","Instruction Memory Fault","Data Memory Fault","Division by 0"};char pgmName[20];
FILE *pgm ;char in_Line[LINESIZE] ;
int lineLen ;
int inCol ;
int num ;
char word[WORDSIZE] ;
char ch ;
int done ;/********************************************/
int opClass( int c )
{ if ( c <= opRRLim) return ( opclRR );else if ( c <= opRMLim) return ( opclRM );else return ( opclRA );
} /* opClass *//********************************************/
void writeInstruction ( int loc )
{ printf( "%5d: ", loc) ;if ( (loc >= 0) && (loc < IADDR_SIZE) ){ printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);switch ( opClass(iMem[loc].iop) ){ case opclRR: printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);break;case opclRM:case opclRA: printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);break;}printf ("\n") ;}
} /* writeInstruction *//********************************************/
void getCh (void)
{ if (++inCol < lineLen)ch = in_Line[inCol] ;else ch = ' ' ;
} /* getCh *//********************************************/
int nonBlank (void)
{ while ((inCol < lineLen)&& (in_Line[inCol] == ' ') )inCol++ ;if (inCol < lineLen){ ch = in_Line[inCol] ;return TRUE ; }else{ ch = ' ' ;return FALSE ; }
} /* nonBlank *//********************************************/
int getNum (void)
{ int sign;int term;int temp = FALSE;num = 0 ;do{ sign = 1;while ( nonBlank() && ((ch == '+') || (ch == '-')) ){ temp = FALSE ;if (ch == '-') sign = - sign ;getCh();}term = 0 ;nonBlank();while (isdigit(ch)){ temp = TRUE ;term = term * 10 + ( ch - '0' ) ;getCh();}num = num + (term * sign) ;} while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;return temp;
} /* getNum *//********************************************/
int getWord (void)
{ int temp = FALSE;int length = 0;if (nonBlank ()){ while (isalnum(ch)){ if (length < WORDSIZE-1) word [length++] = ch ;getCh() ;}word[length] = '\0';temp = (length != 0);}return temp;
} /* getWord *//********************************************/
int skipCh ( char c )
{ int temp = FALSE;if ( nonBlank() && (ch == c) ){ getCh();temp = TRUE;}return temp;
} /* skipCh *//********************************************/
int atEOL(void)
{ return ( ! nonBlank ());
} /* atEOL *//********************************************/
int error( char * msg, int lineNo, int instNo)
{ printf("Line %d",lineNo);if (instNo >= 0) printf(" (Instruction %d)",instNo);printf(" %s\n",msg);return FALSE;
} /* error *//********************************************/
int readInstructions (void)
{ OPCODE op;int arg1, arg2, arg3;int loc, regNo, lineNo;for (regNo = 0 ; regNo < NO_REGS ; regNo++)reg[regNo] = 0 ;dMem[0] = DADDR_SIZE - 1 ;for (loc = 1 ; loc < DADDR_SIZE ; loc++)dMem[loc] = 0 ;for (loc = 0 ; loc < IADDR_SIZE ; loc++){ iMem[loc].iop = opHALT ;iMem[loc].iarg1 = 0 ;iMem[loc].iarg2 = 0 ;iMem[loc].iarg3 = 0 ;}lineNo = 0 ;while (! feof(pgm)){ fgets( in_Line, LINESIZE-2, pgm ) ;inCol = 0 ; lineNo++;lineLen = strlen(in_Line)-1 ;if (in_Line[lineLen]=='\n') in_Line[lineLen] = '\0' ;else in_Line[++lineLen] = '\0';if ( (nonBlank()) && (in_Line[inCol] != '*') ){ if (! getNum())return error("Bad location", lineNo,-1);loc = num;if (loc > IADDR_SIZE)return error("Location too large",lineNo,loc);if (! skipCh(':'))return error("Missing colon", lineNo,loc);if (! getWord ())return error("Missing opcode", lineNo,loc);int opInt = static_cast<int>(opHALT);while ((opInt < opRALim) && (strncmp(opCodeTab[opInt], word, 4) != 0))opInt++;op = static_cast<OPCODE>(opInt);switch ( opClass(op) ){ case opclRR :/***********************************/if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )return error("Bad first register", lineNo,loc);arg1 = num;if ( ! skipCh(','))return error("Missing comma", lineNo, loc);if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )return error("Bad second register", lineNo, loc);arg2 = num;if ( ! skipCh(',')) return error("Missing comma", lineNo,loc);if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )return error("Bad third register", lineNo,loc);arg3 = num;break;case opclRM :case opclRA :/***********************************/if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )return error("Bad first register", lineNo,loc);arg1 = num;if ( ! skipCh(','))return error("Missing comma", lineNo,loc);if (! getNum ())return error("Bad displacement", lineNo,loc);arg2 = num;if ( ! skipCh('(') && ! skipCh(',') )return error("Missing LParen", lineNo,loc);if ( (! getNum ()) || (num < 0) || (num >= NO_REGS))return error("Bad second register", lineNo,loc);arg3 = num;break;}iMem[loc].iop = op;iMem[loc].iarg1 = arg1;iMem[loc].iarg2 = arg2;iMem[loc].iarg3 = arg3;}}return TRUE;
} /* readInstructions *//********************************************/
STEPRESULT stepTM (void)
{ INSTRUCTION currentinstruction ;int pc ;int r,s,t,m ;int ok ;pc = reg[PC_REG] ;if ( (pc < 0) || (pc > IADDR_SIZE) )return srIMEM_ERR ;reg[PC_REG] = pc + 1 ;currentinstruction = iMem[ pc ] ;switch (opClass(currentinstruction.iop) ){ case opclRR :/***********************************/r = currentinstruction.iarg1 ;s = currentinstruction.iarg2 ;t = currentinstruction.iarg3 ;break;case opclRM :/***********************************/r = currentinstruction.iarg1 ;s = currentinstruction.iarg3 ;m = currentinstruction.iarg2 + reg[s] ;if ( (m < 0) || (m > DADDR_SIZE))return srDMEM_ERR ;break;case opclRA :/***********************************/r = currentinstruction.iarg1 ;s = currentinstruction.iarg3 ;m = currentinstruction.iarg2 + reg[s] ;break;} /* case */switch ( currentinstruction.iop){ /* RR instructions */case opHALT :/***********************************/printf("HALT: %1d,%1d,%1d\n",r,s,t);return srHALT ;/* break; */case opIN :/***********************************/do{ printf("Enter value for IN instruction: ") ;fflush (stdin);fflush (stdout);gets(in_Line);lineLen = strlen(in_Line) ;inCol = 0;ok = getNum();if ( ! ok ) printf ("Illegal value\n");else reg[r] = num;}while (! ok);break;case opOUT : printf ("OUT instruction prints: %d\n", reg[r] ) ;break;case opADD : reg[r] = reg[s] + reg[t] ; break;case opSUB : reg[r] = reg[s] - reg[t] ; break;case opMUL : reg[r] = reg[s] * reg[t] ; break;case opDIV :/***********************************/if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t];else return srZERODIVIDE ;break;/*************** RM instructions ********************/case opLD : reg[r] = dMem[m] ; break;case opST : dMem[m] = reg[r] ; break;/*************** RA instructions ********************/case opLDA : reg[r] = m ; break;case opLDC : reg[r] = currentinstruction.iarg2 ; break;case opJLT : if ( reg[r] < 0 ) reg[PC_REG] = m ; break;case opJLE : if ( reg[r] <= 0 ) reg[PC_REG] = m ; break;case opJGT : if ( reg[r] > 0 ) reg[PC_REG] = m ; break;case opJGE : if ( reg[r] >= 0 ) reg[PC_REG] = m ; break;case opJEQ : if ( reg[r] == 0 ) reg[PC_REG] = m ; break;case opJNE : if ( reg[r] != 0 ) reg[PC_REG] = m ; break;/* end of legal instructions */} /* case */return srOKAY ;
} /* stepTM *//********************************************/
int doCommand (void)
{ char cmd;int stepcnt=0, i;int printcnt;int stepResult;int regNo, loc;do{ printf ("Enter command: ");fflush (stdin);fflush (stdout);gets(in_Line);lineLen = strlen(in_Line);inCol = 0;}while (! getWord ());cmd = word[0] ;switch ( cmd ){ case 't' :/***********************************/traceflag = ! traceflag ;printf("Tracing now ");if ( traceflag ) printf("on.\n"); else printf("off.\n");break;case 'h' :/***********************************/printf("Commands are:\n");printf(" s(tep <n> "\"Execute n (default 1) TM instructions\n");printf(" g(o "\"Execute TM instructions until HALT\n");printf(" r(egs "\"Print the contents of the registers\n");printf(" i(Mem <b <n>> "\"Print n iMem locations starting at b\n");printf(" d(Mem <b <n>> "\"Print n dMem locations starting at b\n");printf(" t(race "\"Toggle instruction trace\n");printf(" p(rint "\"Toggle print of total instructions executed"\" ('go' only)\n");printf(" c(lear "\"Reset simulator for new execution of program\n");printf(" h(elp "\"Cause this list of commands to be printed\n");printf(" q(uit "\"Terminate the simulation\n");break;case 'p' :/***********************************/icountflag = ! icountflag ;printf("Printing instruction count now ");if ( icountflag ) printf("on.\n"); else printf("off.\n");break;case 's' :/***********************************/if ( atEOL ()) stepcnt = 1;else if ( getNum ()) stepcnt = abs(num);else printf("Step count?\n");break;case 'g' : stepcnt = 1 ; break;case 'r' :/***********************************/for (i = 0; i < NO_REGS; i++){ printf("%1d: %4d ", i,reg[i]);if ( (i % 4) == 3 ) printf ("\n");}break;case 'i' :/***********************************/printcnt = 1 ;if ( getNum ()){ iloc = num ;if ( getNum ()) printcnt = num ;}if ( ! atEOL ())printf ("Instruction locations?\n");else{ while ((iloc >= 0) && (iloc < IADDR_SIZE)&& (printcnt > 0) ){ writeInstruction(iloc);iloc++ ;printcnt-- ;}}break;case 'd' :/***********************************/printcnt = 1 ;if ( getNum ()){ dloc = num ;if ( getNum ()) printcnt = num ;}if ( ! atEOL ())printf("Data locations?\n");else{ while ((dloc >= 0) && (dloc < DADDR_SIZE)&& (printcnt > 0)){ printf("%5d: %5d\n",dloc,dMem[dloc]);dloc++;printcnt--;}}break;case 'c' :/***********************************/iloc = 0;dloc = 0;stepcnt = 0;for (regNo = 0; regNo < NO_REGS ; regNo++)reg[regNo] = 0 ;dMem[0] = DADDR_SIZE - 1 ;for (loc = 1 ; loc < DADDR_SIZE ; loc++)dMem[loc] = 0 ;break;case 'q' : return FALSE; /* break; */default : printf("Command %c unknown.\n", cmd); break;} /* case */stepResult = srOKAY;if ( stepcnt > 0 ){ if ( cmd == 'g' ){ stepcnt = 0;while (stepResult == srOKAY){ iloc = reg[PC_REG] ;if ( traceflag ) writeInstruction( iloc ) ;stepResult = stepTM ();stepcnt++;}if ( icountflag )printf("Number of instructions executed = %d\n",stepcnt);}else{ while ((stepcnt > 0) && (stepResult == srOKAY)){ iloc = reg[PC_REG] ;if ( traceflag ) writeInstruction( iloc ) ;stepResult = stepTM ();stepcnt-- ;}}printf( "%s\n",stepResultTab[stepResult] );}return TRUE;
} /* doCommand *//********************************************/
/* E X E C U T I O N B E G I N S H E R E */
/********************************************/main( int argc, char * argv[] )
{ if (argc != 2){ printf("usage: %s <filename>\n",argv[0]);exit(1);}strcpy(pgmName,argv[1]) ;if (strchr (pgmName, '.') == NULL)strcat(pgmName,".tm");pgm = fopen(pgmName,"r");if (pgm == NULL){ printf("file '%s' not found\n",pgmName);exit(1);}/* read the program */if ( ! readInstructions ())exit(1) ;/* switch input file to terminal *//* reset( input ); *//* read-eval-print */printf("TM simulation (enter h for help)...\n");dodone = ! doCommand ();while (! done );printf("Simulation done.\n");return 0;
}
- 如果修改了这个
TM.c
,那就需要编译一下
gcc TM.C -o TM
-
OK,接下来就是正式的测试
-
首先需要修改这个
main.c
程序,下面的main.c
已经是修改好了的,可以直接复制来用
/****************************************************/
/* File: main.c */
/* Main program for TINY compiler */
/****************************************************/#include "globals.h"/* set NO_PARSE to FALSE to enable the parser */
#define NO_PARSE FALSE
/* set NO_ANALYZE to FALSE to enable semantic analysis */
#define NO_ANALYZE FALSE
/* set NO_CODE to TRUE to disable code generation */
#define NO_CODE FALSE#include "util.h"
#if NO_PARSE
#include "scan.h"
#else
#include "parse.h"
#if !NO_ANALYZE
#include "analyze.h"
#if !NO_CODE
#include "cgen.h"
#endif
#endif
#endif/* allocate global variables */
int lineno = 0;
FILE * source;
FILE * listing;
FILE * code;/* allocate and set tracing flags */
int EchoSource = TRUE;
int TraceScan = FALSE; // 禁用词法分析输出
int TraceParse = TRUE; // 启用语法分析输出
int TraceAnalyze = TRUE; // 启用语义分析输出
int TraceCode = FALSE;
int Error = FALSE;int main(int argc, char * argv[])
{ TreeNode * syntaxTree;char pgm[120]; /* source code file name */if (argc != 2){ fprintf(stderr,"usage: %s <filename>\n",argv[0]);exit(1);}strcpy(pgm,argv[1]) ;if (strchr (pgm, '.') == NULL)strcat(pgm,".tny");source = fopen(pgm,"r");if (source==NULL){ fprintf(stderr,"File %s not found\n",pgm);exit(1);}listing = stdout; /* send listing to screen */fprintf(listing,"\nTINY COMPILATION: %s\n",pgm);
#if NO_PARSEwhile (getToken()!=ENDFILE); /* ʷʷ */
#elsesyntaxTree = parse(); /* */if (TraceParse) {fprintf(listing,"\nSyntax tree:\n");printTree(syntaxTree);}#if !NO_ANALYZE /* ֣ע͵ */if (! Error){ if (TraceAnalyze) fprintf(listing,"\nBuilding Symbol Table...\n");buildSymtab(syntaxTree);if (TraceAnalyze) fprintf(listing,"\nChecking Types...\n");typeCheck(syntaxTree);if (TraceAnalyze) fprintf(listing,"\nType Checking Finished\n");}
#if !NO_CODEif (! Error){ char * codefile;int fnlen = strcspn(pgm,".");codefile = (char *) calloc(fnlen+4, sizeof(char));strncpy(codefile,pgm,fnlen);strcat(codefile,".tm");code = fopen(codefile,"w");if (code == NULL){ printf("Unable to open %s\n",codefile);exit(1);}codeGen(syntaxTree, codefile);fclose(code);}
#endif
#endif
#endiffclose(source);return 0;
}
- 编译程序,其余的程序和上次一样
gcc main.c util.c scan.c parse.c analyze.c symtab.c cgen.c code.c -o tiny
- 使用
TINY
编译器编译sample.tny
,会生成这个sample.tm
文件
./tiny sample.tny
- 运行
TM
虚拟机,并加载sample.tm
文件
./TM sample.tm
- 然后就输入
g
- 注意这是一个测试
阶乘
的程序,所以,你输入一个数字
,就可以输出结果
- 如果想要退出这个虚拟机,按
CTRL+C
即可
任务2
2、自行编写Tiny C语言源程序,上交源代码,有运行结果的截图。
Attention!
- 发现
ai
写的会报错,会一直报错! - 所以十分建议在原本的
SAMPLE.TNY
的基础上,自己修改!
之前的
SAMPLE.TNY
是计算阶乘的,你只需要让ai
修改一下,换一个功能,然后按照任务1的流程进行测试即可