package project.phase2; import project.phase2.exc.InvalidArgumentException; import project.phase2.exc.ParseException; import project.phase2.exc.TypeException; import project.phase2.file.StringMatchOperations; import project.phase2.ll1parsergenerator.ASTNode; import project.phase2.structs.StringMatchList; import project.scangen.ScannerGenerator; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; public class Interpreter { private class Variable { final public Object val; public Variable(Object val) { this.val = val; } @Override public String toString() { return this.val.toString(); } } private final MiniREParser parser; private final Map<String, Variable> varTable; public Interpreter(MiniREParser parser) { this.parser = parser; varTable = new HashMap<String, Variable>(); } public void interpret() throws ParseException { ASTNode<String> root = parser.parse().getRoot(); ASTNode<String> minire_program = root.get(0); statement_list(minire_program.get(1)); } private String fromQuotedString(final String asciiString) { return asciiString.substring(1, asciiString.length() - 1); } public void statement_list(final ASTNode<String> statement_list) { if (statement_list.getChildren().size() == 0) { return; } ASTNode<String> statement = statement_list.get(0); if (statement.getChildren().size() == 0) { return; } String nextTokenType = statement.get(0).getValue(); if (nextTokenType.equals("ID")) { assignment(statement); } else if (nextTokenType.equals("REPLACE")) { replace(statement, false); } else if (nextTokenType.equals("RECURSIVEREPLACE")) { replace(statement, true); } else if (nextTokenType.equals("PRINT")) { print(statement.get(2)); } statement_list(statement_list.get(1)); } private void assignment(ASTNode<String> statement) { String id = statement.get(0).get(0).getValue(); if (statement.get(2).getValue().equals("OCTOTHORPE")) { Variable var = expression(statement.get(3)); if (var.val instanceof Integer) { varTable.put(id, var); } else { varTable.put(id, new Variable(((StringMatchList) var.val).size())); } } else if (statement.get(2).getValue().equals("MAXFREQSTRING")) { Variable var = varTable.get(statement.get(4).get(0).getValue()); if (var.val instanceof StringMatchList) { varTable.put(id, new Variable(((StringMatchList) var.val).getMostFrequentString())); } else { throw new TypeException(String.format("Can't call `maxfreqstring' on variable `%s' of type `Integer'", id)); } } else { varTable.put(id, expression(statement.get(2))); } } private void print(ASTNode<String> exp_list) { System.out.println(expression(exp_list.get(0))); if (exp_list.getChildren().size() > 1) { print(exp_list.get(2)); } } private Variable expression(ASTNode<String> exp) { ASTNode<String> toke = exp.get(0); if (toke.getValue().equals("ID")) { return varTable.get(toke.get(0).getValue()); } else if (toke.getValue().equals("OPEN-PAREN")) { return expression(toke.get(1)); } else if (toke.getValue().equals("term")) { StringMatchList res = term(toke); ASTNode<String> exp_tail = exp.get(1); return new Variable(expression_tail(res, exp_tail)); } else { throw new RuntimeException(); } } private StringMatchList expression_tail(StringMatchList res, ASTNode<String> exp_tail) { if (exp_tail.getChildren().size() == 1) { return res; } StringMatchList stuff = term(exp_tail.get(1)); StringMatchList next = expression_tail(stuff, exp_tail.get(2)); String op = exp_tail.get(0).get(0).getValue(); if (op.equals("DIFF")) { return res.difference(next); } else if (op.equals("UNION")) { return res.union(next); } else if (op.equals("INTERS")) { return res.intersection(next); } else { throw new RuntimeException(); } } private StringMatchList term(ASTNode<String> term) { String regex = fromQuotedString(term.get(1).get(0).getValue()); String filename = fromQuotedString(term.get(3).get(0).get(0).getValue()); return StringMatchOperations.find(new File(filename), regex); } private void replace(ASTNode<String> statement, boolean recursive) { String regex = fromQuotedString(statement.get(1).get(0).getValue()); String replaceText = fromQuotedString(statement.get(3).get(0).getValue()); if (recursive && Pattern.compile(regex).matcher(replaceText).find()) { throw new InvalidArgumentException(String.format("Replacement text `%s' must not match regex `%s'.", replaceText, regex)); } String srcFile = fromQuotedString(statement.get(5).get(0).get(0).get(0).getValue()); String dstFile = fromQuotedString(statement.get(5).get(2).get(0).get(0).getValue()); StringMatchOperations.replace(regex, replaceText, new File(srcFile), new File(dstFile), recursive); } public static void main(String[] args) { if (args.length != 1) { System.err.println("Parameters: <program-file>"); System.exit(1); } String programFilePath = args[0]; ScannerGenerator scannerGenerator = null; try { InputStream specFileInputStream = new ByteArrayInputStream(MiniRESpec.spec.getBytes()); InputStream programFileInputStream = new FileInputStream(programFilePath); scannerGenerator = new ScannerGenerator(specFileInputStream, programFileInputStream); } catch (FileNotFoundException ex) { System.err.println(ex); System.exit(1); } MiniREParser parser = new MiniREParser(scannerGenerator); Interpreter interpreter = new Interpreter(parser); try { interpreter.interpret(); } catch (ParseException ex) { System.out.println(String.format("%s (%s:%d:%d)", ex, programFilePath, ex.getToken().line, ex.getToken().pos)); System.exit(2); } catch (InvalidArgumentException ex) { System.out.println(ex); System.exit(3); } } }