Java理论期末大作业_TPL解释器
TPL解释器—作业说明
编写一个Java程序,该程序读取一个文件中的TPL指令(见下文),并执行这些指令。该程序应将TPL文件的名称作为命令行参数,并将结果输出到控制台。一个例子TPL会话如下所示(假设程序名称为cw2):
java cw2 factor.tpl
TPL Interpreter by Shan Zhang
Factorial Calculation
The factorial of 10 is 3628800
TPL Finished OK [16 lines processed].
关于TPL
TPL(Tiny Programming Language)是为本次练习所设计的一种非常简易的编程语言。该语言是完全线性的,它没有分支或循环,每个语句都是按顺序执行。TPL能够处理文本和简单的算法,它具有整型和字符串型两个变量类型。它有8个保留字,具体如下表所示。
保留字名称 |
描述 |
# |
注释符 |
INTEGER |
声明整型变量 |
STRING |
声明字符串型变量 |
LET |
分配一个变量 |
CALCULATE |
执行算术运算 |
|
写入数据到控制台 |
PRINTLN |
在PRINT执行基础上附带一个空行 |
END |
终止程序 |
该语言编写的程序每一行都必须以这些单词中的一个开头,不区分大小写。
COMMENT
#是注释符,所以任何以#字符开头的行都被完全忽略。
例:
# ignore this line!
INTEGER
INTEGER可以声明一个整型变量,默认值为0。
例:
INTEGER myInt
这等同于JAVA中的表达“int myInt=0;”
STRING
STRING可以声明一个字符串型变量,默认值为空串。
例:
STRING myString
这等同于JAVA中的表达“String myString;”
LET
LET将值分配给变量(整数或双引号括起来的字符串)。
例:
LET myInt=42
LET myString="Hello World!"
CALCULATE
CALCULATE对数值或变量执行数值计算,并将结果赋值给变量(必须提前声明)。支持四个运算符:+, -, *和/(分别为加法、减法,乘法和整数除法)。
例:
CALCULATE myInt=2*2
CALCULATE myInt=myInt+24
CALCULATE myInt=intA/intB
PRINT和PRINTLN
PRINT和PRINTLN可以将内容打印到控制台上,唯一的区别是PRINTLN打印完后追加一个新的行(类似Java中的Systme.out.println)。它们可以打印作为参数的文本或变量(字符串或整数)。
例:
PRINTLN "Hello World!"
PRINT myString
PRINTLN myInt
END
END将终止程序,并打印一条提示来表明。
TPL完整程序样例
左边是一个示例TPL输入文件,用于计算5的阶乘。 |
# A TPL Program to calculate the factorial of 5 INTEGER myInt INTEGER factorial STRING myString LET mystring="Factorial Program" LET myInt=5 CALCULATE factorial=myInt*4 CALCULATE factorial=factorial*3 CALCULATE factorial=factorial*2 PRINTLN mystring PRINTLN PRINT "The factorial of " PRINT myInt PRINT " is " PRINTLN factorial END |
package work; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Locale; import java.util.Scanner; import java.io.IOException; public class theoreticalwork { public static void main(String[] args){ virtual_TPL TPL_edit = new virtual_TPL(); TPL_edit.run(); } } class virtual_TPL{ static int count = 0;//定义行数 static int countString = 0;//定义String个数 static int countInt = 0;//定义int个数 static int countError = 0;//定义编译错误个数 static int countPrint = 0;//定义要输出的个数 static TPL_Int[] IntStruct = new TPL_Int[10100];//定义int类数组 static TPL_String[] StringStruct = new TPL_String[10100];//定义String类数组 static TPL_CompileError[] ErrorStruct = new TPL_CompileError[10100];//定义编译错误类数组 static TPL_Print[] PrintStruct = new TPL_Print[10100];//定义输出类数组 public static void run(){ Scanner input = new Scanner(System.in); BufferedReader in = null; try{ System.out.println("java cw2 factor.tpl"); System.out.println("TPL Interpreter Cheng Li\n"); in = new BufferedReader(new FileReader("/Users/licheng/Desktop/Java/JAVA_TPL/文档/2019212212042物联网191李骋/input2.txt"));//读取文件路径 String check; while((check = in.readLine()) != null){ count ++; check = check.trim(); //去除首尾空格 /*-----------------注释-------------------*/ if(check.charAt(0) == '#') continue; /*----------------------------------------*/ /*--------------------------------------*/ //判断最后一个字符串 if(!check_last(check.charAt(check.length()-1))){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,9,"xxxx"); continue; } /*----------------------------------------*/ String before = check; check = check.toUpperCase(Locale.ROOT); String s1 = getfirstString(check); /*------------判断第一个字符串--------------*/ int flag = getnum(s1); /*---------------------------------------*/ /*--------------首字符编译报错--------------*/ if(flag == -1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,flag,s1); continue; } /*---------------------------------------*/ /*---------------构造int-----------------*/ if(flag == 1){ String str = check.substring(s1.length()).trim();//删除头尾空格 String[] as = str.split(",");//按空格分割 for(int i=0;i<as.length;i++){ String Intname = as[i].trim(); int flagint = getstatusInt(Intname); if(flagint!=-1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,7,Intname);//int变量名存在报错 break; } int flagString = getstatusString(Intname); if (flagString!=-1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,7,Intname);//string变量名存在报错 break; } countInt++; IntStruct[countInt] = new TPL_Int(Intname); if (!IntStruct[countInt].check_name()){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,flag,Intname);//变量名错误 break; } } } /*---------------------------------------*/ /*---------------构造String-----------------*/ if(flag == 2){ String str = check.substring(s1.length()).trim(); String[] as = str.split(","); for (int i=0;i<as.length;i++){ String Stringname = as[i].trim(); int flagstring = getstatusString(Stringname); int flagint = getstatusInt(Stringname); if(flagint!=-1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,7,Stringname);//int变量名存在报错 break; } if(flagstring!=-1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,7,Stringname);//string变量名存在报错 break; } countString++; StringStruct[countString] = new TPL_String(Stringname); if (!StringStruct[countString].check_name()){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,flag,Stringname);//变量名错误 break; } } } /*---------------------------------------*/ /*----------------赋值语句-----------------*/ if(flag == 3){ int pos1 = check.indexOf('='); // 第一个等于号的位置 if (pos1 == -1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,8,"xxxx");//格式错误 continue; } String name_let = getvaluename(check,s1.length(),pos1); if(name_let == null||check_intvalue(name_let)){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,8,"xxxxx");//格式错误 continue; } int getflag1 = getstatusInt(name_let);//判断int变量是否存在 int getflag2 = getstatusString(name_let);//判断string变量名是否存在 if(getflag1!=-1){//int类型存在时 String value_int = getIntvalue(check,pos1); int value = 0; if(check_intvalue(value_int)){//判断为数字时 value = Integer.parseInt(value_int);//存入数据 IntStruct[getflag1].putsvalue(value); }else{ int flagx = getstatusInt(value_int);//赋值变量名是否存在 if (flagx == -1){ countError++;//报错 ErrorStruct[countError] = new TPL_CompileError(count,4,value_int); }else{ IntStruct[getflag1].putsvalue(IntStruct[flagx].getValue());//赋值 } } }else if(getflag2!=-1){//string类型存在时 String value_String = getStringvalue(before,pos1);//获取字符串赋值 String value; if(value_String.charAt(0) == '\"'&&value_String.charAt(value_String.length()-1) == '\"'){//格式错误 value = value_String.substring(1,value_String.length()-1);//取出所附的值 StringStruct[getflag2].putsvalue(value);//给变量名赋值 }else{ int flagx = getstatusInt(value_String);//判读是否存在 if (flagx == -1){//不能存在编译错误加一 countError++; ErrorStruct[countError] = new TPL_CompileError(count,5,value_String); }else{//赋值 IntStruct[getflag2].putsvalue(IntStruct[flagx].getValue()); } } }else{//都不存在直接报错 countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,name_let); } } /*---------------------------------------*/ /*---------------算数语句------------------*/ if(flag == 4){ int pos1 = -1; pos1 = check.indexOf('='); if(pos1 == -1){//不存在等号报错 countError++; ErrorStruct[countError] = new TPL_CompileError(count,6,"xxxx"); }else{//存在等号 String num1 = check.substring(s1.length()+1,pos1);//获取算数的变量名 num1 = num1.trim(); int flagnum1 = getstatusInt(num1);//判断有没有变量名 if(flagnum1 == -1){ boolean isDagit = check_intvalue(num1);//判断等号后面全是数字 if (isDagit){//如果是编译错误加一 countError++; ErrorStruct[countError] = new TPL_CompileError(count,6,num1); }else{//错误类型不一致 countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,num1); } }else{ //判断加减乘除然后进行计算 int poschar1 = check.indexOf('+'); int poschar2 = check.indexOf('-'); int poschar3 = check.indexOf('*'); int poschar4 = check.indexOf('/'); if(poschar1!=-1){ Cal(1,check,pos1,poschar1,flagnum1); }else if(poschar2!=-1){ Cal(2,check,pos1,poschar2,flagnum1); }else if(poschar3!=-1){ Cal(3,check,pos1,poschar3,flagnum1); }else if(poschar4!=-1){ Cal(4,check,pos1,poschar4,flagnum1); }else{ countError++; ErrorStruct[countError] = new TPL_CompileError(count,6,"xxx"); } } } } /*---------------------------------------*/ /*---------------PRINT语句------------------*/ if(flag == 5){ String Print_met = getprintString(before,s1.length()); if(Print_met.length() == 0){ //如果长度为0,直接加入print/println countPrint++; PrintStruct[countPrint] = new TPL_Print(3,"",0); continue; } if(Print_met.charAt(0) == '\"'&&Print_met.charAt(Print_met.length()-1) == '\"'){//获取直接输出语句 String value = Print_met.substring(1,Print_met.length()-1); countPrint++; PrintStruct[countPrint] = new TPL_Print(3,value,0); }else{//获取变量名输出 Print_met = Print_met.toUpperCase(Locale.ROOT); int flag1 = getstatusInt(Print_met); int flag2 = getstatusString(Print_met); if(flag1!=-1){//如果是int类型 countPrint++; PrintStruct[countPrint] = new TPL_Print(1,"xxxx",IntStruct[flag1].getValue()); }else if(flag2!=-1){//string类型 countPrint++; PrintStruct[countPrint] = new TPL_Print(3,StringStruct[flag2].getValue(),0); }else{//都不是直接报错 countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,Print_met); } } } /*---------------------------------------*/ /*---------------PRINTLN语句------------------*/ //与print类似 if(flag == 6){ String Print_met = getprintString(before,s1.length()); if(Print_met.length() == 0){ countPrint++; PrintStruct[countPrint] = new TPL_Print(4,"",0); continue; } if(Print_met.charAt(0) == '\"'&&Print_met.charAt(Print_met.length()-1) == '\"'){ String value = Print_met.substring(1,Print_met.length()-1); countPrint++; PrintStruct[countPrint] = new TPL_Print(4,value,0); }else{ Print_met = Print_met.toUpperCase(Locale.ROOT); int flag1 = getstatusInt(Print_met); int flag2 = getstatusString(Print_met); if(flag1!=-1){ countPrint++; PrintStruct[countPrint] = new TPL_Print(2,"xxxx",IntStruct[flag1].getValue()); }else if(flag2!=-1){ countPrint++; PrintStruct[countPrint] = new TPL_Print(4,StringStruct[flag2].getValue(),0); }else{ countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,Print_met); } } } /*---------------------------------------*/ /*----------------结束程序----------------*/ if(flag == 7){ break; } /*---------------------------------------*/ } } catch (FileNotFoundException e){ //路径错误 System.out.println("文件找不到请检查路径"); return; } catch (IOException e){ //输出错误 System.out.println("输出错误"); return; } if(countError == 0){ //无错误控制台输出 for (int i=1;i<=countPrint;i++){ PrintStruct[i].Print_result(); } System.out.println("TPL Finshed OK["+count+" lines processed]"); }else{ //有错误输出错误提示 for (int i=1;i<=countError;i++){ System.out.print("Error line"); System.out.print(ErrorStruct[i].get_line()+":"); System.out.println(ErrorStruct[i].getError_String()); } } } /*---------------获取第一个字符串编号函数-----------------*/ public static int getnum(String s){ if(s.equals("INTEGER")) return 1; if(s.equals("STRING")) return 2; if(s.equals("LET")) return 3; if(s.equals("CALCULATE")) return 4; if(s.equals("PRINT")) return 5; if(s.equals("PRINTLN")) return 6; if(s.equals("END")) return 7; return -1; } /*------------------------------------------------------*/ /*---------------获取每行第一个字符串函数-------------------*/ public static String getfirstString(String check){ StringBuilder s1 = new StringBuilder(); for(int i=0;i<check.length();i++){ if(check.charAt(i) == ' ') break; s1.append(check.charAt(i)); } return s1.toString().trim(); } /*------------------------------------------------------*/ /*------------获取int类型name函数------------------------*/ public static String getIntname(String check,int pos){ boolean flagint = false; StringBuilder name = new StringBuilder(); for(int i=pos;i<check.length();i++){ if(check.charAt(i) == '#') break; if(check.charAt(i)!=' '){ flagint = true; } if (flagint){ name.append(check.charAt(i)); } } return name.toString().trim(); } /*------------------------------------------------------*/ /*------------获取String类型name函数------------------------*/ public static String getStringname(String check,int pos){ boolean flagint = false; StringBuilder name = new StringBuilder(); for(int i=pos;i<check.length();i++){ if (check.charAt(i) == '#') break; if(check.charAt(i)!=' '){ flagint = true; } if (flagint){ name.append(check.charAt(i)); } } return name.toString().trim(); } /*------------------------------------------------------*/ /*-----------------获取赋值语句变量函数------------------------*/ public static String getvaluename(String check,int pos1,int pos2){ int posx = check.length()+1; int posy = check.length(); for(int i=pos1;i<pos2;i++){ if(check.charAt(i)!=' '){ posx = i; break; } } for(int i=pos2-1;i>=pos1;i--){ if(check.charAt(i) != ' '){ posy = i; break; } } if(posx>posy) return null; return check.substring(posx,posy+1).trim(); } /*------------------------------------------------------*/ /*-------------------判断变量名Int------------------------*/ public static int getstatusInt(String check){ for(int i=1;i<=countInt;i++){ if(IntStruct[i].getName().equals(check)){ return i; } } return -1; } /*------------------------------------------------------*/ /*-------------------判断变量名String------------------------*/ public static int getstatusString(String check){ for(int i=1;i<=countString;i++){ if(StringStruct[i].getName().equals(check)){ return i; } } return -1; } /*------------------------------------------------------*/ /*-------------------获取int类型的value-------------------*/ public static String getIntvalue(String check,int pos){ StringBuilder value = new StringBuilder(); boolean flag_s = false; for (int i=pos+1;i<check.length();i++){ if (check.charAt(i) != ' ') { flag_s = true; } if (flag_s){ value.append(check.charAt(i)); } } return value.toString().trim(); } /*------------------------------------------------------*/ /*-----------------判断是否为数字--------------------*/ public static boolean check_intvalue(String check){ int pos = (check.charAt(0) == '-')?1:0; for (int i=pos;i<check.length();i++){ if(!Character.isDigit(check.charAt(i))){ return false; } } return true; } /*------------------------------------------------------*/ /*-------------------获取String类型的value-------------------*/ public static String getStringvalue(String check,int pos){ StringBuilder value = new StringBuilder(); boolean flag_s = false; for (int i=pos+1;i<check.length();i++){ if (check.charAt(i) != ' ') { flag_s = true; } if (flag_s){ value.append(check.charAt(i)); } } return value.toString().trim(); } /*------------------------------------------------------*/ /*---------------------print/println---------------------*/ public static String getprintString(String check,int pos){ StringBuilder value = new StringBuilder(); boolean flag = false; for (int i=pos;i<check.length();i++){ if(check.charAt(i)!=' ') flag = true; if(flag) value.append(check.charAt(i)); } return value.toString().trim(); } /*------------------------------------------------------*/ /*-----------------------算数操作-------------------------*/ public static void Cal(int x,String check,int pos1,int poschar1,int flagnum1){ String num2 = check.substring(pos1+1,poschar1); num2 = num2.trim(); String num3 = check.substring(poschar1+1); num3 = num3.trim(); boolean flagnum2 = check_intvalue(num2); boolean flagnum3 = check_intvalue(num3); int value2 = 0; int value3 = 0; if (flagnum2){ value2 = Integer.parseInt(num2); }else{ int x2 = getstatusInt(num2); if(x2 == -1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,num2); return ; }else{ value2 = IntStruct[x2].getValue(); } } if (flagnum3){ value3 = Integer.parseInt(num3); }else{ int x2 = getstatusInt(num3); if(x2 == -1){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,3,num3); return; }else{ value3 = IntStruct[x2].getValue(); } } if(value3 == 0&&x == 4){ countError++; ErrorStruct[countError] = new TPL_CompileError(count,10,"xxxxx"); return; } int result = 0; if (x == 1) result = value2 + value3; else if (x == 2) result = value2 - value3; else if (x == 3) result = value2 * value3; else result = value2 / value3; IntStruct[flagnum1].putsvalue(result); } /*------------------------------------------------------*/ /*-----------------------判断最后一个字母------------------*/ public static boolean check_last(char ch){ if(ch>='A'&&ch<='Z'){ return true; } if(ch>='a'&&ch<='z'){ return true; } if(ch>='0'&&ch<='9'){ return true; } if(ch == '\"') return true; return false; } /*------------------------------------------------------*/ } /*-------------------封装TPL_String类------------------*/ class TPL_String{ private String name; private String value; TPL_String(){} TPL_String(String sx){ this.name = sx; } public boolean check_name(){ if(this.name.charAt(0)<='9'&&this.name.charAt(0)>='0'){ return false; } for (int i=0;i<name.length();i++){ if (name.charAt(i) == ' ') return false; } if (name.length() == 0) return false; return true; } public String getName(){ return this.name; } public String getValue(){ return this.value; } public void putsvalue(String x){ this.value = x; } } /*------------------------------------------------------*/ /*-------------------封装TPL_Int类------------------*/ class TPL_Int{ private String name; private int value = 0; TPL_Int(){} TPL_Int(String sx){ this.name = sx; } public boolean check_name(){ if(this.name.charAt(0)<='9'&&this.name.charAt(0)>='0'){ return false; } for (int i=0;i<name.length();i++){ if (name.charAt(i) == ' ') return false; } if (name.length() == 0) return false; return true; } public String getName(){ return name; } public int getValue(){ return value; } public void putsvalue(int x){ this.value = x; } } /*------------------------------------------------------*/ /*-------------------封装TPL_CompileError类------------------*/ class TPL_CompileError{ private int line = 0; private String ERRORStruct; TPL_CompileError(){} TPL_CompileError(int nline,int flag,String nError){ this.line = nline; if(flag == -1) ERRORStruct = nError + "无法识别"; if(flag == 1) ERRORStruct = "INTEGER类型" + nError + "声明错误/命名错误"; if(flag == 2) ERRORStruct = "STRING类型" + nError + "声明错误/命名错误"; if(flag == 3) ERRORStruct = nError + "未声明此变量"; if(flag == 4) ERRORStruct = nError + "Integer类型赋值错误"; if(flag == 5) ERRORStruct = nError + "String类型赋值错误"; if(flag == 6) ERRORStruct = "CALCULATE计算格式不正确"; if(flag == 7) ERRORStruct = nError + "重复定义"; if(flag == 8) ERRORStruct = "赋值语句格式不正确"; if(flag == 9) ERRORStruct = "格式错误"; if(flag == 10) ERRORStruct = "除数为零"; } public int get_line(){ return this.line; } public String getError_String(){ return ERRORStruct; } } /*------------------------------------------------------*/ /*------------------封装需要print(ln)的语句类-------------------*/ class TPL_Print{ private int flag = -1; private int print_int = -1; private int println_int = -1; private String print_String = "xxx"; private String println_String = "xxx"; TPL_Print(){} TPL_Print(int flag,String s,int num){ this.flag = flag; if (flag == 1) this.print_int = num; else if (flag == 2) this.println_int = num; else if (flag == 3) this.print_String = s; else if (flag == 4) this.println_String = s; } public void Print_result(){ if (flag == 1) System.out.print(print_int); else if (flag == 2) System.out.println(println_int); else if (flag == 3) System.out.print(print_String); else if (flag == 4) System.out.println(println_String); } public int getFlag() { return flag; } } /*------------------------------------------------------*/