package z1; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Program implements Runnable { final String operator = "[<>][>=]?"; final String operation = "[-+*/]"; final String variable = "\\w*[a-zA-Z]\\w*"; final String value = "\\w+"; final String letExp = "^let "+variable+" = "+value+" "+operation+" "+value+"$"; protected Map labels; protected Map vars; protected List commands; protected BufferedReader in; abstract class Command { protected Command next; protected int nextLine; public Command go() { job(); return next(); } protected void job() { //Do nothing } protected Command next() { return next; } public void translateJump() throws Exception { try { next = commands.get(nextLine); } catch (IndexOutOfBoundsException e) { next = null; } } } class EmptyCommand extends Command { public EmptyCommand(int nl) { nextLine = nl; } } class PrintCommand extends Command { String value; public PrintCommand(String v, int nl) { value = v; nextLine = nl; } @Override public void job() { println(getValueOf(value)); } } class ReadCommand extends Command { String var; public ReadCommand(String v, int nl) { var = v; nextLine = nl; } @Override protected void job() { try { vars.put(var, Integer.parseInt(in.readLine())); } catch (IOException e) { System.err.println("Systemova chyba"); System.exit(0); } } } class LabelCommand extends Command { String label; public LabelCommand(String l, int nl) throws Exception { label = l; nextLine = nl; addLabel(label, this); } } class GotoCommand extends Command { String label; public GotoCommand(String g) { label = g; } @Override public void translateJump() throws Exception { next = labels.get(label); if (next == null) throw new Exception("Neznamy label"); } } class SetCommand extends Command { String var; String value; public SetCommand(String va, String val, int nl) { nextLine = nl; value = val; var = va; } @Override protected void job() { vars.put(var, getValueOf(value)); } } class LetCommand extends Command { String var; String value1; String value2; char op; public LetCommand(String v, String val1, String val2, char o, int nl) { var = v; value1 = val1; value2 = val2; op = o; nextLine = nl; } @Override protected void job() { int result = 0; switch (op) { case '+': result = getValueOf(value1) + getValueOf(value2); break; case '-': result = getValueOf(value1) - getValueOf(value2); break; case '*': result = getValueOf(value1) * getValueOf(value2); break; case '/': result = getValueOf(value1) / getValueOf(value2); break; } vars.put(var, result); } } class IfCommand extends Command { Command then; char op; String value1; String value2; public IfCommand(String val1, String val2, String o, String restOfLine, int nl) throws Exception { if (o.equals("<")) { op = '<'; } else if (o.equals(">")) { op = '>'; } else if (o.equals(">=")) { op = ']'; } else if (o.equals("<=")) { op = '['; } else if (o.equals("<>")) { op = '!'; } value1 = val1; value2 = val2; then = parseLine(restOfLine, nl); nextLine = nl; } @Override public Command go() { boolean cond = false; switch (op) { case '<': cond = getValueOf(value1) < getValueOf(value2); break; case '>': cond = getValueOf(value1) > getValueOf(value2); break; case '[': cond = getValueOf(value1) <= getValueOf(value2); break; case ']': cond = getValueOf(value1) >= getValueOf(value2); break; case '!': cond = getValueOf(value1) != getValueOf(value2); break; } if (cond) { return then; } else { return next(); } } @Override public void translateJump() throws Exception { super.translateJump(); then.translateJump(); } } protected int getValueOf(String var) { if (checkNum(var)) return Integer.parseInt(var); if (!vars.containsKey(var)) vars.put(var, 0); return vars.get(var); } public void addLabel(String label, Command labelCommand) throws Exception { if (labels.get(label)!=null) { throw new Exception(); } labels.put(label, labelCommand); } public Program(BufferedReader reader) throws Exception { commands = new ArrayList(); vars = new HashMap(); labels = new HashMap(); in = new BufferedReader(new InputStreamReader(System.in)); String line; int num = 0; while ((line = reader.readLine()) != null) { commands.add(parseLine(line, num++)); } translateJumps(); } protected void translateJumps() throws Exception { for (Command c:commands) { c.translateJump(); } } public void println(Integer integer) { System.out.println(integer); } protected Command parseLine(String line, int num) throws Exception { Command ret = null; if (line.equals("") || line.matches("^#.*")) { ret = new EmptyCommand(num+1); } else if (line.matches("^println .*")) { String var = line.substring(8); //za println if (!checkValue(var)) { throw new Exception("Chyba v prikazu: "+ line); } ret = new PrintCommand(var, num+1); } else if (line.matches("^readln .*")) { String var = line.substring(7); if (!checkVar(var)) { throw new Exception("Chyba v prikazu: " + line); } ret = new ReadCommand(var, num+1); } else if (line.matches("^goto .*")) { String label = line.substring(5); ret = new GotoCommand(label); } else if (line.matches("^set "+ variable + " = " + value +"$")) { int pos = line.indexOf('='); String var = line.substring(4, pos - 1); String value = line.substring(pos + 2); ret = new SetCommand(var, value,num+1); } else if (line.matches(letExp)) { int pos = line.indexOf('='); char op = '+'; if (line.indexOf('+') >= 0) {op = '+';} if (line.indexOf('-') >= 0) {op = '-';} if (line.indexOf('*') >= 0) {op = '*';} if (line.indexOf('/') >= 0) {op = '/';} int opPos = line.indexOf(op); String var = line.substring(4, pos - 1); String value1 = line.substring(pos + 2, opPos - 1); String value2 = line.substring(opPos + 2); /*Pattern pat = Pattern.compile(letExp); Matcher mat = pat.matcher(line);*/ ret = new LetCommand(var, value1, value2, op, num+1); } else if (line.matches("^if "+ value + " " + operator + " " + value + ", " + ".*$")) { String op = null; if (line.indexOf("<") >= 0) {op = "<";} if (line.indexOf(">") >= 0) {op = ">";} if (line.indexOf("<=") >= 0) {op = "<=";} if (line.indexOf(">=") >= 0) {op = ">=";} if (line.indexOf("<>") >= 0) {op = "<>";} if (op == null) { throw new Exception("Spatny operator: " + line); } int opPos = line.indexOf(op); int thenPos = line.indexOf(','); if (thenPos < 0) { throw new Exception("Chybi prikaz pri splneni podminky:" + line); } String value1 = line.substring(3, opPos-1); String value2 = line.substring(opPos + op.length()+1, thenPos); String rest = line.substring(thenPos+2); ret = new IfCommand(value1, value2, op, rest, num+1); } else if (false) { } else if (false) { } else if (false) { } else if (line.matches(".*:$")) { String label = line.substring(0, line.length()-1); ret = new LabelCommand(label, num+1); } else { throw new Exception("Neznamy prikaz:" + line); } return ret; } protected boolean checkValue(String value) { try { Integer.parseInt(value); return true; } catch (NumberFormatException e) { return value.matches("^\\w+$"); } } protected boolean checkVar(String var) { return var.matches("^\\w*[a-zA-Z]\\w*$"); } protected boolean checkNum(String s) { try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; } } @Override public void run() { Command next; try { next = commands.get(0); } catch (IndexOutOfBoundsException e) { next = null; } while (next != null) { next = next.go(); } } }