/** * Creates a new warning for the given position with the given message. * <p> * If no position is available {@link Position#UNKNOWN} can be used * * @param pos the position where the warning occurred * @param msg the message explaining the warning * @return a new ParseError containing the warning */ public static ParseError warning(Position pos, String msg) { String message = msg; if (pos.getLine() > 0) { message = String.format("%3d:%2d: %s", pos.getLine(), pos.getPos(), msg); } return new ParseError(pos, message, Severity.WARNING); }
/** * Adds a parse error to the internal problem collector. * <p> * It is preferred to collect as much errors as possible and then fail with an exception instead of failing * at the first problem. Often syntax errors can be worked out by the parser and we can report a set of * errors at once. * * @param pos the position of the error. Note that {@link Token} implements {@link Position}. Therefore the * current token is often a good choice for this parameter. * @param message the message to describe the error. Can contain formatting parameters like %s or %d as defined * by {@link String#format(String, Object...)} * @param parameters Contains the parameters used to format the given message */ public void addError(Position pos, String message, Object... parameters) { getProblemCollector().add(ParseError.error(pos, String.format(message, parameters))); }
/** * Creates a new exception based on the list of errors. * * @param errors the errors which occurred while processing the user input * @return a new ParseException which can be thrown */ public static ParseException create(List<ParseError> errors) { if (errors.size() == 1) { return new ParseException(errors.get(0).getMessage(), errors); } else if (errors.size() > 1) { return new ParseException(String.format("%d errors occured. First: %s", errors.size(), errors.get(0).getMessage()), errors); } else { return new ParseException("An unknown error occured", errors); } }
/** * Adds a warning to the internal problem collector. * <p> * A warning indicates an anomaly which might lead to an error but still, the parser can continue to complete its * work. * * @param pos the position of the warning. Note that {@link Token} implements {@link Position}. * Therefore the current token is often a good choice for this parameter. * @param message the message to describe the earning. Can contain formatting parameters like %s or %d as * defined by {@link String#format(String, Object...)} * @param parameters Contains the parameters used to format the given message */ public void addWarning(Position pos, String message, Object... parameters) { getProblemCollector().add(ParseError.warning(pos, String.format(message, parameters))); }
/** * Throws a {@link ParseException} if an error occurred while parsing the input. * <p> * All warnings which occurred will be ignored. * * @throws ParseException if an error occurred while parsing. */ public void throwOnError() throws ParseException { for (ParseError e : getProblemCollector()) { if (e.getSeverity() == ParseError.Severity.ERROR) { throw ParseException.create(getProblemCollector()); } } } }
/** * Adds a warning to the internal problem collector. * <p> * A warning indicates an anomaly which might lead to an error but still, the parser can continue to complete its * work. * * @param pos the position of the warning. Note that {@link Token} implements {@link Position}. * Therefore the current token is often a good choice for this parameter. * @param message the message to describe the earning. Can contain formatting parameters like %s or %d as * defined by {@link String#format(String, Object...)} * @param parameters Contains the parameters used to format the given message */ public void addWarning(Position pos, String message, Object... parameters) { getProblemCollector().add(ParseError.warning(pos, String.format(message, parameters))); }
/** * Throws a {@link ParseException} if an error occurred while parsing the input. * <p> * All warnings which occurred will be ignored. * * @throws ParseException if an error occurred while parsing. */ public void throwOnError() throws ParseException { for (ParseError e : getProblemCollector()) { if (e.getSeverity() == ParseError.Severity.ERROR) { throw ParseException.create(getProblemCollector()); } } } }
/** * Adds a parse error to the internal problem collector. * <p> * It is preferred to collect as much errors as possible and then fail with an exception instead of failing * at the first problem. Often syntax errors can be worked out by the parser and we can report a set of * errors at once. * * @param pos the position of the error. Note that {@link Token} implements {@link Position}. Therefore the * current token is often a good choice for this parameter. * @param message the message to describe the error. Can contain formatting parameters like %s or %d as defined * by {@link String#format(String, Object...)} * @param parameters Contains the parameters used to format the given message */ public void addError(Position pos, String message, Object... parameters) { getProblemCollector().add(ParseError.error(pos, String.format(message, parameters))); }
/** * Creates a new error for the given position with the given message. * <p> * If no position is available {@link Position#UNKNOWN} can be used * * @param pos the position where the error occurred * @param msg the message explaining the error * @return a new ParseError containing the error */ public static ParseError error(Position pos, String msg) { String message = msg; if (pos.getLine() > 0) { message = String.format("%3d:%2d: %s", pos.getLine(), pos.getPos(), msg); } return new ParseError(pos, message, Severity.ERROR); }
/** * Creates a new exception based on the list of errors. * * @param errors the errors which occurred while processing the user input * @return a new ParseException which can be thrown */ public static ParseException create(List<ParseError> errors) { if (errors.size() == 1) { return new ParseException(errors.get(0).getMessage(), errors); } else if (errors.size() > 1) { return new ParseException(String.format("%d errors occured. First: %s", errors.size(), errors.get(0).getMessage()), errors); } else { return new ParseException("An unknown error occured", errors); } }
@Override protected Char fetch() { try { int character = input.read(); if (character == -1) { return null; } if (character == '\n') { line++; pos = 0; } pos++; return new Char((char) character, line, pos); } catch (IOException e) { problemCollector.add(ParseError.error(new Char('\0', line, pos), e.getMessage())); return null; } }
/** * Creates a new error for the given position with the given message. * <p> * If no position is available {@link Position#UNKNOWN} can be used * * @param pos the position where the error occurred * @param msg the message explaining the error * @return a new ParseError containing the error */ public static ParseError error(Position pos, String msg) { String message = msg; if (pos.getLine() > 0) { message = String.format("%3d:%2d: %s", pos.getLine(), pos.getPos(), msg); } return new ParseError(pos, message, Severity.ERROR); }
@Override protected Char fetch() { try { int character = input.read(); if (character == -1) { return null; } if (character == '\n') { line++; pos = 0; } pos++; return new Char((char) character, line, pos); } catch (IOException e) { problemCollector.add(ParseError.error(new Char('\0', line, pos), e.getMessage())); return null; } }
/** * Creates a new warning for the given position with the given message. * <p> * If no position is available {@link Position#UNKNOWN} can be used * * @param pos the position where the warning occurred * @param msg the message explaining the warning * @return a new ParseError containing the warning */ public static ParseError warning(Position pos, String msg) { String message = msg; if (pos.getLine() > 0) { message = String.format("%3d:%2d: %s", pos.getLine(), pos.getPos(), msg); } return new ParseError(pos, message, Severity.WARNING); }
/** * Checks if we're looking at an end of block comment */ protected void skipBlockComment() { while (!input.current().isEndOfInput()) { if (isAtEndOfBlockComment()) { return; } input.consume(); } problemCollector.add(ParseError.error(input.current(), "Premature end of block comment")); }
/** * Checks if we're looking at an end of block comment */ protected void skipBlockComment() { while (!input.current().isEndOfInput()) { if (isAtEndOfBlockComment()) { return; } input.consume(); } problemCollector.add(ParseError.error(input.current(), "Premature end of block comment")); }
/** * Parses the expression in <tt>input</tt> * * @return the parsed expression * @throws ParseException if the expression contains one or more errors */ protected Expression parse() throws ParseException { Expression result = expression().simplify(); if (tokenizer.current().isNotEnd()) { Token token = tokenizer.consume(); errors.add(ParseError.error(token, String.format("Unexpected token: '%s'. Expected an expression.", token.getSource()))); } if (!errors.isEmpty()) { throw ParseException.create(errors); } return result; }
/** * Parses the expression in <tt>input</tt> * * @return the parsed expression * @throws ParseException if the expression contains one or more errors */ protected Expression parse() throws ParseException { Expression result = expression().simplify(); if (tokenizer.current().isNotEnd()) { Token token = tokenizer.consume(); errors.add(ParseError.error(token, String.format("Unexpected token: '%s'. Expected an expression.", token.getSource()))); } if (!errors.isEmpty()) { throw ParseException.create(errors); } return result; }
/** * Signals that the given token is expected. * <p> * If the current input is pointing at the specified token, it will be consumed. If not, an error will be added * to the error list and the input remains unchanged. * * @param type the type of the expected token * @param trigger the trigger of the expected token */ protected void expect(Token.TokenType type, String trigger) { if (tokenizer.current().matches(type, trigger)) { tokenizer.consume(); } else { errors.add(ParseError.error(tokenizer.current(), String.format("Unexpected token '%s'. Expected: '%s'", tokenizer.current().getSource(), trigger))); } } }
/** * Signals that the given token is expected. * <p> * If the current input is pointing at the specified token, it will be consumed. If not, an error will be added * to the error list and the input remains unchanged. * * @param type the type of the expected token * @param trigger the trigger of the expected token */ protected void expect(Token.TokenType type, String trigger) { if (tokenizer.current().matches(type, trigger)) { tokenizer.consume(); } else { errors.add(ParseError.error(tokenizer.current(), String.format("Unexpected token '%s'. Expected: '%s'", tokenizer.current().getSource(), trigger))); } } }