COP 5021 Lecture -*- Outline -*- * Attributes ** What are attributes? ------------------------------------------ ATTRIBUTES defn: an *attribute* is Two kinds of attributes: Synthesized: (passed up) AST's value computed from attributes of subtrees Inherited: (passed down) AST's value given to it from its parent in the AST ------------------------------------------ ... a property of an AST (can be any Java value in JastAdd) ** Examples of Synthesized Attributes ------------------------------------------ SYNTHESIZED ATTRIBUTE EXAMPLE // file Unparse.jrag aspect Unparse { syn String Program.unparse(); syn String S.unparse(); syn String Expr.unparse(); syn String Op.unparse(); syn String Label.unparse(); eq Program.unparse() = getS().unparse(); eq CompoundS.unparse() { StringBuffer s = new StringBuffer(); s.append("{\n"); int len = getNumSList(); for (int i = 0; i < len; i++) { s.append(getSList(i).unparse()); if (i < len-1) { s.append(";\n"); } } s.append("\n}"); return s.toString(); } eq VarRefExpr.unparse() { return getContents();} eq NumLitExpr.unparse() { return getContents();} eq BoolLitExpr.unparse() { return getContents();} eq ABinaryExpr.unparse() { return "(" + getLeft().unparse() + " " + getOp().unparse() + " " + getRight().unparse() + ")";} eq NotExpr.unparse() { return "not " + getExpr().unparse();} eq LogicExpr.unparse() { return "(" + getLeft().unparse() + " " + getOp().unparse() + " " + getRight().unparse() + ")";} eq RelExpr.unparse() { return "(" + getLeft().unparse() + " " + getOp().unparse() + " " + getRight().unparse() + ")";} eq SkipS.unparse() = "[skip]^" + getLabelAST().unparse(); eq AssignS.unparse() { return "[" + getVar() + " := " + getExpr().unparse() + "]" + "^" + getLabelAST().unparse(); } // ... similarly, see Unparse.jrag } ------------------------------------------ Show how to program this, show also toString in Unparse.jrag ** inherited attribute example Q: Suppose we want to have indentation for prettyprinting? For this use an inherited attribute ------------------------------------------ // file PrettyPrint.jrag import utility.PPUtility; aspect PrettyPrint { inh int S.nestingLevel(); eq Program.getS().nestingLevel() = 0; eq CompoundS.getSList(int index).nestingLevel() = nestingLevel()+1; eq IfS.getS1().nestingLevel() = nestingLevel(); eq IfS.getS2().nestingLevel() = nestingLevel(); eq WhileS.getS().nestingLevel() = nestingLevel(); eq StmtBlock.getS().nestingLevel() = 0; // just for sake of form // ... syn String Program.prettyPrint(); syn String S.prettyPrint(); syn String Expr.prettyPrint(); syn String Op.prettyPrint(); syn String Label.prettyPrint(); // ... eqs use nestingLevel()... } ------------------------------------------ show how this is done in PrettyPrint.jrag Q: Why does nestingLevel need to be inherited?