Package info.bliki.wiki.template.expr

Source Code of info.bliki.wiki.template.expr.Parser

package info.bliki.wiki.template.expr;

import info.bliki.wiki.template.expr.ast.ASTNode;
import info.bliki.wiki.template.expr.ast.IParserFactory;
import info.bliki.wiki.template.expr.ast.NumberNode;
import info.bliki.wiki.template.expr.operator.ASTNodeFactory;
import info.bliki.wiki.template.expr.operator.InfixOperator;
import info.bliki.wiki.template.expr.operator.Operator;
import info.bliki.wiki.template.expr.operator.PostfixOperator;
import info.bliki.wiki.template.expr.operator.PrefixOperator;

/**
* Create an expression of the <code>ASTNode</code> class-hierarchy from a
* math formulas string representation
*
* See <a
* href="http://en.wikipedia.org/wiki/Operator-precedence_parser">Operator-precedence
* parser</a> for the idea, how to parse the operators depending on their
* precedence.
*/
public class Parser extends Scanner {
  /**
   * Use '('...')' as brackets for arguments
   */
  boolean fRelaxedSyntax;

  public Parser() {
    this(ASTNodeFactory.MMA_STYLE_FACTORY, false);
  }

  public Parser(final boolean relaxedSyntax) throws SyntaxError {
    this(ASTNodeFactory.MMA_STYLE_FACTORY, relaxedSyntax);
  }

  public Parser(IParserFactory factory, final boolean relaxedSyntax) throws SyntaxError {
    super();
    fRelaxedSyntax = relaxedSyntax;
    fFactory = factory;
  }

  public void setFactory(final IParserFactory factory) {
    this.fFactory = factory;
  }

  public IParserFactory getFactory() {
    return fFactory;
  }

  /**
   * Determine the current PrefixOperator
   *
   * @return <code>null</code> if no prefix operator could be determined
   */
  private PrefixOperator determinePrefixOperator() {
    Operator oper = null;
    for (int i = 0; i < fOperList.size(); i++) {
      oper = (Operator) fOperList.get(i);
      if (oper instanceof PrefixOperator) {
        return (PrefixOperator) oper;
      }
    }
    return null;
  }

  /**
   * Determine the current PostfixOperator
   *
   * @return <code>null</code> if no postfix operator could be determined
   */
  private PostfixOperator determinePostfixOperator() {
    Operator oper = null;
    for (int i = 0; i < fOperList.size(); i++) {
      oper = (Operator) fOperList.get(i);
      if (oper instanceof PostfixOperator) {
        return (PostfixOperator) oper;
      }
    }
    return null;
  }

  /**
   * Determine the current BinaryOperator
   *
   * @return <code>null</code> if no binary operator could be determined
   */
  private InfixOperator determineBinaryOperator() {
    Operator oper = null;
    for (int i = 0; i < fOperList.size(); i++) {
      oper = (Operator) fOperList.get(i);
      if (oper instanceof InfixOperator) {
        return (InfixOperator) oper;
      }
    }
    return null;
  }

  private ASTNode parsePrimary() {
    if (fToken == TT_OPERATOR) {
      final Operator oper = determinePrefixOperator();

      if (oper instanceof PrefixOperator) {
        getNextToken();
        final ASTNode temp = parseLookaheadOperator(oper.getPrecedence());
        if (oper.getFunctionName().equals("PreMinus")) {
          // special cases for negative numbers
          if (temp instanceof NumberNode) {
            ((NumberNode) temp).toggleSign();
            return temp;
          }
        }
        return ((PrefixOperator) oper).createFunction(fFactory, temp);
      }
      throwSyntaxError("Operator: " + fOperatorString + " is no prefix operator.");

    }
    return getFactor();
  }

  private ASTNode parseLookaheadOperator(final int min_precedence) {
    ASTNode rhs = parsePrimary();
    Operator operLookahead;
    InfixOperator binOper;
    while (true) {
      final int lookahead = fToken;
      if (lookahead != TT_OPERATOR) {
        break;
      }
      operLookahead = determineBinaryOperator();
      if (operLookahead instanceof InfixOperator) {
        binOper = (InfixOperator) operLookahead;
        if (binOper.getPrecedence() > min_precedence) {
          rhs = parseOperators(rhs, operLookahead.getPrecedence());
          continue;
        } else if ((binOper.getPrecedence() == min_precedence) && (binOper.getGrouping() == InfixOperator.RIGHT_ASSOCIATIVE)) {
          rhs = parseOperators(rhs, operLookahead.getPrecedence());
          continue;
        }
      } else {
        operLookahead = determinePostfixOperator();

        if (operLookahead instanceof PostfixOperator) {
          if (operLookahead.getPrecedence() > min_precedence) {
            getNextToken();
            rhs = ((PostfixOperator) operLookahead).createFunction(fFactory, rhs);
            continue;
          }
        }
      }
      break;
    }
    return rhs;
  }

  /**
   * See <a
   * href="http://en.wikipedia.org/wiki/Operator-precedence_parser">Operator-precedence
   * parser</a> for the idea, how to parse the operators depending on their
   * precedence.
   *
   * @param lhs
   *          the already parsed left-hand-side of the operator
   * @param min_precedence
   * @return
   */
  private ASTNode parseOperators(ASTNode lhs, final int min_precedence) {
    ASTNode rhs = null;
    Operator oper;
    while (true) {
      if (fToken != TT_OPERATOR) {
        break;
      }
      oper = determineBinaryOperator();

      if (oper instanceof InfixOperator) {
        if (oper.getPrecedence() >= min_precedence) {
          getNextToken();
          rhs = parseLookaheadOperator(oper.getPrecedence());
          lhs = ((InfixOperator) oper).createFunction(fFactory, lhs, rhs);
          // lhs = parseArguments(lhs);
          continue;
        }
      } else {
        oper = determinePostfixOperator();

        if (oper instanceof PostfixOperator) {
          getNextToken();
          lhs = ((PostfixOperator) oper).createFunction(fFactory, lhs);
          // lhs = parseArguments(lhs);
          continue;
        }
        throwSyntaxError("Operator: " + fOperatorString + " is no infix or postfix operator.");
      }
      // }
      break;
    }
    return lhs;
  }

  /**
   * Parse the given <code>expression</code> String into an ASTNode.
   *
   * @param expression
   *          a formula string which should be parsed.
   * @return the parsed ASTNode representation of the given formula string
   * @throws SyntaxError
   */
  public ASTNode parse(final String expression) throws SyntaxError {
    initialize(expression);
    final ASTNode temp = parseOperators(parsePrimary(), 0);
    if (fToken != TT_EOF) {
      if (fToken == TT_PRECEDENCE_CLOSE) {
        throwSyntaxError("Too many closing ')'; End-of-file not reached.");
      }

      if (fOperatorString=="E") {
        fCurrentPosition--;
      }
      throwSyntaxError("End-of-file not reached.");
    }

    return temp;
  }

  /**
   * Method Declaration.
   *
   * @return
   * @see
   */
  private ASTNode getNumber(final boolean negative) throws SyntaxError {
    ASTNode temp = null;
    final Object[] result = getNumberString();
    String number = (String) result[0];
    final int numFormat = ((Integer) result[1]).intValue();
    try {
      if (negative) {
        number = '-' + number;
      }
      if (numFormat < 0) {
        temp = fFactory.createDouble(number);
      } else {
        temp = fFactory.createInteger(number, numFormat);
      }
    } catch (final Throwable e) {
      throwSyntaxError("Number format error: " + number, number.length());
    }
    getNextToken();
    return temp;
  }

  private int getIntegerNumber() throws SyntaxError {
    final Object[] result = getNumberString();
    final String number = (String) result[0];
    final int numFormat = ((Integer) result[1]).intValue();
    int intValue = 0;
    try {
      intValue = Integer.parseInt(number, numFormat);
    } catch (final NumberFormatException e) {
      throwSyntaxError("Number format error (not an int type): " + number, number.length());
    }
    getNextToken();
    return intValue;
  }

  // private ASTNode getString() throws SyntaxError {
  // final StringBuffer ident = getStringBuffer();
  //
  // getNextToken();
  //
  // return fFactory.createString(ident);
  // }

  private ASTNode getFactor() throws SyntaxError {
    ASTNode temp;

    if (fToken == TT_CONSTANT) {
      temp = fFactory.createSymbol(fOperatorString);
      getNextToken();
      return temp;
    }
    if (fToken == TT_DIGIT) {
      return getNumber(false);
    }
    if (fToken == TT_PRECEDENCE_OPEN) {
      getNextToken();

      temp = parseOperators(parsePrimary(), 0);

      if (fToken != TT_PRECEDENCE_CLOSE) {
        throwSyntaxError("\')\' expected.");
      }

      getNextToken();

      return temp;
    }

    // if (fToken == TT_STRING) {
    // return getString();
    // }

    switch (fToken) {

    case TT_PRECEDENCE_CLOSE:
      throwSyntaxError("Too much open ) in factor.");
      break;
    }

    throwSyntaxError("Error in factor at character: '" + fCurrentChar + "' (" + fToken + ")");
    return null;
  }

}
TOP

Related Classes of info.bliki.wiki.template.expr.Parser

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.