Package org.drools.lang

Source Code of org.drools.lang.DroolsParserExceptionFactory

package org.drools.lang;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.Map.Entry;

import org.antlr.runtime.EarlyExitException;
import org.antlr.runtime.FailedPredicateException;
import org.antlr.runtime.MismatchedNotSetException;
import org.antlr.runtime.MismatchedSetException;
import org.antlr.runtime.MismatchedTokenException;
import org.antlr.runtime.MismatchedTreeNodeException;
import org.antlr.runtime.NoViableAltException;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.drools.compiler.DroolsParserException;

/**
* Helper class that generates DroolsParserException with user friendly error
* messages.
*
* @author porcelli
* @see DroolsParserException
*/
public class DroolsParserExceptionFactory {
  public final static String MISMATCHED_TOKEN_MESSAGE_COMPLETE = "Line %1$d:%2$d mismatched input '%3$s' expecting '%4$s'%5$s";
  public final static String MISMATCHED_TOKEN_MESSAGE_PART = "Line %1$d:%2$d mismatched input '%3$s'%4$s";
  public final static String MISMATCHED_TREE_NODE_MESSAGE_COMPLETE = "Line %1$d:%2$d mismatched tree node '%3$s' expecting '%4$s'%5$s";
  public final static String MISMATCHED_TREE_NODE_MESSAGE_PART = "Line %1$d:%2$d mismatched tree node '%3$s'%4$s";
  public final static String NO_VIABLE_ALT_MESSAGE = "Line %1$d:%2$d no viable alternative at input '%3$s'%4$s";
  public final static String EARLY_EXIT_MESSAGE = "Line %1$d:%2$d required (...)+ loop did not match anything at input '%3$s'%4$s";
  public final static String MISMATCHED_SET_MESSAGE = "Line %1$d:%2$d mismatched input '%3$' expecting set '%4$s'%5$s.";
  public final static String MISMATCHED_NOT_SET_MESSAGE = "Line %1$d:%2$d mismatched input '%3$' expecting set '%4$s'%5$s";
  public final static String FAILED_PREDICATE_MESSAGE = "Line %1$d:%2$d rule '%3$s' failed predicate: {%4$s}?%5$s";
  public final static String TRAILING_SEMI_COLON_NOT_ALLOWED_MESSAGE = "Line %1$d:%2$d trailing semi-colon not allowed%3$s";
  public final static String PARSER_LOCATION_MESSAGE_COMPLETE = " in %1$s %2$s";
  public final static String PARSER_LOCATION_MESSAGE_PART = " in %1$s";

  private String[] tokenNames = null;
  private Stack<Map<DroolsParaphraseTypes, String>> paraphrases = null;

  /**
   * DroolsParserErrorMessages constructor.
   *
   * @param tokenNames
   *            tokenNames generated by ANTLR
   * @param paraphrases
   *            paraphrases parser structure
   */
  public DroolsParserExceptionFactory(String[] tokenNames,
      Stack<Map<DroolsParaphraseTypes, String>> paraphrases) {
    this.tokenNames = tokenNames;
    this.paraphrases = paraphrases;
  }

  /**
   * This method creates a DroolsParserException for trailing semicolon
   * exception, full of information.
   *
   * @param line
   *            line number
   * @param column
   *            column position
   * @param offset
   *            char offset
   * @return DroolsParserException filled.
   */
  public DroolsParserException createTrailingSemicolonException(int line,
      int column, int offset) {
    String message = String
        .format(
            DroolsParserExceptionFactory.TRAILING_SEMI_COLON_NOT_ALLOWED_MESSAGE,
            line, column, formatParserLocation());

    return new DroolsParserException("ERR 108", message, line, column,
        offset, null);
  }

  /**
   * This method creates a DroolsParserException full of information.
   *
   * @param e
   *            original exception
   * @return DroolsParserException filled.
   */
  public DroolsParserException createDroolsException(RecognitionException e) {
    List<String> codeAndMessage = createErrorMessage(e);
    return new DroolsParserException(codeAndMessage.get(1), codeAndMessage
        .get(0), e.line, e.charPositionInLine, e.index, e);
  }

  /**
   * This will take a RecognitionException, and create a sensible error
   * message out of it
   */
  private List<String> createErrorMessage(RecognitionException e) {
    List<String> codeAndMessage = new ArrayList<String>(2);
    String message = "";
    if (e instanceof MismatchedTokenException) {
      MismatchedTokenException mte = (MismatchedTokenException) e;
      if (mte.expecting >= 0 && mte.expecting < tokenNames.length) {
        message = String
            .format(
                DroolsParserExceptionFactory.MISMATCHED_TOKEN_MESSAGE_COMPLETE,
                e.line, e.charPositionInLine,
                getBetterToken(e.token),
                getBetterToken(mte.expecting),
                formatParserLocation());
        codeAndMessage.add(message);
        codeAndMessage.add("ERR 101");
      } else {
        message = String
            .format(
                DroolsParserExceptionFactory.MISMATCHED_TOKEN_MESSAGE_PART,
                e.line, e.charPositionInLine,
                getBetterToken(e.token), formatParserLocation());
        codeAndMessage.add(message);
        codeAndMessage.add("ERR 101");
      }
    } else if (e instanceof MismatchedTreeNodeException) {
      MismatchedTreeNodeException mtne = (MismatchedTreeNodeException) e;
      if (mtne.expecting >= 0 && mtne.expecting < tokenNames.length) {
        message = String
            .format(
                DroolsParserExceptionFactory.MISMATCHED_TREE_NODE_MESSAGE_COMPLETE,
                e.line, e.charPositionInLine,
                getBetterToken(e.token),
                getBetterToken(mtne.expecting),
                formatParserLocation());
        codeAndMessage.add(message);
        codeAndMessage.add("ERR 102");
      } else {
        message = String
            .format(
                DroolsParserExceptionFactory.MISMATCHED_TREE_NODE_MESSAGE_PART,
                e.line, e.charPositionInLine,
                getBetterToken(e.token), formatParserLocation());
        codeAndMessage.add(message);
        codeAndMessage.add("ERR 102");
      }
    } else if (e instanceof NoViableAltException) {
      // NoViableAltException nvae = (NoViableAltException) e;
      message = String.format(
          DroolsParserExceptionFactory.NO_VIABLE_ALT_MESSAGE, e.line,
          e.charPositionInLine, getBetterToken(e.token),
          formatParserLocation());
      codeAndMessage.add(message);
      codeAndMessage.add("ERR 103");
    } else if (e instanceof EarlyExitException) {
      // EarlyExitException eee = (EarlyExitException) e;
      message = String.format(
          DroolsParserExceptionFactory.EARLY_EXIT_MESSAGE, e.line,
          e.charPositionInLine, getBetterToken(e.token),
          formatParserLocation());
      codeAndMessage.add(message);
      codeAndMessage.add("ERR 104");
    } else if (e instanceof MismatchedSetException) {
      MismatchedSetException mse = (MismatchedSetException) e;
      message = String.format(
          DroolsParserExceptionFactory.MISMATCHED_SET_MESSAGE,
          e.line, e.charPositionInLine, getBetterToken(e.token),
          mse.expecting, formatParserLocation());
      codeAndMessage.add(message);
      codeAndMessage.add("ERR 105");
    } else if (e instanceof MismatchedNotSetException) {
      MismatchedNotSetException mse = (MismatchedNotSetException) e;
      message = String.format(
          DroolsParserExceptionFactory.MISMATCHED_NOT_SET_MESSAGE,
          e.line, e.charPositionInLine, getBetterToken(e.token),
          mse.expecting, formatParserLocation());
      codeAndMessage.add(message);
      codeAndMessage.add("ERR 106");
    } else if (e instanceof FailedPredicateException) {
      FailedPredicateException fpe = (FailedPredicateException) e;
      message = String.format(
          DroolsParserExceptionFactory.FAILED_PREDICATE_MESSAGE,
          e.line, e.charPositionInLine, fpe.ruleName,
          fpe.predicateText, formatParserLocation());
      codeAndMessage.add(message);
      codeAndMessage.add("ERR 107");
    }
    if (codeAndMessage.get(0).length() == 0) {
      codeAndMessage.add("?????");
    }
    return codeAndMessage;
  }

  /**
   * This will take Paraphrases stack, and create a sensible location
   */
  private String formatParserLocation() {
    StringBuilder sb = new StringBuilder();
    for (Map<DroolsParaphraseTypes, String> map : paraphrases) {
      for (Entry<DroolsParaphraseTypes, String> activeEntry : map
          .entrySet()) {
        if (activeEntry.getValue().length() == 0) {
          sb.append(String.format(PARSER_LOCATION_MESSAGE_PART,
              getLocationName(activeEntry.getKey())));
        } else {
          sb.append(String.format(PARSER_LOCATION_MESSAGE_COMPLETE,
              getLocationName(activeEntry.getKey()), activeEntry
                  .getValue()));
        }
      }
    }
    return sb.toString();
  }

  /**
   * Returns a string based on Paraphrase Type
   *
   * @param type
   *            Paraphrase Type
   * @return a string representing the
   */
  private String getLocationName(DroolsParaphraseTypes type) {
    switch (type) {
    case PACKAGE:
      return "package";
    case IMPORT:
      return "import";
    case FUNCTION_IMPORT:
      return "function import";
    case GLOBAL:
      return "global";
    case FUNCTION:
      return "function";
    case QUERY:
      return "query";
    case TEMPLATE:
      return "template";
    case RULE:
      return "rule";
    case RULE_ATTRIBUTE:
      return "rule attribute";
    case PATTERN:
      return "pattern";
    default:
      return "";
    }
  }

  /**
   * Helper method that creates a user friendly token definition
   *
   * @param token
   *            token
   * @return user friendly token definition
   */
  private String getBetterToken(Token token) {
    return getBetterToken(token.getType(), token.getText());
  }

  /**
   * Helper method that creates a user friendly token definition
   *
   * @param tokenType
   *            token type
   * @return user friendly token definition
   */
  private String getBetterToken(int tokenType) {
    return getBetterToken(tokenType, null);
  }

  /**
   * Helper method that creates a user friendly token definition
   *
   * @param tokenType
   *            token type
   * @param defaultValue
   *            default value for identifier token, may be null
   * @return user friendly token definition
   */
  private String getBetterToken(int tokenType, String defaultValue) {
    switch (tokenType) {
    case DRLLexer.INT:
      return defaultValue == null ? "int" : defaultValue;
    case DRLLexer.FLOAT:
      return defaultValue == null ? "float" : defaultValue;
    case DRLLexer.STRING:
      return defaultValue == null ? "string" : defaultValue;
    case DRLLexer.BOOL:
      return defaultValue == null ? "boolean" : defaultValue;
    case DRLLexer.NULL:
      return "null";
    case DRLLexer.THEN:
      return "then";
    case DRLLexer.END:
      return "end";
    case DRLLexer.GRAVE_ACCENT:
      return "`";
    case DRLLexer.SEMICOLON:
      return ";";
    case DRLLexer.DOT_STAR:
      return ".*";
    case DRLLexer.COLON:
      return ":";
    case DRLLexer.EQUAL:
      return "==";
    case DRLLexer.NOT_EQUAL:
      return "!=";
    case DRLLexer.GREATER:
      return ">";
    case DRLLexer.GREATER_EQUAL:
      return ">=";
    case DRLLexer.LESS:
      return "<";
    case DRLLexer.LESS_EQUAL:
      return "<=";
    case DRLLexer.ARROW:
      return "->";
    case DRLLexer.ID:
      return defaultValue == null ? "identifier" : defaultValue;
    case DRLLexer.LEFT_PAREN:
      return "(";
    case DRLLexer.RIGHT_PAREN:
      return ")";
    case DRLLexer.LEFT_SQUARE:
      return "[";
    case DRLLexer.RIGHT_SQUARE:
      return "]";
    case DRLLexer.LEFT_CURLY:
      return "{";
    case DRLLexer.RIGHT_CURLY:
      return "}";
    case DRLLexer.COMMA:
      return ",";
    case DRLLexer.DOT:
      return ".";
    case DRLLexer.DOUBLE_AMPER:
      return "&&";
    case DRLLexer.DOUBLE_PIPE:
      return "||";
    case DRLLexer.MISC:
      return defaultValue == null ? "misc" : defaultValue;
    case DRLLexer.EOF:
      return "<eof>";
    default:
      return tokenType > tokenNames.length ? "unknown"
          : tokenNames[tokenType];
    }
  }
}
TOP

Related Classes of org.drools.lang.DroolsParserExceptionFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.