Test语言编译器V0.8
感觉这个挺好耍的,书上的代码有错误,而且功能有限。
一、词法分析
特点:
(1)可对中文进行识别
(2)暂不支持负数,可以在读入‘-'时进行简单标记后就能对简单负数进行识别了。
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring> using namespace std; #define KEYWORDNUM 9 // 关键字个数
#define MAXLENGTH 39 // 标识符最大长度
#define MAXFILENAME 100 // 文件名最大长度 namespace Testscan {
FILE *fin, *fout;
char Scanin[MAXFILENAME], Scanout[MAXFILENAME];
char *keyword[KEYWORDNUM] = {"if", "else", "for", "while", "do", "int", "read", "write", "main"};
char singleword[] = "+-*%(){};,:";
char doubleword[] = "><=!";
char token[MAXLENGTH + ]; // 存放识别单词
int frow, brow; // 符号起止行标记
int i, j, k, es; // 临时整型变量
char ch, ch1; // 临时字符变量
} using namespace Testscan; /*****************************
错误列表:
打开输入文件出错
打开输出文件出错
标识符过长
标识符命名不合法
******************************/ int Init() {
// printf("请输入源程序文件名(包括路径):\n");
// scanf("%s", Scanin);
// printf("请输入词法分析输出文件名(包括路径):\n");
// scanf("%s", Scanout); strcpy(Scanin, "C:\\Users\\Administrator\\Desktop\\in.txt");
strcpy(Scanout, "C:\\Users\\Administrator\\Desktop\\out1.txt"); if ((fin = fopen(Scanin, "r")) == NULL) {
printf("打开词法分析输入文件出错!\n");
return ;
}
if ((fout = fopen(Scanout, "w")) == NULL) {
printf("创建词法分析输出文件出错!\n");
return ;
}
return ;
} char getNextChar() {
char ch = getc(fin);
if (ch == '\n') frow++;
return ch;
} int TESTscan() {
int es = Init();
if (es > ) return es; frow = brow = ;
ch = getNextChar();
while (ch != EOF) {
while (ch == ' ' || ch == '\n' || ch == '\t') {
ch = getNextChar();
} brow = frow;
if (ch == EOF) break; if (isalpha(ch)) { // 字母
j = ;
token[j++] = ch;
bool isLong = false; // 超长标记
ch = getNextChar();
while (isalnum(ch)) { // 字母+数字
token[j++] = ch;
ch = getNextChar();
if (j > MAXLENGTH) {
isLong = true;
while (isalnum(ch)) { // 超长自动截断
ch = getNextChar();
}
}
}
token[j] = '\0';
if (isLong == true) { // 标识符太长
es = ;
printf("ERROR(%d): 标识符\"%s\"超长\n", brow, token);
fprintf(fout, "%d\t%s\t%s\n", brow, "ERROR", token);
continue;
} k = ;
char str[MAXLENGTH + ];
for (i = ; i < strlen(token); i++) { // 小写化
str[i] = tolower(token[i]);
}
str[i] = '\0';
while (k < KEYWORDNUM && strcmp(str, keyword[k]))
k++;
if (k >= KEYWORDNUM)
fprintf(fout, "%d\t%s\t%s\n", brow, "ID", token);
else
fprintf(fout, "%d\t%s\t%s\n", brow, str, token);
} else if (isdigit(ch)) { // 数字
j = ;
token[j++] = ch;
ch = getNextChar();
while (isdigit(ch)) {
token[j++] = ch;
ch = getNextChar();
}
token[j] = '\0';
fprintf(fout, "%d\t%s\t%s\n", brow, "NUM", token);
} else if (strchr(singleword, ch) > ) { // 单分界符
token[] = ch;
token[] = '\0';
fprintf(fout, "%d\t%s\t%s\n", brow, token, token);
ch = getNextChar();
} else if (strchr(doubleword, ch) > ) { // 双分界符
token[] = ch;
ch = getNextChar();
if (ch == '=') {
token[] = ch;
token[] = '\0';
ch = getNextChar();
} else token[] = '\0';
fprintf(fout, "%d\t%s\t%s\n", brow, token, token);
} else if (ch == '/') { // 注释
ch = getNextChar();
if (ch == '*') {
ch1 = getNextChar();
do { // 删除注释
ch = ch1;
ch1 = getNextChar();
} while ((ch != '*' || ch1 != '/') && ch1 != EOF);
ch = getNextChar();
} else {
token[] = '/';
token[] = '\0';
fprintf(fout, "%d\t%s\t%s\n", brow, token, token);
}
} else if (ch == '\"') { // 字符串
j = ;
ch = getNextChar();
while (ch != '\"') {
token[j++] = ch;
ch = getNextChar();
}
token[j] = '\0';
fprintf(fout, "%d\t%s\t%s\n", brow, "STR", token);
ch = getNextChar();
} else { // 命名不规范
token[] = ch;
token[] = '\0';
if (ch < ) { //中文处理
ch = getNextChar();
token[] = ch;
token[] = '\0';
}
es = ;
fprintf(fout, "%d\t%s\t%s\n", brow, "ERROR", token);
printf("ERROR(%d): 符号\"%s\"不规范\n", brow, token);
ch = getNextChar();
}
}
fprintf(fout, "%d\tEOF\tEOF\n", brow);
fclose(fin);
fclose(fout);
return es;
}
二、语法分析
特点:
(1)修正书上代码中存在的大量错误
(2)增加对复合语句的处理
(3)支持变量连续定义
(4)支持字符串(可带空白字符)的输出
(5)报错具体到行中的具体位置
(6)无除0报错,首先除0报错不属于语法分析,其次通过改正也只能报5/0这种显式错误,不能报9/(3+2-5)这种错误,因此意义不大
(7)无死循环错误,首先不属于语法分析,其次现在没有一种程序设计语言能报这种错误,循环中可根据条件改变变量的值,是不可预知的
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <windows.h> int TESTparse();
int program();
int compound_Stat();
int statement();
int expression_Stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int write_stat();
int read_stat();
int do_while_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_stat();
int expression_stat(); #define MAXFILENAME 100 // 文件名最大长度
#define MAXLENGTH 40 // 字符串最大长度 namespace Testparse1{
int wrow; // 错误行号
FILE *fin, *fout; // 输入输出文件的指针
char token[MAXLENGTH], token1[MAXLENGTH]; // token保存单词符号,token1保存单词值
char Scanin[MAXFILENAME], Scanout[MAXFILENAME]; // 输入输出文件名
}
using namespace Testparse1; int TESTparse() {
int es = ;
if ((fin = fopen(Scanin, "r")) == NULL) {
printf("\n打开%s错误!\n", Scanout);
es = ;
} if ((fout = fopen(Scanout, "w")) == NULL) {
printf("\n打开%s错误!\n", Scanout);
es = ;
} if (es == ) es = program();
printf("=====语法分析结果!======\n");
switch (es) {
case :
printf("语法分析成功!\n");
break;
case :
printf("打开文件失败!\n");
break;
case :
printf("ERROR(%d): \"%s\"前面缺少{\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少}\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少标识符\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少分号\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少(\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少)\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少操作数\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少主程序\n", wrow, token1);
break;
case :
printf("ERROR(%d): 主程序名错误!\n", wrow);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少while\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"已超出程序末尾\n", wrow, token1);
break;
case :
printf("ERROR(%d): else没有匹配的if\n", wrow);
}
fclose(fin);
fclose(fout);
return es;
} // <程序>::={<声明序列><语句序列>}
// program::={<declaration_list><statement_list>}
int program() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = declaration_list(); // 声明语句
if (es > ) return es; if (strcmp(token, "main")) return ; // main区
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "ID")) return ; // 程序名
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "{")) return ; // 判断是否'{'
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement_list(); // 语句序列
if (es > ) return es;
if (strcmp(token, "}")) return ; // 判断是否'}'
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "EOF")) return ; // 超出程序末尾
return es;
} // <声明序列>::=<声明序列><声明语句>|<声明语句>
// <declaration_list>::=<declaration_list><declaration_stat>|<declaration_stat>
int declaration_list() {
int es = ;
while (strcmp(token, "int") == ) {
es = declaration_stat();
if (es > ) return es;
}
return es;
} // <声明语句>::=int<变量>;
// <declaration_stat>::=int ID;
int declaration_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
while () { // 支持连续定义
if (strcmp(token, "ID")) return ; // 不是标识符
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ",") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
} else break;
}
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <语句序列>::=<语句序列><语句>|<语句>
// <statement_list>::=<statement_list><statement>|<statement>
int statement_list() {
int es = ;
while (strcmp(token, "}")) {
es = statement();
if (es > ) return es;
if (strcmp(token, "EOF") == ) {
return ; // 缺少}
}
}
return es;
} // <语句>::=<if语句>|<while语句>|<for语句>|<read语句>|<write语句>|<复合语句>|<表达式语句>
// <statement>::= <if_stat>|<while_stat>|<for_stat>|<compound_stat>|<expression_stat>
int statement() {
int es = ;
if ((strcmp(token, "if") == || strcmp(token, "else") == )) es = if_stat(); // <IF语句>
else if (strcmp(token, "while") == ) es = while_stat(); // <while语句>
else if (strcmp(token, "for") == ) es = for_stat(); // <for语句>
else if (strcmp(token, "do") == ) es = do_while_stat(); // do_while语句
else if (strcmp(token, "read") == ) es = read_stat(); // <read语句>
else if (strcmp(token, "write") == ) es = write_stat(); // <write语句>
else if (strcmp(token, "{") == ) es = compound_stat(); // <复合语句>
else if ((strcmp(token, "ID") == || strcmp(token, "NUM") == || strcmp(token, "(") == ) ||
strcmp(token, ";") == )
es = expression_stat(); // <表达式语句>
return es;
} // <IF语句>::=if(<表达式>)<语句>[else<语句>]
// <IF_stat>::=if(<expr>)<statement>[else<statement>]
int if_stat() {
if (strcmp(token, "else") == ) return ; // else未匹配if
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement(); // 语句
if (es > ) return es; if (strcmp(token, "else") == ) { // else部分处理
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
}
return es;
} // <复合语句>::={<语句序列>}
// <compound_stat>::={<statement_list>}
int compound_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement_list(); // 语句序列
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <do_whilie语句>::do{语句序列}while(表达式)
// <do_whilie_stat>::do{statment_list}while(expression)
int do_while_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "{")) return ; // 缺少左括号
es = statement(); //语句
if (es > ) return es;
printf("%s %s\n", token, token1);
if (strcmp(token, "while")) return ; // 缺少while fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1); es = expression(); // 表达式
if (es > ) return es; if (strcmp(token, ")")) return ; // 缺少右括号
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <while语句>::=while(<表达式>)<语句>
// <while_stat>::=while(<expr>)<statement >
int while_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
return es;
} // <for语句>::=for(<表达式>;<表达式>;<表达式>)<语句>
// <for_stat>::=for(<expr>,<expr>,<expr>)<statement>
// <for_stat>::=for (<expression>;
int for_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ";")) return ; // 缺少分号 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ";")) return ; // 缺少分号 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
return es;
} // <read_语句>::=read<变量>;
// <read_stat>::=read ID;
int read_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "ID")) return ; // 缺少标识符 fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <write_语句>::=write <表达式>;
// <write_stat>::=write <expression>;
// <write_STR>::write <STR>;
int write_stat() {
int es = ;
fscanf(fin, "%d %s ", &wrow, token);
printf("%s ", token);
if (strcmp(token, "STR") == ) { // 输出字符串
fgets(token1, , fin);
printf("%s", token1);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
}
fscanf(fin, "%s", &token1);
printf("%s\n", token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <表达式语句>::=<<表达式>;|;
// <expression_stat>::=<expression>;|;
int expression_stat() {
int es = ;
if (strcmp(token, ";") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
}
es = expression();
if (es > ) return es;
if (strcmp(token, ";") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} else {
return ; // 缺少分号
}
} // <表达式>::=<标识符>=<布尔表达式>|<布尔表达式>
// <expr>::=ID=<bool_expr>|<bool_expr>
int expression() {
int es = , fileadd;
char token2[MAXLENGTH + ], token3[MAXLENGTH + ];
if (strcmp(token, "ID") == ) {
fileadd = ftell(fin); // 记住当前文件位置
fscanf(fin, "%d %s %s\n", &wrow, token2, token3);
printf("%s %s\n", token2, token3); if (strcmp(token2, "=") == ) { //'='
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = bool_expr();
if (es > ) return es;
} else { // "=="
fseek(fin, fileadd, ); // 若非'='则文件指针回到'='前的标识符
es = bool_expr();
if (es > ) return es;
}
} else {
es = bool_expr();
}
return es;
} // <布尔表达式>::=<算术表达式>|<算术表达式>(>|<|>=|<=|==|!=)<算术表达式>
// <bool_expr>::=<additive_expr>|< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
int bool_expr() {
int es = ;
es = additive_expr();
if (es > ) return es;
if (strcmp(token, ">") == || strcmp(token, ">=") == || strcmp(token, "<") == ||
strcmp(token, "<=") == || strcmp(token, "==") == || strcmp(token, "!=") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token); // 保存运算符
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = additive_expr();
if (es > ) return es;
}
return es;
} // <算术表达式>::=<项>{(+|-)<项>}
// <additive_expr>::=<term>{(+|-)< term >}
// < additive_expr>::=<term>{(+< term >@ADD |-<项>@SUB)}
int additive_expr() {
int es = ;
es = term();
if (es > ) return es;
while (strcmp(token, "+") == || strcmp(token, "-") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = term();
if (es > ) return es;
}
return es;
} // <项>::=<因子>{(*|/)<因子>}
// < term >::=<factor>{(*| /)< factor >}
// < term >::=<factor>{(*< factor >@MULT | /< factor >@DIV)}
int term() {
int es = ;
es = factor();
if (es > ) return es;
while (strcmp(token, "*") == || strcmp(token, "/") == || strcmp(token, "%") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = factor();
if (es > ) return es;
}
return es;
} // <因子>::=(<算术表达式>)|<标识符>|<无符号整数>
// < factor >::=(<additive_expr>)| ID|NUM
int factor() {
int es = ;
if (strcmp(token, "(") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression(); // 表达式
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
} else {
if (strcmp(token, "ID") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} else if (strcmp(token, "NUM") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
return es;
} else {
return ; // 缺少操作数
}
}
return es;
}
三、语义分析
特点同上
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <windows.h> int TESTparse();
int program();
int compound_Stat();
int statement();
int expression_Stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int write_stat();
int read_stat();
int do_while_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_stat();
int expression_stat(); #define MAXVARTABLEP 500 // 定义符号表的容量
#define MAXFILENAME 100 // 文件名最大长度
#define MAXLENGTH 40 // 字符串最大长度 namespace Testparse {
struct Table { // 定义符号表结构
char name[MAXLENGTH];
int address;
} vartable[MAXVARTABLEP];
int vartablep = , labelp = , datap = ; int wrow; // 错误行号
FILE *fin, *fout; // 输入输出文件的指针
char token[MAXLENGTH], token1[MAXLENGTH]; // token保存单词符号,token1保存单词值
char Scanin[MAXFILENAME], Scanout[MAXFILENAME]; // 输入输出文件名
}
using namespace Testparse; int TESTparse() {
// system("C:\\Users\\Administrator\\Desktop\\test.exe");
strcpy(Scanin, "C:\\Users\\Administrator\\Desktop\\out1.txt");
strcpy(Scanout, "C:\\Users\\Administrator\\Desktop\\out2.txt"); int es = ;
if ((fin = fopen(Scanin, "r")) == NULL) {
printf("\n打开%s错误!\n", Scanout);
es = ;
} if ((fout = fopen(Scanout, "w")) == NULL) {
printf("\n打开%s错误!\n", Scanout);
es = ;
} if (es == ) es = program();
printf("=====语法分析结果!======\n");
switch (es) {
case :
printf("语义分析成功!\n");
break;
case :
printf("打开文件失败!\n");
break;
case :
printf("ERROR(%d): \"%s\"前面缺少{\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少}\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少标识符\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少分号\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少(\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少)\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少操作数\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少主程序\n", wrow, token1);
break;
case :
printf("ERROR(%d): 主程序名错误!\n", wrow);
break;
case :
printf("ERROR(%d): \"%s\"前面缺少while\n", wrow, token1);
break;
case :
printf("ERROR(%d): 符号表溢出\n", wrow);
break;
case :
printf("ERROR(%d): 变量\"%s\"重复定义\n", wrow, token1);
break;
case :
printf("ERROR(%d): 变量\"%s\"未声明\n", wrow, token1);
break;
case :
printf("ERROR(%d): \"%s\"已超出程序末尾\n", wrow, token1);
break;
case :
printf("ERROR(%d): else没有匹配的if\n", wrow);
}
fclose(fin);
fclose(fout);
return es;
} // 插入符号表
int name_def(char *name) {
if (vartablep >= MAXVARTABLEP) return ; // 符号表溢出
for (int i = vartablep - ; i >= ; i--) {
if (strcmp(vartable[i].name, name) == ) {
return ; // 变量重复定义
}
}
strcpy(vartable[vartablep].name, name);
vartable[vartablep++].address = datap++;
return ;
} // 查询符号表返回地址
int lookup(char *name, int *paddress) {
for (int i = ; i < vartablep; i++) {
if (strcmp(vartable[i].name, name) == ) {
*paddress = vartable[i].address;
return ;
}
}
return ; // 变量未声明
} // <程序>::={<声明序列><语句序列>}
// program::={<declaration_list><statement_list>}
int program() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = declaration_list(); // 声明语句
if (es > ) return es; printf(" 符号表\n"); // 符号表输出
printf(" 名字 地址\n");
for (int i = ; i < vartablep; i++)
printf("%10s%10d\n", vartable[i].name, vartable[i].address); if (strcmp(token, "main")) return ; // main区
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "ID")) return ; // 程序名
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "{")) return ; // 判断是否'{'
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement_list(); // 语句序列
if (es > ) return es;
if (strcmp(token, "}")) return ; // 判断是否'}'
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "EOF")) return ; // 超出程序末尾
fprintf(fout, " STOP\n"); // 产生停止指令
return es;
} // <声明序列>::=<声明序列><声明语句>|<声明语句>
// <declaration_list>::=<declaration_list><declaration_stat>|<declaration_stat>
int declaration_list() {
int es = ;
while (strcmp(token, "int") == ) {
es = declaration_stat();
if (es > ) return es;
}
return es;
} // <声明语句>::=int<变量>;
// <declaration_stat>::=int ID;
// <declaration_stat>↓vartablep,datap,codep ->int ID↑n@name-def↓n,t;
int declaration_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
while () { // 支持连续定义
if (strcmp(token, "ID")) return ; // 不是标识符
es = name_def(token1); //插入到符号表
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ",") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
} else break;
}
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <语句序列>::=<语句序列><语句>|<语句>
// <statement_list>::=<statement_list><statement>|<statement>
int statement_list() {
int es = ;
while (strcmp(token, "}")) {
es = statement();
if (es > ) return es;
if (strcmp(token, "EOF") == ) {
return ; // 缺少}
}
}
return es;
} // <语句>::=<if语句>|<while语句>|<for语句>|<read语句>|<write语句>|<复合语句>|<表达式语句>
// <statement>::= <if_stat>|<while_stat>|<for_stat>|<compound_stat>|<expression_stat>
int statement() {
int es = ;
if ((strcmp(token, "if") == || strcmp(token, "else") == )) es = if_stat(); // <IF语句>
else if (strcmp(token, "while") == ) es = while_stat(); // <while语句>
else if (strcmp(token, "for") == ) es = for_stat(); // <for语句>
else if (strcmp(token, "do") == ) es = do_while_stat(); // do_while语句
else if (strcmp(token, "read") == ) es = read_stat(); // <read语句>
else if (strcmp(token, "write") == ) es = write_stat(); // <write语句>
else if (strcmp(token, "{") == ) es = compound_stat(); // <复合语句>
else if ((strcmp(token, "ID") == || strcmp(token, "NUM") == || strcmp(token, "(") == ) ||
strcmp(token, ";") == )
es = expression_stat(); // <表达式语句>
return es;
} // <IF语句>::=if(<表达式>)<语句>[else<语句>]
// <IF_stat>::=if(<expr>)<statement>[else<statement>]
// if (<expression>)@BRF↑label1 <statement > @BR↑label2 @SETlabel↓label1
// [ else < statement >] @SETlabel↓label2
// 其中动作符号的含义如下
// @BRF↑label1 :输出 BRF label1,
// @BR↑label2:输出 BR label2,
// @SETlabel↓label1:设置标号label1
// @SETlabel↓label2:设置标号label2
int if_stat() {
if (strcmp(token, "else") == ) return ; // else未匹配if
int es = , label1, label2;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号
label1 = labelp++; // 用label1记住条件为假时要转向的标号
fprintf(fout, " BRF LABEL%d\n", label1); fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement(); // 语句
if (es > ) return es; label2 = labelp++; // 用label2记住要转向的标号
fprintf(fout, " BR LABEL%d\n", label2);
fprintf(fout, "LABEL%d:\n", label1); // 设置label1记住的标号 if (strcmp(token, "else") == ) { // else部分处理
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
}
fprintf(fout, "LABEL%d:\n", label2); // 设置label2记住的标号
return es;
} // <复合语句>::={<语句序列>}
// <compound_stat>::={<statement_list>}
int compound_stat() {
int es = ;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement_list(); // 语句序列
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <do_whilie语句>::do{语句序列}while(表达式)
// <do_whilie_stat>::do{statment_list}while(expression)
int do_while_stat() {
int es = , label1, label2;
label1 = labelp++;
fprintf(fout, "LABEL%d:\n", label1); // 设置label1标号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "{")) return ; // 缺少左括号
es = statement(); // 语句
if (es > ) return es;
printf("%s %s\n", token, token1);
if (strcmp(token, "while")) return ; //缺少while fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1); es = expression(); // 表达式
if (es > ) return es;
label2 = labelp++;
fprintf(fout, " BRF LABEL%d\n", label2);
fprintf(fout, " BR LABEL%d\n", label1); if (strcmp(token, ")")) return ; // 缺少右括号
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
fprintf(fout, "LABEL%d:\n", label2); // 设置label2标号
return es;
} // <while语句>::=while(<表达式>)<语句>
// <while_stat>::=while(<expr>)<statement >
// <while_stat>::=while @SET↑labellabel1(<expression>) @BRF↑label2
// <statement >@BR↓label1 @SETlabel↓label2
// 动作解释如下:
// @SETlabel↑label1:设置标号label1
// @BRF↑label2 :输出 BRF label2,
// @BR↓label1:输出 BR label1,
// @SETlabel↓label2:设置标号label2
int while_stat() {
int es = , label1, label2;
label1 = labelp++;
fprintf(fout, "LABEL%d:\n", label1); // 设置label1标号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号 label2 = labelp++;
fprintf(fout, " BRF LABEL%d\n", label2);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
fprintf(fout, " BR LABEL%d\n", label1);
fprintf(fout, "LABEL%d:\n", label2); // 设置label2标号
return es;
} // <for语句>::=for(<表达式>;<表达式>;<表达式>)<语句>
// <for_stat>::=for(<expr>,<expr>,<expr>)<statement>
// <for_stat>::=for (<expression>;
// @SETlabel↑label1< expression >@BRF↑label2@BR↑label3;
// @SETlabel↑label4 < expression >@BR↓label1)
// @SETlabel↓label3 <语句 >@BR↓label4@SETlabel↓label2
// 动作解释:
// @SETlabel↓label1:设置标号label1
// @BRF↑label2 :输出 BRF label2,
// @BR↑label3:输出 BR label3,
// @SETlabel↓label4:设置标号label4
// @BR↑label1:输出 BR label1,
// @SETlabel↓label3:设置标号label3
// @BR↑label4:输出 BR label4,
// @SETlabel↓label2:设置标号label2
int for_stat() {
int es = , label1, label2, label3, label4;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "(")) return ; // 缺少左括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ";")) return ; //缺少分号 label1 = labelp++;
fprintf(fout, "LABEL%d:\n", label1); // 设置label1标号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
label2 = labelp++;
fprintf(fout, " BRF LABEL%d\n", label2);
label3 = labelp++;
fprintf(fout, " BR LABEL%d\n", label3);
if (strcmp(token, ";")) return ; // 缺少分号 label4 = labelp++;
fprintf(fout, "LABEL%d:\n", label4); // 设置label4标号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression();
if (es > ) return es;
fprintf(fout, " BR LABEL%d\n", label1);
if (strcmp(token, ")")) return ; // 缺少右括号 fprintf(fout, "LABEL%d:\n", label3); // 设置label3标号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = statement();
if (es > ) return es;
fprintf(fout, " BR LABEL%d\n", label4);
fprintf(fout, "LABEL%d:\n", label2); // 设置label2标号
return es;
} // <read_语句>::=read<变量>;
// <read_stat>::=read ID;
// <read_stat>::=read ID↑n LOOK↓n↑d @IN@STI↓d;
// 动作解释:
// @LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义
// @IN:输出IN
// @STI↓d:输出指令代码STI d
int read_stat() {
int es = , address;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, "ID")) return ; // 缺少标识符 es = lookup(token1, &address);
if (es > ) return es;
fprintf(fout, " IN \n");
fprintf(fout, " STO %d\n", address);
fprintf(fout, " POP\n"); fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ";")) return ; // 缺少分号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <write_语句>::=write <表达式>;
// <write_stat>::=write <expression>;
// <write_STR>::write <STR>;
// 动作解释:
// @ OUT:输出 OUT
int write_stat() {
int es = ;
fscanf(fin, "%d %s ", &wrow, token);
printf("%s ", token);
if (strcmp(token, "STR") == ) { // 输出字符串
fgets(token1, , fin);
printf("%s", token1);
fprintf(fout, " OUTS %s", token1); // 由于字符串不参与运算,单独考虑,定义OUTS为输出字符串指令
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
if (strcmp(token, ";")) return ; // 缺少分号
// fprintf(fout," OUT\n");
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
}
fscanf(fin, "%s", &token1);
printf("%s\n", token1);
es = expression();
if (es > ) return es;
if (strcmp(token, ";")) return ; // 缺少分号
fprintf(fout, " OUT\n");
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} // <表达式语句>::=<<表达式>;|;
// <expression_stat>::=<expression>;|;
int expression_stat() {
int es = ;
if (strcmp(token, ";") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
}
es = expression();
if (es > ) return es;
if (strcmp(token, ";") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} else {
return ; //缺少分号
}
} // <表达式>::=<标识符>=<布尔表达式>|<布尔表达式>
// <expr>::=ID=<bool_expr>|<bool_expr>
// <expression>::=ID↑n@LOOK↓n↑d@ASSIGN=<bool_expr>@STO↓d |<bool_expr>
int expression() {
int es = , fileadd;
char token2[MAXLENGTH + ], token3[MAXLENGTH + ];
if (strcmp(token, "ID") == ) {
fileadd = ftell(fin); // 记住当前文件位置
fscanf(fin, "%d %s %s\n", &wrow, token2, token3);
printf("%s %s\n", token2, token3); if (strcmp(token2, "=") == ) { //'='
int address;
es = lookup(token1, &address);
if (es > ) return es;
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = bool_expr();
if (es > ) return es;
fprintf(fout, " STO %d\n", address);
fprintf(fout, " POP\n");
} else { //"=="
fseek(fin, fileadd, ); // 若非'='则文件指针回到'='前的标识符
es = bool_expr();
if (es > ) return es;
}
} else {
es = bool_expr();
}
return es;
} // <布尔表达式>::=<算术表达式>|<算术表达式>(>|<|>=|<=|==|!=)<算术表达式>
// <bool_expr>::=<additive_expr>|< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
// <bool_expr>::=<additive_expr>
// |< additive_expr >><additive_expr>@GT
// |< additive_expr ><<additive_expr>@LES
// |< additive_expr >>=<additive_expr >@GE
// |< additive_expr ><=< additive_expr >@LE
// |< additive_expr >==< additive_expr >@EQ
// |< additive_expr >!=< additive_expr >@NOTEQ
int bool_expr() {
int es = ;
es = additive_expr();
if (es > ) return es;
if (strcmp(token, ">") == || strcmp(token, ">=") == || strcmp(token, "<") == ||
strcmp(token, "<=") == || strcmp(token, "==") == || strcmp(token, "!=") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token); // 保存运算符
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = additive_expr();
if (es > ) return es; if (strcmp(token2, ">") == ) fprintf(fout, " GT\n");
if (strcmp(token2, ">=") == ) fprintf(fout, " GE\n");
if (strcmp(token2, "<") == ) fprintf(fout, " LES\n");
if (strcmp(token2, "<=") == ) fprintf(fout, " LE\n");
if (strcmp(token2, "==") == ) fprintf(fout, " EQ\n");
if (strcmp(token2, "!=") == ) fprintf(fout, " NOTEQ\n");
}
return es;
} // <算术表达式>::=<项>{(+|-)<项>}
// <additive_expr>::=<term>{(+|-)< term >}
// < additive_expr>::=<term>{(+< term >@ADD |-<项>@SUB)}
int additive_expr() {
int es = ;
es = term();
if (es > ) return es;
while (strcmp(token, "+") == || strcmp(token, "-") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = term();
if (es > ) return es; if (strcmp(token2, "+") == ) fprintf(fout, " ADD\n");
if (strcmp(token2, "-") == ) fprintf(fout, " SUB\n");
}
return es;
} // <项>::=<因子>{(*|/)<因子>}
// < term >::=<factor>{(*| /)< factor >}
// < term >::=<factor>{(*< factor >@MULT | /< factor >@DIV)}
int term() {
int es = ;
es = factor();
if (es > ) return es;
while (strcmp(token, "*") == || strcmp(token, "/") == || strcmp(token, "%") == ) {
char token2[MAXLENGTH + ];
strcpy(token2, token);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = factor();
if (es > ) return es; if (strcmp(token2, "*") == ) fprintf(fout, " MULT\n");
if (strcmp(token2, "/") == ) fprintf(fout, " DIV\n");
if (strcmp(token2, "%") == ) fprintf(fout, " MOD\n");
}
return es;
} // <因子>::=(<算术表达式>)|<标识符>|<无符号整数>
// < factor >::=(<additive_expr>)| ID|NUM
// < factor >::=(< expression >)| ID↑n@LOOK↓n↑d@LOAD↓d |NUM↑i@LOADI↓i
int factor() {
int es = ;
if (strcmp(token, "(") == ) {
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
es = expression(); // 表达式
if (es > ) return es;
if (strcmp(token, ")")) return ; // 缺少右括号
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
} else {
if (strcmp(token, "ID") == ) {
int address;
es = lookup(token1, &address); // 查符号表获取地址
if (es > ) return es; // 变量没声明
fprintf(fout, " LOAD %d\n", address);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
printf("%s %s\n", token, token1);
return es;
} else if (strcmp(token, "NUM") == ) {
fprintf(fout, " LOADI %s\n", token1);
fscanf(fin, "%d %s %s\n", &wrow, token, token1);
return es;
} else {
return ; // 缺少操作数
}
}
return es;
}
四、模拟机(解释器)
特点:
(1)支持字符串(可带空白字符)输出
(2)消除LABEL:中:与带:字符串的冲突
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cstring> using namespace std;
#define INF 0x3f3f3f3f
#define MAXFILENAME 100
#define MAXCODENUM 1000
#define MAXCODELENGTH 100
#define MAXDATANUM 1000
#define MAXLABELNUM 100
#define MAXSTACK 1000 namespace Testmachine {
FILE *fin; // 用于指向输入文件的指针
char Scanin[MAXFILENAME]; // 用于接收输入的文件名
char code[MAXCODENUM][MAXCODELENGTH]; // 代码存放数组
int data[MAXDATANUM]; // data[i]表示i地址的数值
int label[MAXLABELNUM]; // LABEL数组
int stack[MAXSTACK], stacktop; // 操作栈
char lno[];
int codecnt;
int i, j, es;
}
using namespace Testmachine; int TESTmachine() {
// printf("请输入目标文件名(包括路径):\n");
// system("C:\\Users\\Administrator\\Desktop\\test4.exe");
strcpy(Scanin, "C:\\Users\\Administrator\\Desktop\\out2.txt"); es = , i = , j = , stacktop = ;
memset(data, -INF, sizeof(data));
if ((fin = fopen(Scanin, "r")) == NULL) {
printf("\n打开%s错误!\n", code);
return ;
} codecnt = ;
i = fscanf(fin, "%s", &code[codecnt]);
while (!feof(fin)) { // 读入
i = strlen(code[codecnt]) - ;
strncpy(lno, code[codecnt], );
lno[] = '\0';
if (strcmp(lno, "OUTS") == ) { // 带空格字符串处理
codecnt++;
getc(fin); // 跳过空格
fgets(code[codecnt], , fin);
i = strlen(code[codecnt]) - ;
code[codecnt][i] = '\0';
} else if (code[codecnt][i] == ':') { // LABEL,已消除":"冲突
i = i - ;
strncpy(lno, &code[codecnt][], i);
lno[i] = '\0';
label[atoi(lno)] = codecnt; // 用label数组记住每个标号的地址
code[codecnt][] = ':';
code[codecnt][] = '\0';
strcat(code[codecnt], lno);
j++;
}
codecnt++;
i = fscanf(fin, "%s", &code[codecnt]);
}
fclose(fin); for (i = ; i < codecnt; i++) { // 处理
int l = strlen(code[i]);
// printf("%d %s %d\n",i,code[i],l);
if ((l > ) && (code[i][] == 'A')) {
strncpy(lno, &code[i][], l - );
lno[i] = '\0';
itoa(label[atoi(lno)], code[i], );
}
} i = ;
while (i < codecnt) { // 运行
if (strcmp(code[i], "LOAD") == ) { // LOAD D将D中的内容加载到操作数栈
i++;
stack[stacktop] = data[atoi(code[i])];
stacktop++;
} else if (strcmp(code[i], "LOADI") == ) { // LOADI a将常量a压入操作数栈
i++;
stack[stacktop] = atoi(code[i]);
stacktop++;
} else if (strcmp(code[i], "STO") == ) { // STO D将操作数栈栈顶单元内容存入D,且栈顶单元内容保持不变
i++;
data[atoi(code[i])] = stack[stacktop - ];
} else if (strcmp(code[i], "STI") == ) { // STI D 将操作数栈栈顶单元内容存入D,且栈顶单元内容出栈
i++;
data[atoi(code[i])] = stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "POP") == ) { // POP出栈
stacktop--;
} else if (strcmp(code[i], "ADD") == ) { // ADD将次栈顶单元与栈顶单元内容出栈并相加,和置于栈顶
stack[stacktop - ] = stack[stacktop - ] + stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "SUB") == ) { // SUB将次栈顶单元减去栈顶单元内容并出栈,差置于栈顶
stack[stacktop - ] = stack[stacktop - ] - stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "MULT") == ) { // MULT将次栈顶单元与栈顶单元内容出栈并相乘,积置于栈顶
stack[stacktop - ] = stack[stacktop - ] * stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "DIV") == ) { // DIV将次栈顶单元与栈顶单元内容出栈并相除,商置于栈顶
stack[stacktop - ] = stack[stacktop - ] / stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "MOD") == ) { // MOD将次栈顶单元模栈顶单元内容并出栈,余数置于栈顶
stack[stacktop - ] = stack[stacktop - ] % stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "BR") == ) { // BR lab无条件转移到lab
i++;
i = atoi(code[i]);
} else if (strcmp(code[i], "BRF") == ) { // BRF lab检查栈顶单元逻辑值,若为假则转移到lab
i++;
if (stack[stacktop - ] == ) i = atoi(code[i]);
stacktop--;
} else if (strcmp(code[i], "EQ") == ) { // EQ将栈顶两单元做等于比较,并将结果真或假置于栈顶
stack[stacktop - ] = stack[stacktop - ] == stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "NOTEQ") == ) { // NOTEQ将栈顶两单元做不等于比较,并将结果真或假置于栈顶
stack[stacktop - ] = stack[stacktop - ] != stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "GT") == ) { // GT次栈顶大于栈顶操作数,则栈顶置1,否则置0
stack[stacktop - ] = stack[stacktop - ] > stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "LES") == ) { // LES次栈顶小于栈顶操作数,则栈顶置1,否则置0
stack[stacktop - ] = stack[stacktop - ] < stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "GE") == ) { // GE次栈顶大于等于栈顶操作数,则栈顶置1,否则置0
stack[stacktop - ] = stack[stacktop - ] >= stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "LE") == ) { // LE 次栈顶小于等于栈顶操作数,则栈顶置1,否则置0
stack[stacktop - ] = stack[stacktop - ] <= stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "AND") == ) { // AND 将栈顶两单元做逻辑与运算,并将结果真或假置于栈顶
stack[stacktop - ] = stack[stacktop - ] && stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "OR") == ) { // OR将栈顶两单元做逻辑或运算,并将结果真或假置于栈顶
stack[stacktop - ] = stack[stacktop - ] || stack[stacktop - ];
stacktop--;
} else if (strcmp(code[i], "NOT") == ) { // NOT将栈顶的逻辑值取反
stack[stacktop - ] = !stack[stacktop - ];
} else if (strcmp(code[i], "IN") == ) { // IN从标准输入设备读入一个整型数据,并入栈
scanf("%d", &stack[stacktop]);
stacktop++;
} else if (strcmp(code[i], "OUT") == ) { // OUT将栈顶单元内容出栈,并输出到标准输出
printf("%d\n", stack[stacktop - ]);
stacktop--;
} else if (strcmp(code[i], "OUTS") == ) { // OUTS 字符串输出
i++;
printf("%s\n", code[i]);
} else if (strcmp(code[i], "STOP") == ) { // STOP 停止执行
break;
}
i++;
}
return es;
}
五、主程序
#include <stdio.h> extern int TESTscan();
extern int TESTparse();
extern int TESTmachine(); int main() {
int es = ;
es = TESTscan();
if (es > ) {
printf("词法分析有错,编译停止!\n");
} else {
printf("词法分析成功!\n");
es = TESTparse();
if (es > ) {
printf("语义分析有错,编译停止!\n");
} else {
printf("语义分析成功!\n");
es = TESTmachine();
if (es > ) {
printf("启动模拟机失败\n");
}
}
}
}
另外用QT写了一个简单界面,如图所示:
后面又改了下,如图:
(额、V1.0改成了V0.8,不要在意这些细节)
Test语言编译器V0.8的更多相关文章
- 第一个C语言编译器是怎样编写的?
首先向C语言之父Dennis MacAlistair Ritchie致敬! 当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用C语言编写的,有一些语言比如Clojure,Jython等是基于J ...
- 【转】自己动手写SC语言编译器
自序 编译原理与技术的一整套理论在整个计算机科学领域占有相当重要的地位,学习它对程序设计人员有很大的帮助.我们考究历史会发现那些人人称颂的程序设 计大师都是编译领域的高手,像写出BASIC语言的BIL ...
- 在线C语言编译器/解释器
在线C语言编译器/解释器 本文介绍两个C语言在线解释器/编译器,这些工具可以提高代码片段检测方便的工作效率,并可以保证这些代码的正确性,而且还可以和别人一起编辑/分享之间的代码,这样可以共同分析代码并 ...
- 简单的C语言编译器--概述
在学习了编译原理的相关知识后,逐渐的掌握一个编译器的结构.作用和实现方法.同时,希望自己在不断的努力下写出一个简单的C语言编译器. 实现步骤 词法分析器:将C语言测试代码分解成一个一个的词法单元: ...
- windows系统安装gcc编译器----c/c++语言编译器
1.安装MinGW编译管理安装软件 官方下载:https://osdn.net/projects/mingw/releases/ 作者百度云备份下载:https://pan.baidu.com/s/1 ...
- C语言编译器CL.exe
下载地址CL.7z版权问题:仅供学习交流,请于24小时内删除,本人不承担版权问题… 基本使用: 1.解压缩,例如解压缩到E盘根目录下 2.打开cmd命令行界面(快捷方式win+R输入cmd回车)cd命 ...
- C语言编译器不检查数组下标越界
这两天被人问了一个问题说假如C/C++访问下表越界的数组元素会报错么,于是充满好奇心的我动手试了一下,WTF,果然没有报错,但是会给程序带来莫名其妙的结果(比如十次的循环但是变成了死循环,但八次却可以 ...
- C语言编译器和IDE的选择
什么是编译器: CPU只认识几百个二进制形式的指令,C语言对CPU而言简直就是天书.C语言是用固定的词汇与格式组织起来,简单直观,程序员容易识别和理解. 这时候就需要一个工具,将C语言代码转换成CPU ...
- C语言编译器,写给萌新们看看。
就我已经经历过的大学课程,仿佛每一门计算机的专业课程的开头,都是在介绍计算机发展的历史,和大名鼎鼎的冯诺依曼结构. 譬如C语言,比较水的计算机导论,c++,数据结构,计算机组成原理,甚至是Linux实 ...
随机推荐
- 【BZOJ】【2594】【WC2006】水管局长数据加强版
LCT 动态维护MST嘛……但是有删边= =好像没法搞的样子 离线记录所有修改&询问,倒序处理,就可以变删边为加边了- 论如何用LCT维护最小生成树:先搞出一棵最小生成树,然后每次加边(u,v ...
- 让32位Eclipse和64位Eclipse同时在64的Windows7上运行
转自让32位Eclipse和64位Eclipse同时在64的Windows7上运行 参考这篇文章:http://wenku.baidu.com/view/57994c270066f5335a81214 ...
- Google 网站打不开
http://209.116.186.246/ http://91.213.30.153/ (2014年6月30日 新增) https://wen.lu/ (2014年6月30日 新增,注意下是ht ...
- Unity3D脚本中文系列教程(三)
http://dong2008hong.blog.163.com/blog/static/4696882720140302323886/ Unity3D脚本中文系列教程(二) 示,属性不被序列化或显示 ...
- [转载]Spring Annotation Based Configuration
Annotation injection is performed before XML injection, thus the latter configuration will override ...
- POJ 1930
Dead Fraction Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 1762 Accepted: 568 Desc ...
- POJ 1674
#include<iostream>//cheng da cai zi 08 .11 .13 using namespace std; int main() { int digit_num ...
- 1009-2的N次方
描述 编程精确计算2的N次方.(N是介于100和1000之间的整数). 输入 正整数N (100≤N≤1000) 输出 2的N次方 样例输入 200 样例输出 16069380442589902755 ...
- hdu 4579 Random Walk 概率DP
思路:由于m非常小,只有5.所以用dp[i]表示从位置i出发到达n的期望步数. 那么dp[n] = 0 dp[i] = sigma(dp[i + j] * p (i , i + j)) + 1 . ...
- asp.net后台获取路径的各种方法归纳
asp.net后台获取路径的各种方法归纳 1.Request.CurrentExecutionFilePath 获取当前请求的虚拟路径,不同于 FilePath,差别在于如果请求已在服务器代 ...