diff --git a/java/counting.bb b/java/counting.bb new file mode 100644 index 0000000000000000000000000000000000000000..7c0ee2323b5ab0fcae6e378a910eef855a214961 --- /dev/null +++ b/java/counting.bb @@ -0,0 +1,7 @@ +clear X; +incr X; +incr X; +incr X; +while X not 0 do; + decr X; +end; diff --git a/java/multiply.bb b/java/multiply.bb new file mode 100644 index 0000000000000000000000000000000000000000..2ab092c4c8491b6a9a22fcf059414a047b650c43 --- /dev/null +++ b/java/multiply.bb @@ -0,0 +1,21 @@ +clear X; +incr X; +incr X; +clear Y; +incr Y; +incr Y; +incr Y; +clear Z; +while X not 0 do; + clear W; + while Y not 0 do; + incr Z; + incr W; + decr Y; + end; + while W not 0 do; + incr Y; + decr W; + end; + decr X; +end; diff --git a/java/negative.bb b/java/negative.bb new file mode 100644 index 0000000000000000000000000000000000000000..1522cde1839f15fa58410cccdbc477a11936ac42 --- /dev/null +++ b/java/negative.bb @@ -0,0 +1,2 @@ +clear x; +decr x; \ No newline at end of file diff --git a/java/src/jrr1g18/bb/Interpreter.java b/java/src/jrr1g18/bb/Interpreter.java new file mode 100644 index 0000000000000000000000000000000000000000..871072be8c9d091bc5fd48539055593218c6f55d --- /dev/null +++ b/java/src/jrr1g18/bb/Interpreter.java @@ -0,0 +1,262 @@ +package jrr1g18.bb; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Interpreter { + private Map<String, Integer> m_vars = new HashMap<>(); + private List<String> m_code = new ArrayList<>(); + private Map<Integer, Integer> m_whiles = new HashMap<>(); + private int m_lineCount = 0; + private int m_whileDepth = 0; + + private final String m_filename; + + private static final Map<InstructionType, String> INSTRUCTION_NAMES; + + static { + Map<InstructionType, String> tempMap = new HashMap<>(); + tempMap.put(InstructionType.CLEAR, "clear"); + tempMap.put(InstructionType.DECR, "decr"); + tempMap.put(InstructionType.INCR, "incr"); + tempMap.put(InstructionType.WHILE, "while"); + tempMap.put(InstructionType.END, "end;"); + INSTRUCTION_NAMES = Collections.unmodifiableMap(tempMap); + } + + private enum InstructionType { + INCR, DECR, CLEAR, WHILE, END, + } + + private static InstructionType stringToInstructionType(String instruction) { + for(Entry<InstructionType, String> entry : INSTRUCTION_NAMES + .entrySet()) { + if(Objects.equals(instruction, entry.getValue())) { + return entry.getKey(); + } + } + return null; + } + + private static String getVarFromLine(String line) { + Matcher m = + Pattern.compile("(?<=incr|clear|decr)(.+)(?=;)").matcher(line); + if(!m.find()) { + System.err.println(line); + System.exit(1); + } + return stripWhitespace(m.group(1)); + } + + public Interpreter(String fileName) { + m_filename = fileName; + } + + public void run() { + readCode(); + validateCode(); + exec(); + } + + public String variablesToString() { + return m_vars.toString(); + } + + private String getLine(int line) { + return m_code.get(line); + } + + private static String[] splitLine(String line) { + return stripWhitespace(line).split("\\s+"); + } + + public static String stripWhitespace(String str) { + return str.replaceAll("(^\\s+|\\s+$)", ""); + } + + private String[] getSplitLine(int line) { + return splitLine(getLine(line)); + } + + private boolean isVariableNull(String name) { + return m_vars.get(name) == null; + } + + private void validateCode() { + String line; + String[] splitLine; + int whileDepth = 0; + + for(int idx = 0; idx < m_lineCount; ++idx) { + line = stripWhitespace(getLine(idx)); + splitLine = splitLine(line); + + if(line.equals("")) { + continue; + } + if(!line.matches(".*;$")) { + System.err.println("missing ; on line " + (idx + 1)); + System.exit(1); + } + + if(!splitLine[0].equals("incr") && !splitLine[0].equals("decr") + && !splitLine[0].equals("end;") + && !splitLine[0].equals("clear") + && !splitLine[0].equals("while")) { + System.err.println("Syntax error on line " + (idx + 1)); + System.exit(1); + + } + + InstructionType instruction = stringToInstructionType(splitLine[0]); + if((instruction == InstructionType.CLEAR + || instruction == InstructionType.DECR + || instruction == InstructionType.INCR) + && splitLine.length > 2) { + System.err.println("Too many arguments on line " + (idx + 1)); + System.exit(1); + } + + switch (instruction) { + case WHILE: + whileDepth++; + if(!splitLine[2].equals("not") || splitLine.length > 5) { + System.err.println("Syntax error on line " + (idx + 1)); + System.exit(1); + } + break; + case END: + whileDepth--; + if(splitLine.length > 1) { + System.err.println("Syntax error on line " + (idx + 1)); + System.exit(1); + } + break; + default: + break; + } + + } + + if(whileDepth > 0) { + System.err.println("Syntax error: unclosed while"); + } else if(whileDepth < 0) { + System.err.println("Syntax error: overclosed while"); + } + } + + private void readCode() { + try(BufferedReader reader = + new BufferedReader(new FileReader(m_filename))) { + String line; + while((line = reader.readLine()) != null) { + m_code.add(line); + m_lineCount++; + } + } catch(FileNotFoundException e) { + e.printStackTrace(); + } catch(IOException e) { + e.printStackTrace(); + } + } + + private void exec() { + String[] splitLine; + + for(int idx = 0; idx < m_lineCount; ++idx) { + splitLine = getSplitLine(idx); + InstructionType instruction = stringToInstructionType(splitLine[0]); + switch (instruction) { + case WHILE: + case END: + idx = loop(idx, splitLine); + continue; + default: + break; + } + String var = getVarFromLine(getLine(idx)); + switch (instruction) { + case CLEAR: + clear(var); + break; + case INCR: + incr(var); + break; + case DECR: + decr(var); + break; + default: + break; + } + } + } + + private void incr(String name) { + if(isVariableNull(name)) { + System.err.println("Error: Variable " + name + " doesn't exist"); + System.exit(1); + } else { + m_vars.put(name, m_vars.get(name) + 1); + } + } + + private void decr(String name) { + if(isVariableNull(name)) { + System.err.println("Error: Variable " + name + " doesn't exist"); + System.exit(1); + } else if(m_vars.get(name) == 0) { +// System.err +// .println("Error: Variable " + name + " cannot be negative"); +// System.exit(1); + m_vars.put(name, Integer.MAX_VALUE); + } else { + m_vars.put(name, m_vars.get(name) - 1); + } + } + + private void clear(String name) { + m_vars.put(name, 0); + } + + private int loop(int idx, String[] splitLine) { + String line; + if(splitLine[0].equals("while")) { + m_whileDepth++; + m_whiles.put(m_whileDepth, idx); + + int condition = Integer.parseInt(splitLine[3]); + if(isVariableNull(splitLine[1]) + && m_vars.get(splitLine[1]) == condition) { + while(!splitLine[0].equals("end;")) { + idx++; + line = getLine(idx); + splitLine = splitLine(line); + } + } + } else { + line = m_code.get(m_whiles.get(m_whileDepth)); + splitLine = splitLine(line); + int condition = Integer.parseInt(splitLine[3]); + + if(m_vars.get(splitLine[1]) != condition) + idx = m_whiles.get(m_whileDepth); + else { + m_whileDepth--; + } + + } + return idx; + } + +} diff --git a/java/src/jrr1g18/bb/Main.java b/java/src/jrr1g18/bb/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..7d3d9c8af199892ea9b02e2a466d670cc9405644 --- /dev/null +++ b/java/src/jrr1g18/bb/Main.java @@ -0,0 +1,11 @@ +package jrr1g18.bb; + +public class Main { + + public static void main(String[] args) { + Interpreter interpreter = new Interpreter("negative.bb"); + interpreter.run(); + System.out.println(interpreter.variablesToString()); + } + +}