/** * Copyright (c) 2014, Rudolf Schlatte. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.frontend.antlr.parser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeProperty; import abs.frontend.antlr.parser.ABSParser.MethodsigContext; import abs.frontend.antlr.parser.ABSParser.TraitApplyFragmentContext; import abs.frontend.antlr.parser.ABSParser.TraitNameFragmentContext; import abs.frontend.antlr.parser.ABSParser.TraitSetFragmentContext; import abs.frontend.antlr.parser.ABSParser.Trait_operContext; import abs.frontend.ast.*; /** * This class creates the JastAdd AST from an Antlr parse tree. * * @author Rudi Schlatte */ public class CreateJastAddASTListener extends ABSBaseListener { String filename = "<unknown file>"; /** maps antlr nodes to JastAdd nodes - see antlr book Sec.7.5 */ ParseTreeProperty<ASTNode<?>> values = new ParseTreeProperty<ASTNode<?>>(); UnresolvedTypeUse t = null; CompilationUnit result = null; public CreateJastAddASTListener(java.io.File filename) { if (filename != null) this.filename = filename.getPath(); } private ASTNode<?> setASTNodePosition(ParserRuleContext node, ASTNode<?> value) { assert node != null; int startline = node.start.getLine(); int startcol = node.start.getCharPositionInLine(); // for a completely empty file, CompilationUnit.stop will be null int endline = (node.stop == null ? node.start : node.stop).getLine(); int endcol = (node.stop == null ? node.start : node.stop).getCharPositionInLine(); value.setPosition(startline, startcol, endline, endcol); value.setFileName(this.filename); return value; } private ASTNode<?> setASTNodePosition(Token node, ASTNode<?> value) { assert node != null; int startline = node.getLine(); int startcol = node.getCharPositionInLine(); // for a completely empty file, CompilationUnit.stop will be null int endline = startline; int endcol = startcol + node.getText().length(); value.setPosition(startline, startcol, endline, endcol); value.setFileName(this.filename); return value; } /** * Associates JastAdd value with antlr node such that v(node) will * return value. Also sets filename and position of the JastAdd * value. Returns the passed-in JastAdd value. */ private ASTNode<?> setV(ParserRuleContext node, ASTNode<?> value) { setASTNodePosition(node, value); values.put(node, value); return value; } /** * Returns the AstNode for the given antlr parse node. The result * is guaranteed to be non-null. */ private ASTNode<?> v(ParseTree node) { ASTNode<?> result = values.get(node); if (result == null) throw new NullPointerException(); return result; } /** * Returns a fresh Opt<ASTNode> filled with the result of v(node) if * node is non-null, empty otherwise. */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Opt o(ParseTree node) { if (node == null) return new Opt(); else return new Opt(v(node)); } /** * Returns a list of ASTNodes given a list of antlr parse nodes. * The result list elements are found via 'v' and are guaranteed * non-null. */ @SuppressWarnings({ "rawtypes", "unchecked" }) private List l(java.util.List<? extends ParseTree> l) { List result = new List(); for (ParseTree n : l) { result.add(v(n)); } return result; } public CompilationUnit getCompilationUnit() { return result; } private StringLiteral makeStringLiteral(String tokenText) { StringBuffer s = new StringBuffer(tokenText.length() - 2); // i = 1..len-1 to skip beginning and ending \" of the stringliteral for (int i = 1; i < tokenText.length() - 1; i++) { char c = tokenText.charAt(i); if (c == '\\') { i++; c = tokenText.charAt(i); switch (c) { case 'n' : s.append('\n'); break; case 'r' : s.append('\r'); break; case 't' : s.append('\t'); break; default : s.append(c); break; } } else { s.append(c); } } return new StringLiteral(s.toString()); } @Override public void enterCompilation_unit(ABSParser.Compilation_unitContext ctx) { this.result = (CompilationUnit)setV(ctx, new CompilationUnit(this.filename, new List<ModuleDecl>(), new List<DeltaDecl>(),new List<UpdateDecl>(), new Opt<ProductLine>(),new List<ProductDecl>(), new List<FeatureDecl>(),new List<FExt>())); } @Override public void exitCompilation_unit(ABSParser.Compilation_unitContext ctx) { result.setModuleDeclList(l(ctx.module_decl())); result.setDeltaDeclList(l(ctx.delta_decl())); result.setProductLineOpt(o(ctx.productline_decl())); result.setProductDeclList(l(ctx.product_decl())); result.setFeatureDeclList(l(ctx.feature_decl())); result.setFExtList(l(ctx.fextension())); } // Traits @Override public void exitDeltaTraitFragment(ABSParser.DeltaTraitFragmentContext ctx) { setV(ctx,new DeltaTraitModifier((MethodModifier) v(ctx.trait_oper()))); } @Override public void exitTraitAddFragment(abs.frontend.antlr.parser.ABSParser.TraitAddFragmentContext ctx) { setV(ctx,new AddMethodModifier((TraitExpr) v(ctx.trait_expr()))); } @Override public void exitTraitModifyFragment(abs.frontend.antlr.parser.ABSParser.TraitModifyFragmentContext ctx) { setV(ctx,new ModifyMethodModifier((TraitExpr) v(ctx.trait_expr()))); } @Override public void exitTraitRemoveFragment(abs.frontend.antlr.parser.ABSParser.TraitRemoveFragmentContext ctx) { List<MethodSig> l = new List<MethodSig>(); for (MethodsigContext methodSig : ctx.methodsig()) { l.add((MethodSig)v(methodSig)); } setV(ctx,new RemoveMethodModifier(l)); } @Override public void exitTraitApplyFragment(TraitApplyFragmentContext ctx) { setV(ctx, new TraitModifyExpr((TraitExpr)v(ctx.trait_expr()), (MethodModifier)v(ctx.trait_oper()))); } @Override public void exitTraitNameFragment(TraitNameFragmentContext ctx) { setV(ctx, new TraitNameExpr(ctx.TYPE_IDENTIFIER().getText())); } @Override public void exitTraitSetFragment(TraitSetFragmentContext ctx) { setV(ctx, new TraitSetExpr(l(ctx.method()))); } @Override public void exitTrait_usage( ABSParser.Trait_usageContext ctx) { //setV(ctx, new TraitUse(ctx.TYPE_IDENTIFIER().toString(), new List())); setV(ctx, new TraitUse((TraitExpr)v(ctx.trait_expr()))); } @Override public void exitTrait_decl( ABSParser.Trait_declContext ctx) { setV(ctx, new TraitDecl(ctx.TYPE_IDENTIFIER().getText(), (TraitExpr)v(ctx.trait_expr()))); } // Declarations @Override public void exitDecl(ABSParser.DeclContext ctx) { setV(ctx, v(ctx.getChild(0))); // relies on decl having one token } @Override public void exitModule_decl(ABSParser.Module_declContext ctx) { setV(ctx, new ModuleDecl(ctx.qualified_type_identifier().getText(), l(ctx.module_export()), l(ctx.module_import()), l(ctx.decl()), o(ctx.main_block()))); } @Override public void exitModule_export(ABSParser.Module_exportContext ctx) { if (ctx.f == null) { if (ctx.s == null || ctx.s.isEmpty()) setV(ctx, new StarExport()); else setV(ctx, new NamedExport(l(ctx.s))); } else { if (ctx.s == null || ctx.s.isEmpty()) setV(ctx, new StarExport(o(ctx.f))); else setV(ctx, new FromExport(l(ctx.s), ctx.f.getText())); } } @Override public void exitModule_import(ABSParser.Module_importContext ctx) { if (ctx.s == null || ctx.s.isEmpty()) setV(ctx, new StarImport(ctx.f.getText())); else if (ctx.f == null) setV(ctx, new NamedImport(l(ctx.s))); else setV(ctx, new FromImport(l(ctx.s), ctx.f.getText())); } @Override public void exitDatatype_decl(ABSParser.Datatype_declContext ctx) { ParametricDataTypeDecl d = (ParametricDataTypeDecl)setV(ctx, new ParametricDataTypeDecl(ctx.n.getText(), l(ctx.c), l(ctx.annotation()), new List<TypeParameterDecl>())); for (Token t : ctx.p) { TypeParameterDecl tpd = new TypeParameterDecl(t.getText()); setASTNodePosition(t, tpd); d.addTypeParameter(tpd); } } @Override public void exitData_constructor(ABSParser.Data_constructorContext ctx) { DataConstructor d = (DataConstructor)setV(ctx, new DataConstructor(ctx.n.getText(), new List<ConstructorArg>())); for (ABSParser.Data_constructor_argContext a : ctx.a) { final TypeUse vt = (TypeUse) v(a.type_use()); final DataTypeUse vtresolved; if (vt instanceof DataTypeUse) { vtresolved = (DataTypeUse) vt; } else { // See below, we may be facing an UnresolvedTypeUse. assert vt instanceof UnresolvedTypeUse : vt.getClass().getName(); vtresolved = new DataTypeUse(vt.getName(), vt.getAnnotations()); vtresolved.setPositionFromNode(vt); } ConstructorArg ca = new ConstructorArg(vtresolved, a.IDENTIFIER() != null ? new Opt(new Name(a.IDENTIFIER().getText())) : new Opt()); setASTNodePosition(a, ca); d.addConstructorArg(ca); } } @Override public void exitFunction_decl(ABSParser.Function_declContext ctx) { // TODO: datatypes do not distinguish between DataTypeDecl and // ParametricDataTypeDecl; it would be nice to do this for // functions as well. FunctionDef d = ctx.e == null ? new BuiltinFunctionDef() : new ExpFunctionDef((PureExp)v(ctx.e)); List<ParamDecl> p = (List<ParamDecl>)v(ctx.paramlist()); TypeUse t = (TypeUse)v(ctx.type_use()); if (ctx.p != null && !ctx.p.isEmpty()) { ParametricFunctionDecl dp = (ParametricFunctionDecl)setV(ctx, new ParametricFunctionDecl(ctx.n.getText(), t, p, d, l(ctx.annotation()), new List<TypeParameterDecl>())); for (Token tp : ctx.p) { TypeParameterDecl tpd = new TypeParameterDecl(tp.getText()); setASTNodePosition(tp, tpd); dp.addTypeParameter(tpd); } } else { setV(ctx, new FunctionDecl(ctx.n.getText(), l(ctx.annotation()), t, p, d)); } } @Override public void exitTypesyn_decl(ABSParser.Typesyn_declContext ctx) { setV(ctx, new TypeSynDecl(ctx.TYPE_IDENTIFIER().getText(), l(ctx.annotation()), (TypeUse)v(ctx.type_use()))); } @Override public void exitException_decl(ABSParser.Exception_declContext ctx) { ExceptionDecl e = (ExceptionDecl)setV(ctx, new ExceptionDecl(ctx.n.getText(), l(ctx.annotation()), new List<ConstructorArg>())); for (ABSParser.Data_constructor_argContext a : ctx.a) { ConstructorArg ca = new ConstructorArg((TypeUse)v(a.type_use()), a.IDENTIFIER() != null ? new Opt(new Name(a.IDENTIFIER().getText())) : new Opt()); setASTNodePosition(a, ca); e.addConstructorArg(ca); } } @Override public void exitMain_block(ABSParser.Main_blockContext ctx) { setV(ctx, new MainBlock(l(ctx.annotation()), l(ctx.stmt()))); } // Interfaces @Override public void exitInterface_decl(ABSParser.Interface_declContext ctx) { setV(ctx, new InterfaceDecl(ctx.TYPE_IDENTIFIER().getText(), l(ctx.annotation()), l(ctx.e), l(ctx.methodsig()))); } @Override public void exitMethodsig(ABSParser.MethodsigContext ctx) { setV(ctx, new MethodSig(ctx.IDENTIFIER().getText(), l(ctx.annotation()), (Access)v(ctx.type_use()), (List<ParamDecl>)v(ctx.paramlist()))); } // Classes @Override public void exitClass_decl(ABSParser.Class_declContext ctx) { ClassDecl c = (ClassDecl)setV(ctx, new ClassDecl(ctx.TYPE_IDENTIFIER().getText(), l(ctx.annotation()), new List<ParamDecl>(), l(ctx.interface_name()), l(ctx.trait_usage()), new Opt<InitBlock>(), l(ctx.casestmtbranch()), l(ctx.field_decl()), l(ctx.method()))); if (ctx.paramlist() != null) { c.setParamList((List<ParamDecl>)v(ctx.paramlist())); } if (ctx.stmt() != null && !ctx.stmt().isEmpty()) { InitBlock b = new InitBlock(new List<Annotation>(), new List<Stmt>()); for (ABSParser.StmtContext s : ctx.stmt()) { b.addStmt((Stmt)v(s)); } c.setInitBlock(b); } } @Override public void exitField_decl(ABSParser.Field_declContext ctx) { // FIXME: 'port' missing (for component model) FieldDecl f = (FieldDecl)setV(ctx, new FieldDecl(ctx.IDENTIFIER().getText(), (Access)v(ctx.type_use()), o(ctx.pure_exp()), l(ctx.annotation()), false)); } @Override public void exitMethod(ABSParser.MethodContext ctx) { MethodSig ms = new MethodSig(ctx.IDENTIFIER().getText(), l(ctx.annotation()), (Access)v(ctx.type_use()), (List<ParamDecl>)v(ctx.paramlist())); Block b = new Block(new List<Annotation>(), new List<Stmt>()); for (ABSParser.StmtContext s : ctx.stmt()) { b.addStmt((Stmt)v(s)); } // FIXME: 'critical' missing (for component model) setV(ctx, new MethodImpl(ms, b, false)); } // Statements @Override public void exitVardeclStmt(ABSParser.VardeclStmtContext ctx) { VarDecl v = new VarDecl(ctx.IDENTIFIER().getText(), (Access)v(ctx.type_exp()), new Opt<Exp>()); setASTNodePosition(ctx, v); if (ctx.exp() != null) { v.setInitExp((Exp)v(ctx.exp())); } setV(ctx, new VarDeclStmt(l(ctx.annotation()), v)); } @Override public void exitAssignStmt(ABSParser.AssignStmtContext ctx) { setV(ctx, new AssignStmt(l(ctx.annotation()), (VarOrFieldUse)v(ctx.var_or_field_ref()), (Exp)v(ctx.exp()))); } @Override public void exitSkipStmt(ABSParser.SkipStmtContext ctx) { setV(ctx, new SkipStmt(l(ctx.annotation()))); } @Override public void exitReturnStmt(ABSParser.ReturnStmtContext ctx) { setV(ctx, new ReturnStmt(l(ctx.annotation()), (Exp)v(ctx.exp()))); } @Override public void exitAssertStmt(ABSParser.AssertStmtContext ctx) { setV(ctx, new AssertStmt(l(ctx.annotation()), (PureExp)v(ctx.exp()))); } @Override public void exitBlockStmt(ABSParser.BlockStmtContext ctx) { setV(ctx, new Block(l(ctx.annotation()), l(ctx.stmt()))); } @Override public void exitIfStmt(ABSParser.IfStmtContext ctx) { Stmt l = (Stmt)v(ctx.l); if (!(l instanceof Block)) { setV(ctx.l, new Block(new List<Annotation>(), new List(l))); } if (ctx.r != null) { Stmt r = (Stmt)v(ctx.r); if (!(r instanceof Block)) { setV(ctx.r, new Block(new List<Annotation>(), new List(r))); } } setV(ctx, new IfStmt(l(ctx.annotation()), (PureExp)v(ctx.c), (Block)v(ctx.l), o(ctx.r))); } @Override public void exitWhileStmt(ABSParser.WhileStmtContext ctx) { Stmt body = (Stmt)v(ctx.stmt()); if (!(body instanceof Block)) { setV(ctx.stmt(), new Block(new List<Annotation>(), new List(body))); } setV(ctx, new WhileStmt(l(ctx.annotation()), (PureExp)v(ctx.c), (Block)v(ctx.stmt()))); } @Override public void exitTryCatchFinallyStmt(ABSParser.TryCatchFinallyStmtContext ctx) { Stmt body = (Stmt)v(ctx.b); if (!(body instanceof Block)) { setV(ctx.b, new Block(new List<Annotation>(), new List(body))); } if (ctx.f != null) { Stmt finall = (Stmt)v(ctx.f); if (!(finall instanceof Block)) { setV(ctx.f, new Block(new List<Annotation>(), new List(finall))); } } setV(ctx, new TryCatchFinallyStmt(l(ctx.annotation()), (Block)v(ctx.b), l(ctx.casestmtbranch()), o(ctx.f))); } @Override public void exitAwaitStmt(ABSParser.AwaitStmtContext ctx) { setV(ctx, new AwaitStmt(l(ctx.annotation()), (Guard)v(ctx.guard()))); } @Override public void exitClaimGuard(ABSParser.ClaimGuardContext ctx) { setV(ctx, new ClaimGuard((VarOrFieldUse)v(ctx.var_or_field_ref()))); } @Override public void exitDurationGuard(ABSParser.DurationGuardContext ctx) { setV(ctx, new DurationGuard((PureExp)v(ctx.min), (PureExp)v(ctx.max))); } @Override public void exitExpGuard(ABSParser.ExpGuardContext ctx) { setV(ctx, new ExpGuard((PureExp)v(ctx.e))); } @Override public void exitAndGuard(ABSParser.AndGuardContext ctx) { setV(ctx, new AndGuard((Guard)v(ctx.l), (Guard)v(ctx.r))); } @Override public void exitSuspendStmt(ABSParser.SuspendStmtContext ctx) { setV(ctx, new SuspendStmt(l(ctx.annotation()))); } @Override public void exitDurationStmt(ABSParser.DurationStmtContext ctx) { setV(ctx, new DurationStmt(l(ctx.annotation()), (PureExp)v(ctx.f), (PureExp)v(ctx.t))); } @Override public void exitThrowStmt(ABSParser.ThrowStmtContext ctx) { setV(ctx, new ThrowStmt(l(ctx.annotation()), (PureExp)v(ctx.pure_exp()))); } @Override public void exitDieStmt(ABSParser.DieStmtContext ctx) { setV(ctx, new DieStmt(l(ctx.annotation()), (PureExp)v(ctx.pure_exp()))); } @Override public void exitMoveCogToStmt(ABSParser.MoveCogToStmtContext ctx) { setV(ctx, new MoveCogToStmt(l(ctx.annotation()), (PureExp)v(ctx.pure_exp()))); } @Override public void exitExpStmt(ABSParser.ExpStmtContext ctx) { setV(ctx, new ExpressionStmt(l(ctx.annotation()), (Exp)v(ctx.exp()))); } @Override public void exitCaseStmt(ABSParser.CaseStmtContext ctx) { List<CaseBranchStmt> branches = l(ctx.casestmtbranch()); // Add default branch that throws PatternMatchFailException. See // "Behavior of non-exhaustive case statement: no branch match = skip // or error?" on abs-dev on Jan 25-26, 2017 Block block = new Block(new List(), new List()); block.addStmt(new ThrowStmt(new List(), new DataConstructorExp("PatternMatchFailException", new List()))); CaseBranchStmt defaultBranch = new CaseBranchStmt(new UnderscorePattern(), block); setASTNodePosition(ctx, defaultBranch); branches.add(defaultBranch); setV(ctx, new CaseStmt(l(ctx.annotation()), (PureExp)v(ctx.c), branches)); } @Override public void exitCasestmtbranch(ABSParser.CasestmtbranchContext ctx) { Stmt body = (Stmt)v(ctx.stmt()); if (!(body instanceof Block)) { setV(ctx.stmt(), new Block(new List<Annotation>(), new List(body))); } setV(ctx, new CaseBranchStmt((Pattern)v(ctx.pattern()), (Block)v(ctx.stmt()))); } // Annotations @Override public void exitAnnotation(ABSParser.AnnotationContext ctx) { if (ctx.l == null) setV(ctx, new Annotation((PureExp)v(ctx.r))); else setV(ctx, new TypedAnnotation((PureExp)v(ctx.r), (Access)v(ctx.l))); } // Expressions @Override public void exitPureExp(ABSParser.PureExpContext ctx) { setV(ctx, v(ctx.pure_exp())); } @Override public void exitEffExp(ABSParser.EffExpContext ctx) { setV(ctx, v(ctx.eff_exp())); } // Side-effectful expressions @Override public void exitGetExp(ABSParser.GetExpContext ctx) { setV(ctx, new GetExp((PureExp)v(ctx.pure_exp()))); } @Override public void exitNewExp(ABSParser.NewExpContext ctx) { NewExp n = (NewExp)setV(ctx, new NewExp(ctx.c.getText(), (List<PureExp>)v(ctx.pure_exp_list()), new Opt<Local>())); if (ctx.l != null) { n.setLocal(new Local()); } } @Override public void exitAsyncCallExp(ABSParser.AsyncCallExpContext ctx) { if (ctx.a != null) { setV(ctx, new AwaitAsyncCall((PureExp)v(ctx.o), ctx.m.getText(), (List<PureExp>)v(ctx.pure_exp_list()))); } else { setV(ctx, new AsyncCall((PureExp)v(ctx.o), ctx.m.getText(), (List<PureExp>)v(ctx.pure_exp_list()))); } } @Override public void exitSyncCallExp(ABSParser.SyncCallExpContext ctx) { setV(ctx, new SyncCall((PureExp)v(ctx.o), ctx.m.getText(), (List<PureExp>)v(ctx.pure_exp_list()))); } @Override public void exitOriginalCallExp(ABSParser.OriginalCallExpContext ctx) { List<PureExp> l = ctx.pure_exp_list() == null ? new List<PureExp>() : (List<PureExp>)v(ctx.pure_exp_list()); if (ctx.c != null) { setV(ctx, new TargetedOriginalCall(new DeltaID("core"), l)); } else if (ctx.d != null) { setV(ctx, new TargetedOriginalCall((DeltaID)v(ctx.d), l)); } else { setV(ctx, new OriginalCall(l)); } } // Pure expressions @Override public void exitFunctionExp(ABSParser.FunctionExpContext ctx) { List<PureExp> l = ctx.pure_exp_list() == null ? new List<PureExp>() : (List<PureExp>)v(ctx.pure_exp_list()); setV(ctx, new FnApp(ctx.qualified_identifier().getText(), l)); } @Override public void exitVariadicFunctionExp(ABSParser.VariadicFunctionExpContext ctx) { List<PureExp> l = (List<PureExp>)v(ctx.pure_exp_list()); // Construct a list literal from all given arguments DataConstructorExp arglist = new DataConstructorExp("Cons", new List<PureExp>()); setASTNodePosition(ctx.pure_exp_list(), arglist); DataConstructorExp current = arglist; /* DO NOT use the iterator here -- it interferes with rewriting [stolz] */ if (l.getNumChildNoTransform() > 0) { PureExp last = l.getChildNoTransform(l.getNumChildNoTransform()-1); for (int i = 0; i < l.getNumChildNoTransform(); i++) { PureExp e = l.getChildNoTransform(i); DataConstructorExp next = new DataConstructorExp("Cons", new List<PureExp>()); next.setPositionFromNode(e); current.addParamNoTransform(e); current.addParamNoTransform(next); current = next; } } current.setConstructor("Nil"); List<PureExp> llist = new List<PureExp>(); llist.add(arglist); setV(ctx, new FnApp(ctx.qualified_identifier().getText(), llist)); } @Override public void exitConstructorExp(ABSParser.ConstructorExpContext ctx) { List<PureExp> l = ctx.pure_exp_list() == null ? new List<PureExp>() : (List<PureExp>)v(ctx.pure_exp_list()); setV(ctx, new DataConstructorExp(ctx.qualified_type_identifier().getText(), l)); } @Override public void exitUnaryExp(ABSParser.UnaryExpContext ctx) { switch (ctx.op.getType()) { case ABSParser.NEGATION : case ABSParser.NEGATION_CREOL : setV(ctx, new NegExp((PureExp)v(ctx.pure_exp()))); break; case ABSParser.MINUS : setV(ctx, new MinusExp((PureExp)v(ctx.pure_exp()))); break; } } @Override public void exitMultExp(ABSParser.MultExpContext ctx) { switch (ctx.op.getType()) { case ABSParser.MULT : setV(ctx, new MultMultExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.DIV : setV(ctx, new DivMultExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.MOD : setV(ctx, new ModMultExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; } } @Override public void exitAddExp(ABSParser.AddExpContext ctx) { switch (ctx.op.getType()) { case ABSParser.PLUS : setV(ctx, new AddAddExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.MINUS : setV(ctx, new SubAddExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; } } @Override public void exitGreaterExp(ABSParser.GreaterExpContext ctx) { switch (ctx.op.getType()) { case ABSParser.LT : setV(ctx, new LTExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.GT : setV(ctx, new GTExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.LTEQ : setV(ctx, new LTEQExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.GTEQ : setV(ctx, new GTEQExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; } } @Override public void exitEqualExp(ABSParser.EqualExpContext ctx) { switch (ctx.op.getType()) { case ABSParser.EQEQ : setV(ctx, new EqExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; case ABSParser.NOTEQ : setV(ctx, new NotEqExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); break; } } @Override public void exitAndExp(ABSParser.AndExpContext ctx) { setV(ctx, new AndBoolExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); } @Override public void exitOrExp(ABSParser.OrExpContext ctx) { setV(ctx, new OrBoolExp((PureExp)v(ctx.l), (PureExp)v(ctx.r))); } @Override public void exitVarOrFieldExp(ABSParser.VarOrFieldExpContext ctx) { setV(ctx, v(ctx.var_or_field_ref())); } @Override public void exitIntExp(ABSParser.IntExpContext ctx) { setV(ctx, new IntLiteral(ctx.INTLITERAL().getText())); } @Override public void exitStringExp(ABSParser.StringExpContext ctx) { setV(ctx, makeStringLiteral(ctx.STRINGLITERAL().getText())); } @Override public void exitThisExp(ABSParser.ThisExpContext ctx) { setV(ctx, new ThisExp()); } @Override public void exitNullExp(ABSParser.NullExpContext ctx) { setV(ctx, new NullExp()); } @Override public void exitIfExp(ABSParser.IfExpContext ctx) { setV(ctx, new IfExp((PureExp)v(ctx.c), (PureExp)v(ctx.l), (PureExp)v(ctx.r))); } @Override public void exitCaseExp(ABSParser.CaseExpContext ctx) { List<CaseBranch> l = new List<CaseBranch>(); for (ABSParser.CasebranchContext b : ctx.casebranch()) { l.add((CaseBranch)v(b)); } setV(ctx, new CaseExp((PureExp)v(ctx.c), l)); } @Override public void exitLetExp(ABSParser.LetExpContext ctx) { ParamDecl pd = new ParamDecl(ctx.IDENTIFIER().getText(), (TypeUse)v(ctx.type_use()), new List<Annotation>()); setASTNodePosition(ctx.IDENTIFIER().getSymbol(), pd); setV(ctx, new LetExp(pd, (PureExp)v(ctx.i), (PureExp)v(ctx.b))); } @Override public void exitParenExp(ABSParser.ParenExpContext ctx) { setV(ctx, v(ctx.pure_exp())); } @Override public void exitCasebranch(ABSParser.CasebranchContext ctx) { setV(ctx, new CaseBranch((Pattern)v(ctx.pattern()), (PureExp)v(ctx.pure_exp()))); } @Override public void exitUnderscorePattern(ABSParser.UnderscorePatternContext ctx) { setV(ctx, new UnderscorePattern()); } @Override public void exitIntPattern(ABSParser.IntPatternContext ctx) { setV(ctx, new LiteralPattern(new IntLiteral(ctx.INTLITERAL().getText()))); } @Override public void exitStringPattern(ABSParser.StringPatternContext ctx) { setV(ctx, new LiteralPattern(makeStringLiteral(ctx.STRINGLITERAL().getText()))); } @Override public void exitVarPattern(ABSParser.VarPatternContext ctx) { setV(ctx, new PatternVarUse(ctx.IDENTIFIER().getText())); } @Override public void exitConstructorPattern(ABSParser.ConstructorPatternContext ctx) { setV(ctx, new ConstructorPattern(ctx.qualified_type_identifier().getText(), l(ctx.pattern()))); } @Override public void exitParamlist(ABSParser.ParamlistContext ctx) { setV(ctx, l(ctx.param_decl())); } @Override public void exitParam_decl(ABSParser.Param_declContext ctx) { setV(ctx, new ParamDecl(ctx.IDENTIFIER().getText(), (Access)v(ctx.type_exp()), l(ctx.annotation()))); } @Override public void exitInterface_name(ABSParser.Interface_nameContext ctx) { setV(ctx, new InterfaceTypeUse(ctx.qualified_type_identifier().getText(), new List())); } @Override public void exitPure_exp_list(ABSParser.Pure_exp_listContext ctx) { List<PureExp> l = (List<PureExp>)setV(ctx, new List<PureExp>()); for (ABSParser.Pure_expContext a : ctx.pure_exp()) { l.add((PureExp)v(a)); } } @Override public void exitType_use(ABSParser.Type_useContext ctx) { /* As we could be looking at an interface type, first keep symbol * unresolved and have rewrite-rules patch it up. * However, this means that in the parser the DataConstructor could * be seeing. But there we know what it must be and "rewrite" it ourselves. */ if (ctx.p.isEmpty()) { // normal type use setV(ctx, new UnresolvedTypeUse(ctx.n.getText(), l(ctx.annotation()))); } else { // parametric type use ParametricDataTypeUse p = (ParametricDataTypeUse)setV(ctx, new ParametricDataTypeUse(ctx.n.getText(), l(ctx.annotation()), new List<TypeUse>())); for (ABSParser.Type_useContext c : ctx.type_use()) { p.addParam((TypeUse)v(c)); } } } @Override public void exitType_exp(ABSParser.Type_expContext ctx) { if (ctx.p.isEmpty()) { // normal type use setV(ctx, new UnresolvedTypeUse(ctx.n.getText(), new List<Annotation>())); } else { // parametric type use ParametricDataTypeUse p = (ParametricDataTypeUse)setV(ctx, new ParametricDataTypeUse(ctx.n.getText(), new List<Annotation>(), new List<TypeUse>())); for (ABSParser.Type_useContext c : ctx.type_use()) { p.addParam((TypeUse)v(c)); } } } @Override public void exitVar_or_field_ref(ABSParser.Var_or_field_refContext ctx) { if (ctx.getChildCount() == 1) { // id setV(ctx, new VarUse(ctx.IDENTIFIER().getText())); } else { // this.id setV(ctx, new FieldUse(ctx.IDENTIFIER().getText())); } } @Override public void exitQualified_type_identifier(ABSParser.Qualified_type_identifierContext ctx) { setV(ctx, new Name(ctx.getText())); } @Override public void exitQualified_identifier(ABSParser.Qualified_identifierContext ctx) { setV(ctx, new Name(ctx.getText())); } @Override public void exitAny_identifier(ABSParser.Any_identifierContext ctx) { setV(ctx, v(ctx.getChild(0))); // relies on any_identifier // having one token } // Deltas @Override public void exitDelta_decl(ABSParser.Delta_declContext ctx) { setV(ctx, new DeltaDecl(ctx.TYPE_IDENTIFIER().getText(), l(ctx.p), l(ctx.delta_access()), l(ctx.module_modifier()))); } @Override public void exitDeltaFieldParam(ABSParser.DeltaFieldParamContext ctx) { setV(ctx, new DeltaFieldParam((ParamDecl)v(ctx.param_decl()))); } @Override public void exitDeltaClassParam(ABSParser.DeltaClassParamContext ctx) { setV(ctx, new DeltaClassParam(ctx.qualified_type_identifier().getText(), (HasCondition)v(ctx.has_condition()))); } @Override public void exitDeltaHasFieldCondition(ABSParser.DeltaHasFieldConditionContext ctx) { setV(ctx, new HasField((FieldDecl)v(ctx.f))); } @Override public void exitDeltaHasMethodCondition(ABSParser.DeltaHasMethodConditionContext ctx) { setV(ctx, new HasMethod((MethodSig)v(ctx.m))); } @Override public void exitDeltaHasInterfaceCondition(ABSParser.DeltaHasInterfaceConditionContext ctx) { setV(ctx, new HasInterface((InterfaceTypeUse)v(ctx.i))); } @Override public void exitDelta_access(ABSParser.Delta_accessContext ctx) { setV(ctx, new DeltaAccess(ctx.qualified_type_identifier().getText())); } @Override public void exitModule_modifier(ABSParser.Module_modifierContext ctx) { setV(ctx, v(ctx.getChild(0))); // relies on node having one token } @Override public void exitDeltaAddFunctionModifier(ABSParser.DeltaAddFunctionModifierContext ctx) { setV(ctx, new AddFunctionModifier((FunctionDecl)v(ctx.function_decl()))); } @Override public void exitDeltaAddDataTypeModifier(ABSParser.DeltaAddDataTypeModifierContext ctx) { setV(ctx, new AddDataTypeModifier((DataTypeDecl)v(ctx.datatype_decl()))); } @Override public void exitDeltaAddTypeSynModifier(ABSParser.DeltaAddTypeSynModifierContext ctx) { setV(ctx, new AddTypeSynModifier((TypeSynDecl)v(ctx.typesyn_decl()))); } @Override public void exitDeltaModifyTypeSynModifier(ABSParser.DeltaModifyTypeSynModifierContext ctx) { setV(ctx, new ModifyTypeSynModifier((TypeSynDecl)v(ctx.typesyn_decl()))); } @Override public void exitDeltaModifyDataTypeModifier(ABSParser.DeltaModifyDataTypeModifierContext ctx) { setV(ctx, new ModifyDataTypeModifier((DataTypeDecl)v(ctx.datatype_decl()))); } @Override public void exitDeltaAddClassModifier(ABSParser.DeltaAddClassModifierContext ctx) { setV(ctx, new AddClassModifier((ClassDecl)v(ctx.class_decl()))); } @Override public void exitDeltaRemoveClassModifier(ABSParser.DeltaRemoveClassModifierContext ctx) { setV(ctx, new RemoveClassModifier(ctx.qualified_type_identifier().getText())); } @Override public void exitDeltaModifyClassModifier(ABSParser.DeltaModifyClassModifierContext ctx) { setV(ctx, new ModifyClassModifier(ctx.n.getText(), l(ctx.ia), l(ctx.ir), l(ctx.class_modifier_fragment()))); } @Override public void exitDeltaAddInterfaceModifier(ABSParser.DeltaAddInterfaceModifierContext ctx) { setV(ctx, new AddInterfaceModifier((InterfaceDecl)v(ctx.interface_decl()))); } @Override public void exitDeltaRemoveInterfaceModifier(ABSParser.DeltaRemoveInterfaceModifierContext ctx) { setV(ctx, new RemoveInterfaceModifier(ctx.qualified_type_identifier().getText())); } @Override public void exitDeltaModifyInterfaceModifier(ABSParser.DeltaModifyInterfaceModifierContext ctx) { setV(ctx, new ModifyInterfaceModifier(ctx.qualified_type_identifier().getText(), l(ctx.interface_modifier_fragment()))); } @Override public void exitDeltaAddFieldFragment(ABSParser.DeltaAddFieldFragmentContext ctx) { setV(ctx, new AddFieldModifier((FieldDecl)v(ctx.field_decl()))); } @Override public void exitDeltaRemoveFieldFragment(ABSParser.DeltaRemoveFieldFragmentContext ctx) { setV(ctx, new RemoveFieldModifier((FieldDecl)v(ctx.field_decl()))); } @Override public void exitDeltaAddMethodsigFragment(ABSParser.DeltaAddMethodsigFragmentContext ctx) { setV(ctx, new AddMethodSigModifier((MethodSig)v(ctx.methodsig()))); } @Override public void exitDeltaRemoveMethodsigFragment(ABSParser.DeltaRemoveMethodsigFragmentContext ctx) { setV(ctx, new RemoveMethodSigModifier((MethodSig)v(ctx.methodsig()))); } @Override public void exitDeltaAddModuleImportFragment(ABSParser.DeltaAddModuleImportFragmentContext ctx) { setV(ctx, new AddImportModifier((Import)v(ctx.module_import()))); } @Override public void exitDeltaAddModuleExportFragment(ABSParser.DeltaAddModuleExportFragmentContext ctx) { setV(ctx, new AddExportModifier((Export)v(ctx.module_export()))); } // Updates (?) @Override public void exitUpdateDecl(ABSParser.UpdateDeclContext ctx) { setV(ctx, new UpdateDecl(ctx.TYPE_IDENTIFIER().getText(), l(ctx.object_update()))); } @Override public void exitObjectUpdateDecl(ABSParser.ObjectUpdateDeclContext ctx) { setV(ctx, new ObjectUpdate(ctx.qualified_type_identifier().getText(), new AwaitStmt(new List(), (Guard)v(ctx.guard())), new UpdatePreamble(l(ctx.update_preamble_decl())), l(ctx.pre), l(ctx.post))); } @Override public void exitObjectUpdateAssignStmt(ABSParser.ObjectUpdateAssignStmtContext ctx) { setV(ctx, new AssignStmt(new List(), (VarOrFieldUse)v(ctx.var_or_field_ref()), (Exp)v(ctx.exp()))); } @Override public void exitUpdatePreambleDecl(ABSParser.UpdatePreambleDeclContext ctx) { setV(ctx, new VarDeclStmt(new List(), new VarDecl(ctx.IDENTIFIER().getText(), (Access)v(ctx.type_exp()), new Opt()))); } // Productline @Override public void exitProductline_decl(ABSParser.Productline_declContext ctx) { setV(ctx, new ProductLine(ctx.TYPE_IDENTIFIER().getText(), l(ctx.feature()), l(ctx.delta_clause()))); } @Override public void exitFeature(ABSParser.FeatureContext ctx) { setV(ctx, new Feature((ctx.p == null ? "" : "$") + ctx.TYPE_IDENTIFIER().getText(), l(ctx.attr_assignment()))); } @Override public void exitAttr_assignment(ABSParser.Attr_assignmentContext ctx) { Value val = null; String id = ctx.IDENTIFIER().getText(); if (ctx.i != null) val = new IntVal(Integer.parseInt(ctx.i.getText())); else if(ctx.s != null) val = new StringVal(ctx.s.getText()); else val = new UnknownVal(ctx.b.getText()); setV(ctx, new AttrAssignment(id, val)); } @Override public void exitDelta_clause(ABSParser.Delta_clauseContext ctx) { setV(ctx, new DeltaClause((Deltaspec)v(ctx.deltaspec()), ctx.after_condition() == null ? new List() : (List)v(ctx.after_condition()), o(ctx.from_condition()), o(ctx.when_condition()))); } @Override public void exitDeltaspec(ABSParser.DeltaspecContext ctx) { setV(ctx, new Deltaspec(ctx.TYPE_IDENTIFIER().getText(), l(ctx.deltaspec_param()))); } @Override public void exitBoolOrIDDeltaspecParam(ABSParser.BoolOrIDDeltaspecParamContext ctx) { String id = ctx.TYPE_IDENTIFIER().getText(); setV(ctx, id.equals("True") ? new Const(new BoolVal(true)) : (id.equals("False") ? new Const(new BoolVal(false)) : new FID(id))); } @Override public void exitIntDeltaspecParam(ABSParser.IntDeltaspecParamContext ctx) { setV(ctx, new Const(new IntVal(Integer.parseInt(ctx.INTLITERAL().getText())))); } @Override public void exitFIDAIDDeltaspecParam(ABSParser.FIDAIDDeltaspecParamContext ctx) { setV(ctx, new FIDAID(ctx.TYPE_IDENTIFIER().getText(), ctx.IDENTIFIER().getText())); } @Override public void exitAfter_condition(ABSParser.After_conditionContext ctx) { setV(ctx, l(ctx.delta_id())); } @Override public void exitDelta_id(ABSParser.Delta_idContext ctx) { setV(ctx, new DeltaID(ctx.TYPE_IDENTIFIER().getText())); } @Override public void exitFrom_condition(ABSParser.From_conditionContext ctx) { setV(ctx, v(ctx.application_condition())); } @Override public void exitWhen_condition(ABSParser.When_conditionContext ctx) { setV(ctx, v(ctx.application_condition())); } @Override public void exitNotApplicationCondition(ABSParser.NotApplicationConditionContext ctx) { setV(ctx, new AppCondNot((AppCond)v(ctx.application_condition()))); } @Override public void exitAndApplicationCondition(ABSParser.AndApplicationConditionContext ctx) { setV(ctx, new AppCondAnd((AppCond)v(ctx.l), (AppCond)v(ctx.r))); } @Override public void exitOrApplicationCondition(ABSParser.OrApplicationConditionContext ctx) { setV(ctx, new AppCondOr((AppCond)v(ctx.l), (AppCond)v(ctx.r))); } @Override public void exitParenApplicationCondition(ABSParser.ParenApplicationConditionContext ctx) { setV(ctx, v(ctx.application_condition())); } @Override public void exitFeatureApplicationCondition(ABSParser.FeatureApplicationConditionContext ctx) { setV(ctx, new AppCondFeature(((Feature)v(ctx.feature())).getName())); } // Products @Override public void exitProduct_decl(ABSParser.Product_declContext ctx) { if(ctx.product_expr() == null) { // old syntax: a product is declared as a set of features setV(ctx, new ProductDecl(ctx.TYPE_IDENTIFIER().getText(), new ProductFeatureSet(l(ctx.feature())), l(ctx.product_reconfiguration()))); } else { // new syntax: using product expressions setV(ctx, new ProductDecl(ctx.TYPE_IDENTIFIER().getText(), (ProductExpr)v(ctx.product_expr()), l(ctx.product_reconfiguration()))); } } @Override public void exitProduct_reconfiguration(ABSParser.Product_reconfigurationContext ctx) { setV(ctx, new Reconfiguration(ctx.product.getText(), l(ctx.delta_id()), ctx.update.getText())); } // Product Expression @Override public void exitProductFeatureSet(ABSParser.ProductFeatureSetContext ctx) { setV(ctx, new ProductFeatureSet(l(ctx.feature()))); } @Override public void exitProductIntersect(ABSParser.ProductIntersectContext ctx) { setV(ctx, new ProductIntersect((ProductExpr)v(ctx.l), (ProductExpr)v(ctx.r))); } @Override public void exitProductUnion(ABSParser.ProductUnionContext ctx) { setV(ctx, new ProductUnion((ProductExpr)v(ctx.l), (ProductExpr)v(ctx.r))); } @Override public void exitProductDifference(ABSParser.ProductDifferenceContext ctx) { setV(ctx, new ProductDifference((ProductExpr)v(ctx.l), (ProductExpr)v(ctx.r))); } @Override public void exitProductName(ABSParser.ProductNameContext ctx) { setV(ctx, new ProductName(ctx.TYPE_IDENTIFIER().getText())); } @Override public void exitProductParen(ABSParser.ProductParenContext ctx) { setV(ctx, v(ctx.product_expr())); } // mTVL @Override public void exitFextension(ABSParser.FextensionContext ctx) { setV(ctx, new FExt(ctx.TYPE_IDENTIFIER().getText(), o(ctx.feature_decl_group()), new AttrConstraints(l(ctx.feature_decl_attribute()), l(ctx.feature_decl_constraint())))); } @Override public void exitFeature_decl(ABSParser.Feature_declContext ctx) { setV(ctx, new FeatureDecl(ctx.TYPE_IDENTIFIER().getText(), o(ctx.feature_decl_group()), new AttrConstraints(l(ctx.feature_decl_attribute()), l(ctx.feature_decl_constraint())))); } @Override public void exitFeature_decl_group(ABSParser.Feature_decl_groupContext ctx) { Cardinality c = null; if (ctx.o != null) c = new CRange(1,1); else if (ctx.a != null) c = new AllOf(); else if (ctx.s != null) c = new Minim(Integer.parseInt(ctx.l.getText())); else c = new CRange(Integer.parseInt(ctx.l.getText()), Integer.parseInt(ctx.u.getText())); setV(ctx, new Group(c, l(ctx.fnode()))); } @Override public void exitFnode(ABSParser.FnodeContext ctx) { if (ctx.o == null) setV(ctx, new MandFeat((FeatureDecl)v(ctx.feature_decl()))); else setV(ctx, new OptFeat((FeatureDecl)v(ctx.feature_decl()))); } @Override public void exitFeatureDeclConstraintIfIn(ABSParser.FeatureDeclConstraintIfInContext ctx) { setV(ctx, new IfIn((MExp)v(ctx.mexp()))); } @Override public void exitFeatureDeclConstraintIfOut(ABSParser.FeatureDeclConstraintIfOutContext ctx) { setV(ctx, new IfOut((MExp)v(ctx.mexp()))); } @Override public void exitFeatureDeclConstraintExclude(ABSParser.FeatureDeclConstraintExcludeContext ctx) { setV(ctx, new Exclude(new FeatVar(ctx.TYPE_IDENTIFIER().getText()))); } @Override public void exitFeatureDeclConstraintRequire(ABSParser.FeatureDeclConstraintRequireContext ctx) { setV(ctx, new Require(new FeatVar(ctx.TYPE_IDENTIFIER().getText()))); } @Override public void exitMexp(ABSParser.MexpContext ctx) { if (ctx.op != null) { switch (ctx.op.getType()) { case ABSParser.OROR : setV(ctx, new MOrBoolExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.ANDAND : setV(ctx, new MAndBoolExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.IMPLIES : setV(ctx, new MImpliesExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.EQUIV : setV(ctx, new MEquivExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.EQEQ : setV(ctx, new MEqExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.NOTEQ : setV(ctx, new MNotEqExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.LT : setV(ctx, new MLTExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.GT : setV(ctx, new MGTExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.LTEQ : setV(ctx, new MLTEQExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.GTEQ : setV(ctx, new MGTEQExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.PLUS : setV(ctx, new MAddAddExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.MINUS : if (ctx.l != null) setV(ctx, new MSubAddExp((MExp)v(ctx.l), (MExp)v(ctx.r))); else setV(ctx, new MMinusExp((MExp)v(ctx.a))); return; case ABSParser.MULT : setV(ctx, new MMultMultExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.DIV : setV(ctx, new MDivMultExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.MOD : setV(ctx, new MModMultExp((MExp)v(ctx.l), (MExp)v(ctx.r))); return; case ABSParser.NEGATION : setV(ctx, new MNegExp((MExp)v(ctx.a))); return; } } else if (ctx.a != null) setV(ctx, v(ctx.a)); else if (ctx.INTLITERAL() != null) setV(ctx, new MValue(new IntVal(Integer.parseInt(ctx.INTLITERAL().getText())))); else if (ctx.IDENTIFIER() != null) { if (ctx.TYPE_IDENTIFIER() != null) setV(ctx, new FAVar(ctx.TYPE_IDENTIFIER().getText(), ctx.IDENTIFIER().getText())); else setV(ctx, new AttVar(ctx.IDENTIFIER().getText())); } else { // TYPE_IDENTIFIER is not null String id = ctx.TYPE_IDENTIFIER().getText(); if (id.equals("True")) setV(ctx, new MValue(new BoolVal(true))); else if (id.equals("False")) setV(ctx, new MValue(new BoolVal(false))); else setV(ctx, new FeatVar(id)); } } @Override public void exitFeature_decl_attribute(ABSParser.Feature_decl_attributeContext ctx) { String t = ctx.TYPE_IDENTIFIER().getText(); if (ctx.l != null) { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new IntMType(t, (BoundaryInt)v(ctx.l), (BoundaryInt)v(ctx.u)))); } else if (ctx.is != null && !ctx.is.isEmpty()) { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new IntListMType(t, l(ctx.is)))); } else if (t.equals("Int")) { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new IntMType(t, new Limit(), new Limit()))); } else if (t.equals("String")) { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new StringMType(t))); } else if (t.equals("Bool")) { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new BoolMType(t))); } else { setV(ctx, new Attribute(ctx.IDENTIFIER().getText(), new UnresolvedMType(t))); } } @Override public void exitBoundary_int(ABSParser.Boundary_intContext ctx) { if (ctx.star != null) setV(ctx, new Limit()); else setV(ctx, v(ctx.boundary_val())); } @Override public void exitBoundary_val(ABSParser.Boundary_valContext ctx) { setV(ctx, new BoundaryVal((ctx.m == null ? +1 : -1) * Integer.parseInt(ctx.INTLITERAL().getText()))); } }