Created
March 6, 2018 15:37
-
-
Save kmalcaba/f7ea509424f9ba6b6c8f0712c1258a15 to your computer and use it in GitHub Desktop.
C++ if-block compiler written in Java which executes console printing and mathematical expressions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package compiler.core; | |
import compiler.SourceCodeCompiler; | |
import java.util.HashMap; | |
/** | |
* | |
* @author Kirsten A. Malcaba | |
*/ | |
public class IfStatement { | |
private final HashMap<String, String> declaredVars; | |
private final HashMap<String, String> varTypes; | |
private boolean isUnary = false; | |
private boolean isLogical = false; | |
private boolean invalidExpr = false; | |
private boolean result = false; | |
private boolean previousResult = false; | |
private final String[] ifLines; | |
private IFTYPE ifType; | |
String id_1 = null; | |
String id_2 = null; | |
String operator = null; | |
String literal_1 = null; | |
String literal_2 = null; | |
int value_1 = 0; | |
int value_2 = 0; | |
String left = null; | |
int leftVal = 0; | |
String right = null; | |
int rightVal = 0; | |
private enum IFTYPE { | |
IF, ELSIF, ELSE; | |
} | |
public IfStatement(String ifBlock, HashMap<String, String> declaredVars, HashMap<String, String> varTypes) { | |
this.declaredVars = declaredVars; | |
this.varTypes = varTypes; | |
this.ifLines = ifBlock.split("\n"); | |
} | |
private String getStringToken(String s, int i) { | |
int j = i; | |
while (j < s.length()) { | |
if (Character.isLetter(s.charAt(j))) { | |
j++; | |
} else { | |
return s.substring(i, j); | |
} | |
} | |
return s.substring(i, j); | |
} | |
private String getIfToken(String s, int i) { | |
int j = i; | |
while (j < s.length()) { | |
if (Character.isLetter(s.charAt(j))) { | |
j++; | |
} else if (Character.isWhitespace(s.charAt(j))) { | |
j++; | |
} else if (s.charAt(j) == '(' || s.charAt(j) == '{') { | |
return s.substring(i, j); | |
} | |
} | |
return s.substring(i, j); | |
} | |
private int getIntToken(String s, int i) { | |
int j = i; | |
while (j < s.length()) { | |
if (Character.isDigit(s.charAt(j))) { | |
j++; | |
} else { | |
return Integer.parseInt(s.substring(i, j)); | |
} | |
} | |
return Integer.parseInt(s.substring(i, j)); | |
} | |
private IFTYPE getIfType(String ifType) { | |
switch (ifType) { | |
case "if": | |
return IFTYPE.IF; | |
case "else if": | |
return IFTYPE.ELSIF; | |
case "else": | |
return IFTYPE.ELSE; | |
default: | |
return null; | |
} | |
} | |
public boolean isValidHeader() { | |
String header = ifLines[0]; | |
System.out.println(header); | |
int i = 0; | |
//tokenizes if, then takes its ifType | |
String ifToken = getIfToken(header, i); | |
ifType = getIfType(ifToken.trim()); | |
if(ifType == null) | |
return false; | |
//checks for correct syntax | |
//otherwise, incorrect syntax | |
for (i += ifToken.length(); i < header.length(); i++) { | |
char ch = header.charAt(i); | |
if (ch == '(') { | |
i++; | |
break; | |
} else if (ch == '{') { | |
if (ifType != IFTYPE.ELSE) { | |
return false; | |
} | |
} else if (ch == '}') { | |
return false; | |
} else if (Character.isWhitespace(ch)) { | |
} else { | |
} | |
} | |
if (ifType == IFTYPE.ELSE) { | |
previousResult = false; | |
} | |
//evaluate which type of if statement | |
//take string of boolean expression | |
String boolExpr = ""; | |
OUTER: | |
for (; i < header.length(); i++) { | |
char ch = header.charAt(i); | |
switch (ch) { | |
case ')': | |
i++; | |
break OUTER; | |
case '{': | |
if (ifType != IFTYPE.ELSE) { | |
return false; | |
} | |
case '}': | |
return false; | |
default: | |
boolExpr += ch; | |
break; | |
} | |
} | |
//call method to evaluate boolean expression | |
if (!isValidBoolExpr(boolExpr)) { | |
return false; | |
} else { | |
//look for opening brace | |
OUTER: | |
for (; i < header.length(); i++) { | |
char ch = header.charAt(i); | |
switch (ch) { | |
case '{': //opening brace found | |
break OUTER; | |
case '}': | |
case ')': | |
case '(': | |
return false; | |
default: | |
i++; | |
break; | |
} | |
} | |
} | |
return true; | |
} | |
//method to validate boolean expression | |
private boolean isValidBoolExpr(String expression) { | |
int i = 0; | |
OUTER: | |
while (i < expression.length()) { | |
char ch = expression.charAt(i); | |
switch (ch) { | |
//wrong syntax | |
case '{': | |
case '}': | |
return false; | |
default: | |
//skips whitespace | |
if (Character.isWhitespace(ch)) { | |
i++; | |
} //is a value | |
else if (Character.isDigit(ch)) { | |
if (value_1 == 0) { | |
value_1 = getIntToken(expression, i); | |
i += Integer.toString(value_1).length(); | |
System.out.println(value_1); | |
} else { | |
value_2 = getIntToken(expression, i); | |
i += Integer.toString(value_2).length(); | |
System.out.println(value_2); | |
} | |
} //is a unary operator ! | |
else if (ch == '!' && expression.charAt(i + 1) != '=') { | |
operator = "!"; | |
String token = getStringToken(expression, i + 1); | |
i += token.length() + 1; | |
//if identifier is not declared | |
if (!declaredVars.containsKey(token)) { | |
return false; | |
} else { //check if the following variable is boolean | |
if (varTypes.get(token).equals("bool")) { | |
if (id_1 == null) { | |
id_1 = token; | |
} else { | |
id_2 = token; | |
} | |
isUnary = true; | |
} else { | |
return false; | |
} | |
} | |
} //is a logical operator | |
//== != <= >= < > | |
else if (ch == '>' || ch == '<' || ch == '!' || ch == '=') { | |
//if == != <= >= | |
if (expression.charAt(i + 1) == '=') { | |
operator = Character.toString(ch) + Character.toString(expression.charAt(i + 1)); | |
isLogical = true; | |
i += 2; | |
} //if < > | |
else if ((ch == '>' || ch == '<') && expression.charAt(i + 1) != '=') { | |
operator = Character.toString(ch); | |
isLogical = true; | |
i++; | |
} //if ! or = only, syntax error | |
else if ((ch == '!' || ch == '=') && expression.charAt(i + 1) != '=') { | |
return false; | |
} | |
System.out.println(operator); | |
} //is an identifier | |
else if (Character.isAlphabetic(ch)) { | |
String token = getStringToken(expression, i); | |
i += token.length(); | |
//if identifier is not declared | |
if (!declaredVars.containsKey(token)) { | |
return false; | |
} else { | |
if (varTypes.get(token).equals("bool")) { | |
isUnary = true; | |
} | |
if (id_1 == null) { | |
id_1 = token; | |
} else { | |
id_2 = token; | |
} | |
} | |
} //is a string literal | |
else if (ch == '\"') { | |
String token = ""; | |
int j = i; | |
for (; j < expression.length(); j++) { | |
if (expression.charAt(j) == '\"') { | |
j++; | |
break; | |
} else { | |
token += expression.charAt(j); | |
} | |
} | |
i += j; | |
} | |
} | |
} | |
return true; | |
} | |
private void getValues() { | |
//check for empty variables | |
//use non empty ones | |
//for left operand | |
if (literal_1 != null) { | |
left = literal_1; | |
} else if (id_1 != null) { | |
left = declaredVars.get(id_1); | |
if (Character.isDigit(left.charAt(0))) { | |
leftVal = Integer.parseInt(left); | |
left = null; | |
} | |
} else if (value_1 != 0) { | |
leftVal = value_1; | |
} | |
//for right operand | |
if (literal_1 != null) { | |
right = literal_1; | |
} else if (literal_2 != null) { | |
right = literal_2; | |
} else if (id_2 != null) { | |
right = declaredVars.get(id_2); | |
if (Character.isDigit(right.charAt(0))) { | |
rightVal = Integer.parseInt(right); | |
right = null; | |
} | |
} else if (value_1 != 0) { | |
rightVal = value_1; | |
} else if (value_2 != 0) { | |
rightVal = value_2; | |
} | |
} | |
private boolean evaluateBoolExpr() { | |
//start evaluation | |
//if unary operator | |
if (isUnary) { | |
//boolean variable only | |
if (operator == null) { | |
return declaredVars.get(left).equals("true"); | |
} //if (!{boolean variable}) | |
else if (operator.equals("!")) { | |
return !declaredVars.get(left).equals("true"); | |
} | |
} else if (isLogical) { | |
switch (operator) { | |
case "<": | |
//left operand contains an int | |
if (left == null) { | |
return leftVal < rightVal; | |
} //cannot compare strings with < | |
else { | |
invalidExpr = true; | |
} | |
break; | |
case ">": | |
//left operand contains an int | |
if (left == null) { | |
return leftVal > rightVal; | |
} //cannot compare strings with > | |
else { | |
invalidExpr = true; | |
} | |
break; | |
case "<=": | |
//left operand contains an int | |
if (left == null) { | |
return leftVal <= rightVal; | |
} //cannot compare strings with <= | |
else { | |
invalidExpr = true; | |
} | |
break; | |
case ">=": | |
//left operand contains an int | |
if (left == null) { | |
return leftVal >= rightVal; | |
} //cannot compare strings with >= | |
else { | |
invalidExpr = true; | |
} | |
break; | |
case "==": | |
//left operand contains an int | |
if (left == null) { | |
return leftVal == rightVal; | |
} else { | |
return left.equals(right); | |
} | |
case "!=": | |
if (left == null) { | |
return leftVal != rightVal; | |
} else { | |
return !left.equals(right); | |
} | |
default: | |
invalidExpr = true; | |
} | |
} | |
return false; | |
} | |
public boolean isInvalidExpr() { | |
return invalidExpr; | |
} | |
public boolean getPreviousResult() { | |
return previousResult; | |
} | |
public String getCompilationResult() { | |
String compiledResult = ""; | |
getValues(); | |
result = evaluateBoolExpr(); | |
//if result is true, execute body inside, | |
//else, skip. | |
if (result || ((ifType == IFTYPE.ELSE || ifType == IFTYPE.ELSIF) && !previousResult)) { | |
compiledResult = evaluateBody(); | |
System.out.println("evaluated body"); | |
previousResult = result; | |
return compiledResult; | |
} else { | |
return compiledResult; | |
} | |
} | |
public String evaluateBody() { | |
System.out.println(ifType + " block is true"); | |
String blockResult = ""; | |
//execute statements inside ifLines[] until loop encounters closing brace | |
String codeLine; | |
String lineType; | |
OUTER: | |
for (int i = 1; i < ifLines.length; i++) { | |
codeLine = ifLines[i].replaceAll("\t", "").trim(); | |
System.out.println(codeLine); | |
if (codeLine.charAt(0) == '}') { | |
continue; | |
} else if (codeLine.equals("")) { | |
continue; | |
} | |
lineType = SourceCodeCompiler.identifyLineType(codeLine); | |
System.out.println(lineType); | |
switch (lineType) { | |
// case "variable declaration": | |
// break; | |
case "display": | |
DisplayFunction display = new DisplayFunction(ifLines[i], declaredVars); | |
if (display.correctSyntax()) { | |
blockResult += display.getResult(); | |
System.out.println("result: " + blockResult); | |
} else { | |
blockResult = "error"; | |
break OUTER; | |
} | |
break; | |
// case "forloop": | |
// break; | |
// case "whileloop": | |
// break; | |
// case "if": | |
// break; | |
case "expression": | |
MathematicalExpression exp = new MathematicalExpression(declaredVars, ifLines[i]); | |
if (exp.checkVariables()) { | |
if (exp.hasAssignment()) { | |
exp.evaluateExpression(); | |
} | |
} else { | |
blockResult = "error"; | |
break OUTER; | |
} | |
break; | |
} | |
} | |
return blockResult; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment