Пример #1
0
  /**
   * Parse a term.
   *
   * @param token the initial token.
   * @return the root of the generated parse subtree.
   * @throws Exception if an error occurred.
   */
  private ICodeNode parseTerm(Token token) throws Exception {
    // Parse a factor and makes its node the root node.
    ICodeNode rootNode = parseFactor(token);
    TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType;

    token = currentToken();
    TokenType tokenType = token.getType();

    // Loop over multiplicative operators.
    while (MULT_OPS.contains(tokenType)) {
      TokenType operator = tokenType;

      // Create a new operator node and adopt the current tree as its first child.
      ICodeNodeType nodeType = MULT_OPS_OPS_MAP.get(operator);
      ICodeNode opNode = ICodeFactory.createICodeNode(nodeType);
      opNode.addChild(rootNode);

      token = nextToken(); // consume the operator

      // Parse another factor.
      // The operator node adopts the term's tree as its secomd child.
      ICodeNode factorNode = parseFactor(token);
      opNode.addChild(factorNode);
      TypeSpec factorType =
          factorNode != null ? factorNode.getTypeSpec() : Predefined.undefinedType;
      // The operator node becomes the new root node.
      rootNode = opNode;

      // Determine the result type.
      switch ((PascalTokenType) operator) {
        case STAR:
          {
            // Both operands integer ==> integer result.
            if (TypeChecker.areBothInteger(resultType, factorType)) {
              resultType = Predefined.integerType;
            }

            // Both real operands or one real and one integer operand
            // ==> real result.
            else if (TypeChecker.isAtLeastOneReal(resultType, factorType)) {
              resultType = Predefined.realType;
            } else {
              errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            }

            break;
          }

        case SLASH:
          {
            // All integer and real operand combinations
            // ==> real result.
            if (TypeChecker.areBothInteger(resultType, factorType)
                || TypeChecker.isAtLeastOneReal(resultType, factorType)) {
              resultType = Predefined.realType;
            } else {
              errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            }

            break;
          }

        case DIV:
        case MOD:
          {
            // Both operands integer ==> integer result.
            if (TypeChecker.areBothInteger(resultType, factorType)) {
              resultType = Predefined.integerType;
            } else {
              errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            }

            break;
          }

        case AND:
          {
            // Both operands boolean ==> boolean result.
            if (TypeChecker.areBothBoolean(resultType, factorType)) {
              resultType = Predefined.booleanType;
            } else {
              errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            }

            break;
          }
      }

      // The operator node becomes the new root node.
      rootNode.setTypeSpec(resultType);

      token = currentToken();
      tokenType = token.getType();
    }
    return rootNode;
  }
Пример #2
0
  /**
   * Parse a simple expression.
   *
   * @param token the initial token.
   * @return the root of the generated parse subtree.
   * @throws Exception if an error occurred.
   */
  private ICodeNode parseSimpleExpression(Token token) throws Exception {
    Token signToken = null;
    TokenType signType = null; // type of leading sign (if any)

    // Look for a leading + or - sign
    TokenType tokenType = token.getType();
    if ((tokenType == PLUS) || (tokenType == MINUS)) {
      signType = tokenType;
      signToken = token;
      token = nextToken(); // consume the + or -
    }

    // Parse a term and make the root of its tree the root node.
    ICodeNode rootNode = parseTerm(token);
    TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType;

    // Type check: Leading sign.
    if ((signType != null) && (!TypeChecker.isIntegerOrReal(resultType)))
      errorHandler.flag(signToken, INCOMPATIBLE_TYPES, this);

    // Was there a leading - sign?
    if (signType == MINUS) {
      // Create a NEGATE node and adopt the current tree as its child.
      // The NEGATE node becomes the new root node.
      ICodeNode negateNode = ICodeFactory.createICodeNode(NEGATE);
      negateNode.addChild(rootNode);
      negateNode.setTypeSpec(rootNode.getTypeSpec());
      rootNode = negateNode;
    }

    token = currentToken();
    tokenType = token.getType();

    // Loop over additive operators.
    while (ADD_OPS.contains(tokenType)) {
      TokenType operator = tokenType;

      // Create a new operator node and adopt the current tree as its first child.
      ICodeNodeType nodeType = ADD_OPS_OPS_MAP.get(operator);
      ICodeNode opNode = ICodeFactory.createICodeNode(nodeType);
      opNode.addChild(rootNode);

      token = nextToken(); // consume the operator

      // Parse another term.
      // The operator node adopts the term's tree as its second child.
      ICodeNode termNode = parseTerm(token);
      opNode.addChild(termNode);
      TypeSpec termType = termNode != null ? termNode.getTypeSpec() : Predefined.undefinedType;

      // The operator node becomes the new root node.
      rootNode = opNode;

      switch ((PascalTokenType) operator) {
        case PLUS:
        case MINUS:
          {
            // Both operands integer => integer result.
            if (TypeChecker.areBothInteger(resultType, termType))
              resultType = Predefined.integerType;

            // Both real operands or one real and one integer operand => real result.
            else if (TypeChecker.isAtLeastOneReal(resultType, termType))
              resultType = Predefined.realType;
            else errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            break;
          }

        case OR:
          {
            // Both operands boolean ==> boolean result.
            if (TypeChecker.areBothBoolean(resultType, termType))
              resultType = Predefined.booleanType;
            else errorHandler.flag(token, INCOMPATIBLE_TYPES, this);
            break;
          }
      }

      rootNode.setTypeSpec(resultType);
      token = currentToken();
      tokenType = token.getType();
    }
    return rootNode;
  }