Skip to content

Instantly share code, notes, and snippets.

@kmalcaba
Created March 6, 2018 15:37
Show Gist options
  • Save kmalcaba/f7ea509424f9ba6b6c8f0712c1258a15 to your computer and use it in GitHub Desktop.
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.
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