public class InstructionParser { // Versione senza eccezioni public static Instruction parse( String statement, ParsingState state ) { String opCode = null; Tokenization tokens = new Tokenization(statement); try { opCode = tokens.nextToken(); } catch (NoSuchElementException e) { state.failure( "No instruction" ); } if ( state.correct() ) { if ( opCode.equals("Z") ) { return parseZParameters(tokens,state); } else if ( opCode.equals("S") ) { return parseSParameters(tokens,state); } else if ( opCode.equals("T") ) { return parseTParameters(tokens,state); } else if ( opCode.equals("J") ) { return parseJParameters(tokens,state); } else { state.failure( opCode, tokens.processed(), "Unknown instruction" ); return null; } } else { return null; } } private static Instruction parseZParameters( Tokenization tokens, ParsingState state ) { int n = 0; parseDelimiter(tokens,"(",state); if ( state.correct() ) { n = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,")",state); } if ( state.correct() ) { return new Z(n); } else { return null; } } private static Instruction parseSParameters( Tokenization tokens, ParsingState state ) { int n = 0; parseDelimiter(tokens,"(",state); if ( state.correct() ) { n = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,")",state); } if ( state.correct() ) { return new S(n); } else { return null; } } private static Instruction parseTParameters( Tokenization tokens, ParsingState state ) { int m = 0, n = 0; parseDelimiter(tokens,"(",state); if ( state.correct() ) { m = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,",",state); } if ( state.correct() ) { n = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,")",state); } if ( state.correct() ) { return new T(m,n); } else { return null; } } private static Instruction parseJParameters(Tokenization tokens, ParsingState state ) { int m = 0, n = 0, q = 0; parseDelimiter(tokens,"(",state); if ( state.correct() ) { m = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,",",state); } if ( state.correct() ) { n = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,",",state); } if ( state.correct() ) { q = parseIndex(tokens,state); } if ( state.correct() ) { parseDelimiter(tokens,")",state); } if ( state.correct() ) { return new J(m,n,q); } else { return null; } } private static void parseDelimiter( Tokenization tokens, String symbol, ParsingState state ) { String token = null; try { token = tokens.nextToken(); } catch (NoSuchElementException e) { state.failure( tokens.processed(), "'" + symbol + "' expected" ); } if ( state.correct() ) { if ( !token.equals(symbol) ) { state.failure( token, tokens.processed(), "'" + symbol + "' expected" ); } } } private static int parseIndex( Tokenization tokens, ParsingState state ) { String index = null; int n = 0; try { index = tokens.nextToken(); } catch (NoSuchElementException e) { state.failure( tokens.processed(), "Index expected" ); } if ( state.correct() ) { try { n = Integer.parseInt(index); } catch (NumberFormatException f) { state.failure( index, tokens.processed(), "Index expected" ); } } if ( state.correct() ) { if (n > 0) { return n; } else { state.failure( index, tokens.processed(), "Bad index" ); return 0; } } else { return 0; } } } public class ParsingState { // Emula "InstructionException" private String message = null; public void failure() { message = "* Error in instruction"; } public void failure(String description) { message = "* Error in instruction: " + description + "\n"; } public void failure(String processed, String description) { message = "\n" + "* Error in instruction:\n" + processed + "\n" + indent( processed.length() - 1 ) + "^ : " + description + "\n"; } public void failure(String token, String processed, String description) { message = "\n" + "* Error in instruction while parsing '" + token + "'\n" + processed + "\n" + indent( processed.length() ) + "^ : " + description + "\n"; } public boolean correct() { return ( message == null ); } public String errorMessage() { return message; } private static String indent(int n) { String right = ""; for (int i=1; i