示例#1
0
  private Identifiable parseFunctionCall(IdentifierToken identifierToken) throws ParserException {
    consumeCharacter('(');

    try {
      if (peek().id() == ')') {
        ++position;
        return Functions.getFunction(identifierToken.getPosition(), identifierToken.value);
      }

      List<RValue> args = new ArrayList<RValue>();

      loop:
      while (true) {
        args.add(parseExpression(false));

        final Token current = peek();
        ++position;

        switch (current.id()) {
          case ',':
            continue;

          case ')':
            break loop;

          default:
            throw new ParserException(current.getPosition(), "Unmatched opening bracket");
        }
      }

      return Functions.getFunction(
          identifierToken.getPosition(),
          identifierToken.value,
          args.toArray(new RValue[args.size()]));
    } catch (NoSuchMethodException e) {
      throw new ParserException(
          identifierToken.getPosition(), "Function '" + identifierToken.value + "' not found", e);
    }
  }
示例#2
0
  private RValue parseStatements(boolean singleStatement) throws ParserException {
    List<RValue> statements = new ArrayList<RValue>();
    loop:
    while (true) {
      if (position >= tokens.size()) {
        break;
      }

      final Token current = peek();
      switch (current.id()) {
        case '{':
          consumeCharacter('{');

          statements.add(parseStatements(false));

          consumeCharacter('}');

          if (singleStatement) {
            break loop;
          }
          break;

        case '}':
          break loop;

        case 'k':
          final String keyword = ((KeywordToken) current).value;
          switch (keyword.charAt(0)) {
            case 'i':
              { // if
                ++position;
                final RValue condition = parseBracket();
                final RValue truePart = parseStatements(true);
                final RValue falsePart;

                if (hasKeyword("else")) {
                  ++position;
                  falsePart = parseStatements(true);
                } else {
                  falsePart = null;
                }

                statements.add(
                    new Conditional(current.getPosition(), condition, truePart, falsePart));
                break;
              }

            case 'w':
              { // while
                ++position;
                final RValue condition = parseBracket();
                final RValue body = parseStatements(true);

                statements.add(new While(current.getPosition(), condition, body, false));
                break;
              }

            case 'd':
              { // do
                ++position;
                final RValue body = parseStatements(true);

                consumeKeyword("while");

                final RValue condition = parseBracket();

                statements.add(new While(current.getPosition(), condition, body, true));
                break;
              }

            case 'f':
              { // for
                ++position;
                consumeCharacter('(');
                int oldPosition = position;
                final RValue init = parseExpression(true);
                // if ((init instanceof LValue) && )
                if (peek().id() == ';') {
                  ++position;
                  final RValue condition = parseExpression(true);
                  consumeCharacter(';');
                  final RValue increment = parseExpression(true);
                  consumeCharacter(')');
                  final RValue body = parseStatements(true);

                  statements.add(new For(current.getPosition(), init, condition, increment, body));
                } else {
                  position = oldPosition;

                  final Token variableToken = peek();
                  if (!(variableToken instanceof IdentifierToken)) {
                    throw new ParserException(variableToken.getPosition(), "Expected identifier");
                  }

                  // In theory, I should have to create non-existant variables here.
                  // However, the java-for parsing attempt further up already takes care of that :)
                  RValue variable = variables.get(((IdentifierToken) variableToken).value);
                  if (!(variable instanceof LValue)) {
                    throw new ParserException(variableToken.getPosition(), "Expected variable");
                  }

                  ++position;

                  final Token equalsToken = peek();
                  if (!(equalsToken instanceof OperatorToken)
                      || !((OperatorToken) equalsToken).operator.equals("=")) {
                    throw new ParserException(
                        variableToken.getPosition(), "Expected '=' or a term and ';'");
                  }
                  ++position;

                  final RValue first = parseExpression(true);
                  consumeCharacter(',');
                  final RValue last = parseExpression(true);
                  consumeCharacter(')');
                  final RValue body = parseStatements(true);

                  statements.add(
                      new SimpleFor(current.getPosition(), (LValue) variable, first, last, body));
                }
                break;
              }

            case 'b': // break
              ++position;
              statements.add(new Break(current.getPosition(), false));
              break;

            case 'c': // continue
              ++position;
              statements.add(new Break(current.getPosition(), true));
              break;

            case 'r': // return
              ++position;
              statements.add(new Return(current.getPosition(), parseExpression(true)));

              if (peek().id() == ';') {
                ++position;
                break;
              } else {
                break loop;
              }

            default:
              throw new ParserException(
                  current.getPosition(), "Unimplemented keyword '" + keyword + "'");
          }

          if (singleStatement) {
            break loop;
          }
          break;

        default:
          statements.add(parseExpression(true));

          if (peek().id() == ';') {
            ++position;
            if (singleStatement) {
              break loop;
            }
            break;
          } else {
            break loop;
          }
      }
    }

    switch (statements.size()) {
      case 0:
        if (singleStatement) {
          throw new ParserException(peek().getPosition(), "Statement expected.");
        } else {
          return new Sequence(peek().getPosition());
        }

      case 1:
        return statements.get(0);

      default:
        return new Sequence(
            peek().getPosition(), statements.toArray(new RValue[statements.size()]));
    }
  }
示例#3
0
 private void assertCharacter(char character) throws ParserException {
   final Token next = peek();
   if (next.id() != character) {
     throw new ParserException(next.getPosition(), "Expected '" + character + "'");
   }
 }
示例#4
0
  private final RValue parseExpression(boolean canBeEmpty) throws ParserException {
    LinkedList<Identifiable> halfProcessed = new LinkedList<Identifiable>();

    // process brackets, numbers, functions, variables and detect prefix operators
    boolean expressionStart = true;
    loop:
    while (position < tokens.size()) {
      final Token current = peek();

      switch (current.id()) {
        case '0':
          halfProcessed.add(new Constant(current.getPosition(), ((NumberToken) current).value));
          ++position;
          expressionStart = false;
          break;

        case 'i':
          final IdentifierToken identifierToken = (IdentifierToken) current;
          ++position;

          final Token next = peek();
          if (next.id() == '(') {
            halfProcessed.add(parseFunctionCall(identifierToken));
          } else {
            RValue variable = variables.get(identifierToken.value);
            if (variable == null) {
              if (next instanceof OperatorToken && ((OperatorToken) next).operator.equals("=")) {
                // Ugly hack to make temporary variables work while not sacrificing error reporting.
                variables.put(identifierToken.value, variable = new Variable(0));
              } else {
                throw new ParserException(
                    current.getPosition(), "Variable '" + identifierToken.value + "' not found");
              }
            }
            halfProcessed.add(variable);
          }
          expressionStart = false;
          break;

        case '(':
          halfProcessed.add(parseBracket());
          expressionStart = false;
          break;

        case ',':
        case ')':
        case '}':
        case ';':
          break loop;

        case 'o':
          if (expressionStart) {
            // Preprocess prefix operators into unary operators
            halfProcessed.add(new UnaryOperator((OperatorToken) current));
          } else {
            halfProcessed.add(current);
          }
          ++position;
          expressionStart = true;
          break;

        default:
          halfProcessed.add(current);
          ++position;
          expressionStart = false;
          break;
      }
    }

    if (halfProcessed.isEmpty() && canBeEmpty) {
      return new Sequence(peek().getPosition());
    }

    return ParserProcessors.processExpression(halfProcessed);
  }