-
Notifications
You must be signed in to change notification settings - Fork 1
/
Operation.java
224 lines (221 loc) · 9 KB
/
Operation.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// This class is used to define all static functionality funtions.
public class Operation {
//call print function: three situations
public static void callprint(String code){
String tempcode = code.trim();
//1. print "string here"
if (tempcode.toLowerCase().matches("(print)( +)(\".*\")")){
tempcode=tempcode.replaceAll("^(?i)(print)","").trim();
tempcode=Parse.parseStringAndEcapse(tempcode);
if (tempcode!=null){
System.out.print(tempcode);
}
//2. print cr
}else if(code.toLowerCase().matches("(print)( +)(cr)")){
System.out.println("\r");
//2. print var
}else if(code.toLowerCase().matches("(print)( +)([a-zA-Z_][a-zA-Z_0-9]*)")){
tempcode=tempcode.replaceAll("^(?i)(print)","").trim();
//get the value from hashmap and check if it is initizlized
if(RudiInnerStructure.has_Var_From_PeekMap(tempcode)==false){
Parse.error("Unrecogonized Variable name.(Define variable in DECS first)");
}else if(RudiInnerStructure.getAttributes_of_Var_From_PeekMap(tempcode)[1].equals("")){
Parse.error("Variable has not been initialized.");
}else{
System.out.print(RudiInnerStructure.getAttributes_of_Var_From_PeekMap(tempcode)[1]);
}
}else{
Parse.error("syntax error: Print funtion.");
}
}
//call input functions: check input valid
public static void callinput(String code){
String tempcode = code.trim();
//parse it the input string is valid
if (tempcode.toLowerCase().matches("(input)( +)(\".*\")")){
tempcode=tempcode.replaceAll("^(?i)(input)","").trim();
tempcode=Parse.parseStringAndEcapse(tempcode);
if (tempcode!=null){
System.out.print(tempcode);
}
//when input happens, it will match input and variable, they match then call the assignment function.
}else if(code.toLowerCase().matches("(input)( +)([a-zA-Z_][a-zA-Z_0-9]*)")){
tempcode=tempcode.replaceAll("^(?i)(input)","").trim();
String input = Action.keyInput();
MatchThenAssign(tempcode,input);
}else{
Parse.error("syntax error: Input funtion.");
}
}
//call assignment functions: check assignment valid
public static void callassign(String code){
String tempcode = code.trim();
String parts[];
String var;
String express;
//there is "=" that is an assignment
if (tempcode.toLowerCase().matches("([a-zA-Z_])([a-zA-Z_0-9]*)( *)=( *)(.+)")){
parts=tempcode.split(" *= *",2);
var = parts[0];
express = parts[1];
//check if the variable is defined in decs
if(RudiInnerStructure.has_Var_From_PeekMap(var)==false){
Parse.error("Unrecogonized Variable name.(Define variable in DECS first)");
}else{
String type_value[] = RudiInnerStructure.getAttributes_of_Var_From_PeekMap(var);
try{
//check if the value matches to the type of variable
if(type_value[0].equalsIgnoreCase("string")){
if (express.trim().toLowerCase().matches("( *)\".*\"")==true){
express = Parse.parseStringAndEcapse(express.trim());
if (express!=null){
type_value[1]=express;
//update a related variable map
RudiInnerStructure.update_PeekVarMap(var, type_value);
}
}else{
Parse.error("String matches error.");
}
}else{
//do calculate when assignment is a function
ParseOperation math = new ParseOperation(express);
Float value = Float.parseFloat(math.parseInput());
if(type_value[0].equalsIgnoreCase("float")){
type_value[1]=Float.toString(value);
//update a related variable map
RudiInnerStructure.update_PeekVarMap(var, type_value);
}else if (type_value[0].equalsIgnoreCase("integer")){
type_value[1]=Integer.toString(Math.round(value));
//update a related variable map
RudiInnerStructure.update_PeekVarMap(var, type_value);
}
}
}catch(NumberFormatException e){
Parse.error("Variable can only receieve a valid float or int number.");
}
}
}else{
Parse.error("Unrecoginzed error.");
}
}
//remove some contained string in a string with case insensitive situation.
//check if the remove only happen at the beginning of a string
public static String removeCaseInsentive(String code, String remove, Boolean head){
if (head == false){
return code.replaceAll("(?i)"+remove,"");
}else{
return code.replaceAll("^(?i)"+remove,"");
}
}
//remove some contained string in a string with case insensitive situation.
public static String removeCaseInsentive(String code, String remove){
return code.replaceAll("(?i)"+remove,"");
}
//check it a assignment match (value and variable)
public static void MatchThenAssign(String var_name, String express){
if(RudiInnerStructure.has_Var_From_PeekMap(var_name)==false){
Parse.error("Unrecogonized Variable name.(Define variable in DECS first)");
}else{
String type_value[] = RudiInnerStructure.getAttributes_of_Var_From_PeekMap(var_name);
try{
if(type_value[0].equalsIgnoreCase("string")){
type_value[1]=express;
RudiInnerStructure.update_PeekVarMap(var_name, type_value);
}else{
//do calculate when assignment is a function
Float value = Float.parseFloat(express);
if(type_value[0].equalsIgnoreCase("float")){
type_value[1]=Float.toString(value);
RudiInnerStructure.update_PeekVarMap(var_name, type_value);
}else if (type_value[0].equalsIgnoreCase("integer")){
type_value[1]=Integer.toString(Math.round(value));
RudiInnerStructure.update_PeekVarMap(var_name, type_value);
}
}
}catch(NumberFormatException e){
Parse.error("Variable can only receieve a valid float or int number.");
}
}
}
//this is a parse function is operating process
// if check if there is a [ or ] exists in the same line with special symbol. That is not allowed in this interpreter
//Also this functions is used to manage complex functions like ,if ,while and subroutine.
//condition is used to decide if next few lines is executed
public static void morefxn_oneline(ComplexFxn fxn){
String tempcode = fxn.code.trim();
//if condition is false, that means next few lines cannot be execuate. Only record [ and ]
if(fxn.condition==false){
if (tempcode.toLowerCase().matches("\\[")){
fxn.brackets_stack.push("[");
}else if(tempcode.toLowerCase().matches("\\]")){
if(fxn.brackets_stack.empty()){
Parse.error("Brackets do not match.");
}else{
fxn.brackets_stack.pop();
if(fxn.brackets_stack.empty()){
fxn.is_valid=false;
}
}
}
}else if (Parse.isEmptyLine(tempcode)){
//do nothing
}else if (tempcode.toLowerCase().matches("\\[.+\\]")){//--------------[statement]
Parse.error("\"]\" can not follow by other statements or expressions ");
}else if (tempcode.toLowerCase().matches("\\[.+")){//-----------------[statement
Parse.error("\"]\" can not follow by other statements or expressions ");
}else if (tempcode.toLowerCase().matches("\\].+")){//-----------------]statement
Parse.error("\"]\" can not follow by other statements or expressions ");
}else if (tempcode.toLowerCase().matches(".+\\]")){//-----------------statement]
Parse.error("\"]\" can not follow by other statements or expressions ");
}else if (tempcode.toLowerCase().matches("\\[")){//-------------------[
if(fxn.brackets_stack.empty()==false){
Parse.error("Brackets do not match.");
}else{
fxn.brackets_stack.push("[");
}
}else if (tempcode.toLowerCase().matches("\\]")){//-------------------]
if(fxn.brackets_stack.empty()){
Parse.error("Brackets do not match.");
}else{
fxn.brackets_stack.pop();
fxn.is_valid=false;
}
}
else if(Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("stop")){
System.out.println("<RUDI PROGRAM: Stop succesfully>");
System.exit(0);
//when if there is a "if", create a new object and do its functions
}else if(Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("if")){
if(fxn.brackets_stack.empty()){
Parse.error("Brackets do not match.");
}else{
if_fxn newif = new if_fxn(tempcode);
newif.doif();
}
//when if there is a "while", create a new object and do its functions
}else if (Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("while")){
if(fxn.brackets_stack.empty()){
Parse.error("Brackets do not match.");
}else{
while_fxn newwhile = new while_fxn(tempcode);
newwhile.dowhile();
}
//other if there are other operations, the process it the same in begin block
}else if (Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("print")){
Operation.callprint(tempcode);
}else if (Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("input")){
Operation.callinput(tempcode);
}else if (Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("assignment")){
Operation.callassign(tempcode);
//when if there is a "subroutine call", create a new object and do its functions
}else if (Parse.line_Begin_Fxn(tempcode).equalsIgnoreCase("call_sub")){
RudiInnerStructure.setMarkLineNum();
sub_fxn newsub_call = new sub_fxn(tempcode);
newsub_call.dosub();
}else if (Parse.line_Begin_Fxn(tempcode)==null){
Parse.error("Statement or expression cannot be outside block.");
}else{
Parse.error("Unrecoginzed type or invalid syntax.");
}
}
}