package pex.parser; import java.io.IOException; import java.io.StreamTokenizer; import java.io.FileReader; import java.io.StringReader; import java.io.Reader; import java.util.Collection; import java.util.ArrayList; import pex.core.*; public class NewParser { private Program _program; private StreamTokenizer _tokenizer; // may need aditional fields public NewParser() { } private void initTokenizer(Reader reader) { _tokenizer = new StreamTokenizer(reader); _tokenizer.eolIsSignificant(false); } public Program parseFile(String fileName, String programName /* may need aditional parameters */) throws BadSourceException, BadNumberException, InvalidExpressionException, MissingClosingParenthesisException, UnknownOperationException, EndOfInputException { _program = new Program(programName /* may need additional parameters */); try (FileReader reader = new FileReader(fileName)) { initTokenizer(reader); Collection<Expression> expressions = new ArrayList<>(); Expression exp; while ((exp = parseExpression()) != null) expressions.add(exp); _program.set(expressions); } catch (IOException ioe) { throw new BadSourceException(fileName, ioe); } return _program; } public Expression parseString(String expression, Program program) throws BadSourceException, BadNumberException, InvalidExpressionException, MissingClosingParenthesisException, UnknownOperationException, EndOfInputException { _program = program; try (StringReader reader = new StringReader(expression)) { initTokenizer(reader); return parseExpression(); } catch (IOException ioe) { throw new BadSourceException(expression, ioe); } } private Expression parseExpression() throws IOException, BadNumberException, InvalidExpressionException, MissingClosingParenthesisException, UnknownOperationException, EndOfInputException { int token = _tokenizer.nextToken(); switch (token) { case StreamTokenizer.TT_EOF: return null; case StreamTokenizer.TT_NUMBER: // Literal inteiro if (_tokenizer.nval < 0 || _tokenizer.nval - (int)_tokenizer.nval != 0) throw new BadNumberException("" + _tokenizer.nval); return new IntegerLiteral((int)_tokenizer.nval); case '"': return new StringLiteral(_tokenizer.sval); case StreamTokenizer.TT_WORD: return new Identifier(_tokenizer.sval /* may need aditional parameters */); case '(': Expression exp = parseCompositeExpression(); // process closing parenthesis if (_tokenizer.nextToken() != ')') throw new MissingClosingParenthesisException(exp.toString()); return exp; default: throw new InvalidExpressionException(_tokenizer.lineno()); } } // Return value cannot be null private Expression parseArgument() throws IOException, BadNumberException, UnknownOperationException, MissingClosingParenthesisException, EndOfInputException, InvalidExpressionException { Expression exp = parseExpression(); if (exp == null) throw new EndOfInputException(); return exp; } // the opening '(' was already processed private CompositeExpression parseCompositeExpression() throws IOException, BadNumberException, UnknownOperationException, MissingClosingParenthesisException, EndOfInputException, InvalidExpressionException { int token = _tokenizer.nextToken(); if (token != StreamTokenizer.TT_WORD) throw new InvalidExpressionException(_tokenizer.lineno()); String operatorName = _tokenizer.sval; // The way each composite expression is inntanciated mey need to be changed since // this depends on the specific code of each group switch (operatorName) { // process no-args expressions case "reads": return new ReadS(/* may need additional parameters */); case "readi": return new ReadI(/* may need additional parameters */); // processing unary expressions case "neg": return new Neg(parseArgument()); case "not": return new Not(parseArgument()); case "call": try { return new Call((StringLiteral)parseArgument() /* may need additional parameter */); } catch(ClassCastException cce) { // it is not a StringLiteral throw new InvalidExpressionException(_tokenizer.lineno()); } // processing binary expressions case "add": return new Add(parseArgument(), parseArgument()); case "mul": return new Mul(parseArgument(), parseArgument()); case "div": return new Div(parseArgument(), parseArgument()); case "mod": return new Mod(parseArgument(), parseArgument()); case "sub": return new Sub(parseArgument(), parseArgument()); case "lt": return new Lt(parseArgument(), parseArgument()); case "le": return new Le(parseArgument(), parseArgument()); case "gt": return new Gt(parseArgument(), parseArgument()); case "ge": return new Ge(parseArgument(), parseArgument()); case "eq": return new Eq(parseArgument(), parseArgument()); case "ne": return new Ne(parseArgument(), parseArgument()); case "and": return new And(parseArgument(), parseArgument()); case "or": return new Or(parseArgument(), parseArgument()); case "set": return new Set(parseArgument(), parseArgument() /* may need additional parameters */); case "while": return new While(parseArgument(), parseArgument()); // processing ternary expressions case "if": return new If(parseArgument(), parseArgument(), parseArgument()); // processing variadic expressions case "seq": case "print": // process args ArrayList<Expression> args = new ArrayList<>(); while (true) { try { args.add(parseArgument()); } catch (InvalidExpressionException iee) { // reaching the closing parenthisis of current composite expression if (_tokenizer.ttype == ')') { // no more arguments _tokenizer.pushBack(); break; } throw iee; } } if (operatorName.equals("seq")) return new Seq(args); else return new Print(args /* may need additional parameters */); default: throw new UnknownOperationException(_tokenizer.sval); } } }