public Expression gen(Context ctx) throws SemanticException {
    Expression res = null;
    Expression srcExpr = null;
    String opname = fOp.getText();

    if (fSrcExpr != null) {
      srcExpr = fSrcExpr.gen(ctx);
      res = gen1(ctx, srcExpr);
    } else {
      // if no source expression is given, it is either a
      // variable or a reference to expression determined by
      // context. In the latter case we use the context as
      // source expression and proceed as if it has been given
      // explicitly.
      if (!fHasParentheses) {
        // variable?
        // (7) check for variable
        Type type = ctx.varTable().lookup(opname);
        if (type != null) res = new ExpVariable(opname, type);
      }

      // do we have a context expression that is implicitly
      // assumed to be the source expression?
      if (res == null) {
        ExprContext ec = ctx.exprContext();
        if (!ec.isEmpty()) {
          // construct source expression
          ExprContext.Entry e = ec.peek();
          srcExpr = new ExpVariable(e.fName, e.fType);
          if (e.fType.isCollection()) fFollowsArrow = true;
          res = gen1(ctx, srcExpr);
        } else
          throw new SemanticException(
              fOp,
              "Undefined " + (fHasParentheses ? "operation" : "variable") + " `" + opname + "'.");
      }
    }

    if (fIsPre) {
      if (!ctx.insidePostCondition())
        throw new SemanticException(fOp, "Modifier @pre is only allowed in postconditions.");
      res.setIsPre();
    }

    if (opname.equals("oclIsNew")) {
      if (!ctx.insidePostCondition())
        throw new SemanticException(fOp, "Operation oclIsNew is only allowed in postconditions.");
    }
    return res;
  }
Exemplo n.º 2
0
  public Expression gen(Context ctx) throws SemanticException {
    String opname = fOp.getText();
    Expression res = null;
    Expression range, expr;

    // check for empty range: do we have a context expression that
    // is implicitly assumed to be the source expression?
    if (fRange != null) range = fRange.gen(ctx);
    else {
      ExprContext ec = ctx.exprContext();
      if (!ec.isEmpty()) {
        // construct source expression
        ExprContext.Entry e = ec.peek();
        range = new ExpVariable(e.fName, e.fType);
      } else throw new SemanticException(fOp, "Need a collection to apply `" + opname + "'.");
    }

    if (!range.type().isCollection())
      throw new SemanticException(
          fOp,
          "Source of `"
              + opname
              + "' expression must be a collection, "
              + "found source expression of type `"
              + range.type()
              + "'.");

    VarDeclList declList = new VarDeclList(true);

    if (fDeclList.isEmpty()) {
      // when there are no explicit var decls, we declare an
      // internal variable with the element type
      ExprContext ec = ctx.exprContext();
      CollectionType ct = (CollectionType) range.type();
      String var = ec.push(ct.elemType());
      expr = fExpr.gen(ctx);
      ec.pop();

      // use the generated element variable
      VarDecl decl = new VarDecl(var, ct.elemType());
      declList.add(decl);
    } else {
      declList = fDeclList.gen(ctx, range);

      // enter declared variable into scope before evaluating
      // the argument expression
      Symtable vars = ctx.varTable();
      vars.enterScope();
      fDeclList.addVariablesToSymtable(vars, declList.varDecl(0).type());
      expr = fExpr.gen(ctx);
      vars.exitScope();
    }

    try {
      Integer id = (Integer) GParser.queryIdentMap.get(opname);
      if (id == null)
        throw new SemanticException(
            fOp, "Internal error: unknown query operation `" + opname + "'.");

      int idval = id.intValue();
      switch (idval) {
        case GParser.Q_SELECT_ID:
        case GParser.Q_COLLECT_ID:
        case GParser.Q_REJECT_ID:
        case GParser.Q_ISUNIQUE_ID:
        case GParser.Q_SORTEDBY_ID:
        case GParser.Q_ANY_ID:
        case GParser.Q_ONE_ID:
          VarDecl decl;
          if (declList.isEmpty()) decl = null;
          else if (declList.size() == 1) decl = declList.varDecl(0);
          else
            throw new SemanticException(
                fOp, "Only one element variable in " + opname + " expression allowed.");
          switch (idval) {
            case GParser.Q_SELECT_ID:
              res = new ExpSelect(decl, range, expr);
              break;
            case GParser.Q_COLLECT_ID:
              res = new ExpCollect(decl, range, expr);
              break;
            case GParser.Q_REJECT_ID:
              res = new ExpReject(decl, range, expr);
              break;
            case GParser.Q_ISUNIQUE_ID:
              res = new ExpIsUnique(decl, range, expr);
              break;
            case GParser.Q_SORTEDBY_ID:
              res = new ExpSortedBy(decl, range, expr);
              break;
            case GParser.Q_ANY_ID:
              res = new ExpAny(decl, range, expr);
              break;
            case GParser.Q_ONE_ID:
              res = new ExpOne(decl, range, expr);
              break;
          }
          break;
        case GParser.Q_EXISTS_ID:
          res = new ExpExists(declList, range, expr);
          break;
        case GParser.Q_FORALL_ID:
          res = new ExpForAll(declList, range, expr);
          break;
        default:
          // internal error
          throw new SemanticException(
              fOp, "Internal error: unknown query operation `" + opname + "'.");
      }
    } catch (ExpInvalidException ex) {
      throw new SemanticException(fOp, ex);
    }
    return res;
  }