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; }
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; }