Skip to content
Snippets Groups Projects
Commit 43137cf2 authored by Jesper's avatar Jesper
Browse files

Rewrote documentation in Markdown

- all documentation is now formatted using Markdown
- build script process Markdown files before packaging
- processed HTML files are uploaded to jastadd web by release.sh
- JastAdd version is substituted by build script
- removed Google code search links from reference manual (dead links)
- release script takes new version as argument
parent 9f2fec4d
Branches
No related tags found
No related merge requests found
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
/jastadd2.jar /jastadd2.jar
/jastadd2-bin.zip /jastadd2-bin.zip
/jastadd2-src.zip /jastadd2-src.zip
/README-binary-dist.html
*.swp *.swp
# Mac OS stuff
.DS_Store .DS_Store
# generated documentation files
/doc/index.md
/doc/*.html
/README-binary-dist.html
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
</jar> </jar>
</target> </target>
<target name="source-zip" depends="jar"> <target name="source-zip" depends="jar,build-doc">
<zip destfile="jastadd2-src.zip"> <zip destfile="jastadd2-src.zip">
<zipfileset dir="." prefix="jastadd2-src"> <zipfileset dir="." prefix="jastadd2-src">
<include name="src/java/**/*.java"/> <include name="src/java/**/*.java"/>
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
<include name="tinytemplate/src/**/*"/> <include name="tinytemplate/src/**/*"/>
<include name="tinytemplate/LICENSE.txt"/> <include name="tinytemplate/LICENSE.txt"/>
<include name="tinytemplate/README.md"/> <include name="tinytemplate/README.md"/>
<include name="doc/index.html"/>
<include name="doc/reference-manual.html"/> <include name="doc/reference-manual.html"/>
<include name="doc/release-notes.html"/> <include name="doc/release-notes.html"/>
<include name="LICENSE"/> <include name="LICENSE"/>
...@@ -129,9 +130,9 @@ ...@@ -129,9 +130,9 @@
</zip> </zip>
</target> </target>
<target name="bin-zip" depends="jar"> <target name="bin-zip" depends="jar,build-doc">
<exec executable="perl" output="README-binary-dist.html"> <exec executable="perl" output="README-binary-dist.html">
<arg value="tools/Markdown.pl" /> <arg value="${tools.dir}/Markdown.pl" />
<arg value="README-binary-dist.md" /> <arg value="README-binary-dist.md" />
</exec> </exec>
<zip destfile="jastadd2-bin.zip"> <zip destfile="jastadd2-bin.zip">
...@@ -139,6 +140,7 @@ ...@@ -139,6 +140,7 @@
<include name="LICENSE"/> <include name="LICENSE"/>
<include name="ChangeLog"/> <include name="ChangeLog"/>
<include name="jastadd2.jar"/> <include name="jastadd2.jar"/>
<include name="doc/index.html"/>
<include name="doc/reference-manual.html"/> <include name="doc/reference-manual.html"/>
<include name="doc/release-notes.html"/> <include name="doc/release-notes.html"/>
<include name="licenses/*" /> <include name="licenses/*" />
...@@ -175,10 +177,31 @@ ...@@ -175,10 +177,31 @@
</target> </target>
<target name="build-dist" <target name="build-dist"
depends="clean,source-zip,bin-zip"
description="build source and binary distribution files"> description="build source and binary distribution files">
<antcall target="clean"/> </target>
<antcall target="source-zip"/>
<antcall target="bin-zip"/> <target name="build-doc" depends="update-version-string"
description="process documentation Markdown files">
<echo message="Processing Markdown files"/>
<copy file="doc/index.md.in" toFile="doc/index.md" overwrite="true">
<filterset>
<filter token="VERSION" value="${version}"/>
</filterset>
</copy>
<chainedmapper id="mdmapper">
<flattenmapper/>
<globmapper from="*.md" to="doc${file.separator}*.html"/>
</chainedmapper>
<apply executable="perl" dest="doc">
<arg value="${tools.dir}/Markdown.pl"/>
<srcfile/>
<fileset dir="doc" includes="*.md"/>
<mapper refid="mdmapper"/>
<redirector>
<outputmapper refid="mdmapper"/>
</redirector>
</apply>
</target> </target>
<target name="bootstrap" depends="jar" <target name="bootstrap" depends="jar"
......
JastAdd2 Release R20130412 JastAdd2 Release @VERSION@
========================== ==========================
Please view the [ReadMe page][1] for usage and building instructions. Please view the [ReadMe page][1] for usage and building instructions.
......
<?php <?php
include("../../../web/include/functions.php"); include("../../../web/include/functions.php");
printMarkdownFile("index.md"); printHtmlFile("index.html");
?> ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>JastAdd Reference Manual</title>
</head>
<body>
<h1>Reference manual for JastAdd2 R20130412
</h1>
<h3>Index</h3>
<ul>
<li><a href="#AbstractSyntax">Abstract syntax</a>
<ul>
<li><a href="#Predefined">Predefined AST classes</a></li>
<li><a href="#Basic">Basic constructs</a>, <a href="#Naming">Naming</a>, <a href="#Tokens">Tokens</a>, <a href="#Hierarchy">Class hierarchy</a>, <a href="#Inheriting">Inheritance</a>, <a href="#ASTNTAs">NTAs</a></li>
<li><a href="#ListsAndOpts">Lists &amp; Opts</a>, <a href="#creationAPI">Creating</a>, <a href="#JJTree">Using JJTree</a></li>
</ul>
</li>
<li><a href="#Aspects">Aspects</a>
<ul>
<li><a href="#jadd">Aspect files</a>
(defined in .jadd and .jrag files)</li>
<li><a href="#AOPfeatures">Supported AOP features</a>, <a href="#AspectJ">Differences from
AspectJ</a>, <a href="#IdiomPrivate">Idiom for aspect variables</a></li>
</ul>
</li>
<li><a href="#Attributes">Attributes</a>
<ul>
<li><a href="#Synthesized">Synthesized</a>, <a href="#Inherited">inherited</a>, <a href="#Method">method syntax</a>, <a href="#Lazy">lazy/caching</a>, <a href="#RefineAttr">refine</a></li>
<li><a href="#Parameterized">Parameterized</a>, <a href="#Broadcasting">broadcasting</a>, <a href="#Rewrites">rewrites</a>, <a href="#Circular">circular</a>, <a href="#Nonterminal">NTAs</a>, <a href="#Collection">collections</a></li>
</ul>
</li>
<li><a href="#Command">Command line syntax</a></li>
</ul>
<p>&nbsp;</p>
<h2><a name="AbstractSyntax">Abstract syntax</a></h2>
<P>Abstract grammars are specified in .ast files and correspond to a
Java class hierarchy.</P>
<H3><A NAME=Predefined></A>Predefined Java classes in the
hierarchy:</H3>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>Predefined AST class</B></P>
</TD>
<TD>
<P><B>Description</B></P>
</TD>
<TD>
<P><B>Java API for <A NAME=untyped></A>untyped
traversal</B></P>
</TD>
</TR>
<TR>
<TD>
<PRE><A NAME=ASTNode></A>ASTNode</PRE>
</TD>
<TD>
<P>The topmost node in the hierarchy.<BR>
Supports traversal at the relatively "untyped" level of ASTNode.<br />
Children are numbered from 0 to getNumChild()-1.<br />
</P></TD>
<TD>
<PRE>class ASTNode extends Object
implements Iterable {
int getNumChild();
ASTNode getChild(int);
ASTNode getParent();
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE><A NAME=List></A>List</PRE>
</TD>
<TD>
<P>Used to implement lists.<br />
</P></TD>
<TD>
<PRE>class List extends ASTNode { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE><A NAME=Opt></A>Opt</PRE>
</TD>
<TD>
<P>Used to implement optionals.<br />
Has 0 or 1 child.
</P></TD>
<TD>
<PRE>class Opt extends ASTNode { }</PRE>
</TD>
</TR>
</TABLE>
<p><em>Note! </em>The traversal at this &quot;untyped&quot; level includes List and Opt nodes. See also &quot;<a href="#ListsAndOpts">About Lists and Opts</a>&quot;.</p>
<!-- TODO
<p>Example traversal of the complete AST:</p>
<TABLE BORDER = 1>
<TR>
<TD>
<P> <strong>Java 1.4 style traversal </strong></P>
</TD>
<TD>
<P> <strong>Java 5 style traversal </strong></P>
</TD>
</TR>
<TR>
<TD>
<PRE>for (int k=0;k&lt;getNumChild()) {
...getChild(k)...
}</PRE>
</TD>
<TD>
<PRE>for (ASTNode n : this) {
// access each child n here
}</PRE>
</TD>
</TR>
</TABLE>
-->
<p>&nbsp;</p>
<H3>Abstract syntax <A NAME=constructs></A>constructs in the .ast
file</H3>
<!-- TODO: Show List and Opt interfaces individually, before the mixed example. And add getBOpt and getCList ops. -->
<TABLE BORDER=1>
<TR>
<TD>
<P><B><A NAME=Basic></A>Basic constructs</B></P>
</TD>
<TD>
<P></P>
</TD>
<TD>
<P><B><A NAME=typedTraversalAPI>Java API for typed
traversal</A></B></P>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A;</PRE>
</TD>
<TD>
<P>A is an <A NAME=abstract></A>abstract class.<BR>
A corresponds to a nonterminal</P>
</TD>
<TD>
<PRE>abstract class A extends ASTNode { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>B: A ::= ...;</PRE>
</TD>
<TD>
<P>B is a concrete <A NAME=subclass></A>subclass of A<BR>
B corresponds to a production of A</P>
</TD>
<TD>
<PRE>class B extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>C: A ::= A B C;</PRE>
</TD>
<TD>
<P>C has three <A NAME=children></A>children of types A, B,
and C.<BR>
The API supports typed traversal of the children.</P>
</TD>
<TD>
<PRE>class C extends A {
A getA();
B getB();
C getC();</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>D: A;</PRE>
</TD>
<TD>
<P>D has no children.<BR>
D corresponds to an <A NAME=empty></A>empty production of
A</P>
</TD>
<TD>
<PRE>class D extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>E: A ::= A &#91;B&#93; C* &lt;D&gt;;</PRE>
</TD>
<TD>
<P>E has a child of type A, an optional
child of<a name=optional></a> type B, a list of zero or more C children, and a
token of type D.</P>
</TD>
<TD>
<PRE>class E extends A {
A getA();
boolean hasB();
B getB();
int getNumC();
C getC(int);
String getD();
setD(String);
}</PRE>
</TD>
</TR>
</TABLE>
<P></P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B><A NAME=Naming></A>Naming children</B></P>
</TD>
<TD>
<P></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>F: A ::= Foo:A Bar:B;</PRE>
</TD>
<TD>
<P>It is possible to name children.</P>
</TD>
<TD>
<PRE>class F extends A {
A getFoo();
B getBar();
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>G: A ::=
A
First:B
C
Second:B
D;</PRE>
</TD>
<TD>
<P><I>Note!</I> If there is more than one child of the same
type, they <I>must</I> be named. Here there are two children
of type B. They are distinguished with the names "First" and
"Second".</P>
</TD>
<TD>
<PRE>class G extends A {
A getA();
B getFirst();
C getC();
B getSecond();
D getD();
}</PRE>
</TD>
</TR>
</TABLE>
<P></P> <!--Add discussion of intrinsic attributes and inter-ast refs-->
<TABLE BORDER=1>
<TR>
<TD>
<P><B><A NAME=Tokens></A>Typed tokens</B></P>
</TD>
<TD>
<P>Tokens are implictly typed by String. But you can also
give a token an explicit type.</P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T&gt;</PRE>
</TD>
<TD>
<P>Here, T is a token of the Java type String.<BR>
(The set method is intended to be used only by the parser,
to set the token value. This is useful when you are using
JavaCC with JJTree for parsing, since JJTree can construct
the AST nodes for you, but you will need to set the token
values explicitly using the set method.)</P>
</TD>
<TD>
<PRE>class A extends ASTNode {
String getT();
setT(String);
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T:String&gt;</PRE>
</TD>
<TD>
<P>This is equivalent to the example above.</P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T:int&gt;</PRE>
</TD>
<TD>
<P>Here, T is a token of the Java primitive type int.</P>
</TD>
<TD>
<PRE>class A extends ASTNode {
int getT();
setT(int);
}</PRE>
</TD>
</TR>
</TABLE>
<P></P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>Class <A NAME=Hierarchy></A>hierarchy</B></P>
</TD>
<TD>
<P>The class hierarchy can contain any number of levels.</P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<P>For example:</P>
</TD>
<TD>
<PRE>abstract A;
abstract B: A;
C: B;
D: C;</PRE>
</TD>
<TD>
<PRE>abstract class A extends ASTNode { }
abstract class B extends A { }
class C extends B { }
class D extends C { }</PRE>
</TD>
</TR>
</TABLE>
<P></P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B><A NAME=Inheriting></A>Inheriting children</B></P>
</TD>
<TD>
<P></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A ::= B C;
D: A;
E: A;</PRE>
</TD>
<TD>
<P>Children are inherited by subclasses</P>
</TD>
<TD>
<PRE>abstract class A extends ASTNode {
B getB();
C getC();
}
class D extends A { }
class E extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A ::= B C;
D: A ::= F;</PRE>
</TD>
<TD>
<P>Subclasses can add children to those specified by the
superclass.</P>
</TD>
<TD>
<PRE>abstract class A extends ASTNode {
B getB();
C getC();
}
class D extends A {
F getF();
}</PRE>
</TD>
</TR>
<TR>
<TD>
<P>... example to be added ...</P>
</TD>
<TD>
<P>Subclasses can repeat/override children ... (to be
explained)</P>
</TD>
<TD>
<P></P>
</TD>
</TR>
</TABLE>
<P></P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>Nonterminal attributes (<A NAME=ASTNTAs></A>NTAs)</B></P>
</TD>
<TD>
<P></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= B C /D/</PRE>
</TD>
<TD>
<P>A has three children: a B child, a C child, and a D
child. The D child is an NTA (nonterminal attribute): It is
not created by the parser, but must be defined by an
equation. See <A HREF="#Nonterminal">specifying
NTAs</A>.</P>
</TD>
<TD>
<PRE>class A {
B getB();
C getC();
D getD();
}</PRE>
</TD>
</TR>
</TABLE>
<H3>About Lists and Opts<A NAME=ListsAndOpts></A></H3>
<P>The AST representation has additional Opt and List nodes in order
to implement children that are optionals or lists. By using hasX(), getX(), and getX(int), you need not access the Opt and List nodes to traverse the AST. But the Opt and List nodes can be accessed by getXOpt() and getXList(), making it convenient to iterate over the optional/list children. See examples below. Note also that if you use the untyped traversal methods
(getChild(), etc.), you will stop also on the Opt and List nodes.
</P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>.ast construct</B></P>
</TD>
<TD>
<P><B>Java API</B></P>
</TD>
<TD>
<P><B>Example use</B></P>
</TD>
</TR>
<!-- Check Opt in Test case before showing example here.
<TR>
<TD>
<PRE>A ::= &#91;B&#93;</PRE>
</TD>
<TD>
<PRE>class A extends ASTNode {
...
Opt getBOpt();
}</PRE>
</TD>
<TD>
<PRE>A a = ...;
for (B b : getBOpt()) {
// Access b (the optional child).
}
</PRE>
</TD>
</TR>
-->
<TR>
<TD>
<PRE>C ::= D*</PRE>
</TD>
<TD>
<PRE>class C extends ASTNode {
...
List getDList();
}</PRE>
</TD>
<TD>
<PRE>C c = ...;
for (D d : getDList()) {
// Access each d (list children).
}</PRE>
</TD>
</TR>
</TABLE>
<H3><A NAME=creationAPI></A>Creating AST nodes</H3>
<P>Use the following constructor API to create the AST. Typically you create the AST in the action routines of your parser.
But you can of course also create an AST by coding it explicitly, e.g., in a test case. If you use JavaCC+JJTree, see below.</P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>AST class</B></P>
</TD>
<TD>
<P><B>Java API for creating AST nodes</B></P>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= B C &#91;D&#93; E* &lt;G&gt;</PRE>
</TD>
<TD>
<PRE>class A extends ASTNode {
A(B, C, Opt, List, String); //Arguments must not be null
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>ASTList</PRE>
</TD>
<TD>
<PRE>class ASTList extends ASTNode {
ASTList()
ASTList.add(ASTNode); // Returns the same ASTList object
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>ASTOpt</PRE>
</TD>
<TD>
<PRE>class ASTOpt extends ASTNode {
ASTOpt()
ASTOpt(ASTNode); // The argument may be null
}</PRE>
</TD>
</TR>
</TABLE>
<H3>Building ASTs using <A NAME=JJTree></A>JJTree</H3>
If you use JJTree, the creational code is generated. You use the "#X" notation in the JJTree specification to
guide the node creation.
<P>JJTree maintains a stack of created nodes. The "#X" notation
means:</P>
<UL>
<LI>create a new object of type X</LI>
<LI>pop the nodes that were created during this parse method and
insert them as children to the new X node</LI>
<LI>then push the new X node</LI>
</UL>
<P>You need to explicitly create List and Opt nodes. When the parsing
structure does not fit the abstract tree, e.g. when parsing
expressions, you need to use some additional tricks. You also need to
set token values explicitly. An example is available in <A HREF="http://cs.lth.se/kurs/eda180_compiler_construction/assignments/3_tree_building/">assignment 3</A>
in the Lund University compiler course. Download the example zip file and look at the file CalcTree/specification/Parser.jjt .</P>
<H2><A NAME=Aspects>Aspects</A></H2>
<P>JastAdd aspects support <I>intertype declarations</I> for AST
classes. An intertype declaration is a declaration that appears in an
aspect file, but that actually belongs to an AST class. The JastAdd
system reads the aspect files and weaves the intertype declarations
into the appropriate AST classes.</P>
<P>The kinds of intertype declarations that can occur in an aspect
include ordinary Java declarations like methods and fields, and attribute grammar
declarations like attributes, equations, and rewrites.</P>
<P>An aspect file can contain import declarations and one or more
aspects, e.g.:</P>
<PRE> import java.lang.util.*;
aspect A {
abstract public void Stmt.m();
public void WhileStmt.m() { ...&nbsp;}
public void IfStmt.m() { ... }
...
}
aspect B {
private boolean Stmt.count = 0;
}</PRE>
<P>The aspect syntax is similar to AspectJ. But in contrast to
AspectJ, the aspects are not real language constructs. The JastAdd
system simply reads the aspect files and inserts the intertype
declarations into the appropriate AST classes. For example, the
method "m" and its implementations are inserted into classes Stmt,
WhileStmt, and IfStmt. And the declaration of the field "count" is
inserted into the class Stmt. Import declarations are inserted into
all AST classes for which there are intertype declarations in the
aspect. So, the import of java.lang.util.* is inserted into Stmt,
WhileStmt, and IfStmt. For a more detailed discussion on the
similarities and differences between JastAdd aspects and AspectJ, see
<A HREF="#AspectJ">below</A>.</P>
<P>The aspect names, e.g., A and B above, do not show up in the woven Java code. They can be regarded simply as a way to
name the purpose of the aspect, for readability. The aspect names are also used for controlling the order of refine declarations.</P>
<H3>.<A NAME=jadd></A>jadd and .jrag files</H3>
<P>An aspect file can have the suffix .jadd or .jrag. The JastAdd
system does not differ between these two types of files, but we
recommend the following use:</P>
<UL>
<LI>Use .jrag files for declarative aspects, i.e., where you add
attributes, equations, and rewrites to the AST classes</LI>
<LI>Use .jadd files for imperative aspects, i.e., where you add
ordinary fields and methods to the AST classes</LI>
</UL>
<P>It is perfectly fine to not follow this convention, i.e., to mix
both imperative and declarative features in the same aspect, but we
try to follow the convention in our examples in order to enhance the
readability of a system.</P>
<H3><A NAME=example></A>Example <A NAME=imperative></A>imperative
aspect (.jadd)</H3>
<P>Here is an example <em>imperative</em> aspect that adds pretty printing
behavior to some AST classes. Typically, this file would be named
PrettyPrinter.jadd:</P>
<PRE> aspect PrettyPrinter {
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
System.out.println(indent + "while " + getExp().pp(indent + " ") + " do");
getStmt().pp(indent + " ");
}
void IfStmt.pp(String indent) { ...&nbsp;}
...
}</PRE>
<H3>Example <A NAME=declarative></A>declarative aspect (.jrag)</H3>
<P>Here is an example <em>declarative</em> aspect that adds type checking to
some AST classes. Typically, this file would be named
TypeChecking.jrag:</P>
<PRE> import TypeSystem.Type;
aspect TypeChecking {
syn Type Exp.actualType();
inh Type Exp.expectedType();
eq LogicalExp.actualType() = Type.boolean();
eq IdUse.actualType() = decl().getType();
...
eq WhileStmt.getExp().expectedType() = Type.boolean();
syn boolean Exp.typeError() = ! (actualType().equals(expectedType());
}</PRE>
<h3>Supported AOP <A NAME=AOPfeatures></A>features</h3>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>Feature</B></P>
</TD>
<TD>
<P><B>Comment</B></P>
</TD>
</TR>
<TR>
<TD>
<P>intertype declaration of AST fields, methods, and
constructors.</P>
</TD>
<TD>
<P>See the prettyprinting example above. The declarations
are inserted into the corresponding AST classes by the AST
weaver. Any modifiers (public, private, static, etc.), are
interpreted in the context of the AST class. I.e., not as in
AspectJ where the public/private modifiers relate to the
aspect.</P>
</TD>
</TR>
<TR>
<TD>
<P>intertype declaration of attributes, equations, and
rewrites</P>
</TD>
<TD>
<P>See the type checking example above. For more details,
<A HREF="#Attributes">Attributes</A>.</P>
<P>Note that access modifiers (public, private, etc.) are
not supported for attributes. All declared attributes
generate public accessor methods in the AST classes.</P>
</TD>
</TR>
<TR>
<TD>
<P>declare additional interfaces for AST classes</P>
</TD>
<TD>
<P>E.g., in an aspect you can write</P>
<PRE>WhileStmt implements LoopInterface;</PRE>
<P>This will insert an "implements LoopInterface" clause in
the generated WhileStmt class.</P>
</TD>
</TR>
<TR>
<TD>
<P>declare classes and interfaces in an aspect</P>
</TD>
<TD>
<P>E.g., in an aspect you can write</P>
<PRE>interface I { ...&nbsp;}
class C { ... }</PRE>
<P>This is equivalent to declaring the interface and class
in separate ordinary Java files. The possibility to declare
them inside an aspect is just for convenience.</P>
</TD>
</TR>
<TR>
<TD>
<P><a name="refine">refine</a> a method declared in another aspect</P>
<P>(This feature is available in JastAdd version R20051107 and later.)</P>
</TD>
<TD>
<P>Often, it is useful to be able to replace or refine methods declared in another aspect.
This can be done using a "refine" clause. In the following example, the aspect A
declares a method m() in the class C. In the aspect B, the method is replaced,
using a "refine" clause. This is similar to overriding a method in a subclass, but here
the "overridden" method is in the same class, just defined in another aspect.
Inside the body of the refined method, the original method can be called explicitly.
This is similar to a call to super for overriding methods.
</P>
<PRE>
aspect A {
void C.m() { ... }
}
aspect B {
refine A void C.m() { // similar to overriding
...
refined(); // similar to call to super
...
}
}
</PRE>
<P>Note that the refine clause explicitly states which aspect is refined (A in this case).
Additional aspects may further refine the method. For example, an aspect C can refine
the method refined in B.
</P>
<P>The original method can be called using the keyword "refined". JastAdd2 replaces
all occurrences of this keyword with the new name of the refined method. Be careful with
how you use refined - even occurrences in string literals or comments are replaced!
With the command line flag "--refineLegacy" you can use the legacy syntax for calling the
refined method:
</P>
<PRE>
aspect A {
void C.m() { ... }
}
aspect B {
refine A void C.m() { // similar to overriding
...
AspectFile.C.m(); // NB: AspectFile is the name of the file (minus extension) that contains the original declaration
...
}
}
</PRE>
</TD>
</TR>
</TABLE>
<h3>Similarities and differences from
<A NAME=AspectJ></A>AspectJ</h3>
<P>The aspect concept in JastAdd was developed in parallel to the
AspectJ development, and we have gradually adopted the AspectJ
syntax, for features that are similar.</P>
<P>The important similarity between JastAdd aspects and AspectJ
aspects is the intertype declarations. In addition, JastAdd aspects
support attribute grammar features which AspectJ does not. Note,
however, that JastAdd supports intertype declarations only for the
AST classes, not for classes in general like AspectJ. There are many
other features of AspectJ that are not supported in JastAdd,
e.g.:</P>
<UL>
<LI>Fields and methods private to an aspect are not
supported.</LI>
<LI>Declaration of additional parent classes is not
supported.</LI>
<LI>Dynamic features like AspectJ's pointcuts or advice are not
supported.</LI>
</UL>
<h3><A NAME=IdiomPrivate></A>Idiom for private fields and methods</h3>
<P>As mentioned, JastAdd does not support fields and methods that are
private to an aspect. As a workaround idiom, such fields and methods
can be implemented as (non-private) static fields and methods in class ASTNode. As
an example, consider the pretty printer. We might want to
parameterize the prettyprinter so that it can pretty print on any
PrintStream object and not only on System.out. Here is how you could write
this in AspectJ and the corresponding JastAdd implementation:</P>
<TABLE BORDER=1>
<TR>
<TD>
<P><B>AspectJ code</B></P>
</TD>
<TD>
<P><B>JastAdd code</B></P>
</TD>
</TR>
<TR>
<TD>
<PRE>aspect PrettyPrinter {
private PrintStream ppStream = null;
public void prettyprint(ASTNode n, PrintStream s) {
ppStream = s;
n.pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}</PRE>
</TD>
<TD>
<PRE>aspect PrettyPrinter {
static PrintStream ASTNode.ppStream = null;
public void ASTNode.prettyprint(PrintStream s) {
ppStream = s;
pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}</PRE>
</TD>
</TR>
</TABLE>
<h2><a name="Attributes">Attributes</a></h2>
<P>Attributes are specified in <A HREF="#Aspects">JastAdd
aspect files</A>.</P>
<h3 NAME=Basic><A NAME=Basic></A>Basic attribute mechanisms</h3>
<TABLE BORDER=1>
<tbody>
<TR>
<TD WIDTH=266>
<P><B><A NAME=Synthesized></A>Synthesized attributes</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x();</PRE>
</TD>
<TD>
<P>x is a synthesized attribute in class A and of type
T.<BR>
There must be equations defining x in A (if A is concrete)
or in all concrete subclasses of A (if A is abstract).<BR>
<I>Note!</I> Synthesized attributes are conceptually
equivalent to abstract virtual functions (without
side-effects). The main difference is that their values may
be cached (see below). They can be accessed in the same way
as virtual functions. I.e., the declaration generates the
following Java API:</P>
<PRE>T A.x();</PRE>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq A.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
<P>The equation defines the value of the synthesized
attribute x of AST nodes of type A.<BR>
The Java-expression that defines the value must be free from
externally visible side-effects. The context of the
expression is the class A, and any part of the class A's API
may be used in the computation, including accesses to other
attributes.<BR>
<I>Note! </I>Equations defining synthesized attributes are
conceptually equivalent to virtual method
implementations (without side-effects).</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq B.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
<P>Suppose B is a subclass to A. This equation overrides the
corresponding (default) equation for A.x().<BR>
<I>Note! </I>This is equivalent to overriding method
implementations.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<P><B><A NAME=Shorthand></A>Shorthand for synthesized
attributes</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD WIDTH=266 HEIGHT=70>
<PRE>syn T A.x() = <I>Java-expr;</I></PRE>
</TD>
<TD HEIGHT=70>
<P>The declaration of a synthesized attribute and the
(default) equation for it can be written in one clause. So
the clause to the left is equivalent to:</P>
<PRE>syn T A.x();<BR>eq A.x() = <I>Java-expression;</I></PRE>
</TD>
</TR>
</tbody>
</TABLE>
<p></p>
<TABLE BORDER=1>
<tbody>
<TR>
<TD WIDTH=266>
<P><B><A NAME=Inherited></A>Inherited attributes</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T A.y();</PRE>
</TD>
<TD>
<P>y is an inherited attribute in class A and of type T.
There must be equations defining y in all classes that have
children of type A. If a class has several children of type
A, there must be one equation for each of them.</P>
<P>Inherited attributes can be accessed in the same way as
synthesized attributes. I.e., the declaration generates the
following Java API:</P>
<PRE>T A.y();</PRE>
<P><I>Note! </I>Inherited attributes differ from ordinary
virtual functions in that their definitions
(equations/method implementations) are located in the
<I>parent</I> AST node, rather than in the node itself.</P>
<P><I>Note!</I> The concept of <I>inherited</I> attributes
in this Attribute Grammar sense is completely different from
object-oriented inheritance. Both attribute grammars and
object-orientation were invented in the late 60's and the
use of the same term "inheritance" is probably a mere
coincidence: In AGs, inheritance takes place between nodes
in a syntax tree. In OO, inheritance takes place between
classes in a class hierarchy.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq C.getA().y() = <I>Java-expr;</I></PRE>
</TD>
<TD>
<P>This equation defines the value of the inherited attribute
y() of the A child of a C node.<BR>
<I>Note! </I>The Java-expression executes in the context of
C.<BR>
<I>Note!</I> The equation is similar to a method
implementation.<BR>
<I>Note!</I> The equation actually applies to all inherited
attributes y in the subtree rooted at A, provided that they
declare the y attribute. See below under broadcast
attributes.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq D.getA().y() = <I>Java-expr</I>;</PRE>
</TD>
<TD>
<P>Suppose D is a subclass of C. In this case, the equation
overrides the previous one.<BR>
<I>Note!</I> This is analogous to overriding a virtual
method implementation.</P>
</TD>
</TR>
</tbody>
</TABLE>
<p></p>
<TABLE BORDER=1>
<tbody>
<TR>
<TD WIDTH=266>
<P><B><A NAME=Method></A>Method syntax</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x() {<BR> ...<BR> return <I>Java-expr</I>;<BR>}</PRE>
</TD>
<TD>
<P>It is possible to write the computation of an attribute
value as a method body instead of as a single expression.
This may be convenient when the computation is complex.
Inside the method body it is possible to use ordinary
imperative Java code with local variables, assignments,
loops, etc. However, the net result of the computation must
not have any side-effects. (Currently, JastAdd does not check the absence of such side-effects, but future versions might do so.)</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<P><B><A NAME=Lazy></A>Lazy attributes<br />
(cached attributes)
</B></P>
</TD>
<TD>
<P>An attribute can be declared <em>lazy</em> in order to speed up
the evaluation. An attribute that is declared lazy will
automatically have its value is cached after the first
access to it. The next time the attribute is accessed, the
cached value is returned directly. We recommend that
attributes that are expensive to compute and that are
accessed multiple times should be declared lazy. For
example, declaration bindings and type attributes are good
candidates for caching. JastAdd has facilities for automatically computing good cache configurations based on profiling, but this is not yet documented here.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn lazy A.x();</PRE>
</TD>
<TD>
<P>Here, the attribute x of class A is declared lazy.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<P><B><A NAME=RefineAttr></A>Refine attribute</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>refine S eq B.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
<P>Equations defined in one aspect can be refined in another aspect, in the same
way as methods can be refined, see <A HREF="#Aspects">JastAdd
aspect files</A>.
In this example, the equation replaces the corresponding equation declared in the aspect S. The value
from the original equation in S can be accessed by the expression S.B.x()</P>
<P>(This feature is available in JastAdd version R20051107 and later.)</P>
<p>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*refine%5C+.*eq&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">refine eq</a> on Google Code Search.</p>
</TD>
</TR>
</tbody>
</TABLE>
<h3><A NAME=Parameterized></A>Parameterized attributes</h3>
<TABLE BORDER=1><tbody>
<TR>
<TD WIDTH=266>
<P><B>Parameterized attributes</B></P>
</TD>
<TD>
<P>Attributes can have parameters. This is a bit unusual for
attribute grammars, but a natural generalization when you
view attributes as virtual functions.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x(int a);<BR>eq A.x(int a) {<BR> return <I>Java-expr</I>;<BR>}</PRE>
</TD>
<TD>
<P>Here, x is a parameterized synthesized attribute. The
equation is similar to a method implementation and the
argument values can be used in the computation of the resulting
value.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T A.y(int a);<BR>eq C.getA().y(int a) {<BR> return <I>Java-expr</I>;<BR>}</PRE>
</TD>
<TD>
<P>Here, y is a parameterized inherited attribute. The
equation executes in the context of C and can in addition
access the arguments (a in this case).</P>
</TD>
</TR></tbody>
</TABLE>
<h3><A NAME=Broadcasting></A>Broadcasting inherited attributes</h3>
<TABLE BORDER=1><tbody>
<TR>
<TD WIDTH=266>
<P><B>Broadcasting inherited attributes</B></P>
</TD>
<TD>
<P>Often, an inherited attribute is used in a number of
places in a subtree. If basic inherited attributes are used,
the value needs to be copied explicitly using inherited
attributes in all the intermediate nodes. For convenience,
JastAdd supports another technique, namely broadcasting of
an inherited attribute to a complete subtree. An equation
defining an inherited attribute actually broadcasts the
value to the complete subtree of the child. By using this
technique, no explicit copy attributes are needed.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq C.getA().y() = ...;<BR>inh T A.y();</PRE>
</TD>
<TD>
<P>Here, the equation defines an inherited attribute y() declared in
the A child of a C node. This equation actually applies not only to
the inherited y() attribute of the A child, but to all
inherited y() attributes in the whole subtree of A. In order
to for a node N in the subtree to access y(), the attribute
must, however, be exposed by declaring y() as an inherited
attribute of N.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T B.y();</PRE>
</TD>
<TD>
<P>Here, the attribute y() is exposed in B by declaring it as
an inherited attribute there. If there is a B node that is in the subtree rooted at
the A that is a child of a C node, then the equation above
will apply.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266 HEIGHT=22>
<P><B>Overruling broadcast definitions</B></P>
</TD>
<TD HEIGHT=22>
<P>A broadcast definition of an attribute a() applies to all
nodes in a subtree rooted by N. If, however, there is a node
in the subtree which has another equation that defines a()
for a child M, that equation will take precedence for
defining a() in M and its subtree.</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<P><B>Differentiating between children in a list</B></P>
</TD>
<TD>
<P>When defining an inherited attribute of a child node that
is an element of a list, it is sometimes useful to know
which index the child node has. This can be done as
follows:</P>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>C ::= E*;<BR>eq C.getE(int index).y() = ...index...</PRE>
</TD>
<TD>
<P>Here, a C node has a list of E children. When defining
the y() attribute of a given (subtree of an) E child, the
value might depend on the index of the child. For example,
if the E nodes are actual arguments of a procedure, we might
want to pass down the expected type of each argument.</P>
<P>The example equation shows how to declare the index as a
parameter of the getE() method, and to access the index in
the equation body.</P>
</TD>
</TR></tbody>
</TABLE>
<h3><A NAME=Rewrites></A>Rewrites</h3>
<TABLE BORDER=1><tbody>
<TR>
<TD>
<P><B><A NAME=Unconditional></A>Unconditional rewrite
rule</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>rewrite A {<BR> to B {<BR> ...<BR> return <I>exp</I>;<BR> }<BR>}</PRE>
</TD>
<TD>
<P>An A node will be replaced by the node specified in the
Java expression <I>exp</I>. This will happen as soon as the
A node is accessed (by a get() method from its parent), so
if you traverse the tree you will only be able to access the
final rewritten nodes.</P>
<P>A and B must be AST classes.</P>
<P>The <I>exp</I> must be of type B.</P>
<P>Let the set S be the superclasses of A (including A) that
occur on right-hand sides of productions in the abstract
syntax. B must be a subclass of all classes in S. This
guarantees that replacing an A node by a B node does not
break the rules in the abstract syntax.</P>
<P>The code in the body of the rewrite may access and
rearrange the nodes in the subtree rooted at A, but not any
other nodes in the AST. Furthermore, the code may not have
any other side effects.</P>
</TD>
</TR>
<TR>
<TD>
<P><B><A NAME=Conditional></A>Conditional rewrite
rule</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<PRE>rewrite A {<BR> when ( <I>condition</I> )<BR> to B {<BR> ...<BR> return <I>exp</I> <BR> }<BR>}</PRE>
</TD>
<TD>
<P>The conditional rewrite works in the same way as the
unconditional one, but performs the replacement only if the
boolean expression <I>condition</I> is true. The condition
may access anything in the AST, e.g., attributes, other tree
nodes and their attributes, etc.</P>
<p>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*rewrite%5C+.*%5C%7B&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">rewrite</a> on Google Code Search.</p>
</TD>
</TR>
<TR>
<TD>
<P><B><A NAME=Iterative></A>Iterative rewriting</B></P>
</TD>
<TD>
<P>After a node has been replaced according to a rewrite
rule, all conditional rewrite rules are checked again, and a
new rewrite may be performed. This is iterated until no rule
conditions hold.</P>
</TD>
</TR>
<TR>
<TD>
<P><B><A NAME=Order></A>Order of rewriting</B></P>
</TD>
<TD>
<P>At each iteration of rewriting, the rule conditions are
evaluated in a certain order. The first condition that is
true is used for rewriting in that iteration. The order in
which rule condition evaluation occurs is the following:</P>
<UL>
<LI>conditions in superclasses are evaluated before
conditions in subclasses</LI>
<LI>conditions within an aspect file are evaluated in
lexical order</LI>
<LI>conditions in different aspect files are evaluated in
the order the files are listed in the jastadd
command.</LI>
</UL>
</TD>
</TR>
<TR>
<TD>
<P><B><A NAME=Confluency></A>Confluency</B></P>
</TD>
<TD>
<P>If the order of rewriting of a node does not effect the
final result, the rules are said to be <I>confluent</I>.
This is highly desirable, since it makes the specification
more readable to not have to take lexical order of rules
into account. However, JastAdd cannot check that the rules
are confluent. In cases where several conditions for a node
are true at the same time, we recommend that you contemplate
the rules and try to find out if they could be
non-confluent. In that case, we recommend you to refine the
conditions so that only one can apply at a time. This makes
your specification independent of lexical order. Note that
it is often useful to have several different rules that
apply at the same time for a given node, but which are
confluent.</P>
</TD>
</TR>
<TR>
<TD>
<P><B><A NAME=ShorthandRewrite></A>Shorthand
notation</B></P>
</TD>
<TD>
<P></P>
</TD>
</TR>
<TR>
<TD>
<P>If you have several conditional rewrite rules, you may
write them together. So, e.g., writing</P>
<PRE>rewrite A {<BR> when ( <I>condition-1</I> )<BR> to B {<BR> ...<BR> return <I>exp-1</I> <BR> }<BR> when ( <I>condition-2</I> )<BR> to C {<BR> ...<BR> return <I>exp-2</I> <BR> }<BR>}<BR> <BR> </PRE>
</TD>
<TD>
<P>... is equivalent to:</P>
<PRE>rewrite A {<BR> when <I>condition-1</I> <BR> to B {<BR> ...<BR> return <I>exp-1</I> <BR> }<BR>}<BR>rewrite A {<BR> when <I>condition-2</I> <BR> to C {<BR> ...<BR> return <I>exp-2</I> <BR> }<BR>}<BR> </PRE>
</TD>
</TR>
<TR>
<TD>
<P>Sometimes you don't need a block for computing the
resulting node. It may be sufficient with an expression. In
that case, you may simply write the expression instead of
the block, e.g., as follows:</P>
<PRE>rewrite A {<BR> when ( <I>condition-1</I> )<BR> to B <I>exp-1</I> <BR> when ( <I>condition-2</I> )<BR> to C <I>exp-2</I> <BR>}</PRE>
</TD>
<TD>
<P>... which is equivalent to</P>
<PRE>rewrite A {<BR> when ( <I>condition-1</I> )<BR> to B { return <I>exp-1</I> }<BR> when ( <I>condition-2</I> )<BR> to C { <I>return exp-2</I> }<BR>}</PRE>
</TD>
</TR></tbody>
</TABLE>
<h3><A NAME=Circular></A>Circular attributes</h3>
<TABLE BORDER=1> <!--CELLPADDING=2 style="text-align: left; width: 100%;"--><tbody>
<TR>
<TD>
<P><B>Circular attributes</B></P>
</TD>
<TD>
<P>Attributes can be circularly defined. I.e., the value of
the attribute can depend (indirectly) on itself. Circular
attributes are evaluated iteratively, starting with a start
value given in the declaration of the attribute. The
evaluation stops when the value equals that for the previous
iteration.<BR>
Circular attributes are always cached. They do not need to
be declared "lazy".<BR>
If a lazy attribute is circular, but not declared as such,
this will be detected at runtime, and an exception will be
generated.<BR>
To be sure that the evaluation of circular attributes will
converge, the values should be arranged into lattices of
finite height, the bottom values should be used as starting
values, and each equation on the cycle should be monotonic
with respect to the lattices.</P>
</TD>
</TR>
<TR>
<TD>
<PRE>syn T A.x(int a) circular &#91;<span style="font-style: italic;">bv</span>&#93;;<BR>eq A.x(int a) = <span
style="font-style: italic;">rv</span>;<BR><BR></PRE>
</TD>
<TD>
<P>Here, the attribute x is a circular attribute. The
starting value is <span style="font-style: italic;">bv</span>
(a Java expression).<BR>
The equation defines x as having the value computed by the
Java expression <span style="font-style: italic;">rv</span>.
Note that&nbsp; <span style="font-style: italic;">rv</span>
may depend (directly or indirectly) on x.</P>
<p>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*syn.*%5C+circular%5C+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">syn circular </a>at Google Code Search.</p>
<p>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*inh%5C+.*%5C+circular%5C+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">inh circular</a> at Google Code Search.</p>
</TD>
</TR></tbody>
</TABLE>
<h3><a name="Nonterminal"></a>Nonterminal attributes</h3>
<table BORDER=1> <!--style="text-align: left;" class="listing"-->
<tbody>
<tr>
<td>
<p><strong>Newer syntax</strong></p>
<pre>syn nta C A.anNTA() = new C();</pre>
</td>
<td>Nonterminal attributes (NTAs) are nodes in the AST. Whereas normal AST nodes are built by the parser, the NTAs are viewed as attributes and are defined by equations.<br>
<ul><li>NTAs can be inherited or synthesized.</li><li>The value in the equation should be a freshly built AST subtree. It should be complete in the sense that all its children should also be freshly created nodes (i.e., they are not allowed to be initialized to null).</li><li>The NTA can itself have attributes that can be accessed like normal attributes.</li><li>If the NTA has inherited attributes, there must be equations for those attributes in some ancestor, as for normal children.</li><li>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*syn%5C+.*nta%5C+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">syn nta</a> at Google Code Search.</li>
<li>Examples of <a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*inh%5C+.*nta%5C+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">inh nta </a>at Google Code Search. (No matches on 2011-May-03)</li></ul>
</td>
</tr>
<tr>
<td>
<p><strong>Older syntax</strong></p>
</td>
<td>
<p>In the older syntax, you introduce a nonterminal attribute as follows:</p>
<ul><li>Declare the NTA in the ast file, (See also
<a href="#ASTNTAs">NTAs in the abstract syntax</a>).</li><li>Declare the NTA as an attribute in a jrag file. It can be declared as a synthesized or an inherited attribute.
The name of the attribute should be the same as in the <a href="#typedTraversalAPI">AST
traversal API</a>, e.g., <em>getX</em> if the NTA is called <em>X</em>. </li><li>Add equations defining the NTA. The defining value should be a new AST of the appropriate type,
created using the <a href="#creationAPI">AST creation API</a>.
</li></ul>
<p>Note
that if the NTA is a List or an Optional node, you need to create the
appropriate AST with a List or an Opt node as its root. See examples
below.</p>
</td>
</tr>
<tr>
<td>
<p><strong>Simple synthesized NTA</strong></p>
</td>
<td>
<br></td>
</tr>
<tr>
<td>
<em>In an .ast file:</em>
<pre>A ::= B /C/;</pre>
<em> In a .jrag file:</em>
<pre>syn C A.getC() = new C();</pre>
</td>
<td>
<p>The NTA <em>C</em> is declared in the .ast file. It is then declared as a synthesized attribute <em>getC()</em>
in the .jrag file.
The equation is provided directly in the declaration and creates a new <em>C</em> node.</p>
</td>
</tr>
<tr>
<td>
<p><strong>List NTA</strong></p>
</td>
<td>
<br></td>
</tr>
<tr>
<td>
<em>In an .ast file:</em>
<pre>A ::= B /C*/;</pre>
<em>In a .jrag file:</em>
<pre>syn C A.getCList() =
new List().
add(new C()).
add(new C());</pre>
</td>
<td>
<p>The list NTA <em>C*</em> is declared in the .ast file. It is then declared as a synthesized attribute <em>getCList()</em>
(the same name as in the <a href="#ListsAndOpts">implementation
level traversal API</a>) in the .jrag file.
The equation is provided directly in the declaration and creates a <em>List</em> node to which is added a number of
<em>C</em> nodes (two in this example).</p>
</td>
</tr>
</tbody>
</table>
<h3><a name="Collection"></a>Collection attributes</h3>
<table BORDER=1 style="text-align: left;" class="listing">
<tbody>
<tr>
<td>
<p><strong>Collection attributes</strong></p>
</td>
<td>Collection attributes have composite values that are defined by so called <em>contributions</em> that each add a small piece to the composite value. The contributions may be located in any nodes in the AST.</td>
</tr>
<tr>
<td>
<p><strong>Collection attribute declaration</strong></p>
<pre>coll T A.c() [fresh] with m;</pre>
</td>
<td>This example shows a declaration of the collection attribute c in nodetype A, and with type T.<br>
<ul><li>Within square brackets, a Java expression, <em>fresh</em>, should be written that provides a fresh object of type T. For example, new T().</li><li>The composite value will be built by the underlying JastAdd machinery by calling the method m for each contribution.</li><li>The method m, should be a one-argument method of T.</li><li>The method m should mutate the T object by adding a contribution to it.</li><li>The method m should be commutative, in the sense that the order of calling m for different contributions should yield the same resulting T value.&nbsp;</li><li>Examples of&nbsp;<a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*coll%5C+.*%5C%5B+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">coll&nbsp;</a>declarations at Google Code Search.</li></ul>
</td>
</tr>
<tr>
<td>
<p><strong>Contribution declaration</strong></p>
<pre>N1 contributes value-exp
when cond-exp
to N2.a()
for N2-ref-exp;</pre>
</td>
<td>This declares that the nodetype N1 contributes&nbsp;<em>value-exp</em> to a collection attribute N2.a(), or more precisely, to the attribute a in the N2 object denoted by the expression <em>N2-ref-exp</em>.<br>
<ul><li>N<em>2-ref-exp</em> should be a Java expression denoting an object of type N2.</li><li>The <em>value-exp</em> should be a Java expression of the argument type of the method m.</li><li>The contribution is only applied when the boolean condition <em>cond-exp</em> is true.</li><li>The "when"-clause may be omitted.</li></ul>
</td>
</tr>
<tr>
<td>
<p><strong>Contributions to a set of collections</strong></p>
<pre>N1 contributes value-exp
to N2.a()
for each N2-ref-set-exp;</pre>
</td>
<td>
A contribution declaration can define that a certain value is contributed to a whole set of collection attributes by using the "for each" form.<br>
<ul><li>N2-ref-set-exp should denote an object of the Java type java.lang.Iterable, which should contain objects of type N2.</li><li>The contribution is added to each of these N2 objects.</li><li>Examples of&nbsp;<a class="external-link" href="http://www.google.com/codesearch?as_q=%5E.*contributes%5C+&amp;btnG=Search+Code&amp;hl=en&amp;as_lang=&amp;as_license_restrict=i&amp;as_license=&amp;as_package=&amp;as_filename=%5C.%28jrag%7Cjadd%29%24&amp;as_case=y">contribution&nbsp;</a>declarations at Google Code Search.</li></ul>
</td>
</tr>
<tr>
<td>
<p><strong>Scoped collections</strong></p>
<pre>coll N1.a [fresh] with m root R</pre>
</td>
<td>
A collection may be scoped to a certain subtree of the AST. This means that only contributions inside that subtree will be applied when constructing the collection value.
<br>
<ul><li>If R is the same nodetype as N1 (or a subtype of N1), then the subtree root will be the N1 object.</li><li>If R is some other nodetype, the subtree root will be the closets object of type R on the way from N1 towards the AST root.</li>
</td>
</tr>
</table>
<h2><a name="Command"></a>Running JastAdd from the command line</h2>
<h3>Synopsis</h3
>
<PRE>
java -jar jastadd2.jar <I>options arguments</I>
</PRE>
<h3>Options</h3>
<PRE>
--help <I>(prints help text and stops)</I>
--version <I>(prints version information and stops)</I>
--package=PPP <I>(optional package for generated files, default is none)</I>
--o=DDD <I>(optional base output directory, default is current directory)</I>
--beaver <I>(use beaver base node)</I>
--jjtree <I>(use jjtree base node, this requires --grammar to be set)</I>
--grammar=GGG <I>(the parser for the grammar is called GGG, required when using jjtree)</I>
--rewrite <I>(enable ReRAGs support)</I>
--novisitcheck <I>(disable circularity check for attributes)</I>
--noCacheCycle <I>(disable cache cyle optimization for circular attributes)</I>
--java1.4 <I>(generate Java 1.4 source code, rather than Java 5)</I>
</PRE>
<h3>Arguments</h3>
Names of .ast, .jrag and .jadd source files
<h3>Example</h3>
The following command generates classes according to the AST description in Toy.ast.
The generated classes are placed in the package ast. The specifications in the jrag and jadd
files are translated and woven into the generated classes.
<PRE>
java -jar jastadd2.jar --package=ast Toy.ast \
NameAnalysis.jrag TypeAnalysis.jrag PrettyPrinter.jadd
</PRE>
<h3>ANT task</h3>
<p>The options above are also available in an ANT task. For generating Java 1.4 source code, write "java14=true" (without the decimal point). For the other options, use the same names as above.
</p>
</body>
</html>
# Reference manual for JastAdd2
## Index
* [Abstract Syntax](#AbstractSyntax)
* [Predefined AST classes](#Predefined)
* [Basic constructs](#Basic), [Naming](#Naming), [Tokens](#Tokens), [Class hierarchy](#Hierarchy), [Inheritance](#Inheriting), [NTAs](#ASTNTAs)
* [Lists &amp; Opts](#ListsAndOpts), [Creating](#creationAPI), [Using JJTree](#JJTree)
* [Aspects](#Aspects)
* [Aspect files](#jadd) (defined in .jadd and .jrag files)
* [Supported AOP features](#AOPfeatures), [Differences from AspectJ](#AspectJ), [Idiom for aspect variables](#IdiomPrivate)
* [Attributes](#Attributes)
* [Synthesized](#Synthesized), [inherited](#Inherited), [method syntax](#Method), [lazy/caching](#Lazy), [refine](#RefineAttr)
* [Parameterized](#Parameterized), [broadcasting](#Broadcasting), [rewrites](#Rewrites), [circular](#Circular), [NTAs](#Nonterminal), [collections](#Collection)
* [Command line syntax](#Command)
# <a id="AbstractSyntax">Abstract syntax</a>
Abstract grammars are specified in .ast files and correspond to a
Java class hierarchy.
### <a id="Predefined">Predefined Java classes in the hierarchy:</a>
<TABLE BORDER=1>
<TR>
<TD>
<B>Predefined AST class</B>
</TD>
<TD>
<B>Description</B>
</TD>
<TD>
**Java API for <a id="untyped">untyped traversal</a>**
</TD>
</TR>
<TR>
<TD>
<PRE><a id="ASTNode">ASTNode</a></PRE>
</TD>
<TD>
The topmost node in the hierarchy.
Supports traversal at the relatively "untyped" level of ASTNode.<br />
Children are numbered from 0 to getNumChild()-1.<br />
</TD>
<TD>
<PRE>class ASTNode extends Object implements Iterable {
int getNumChild();
ASTNode getChild(int);
ASTNode getParent();
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE><a id="List">List</a></PRE>
</TD>
<TD>
Used to implement lists.
</TD>
<TD>
<PRE>class List extends ASTNode { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE><a id="Opt">Opt</a></PRE>
</TD>
<TD>
Used to implement optionals.
Has 0 or 1 child.
</TD>
<TD>
<PRE>class Opt extends ASTNode { }</PRE>
</TD>
</TR>
</TABLE>
*Note!* The traversal at this &quot;untyped&quot; level includes List and Opt nodes. See also &quot;[About Lists and Opts](#ListsAndOpts)&quot;.
<!--- TODO:
Example traversal of the complete AST:
<TABLE BORDER = 1>
<TR>
<TD>
**Java 1.4 style traversal**
</TD>
<TD>
**Java 5 style traversal**
</TD>
</TR>
<TR>
<TD>
<PRE>for (int k=0;k&lt;getNumChild()) {
...getChild(k)...
}</PRE>
</TD>
<TD>
<PRE>for (ASTNode n : this) {
// access each child n here
}</PRE>
</TD>
</TR>
</TABLE>
-->
### <a id="constructs">Abstract syntax constructs in the .ast file</a>
<!--- TODO: Show List and Opt interfaces individually, before the mixed example. And add getBOpt and getCList ops. -->
<TABLE BORDER=1>
<TR>
<TD>
**<a id="Basic">Basic constructs</a>**
</TD>
<TD></TD>
<TD>
<B><a id="typedTraversalAPI">Java API for typed
traversal</a></B>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A;</PRE>
</TD>
<TD>
<a id="abstract">A is an abstract class.</a><BR>
A corresponds to a nonterminal
</TD>
<TD>
<PRE>abstract class A extends ASTNode { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>B: A ::= ...;</PRE>
</TD>
<TD>
<a id="subclass">B is a concrete subclass of A</a><BR>
B corresponds to a production of A
</TD>
<TD>
<PRE>class B extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>C: A ::= A B C;</PRE>
</TD>
<TD>
C has three <a id="children"></a>children of types A, B, and C.
The API supports typed traversal of the children.
</TD>
<TD>
<PRE>class C extends A {
A getA();
B getB();
C getC();</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>D: A;</PRE>
</TD>
<TD>
D has no children.
D corresponds to an <a id="empty"></a>empty production of A
</TD>
<TD>
<PRE>class D extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>E: A ::= A &#91;B&#93; C* &lt;D&gt;;</PRE>
</TD>
<TD>
E has a child of type A, an optional child of<a id="optional"></a> type B, a
list of zero or more C children, and a token of type D.
</TD>
<TD>
<PRE>class E extends A {
A getA();
boolean hasB();
B getB();
int getNumC();
C getC(int);
String getD();
setD(String);
}</PRE>
</TD>
</TR>
</TABLE>
<TABLE BORDER=1>
<TR>
<TD>
<B><a id="Naming"></a>Naming children</B>
</TD>
<TD></TD>
<TD></TD>
</TR>
<TR>
<TD>
<PRE>F: A ::= Foo:A Bar:B;</PRE>
</TD>
<TD>
It is possible to name children.
</TD>
<TD>
<PRE>class F extends A {
A getFoo();
B getBar();
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>G: A ::=
A
First:B
C
Second:B
D;</PRE>
</TD>
<TD>
*Note!* If there is more than one child of the same type, they *must* be named.
Here there are two children of type B. They are distinguished with the names
"First" and "Second".
</TD>
<TD>
<PRE>class G extends A {
A getA();
B getFirst();
C getC();
B getSecond();
D getD();
}</PRE>
</TD>
</TR>
</TABLE>
<!--- TODO Add discussion of intrinsic attributes and inter-ast refs-->
<TABLE BORDER=1>
<TR>
<TD>
<B><a id="Tokens"></a>Typed tokens</B>
</TD>
<TD>
Tokens are implictly typed by String. But you can also give a token an explicit
type.
</TD>
<TD></TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T&gt;</PRE>
</TD>
<TD>
Here, T is a token of the Java type String.<BR> (The set method is intended to
be used only by the parser, to set the token value. This is useful when you are
using JavaCC with JJTree for parsing, since JJTree can construct the AST nodes
for you, but you will need to set the token values explicitly using the set
method.)
</TD>
<TD>
<PRE>class A extends ASTNode {
String getT();
setT(String);
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T:String&gt;</PRE>
</TD>
<TD>
This is equivalent to the example above.
</TD>
<TD>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= &lt;T:int&gt;</PRE>
</TD>
<TD>
Here, T is a token of the Java primitive type int.
</TD>
<TD>
<PRE>class A extends ASTNode {
int getT();
setT(int);
}</PRE>
</TD>
</TR>
</TABLE>
<TABLE BORDER=1>
<TR>
<TD>
<B>Class <a id="Hierarchy"></a>hierarchy</B>
</TD>
<TD>
The class hierarchy can contain any number of levels.
</TD>
<TD></TD>
</TR>
<TR>
<TD>
For example:
</TD>
<TD>
<PRE>abstract A;
abstract B: A;
C: B;
D: C;</PRE>
</TD>
<TD>
<PRE>abstract class A extends ASTNode { }
abstract class B extends A { }
class C extends B { }
class D extends C { }</PRE>
</TD>
</TR>
</TABLE>
<TABLE BORDER=1>
<TR>
<TD>
<B><a id="Inheriting"></a>Inheriting children</B>
</TD>
<TD>
</TD>
<TD>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A ::= B C;
D: A;
E: A;</PRE>
</TD>
<TD>
Children are inherited by subclasses
</TD>
<TD>
<PRE>abstract class A extends ASTNode {
B getB();
C getC();
}
class D extends A { }
class E extends A { }</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>abstract A ::= B C;
D: A ::= F;</PRE>
</TD>
<TD>
Subclasses can add children to those specified by the
superclass.
</TD>
<TD>
<PRE>abstract class A extends ASTNode {
B getB();
C getC();
}
class D extends A {
F getF();
}</PRE>
</TD>
</TR>
<TR>
<TD>
... example to be added ...
</TD>
<TD>
Subclasses can repeat/override children ... (to be explained)
</TD>
<TD> </TD>
</TR>
</TABLE>
<TABLE BORDER=1>
<TR>
<TD>
<B>Nonterminal attributes (<a id="ASTNTAs"></a>NTAs)</B>
</TD>
<TD> </TD>
<TD> </TD>
</TR>
<TR>
<TD>
<PRE>A ::= B C /D/</PRE>
</TD>
<TD>
A has three children: a B child, a C child, and a D child. The D child is an
NTA (nonterminal attribute): It is not created by the parser, but must be
defined by an equation. See [specifying NTAs](#Nonterminal).
</TD>
<TD>
<PRE>class A {
B getB();
C getC();
D getD();
}</PRE>
</TD>
</TR>
</TABLE>
### About Lists and Opts<a id="ListsAndOpts"></a>
The AST representation has additional Opt and List nodes in order
to implement children that are optionals or lists. By using hasX(), getX(), and getX(int), you need not access the Opt and List nodes to traverse the AST. But the Opt and List nodes can be accessed by getXOpt() and getXList(), making it convenient to iterate over the optional/list children. See examples below. Note also that if you use the untyped traversal methods
(getChild(), etc.), you will stop also on the Opt and List nodes.
<TABLE BORDER=1>
<TR>
<TD>
<B>.ast construct</B>
</TD>
<TD>
<B>Java API</B>
</TD>
<TD>
<B>Example use</B>
</TD>
</TR>
<!--- TODO: Check Opt in Test case before showing example here.
<TR>
<TD>
<PRE>A ::= &#91;B&#93;</PRE>
</TD>
<TD>
<PRE>class A extends ASTNode {
...
Opt getBOpt();
}</PRE>
</TD>
<TD>
<PRE>A a = ...;
for (B b : getBOpt()) {
// Access b (the optional child).
}
</PRE>
</TD>
</TR>
-->
<TR>
<TD>
<PRE>C ::= D*</PRE>
</TD>
<TD>
<PRE>class C extends ASTNode {
...
List getDList();
}</PRE>
</TD>
<TD>
<PRE>C c = ...;
for (D d : getDList()) {
// Access each d (list children).
}</PRE>
</TD>
</TR>
</TABLE>
### <a id="creationAPI"></a>Creating AST nodes
Use the following constructor API to create the AST. Typically you create the
AST in the action routines of your parser. But you can of course also create
an AST by coding it explicitly, e.g., in a test case. If you use JavaCC+JJTree,
see below.
<TABLE BORDER=1>
<TR>
<TD>
<B>AST class</B>
</TD>
<TD>
<B>Java API for creating AST nodes</B>
</TD>
</TR>
<TR>
<TD>
<PRE>A ::= B C &#91;D&#93; E* &lt;G&gt;</PRE>
</TD>
<TD>
<PRE>class A extends ASTNode {
A(B, C, Opt, List, String); //Arguments must not be null
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>ASTList</PRE>
</TD>
<TD>
<PRE>class ASTList extends ASTNode {
ASTList();
add(ASTNode); // Returns the same ASTList object
}</PRE>
</TD>
</TR>
<TR>
<TD>
<PRE>ASTOpt</PRE>
</TD>
<TD>
<PRE>class ASTOpt extends ASTNode {
ASTOpt();
ASTOpt(ASTNode); // The argument may be null
}</PRE>
</TD>
</TR>
</TABLE>
### Building ASTs using <a id="JJTree"></a>JJTree
If you use JJTree, the creational code is generated. You use the "#X" notation
in the JJTree specification to guide the node creation.
JJTree maintains a stack of created nodes. The "#X" notation means:
* create a new object of type X
* pop the nodes that were created during this parse method and
insert them as children to the new X node
* then push the new X node
You need to explicitly create List and Opt nodes. When the parsing structure
does not fit the abstract tree, e.g. when parsing expressions, you need to use
some additional tricks. You also need to set token values explicitly. An
example is available in [assignment
3](http://cs.lth.se/kurs/eda180_compiler_construction/assignments/3_tree_building/)
in the Lund University compiler course. Download the example zip file and look
at the file CalcTree/specification/Parser.jjt .
### <a id="Aspects">Aspects</a>
JastAdd aspects support <I>intertype declarations</I> for AST classes. An
intertype declaration is a declaration that appears in an aspect file, but that
actually belongs to an AST class. The JastAdd system reads the aspect files and
weaves the intertype declarations into the appropriate AST classes.
The kinds of intertype declarations that can occur in an aspect include
ordinary Java declarations like methods and fields, and attribute grammar
declarations like attributes, equations, and rewrites.
An aspect file can contain import declarations and one or more aspects, e.g.:
import java.lang.util.*;
aspect A {
abstract public void Stmt.m();
public void WhileStmt.m() { ... }
public void IfStmt.m() { ... }
...
}
aspect B {
private boolean Stmt.count = 0;
}
The aspect syntax is similar to AspectJ. But in contrast to AspectJ, the
aspects are not real language constructs. The JastAdd system simply reads the
aspect files and inserts the intertype declarations into the appropriate AST
classes. For example, the method "m" and its implementations are inserted into
classes Stmt, WhileStmt, and IfStmt. And the declaration of the field "count"
is inserted into the class Stmt. Import declarations are inserted into all AST
classes for which there are intertype declarations in the aspect. So, the
import of java.lang.util.* is inserted into Stmt, WhileStmt, and IfStmt. For a
more detailed discussion on the similarities and differences between JastAdd
aspects and AspectJ, see [below](#AspectJ).
The aspect names, e.g., A and B above, do not show up in the woven Java code.
They can be regarded simply as a way to name the purpose of the aspect, for
readability. The aspect names are also used for controlling the order of refine
declarations.
### <a id="jadd">.jadd and .jrag files</a>
An aspect file can have the suffix .jadd or .jrag. The JastAdd system does not
differ between these two types of files, but we recommend the following use:
* Use .jrag files for declarative aspects, i.e., where you add
attributes, equations, and rewrites to the AST classes
* Use .jadd files for imperative aspects, i.e., where you add
ordinary fields and methods to the AST classes
It is perfectly fine to not follow this convention, i.e., to mix both
imperative and declarative features in the same aspect, but we try to follow
the convention in our examples in order to enhance the readability of a system.
### <a id="example"></a>Example <a id="imperative"></a> imperative aspect (.jadd)
Here is an example <em>imperative</em> aspect that adds pretty printing
behavior to some AST classes. Typically, this file would be named
PrettyPrinter.jadd:
aspect PrettyPrinter {
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
System.out.println(indent + "while " + getExp().pp(indent + " ") + " do");
getStmt().pp(indent + " ");
}
void IfStmt.pp(String indent) { ... }
...
}
### Example <a id="declarative"></a>declarative aspect (.jrag)
Here is an example <em>declarative</em> aspect that adds type checking to some
AST classes. Typically, this file would be named TypeChecking.jrag:
import TypeSystem.Type;
aspect TypeChecking {
syn Type Exp.actualType();
inh Type Exp.expectedType();
eq LogicalExp.actualType() = Type.boolean();
eq IdUse.actualType() = decl().getType();
...
eq WhileStmt.getExp().expectedType() = Type.boolean();
syn boolean Exp.typeError() = ! (actualType().equals(expectedType());
}
### Supported AOP <a id="AOPfeatures"></a>features
<TABLE BORDER=1>
<TR>
<TD>
<B>Feature</B>
</TD>
<TD>
<B>Comment</B>
</TD>
</TR>
<TR>
<TD>
intertype declaration of AST fields, methods, and
constructors.
</TD>
<TD>
See the prettyprinting example above. The declarations are inserted into the
corresponding AST classes by the AST weaver. Any modifiers (public, private,
static, etc.), are interpreted in the context of the AST class. I.e., not as in
AspectJ where the public/private modifiers relate to the aspect.
</TD>
</TR>
<TR>
<TD>
intertype declaration of attributes, equations, and
rewrites
</TD>
<TD>
See the type checking example above. For more details,
[Attributes](#Attributes).
Note that access modifiers (public, private, etc.) are not supported for
attributes. All declared attributes generate public accessor methods in the AST
classes.
</TD>
</TR>
<TR>
<TD>
declare additional interfaces for AST classes
</TD>
<TD>
E.g., in an aspect you can write
<PRE>WhileStmt implements LoopInterface;</PRE>
This will insert an "implements LoopInterface" clause in
the generated WhileStmt class.
</TD>
</TR>
<TR>
<TD>
declare classes and interfaces in an aspect
</TD>
<TD>
E.g., in an aspect you can write
<PRE>interface I { ... }
class C { ... }</PRE>
This is equivalent to declaring the interface and class
in separate ordinary Java files. The possibility to declare
them inside an aspect is just for convenience.
</TD>
</TR>
<TR>
<TD>
<a id="refine">refine</a> a method declared in another aspect
(This feature is available in JastAdd version R20051107 and later.)
</TD>
<TD>
Often, it is useful to be able to replace or refine methods declared in
another aspect. This can be done using a "refine" clause. In the following
example, the aspect A declares a method m() in the class C. In the aspect B,
the method is replaced, using a "refine" clause. This is similar to overriding
a method in a subclass, but here the "overridden" method is in the same class,
just defined in another aspect. Inside the body of the refined method, the
original method can be called explicitly. This is similar to a call to super
for overriding methods.
<PRE>aspect A {
void C.m() { ... }
}
aspect B {
refine A void C.m() { // similar to overriding
...
refined(); // similar to call to super
...
}
}</PRE>
Note that the refine clause explicitly states which aspect is refined (A in
this case). Additional aspects may further refine the method. For example, an
aspect C can refine the method refined in B.
The original method can be called using the keyword "refined". JastAdd2
replaces all occurrences of this keyword with the new name of the refined
method. Be careful with how you use refined - even occurrences in string
literals or comments are replaced! With the command line flag "--refineLegacy"
you can use the legacy syntax for calling the refined method:
<PRE>aspect A {
void C.m() { ... }
}
aspect B {
refine A void C.m() { // similar to overriding
...
AspectFile.C.m();
...
}
}</PRE>
*Note:* AspectFile is the name of the file (minus extension) that contains the
original declaration.
</TD>
</TR>
</TABLE>
### <a id="AspectJ">Similarities and differences from AspectJ</a>
The aspect concept in JastAdd was developed in parallel to the AspectJ
development, and we have gradually adopted the AspectJ syntax, for features
that are similar. The important similarity between JastAdd aspects and AspectJ
aspects is the intertype declarations. In addition, JastAdd aspects support
attribute grammar features which AspectJ does not. Note, however, that JastAdd
supports intertype declarations only for the AST classes, not for classes in
general like AspectJ. There are many other features of AspectJ that are not
supported in JastAdd, e.g.:
* Fields and methods private to an aspect are not
supported.
* Declaration of additional parent classes is not
supported.
* Dynamic features like AspectJ's pointcuts or advice are not
supported.
</UL>
### <a id="IdiomPrivate"></a>Idiom for private fields and methods
As mentioned, JastAdd does not support fields and methods that are private to
an aspect. As a workaround idiom, such fields and methods can be implemented as
(non-private) static fields and methods in class ASTNode. As an example,
consider the pretty printer. We might want to parameterize the prettyprinter so
that it can pretty print on any PrintStream object and not only on System.out.
Here is how you could write this in AspectJ and the corresponding JastAdd
implementation:
<TABLE BORDER=1>
<TR>
<TD>
<B>AspectJ code</B>
</TD>
<TD>
<B>JastAdd code</B>
</TD>
</TR>
<TR>
<TD>
<PRE>aspect PrettyPrinter {
private PrintStream ppStream = null;
public void prettyprint(ASTNode n, PrintStream s) {
ppStream = s;
n.pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}</PRE>
</TD>
<TD>
<PRE>aspect PrettyPrinter {
static PrintStream ASTNode.ppStream = null;
public void ASTNode.prettyprint(PrintStream s) {
ppStream = s;
pp("");
ppStream = null;
}
void ASTNode.pp(String indent) { }
void WhileStmt.pp(String indent) {
...
ppStream.println(...);
...
}
...
}</PRE>
</TD>
</TR>
</TABLE>
<h2><a id="Attributes">Attributes</a></h2>
Attributes are specified in [JastAdd aspect files](#Aspects).
### <a id="Basic"></a>Basic attribute mechanisms
<TABLE BORDER=1>
<TR>
<TD WIDTH=266>
<B><a id="Synthesized"></a>Synthesized attributes</B>
</TD>
<TD>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x();</PRE>
</TD>
<TD>
x is a synthesized attribute in class A and of type T.
There must be equations defining x in A (if A is concrete) or in all concrete
subclasses of A (if A is abstract).
*Note!* Synthesized attributes are conceptually equivalent to abstract
virtual functions (without side-effects). The main difference is that their
values may be cached (see below). They can be accessed in the same way as
virtual functions. I.e., the declaration generates the following Java API:
<PRE>T A.x();</PRE>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq A.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
The equation defines the value of the synthesized attribute x of AST nodes of
type A.
The Java-expression that defines the value must be free from externally visible
side-effects. The context of the expression is the class A, and any part of the
class A's API may be used in the computation, including accesses to other
attributes.
*Note!* Equations defining synthesized attributes are conceptually
equivalent to virtual method implementations (without side-effects).
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq B.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
Suppose B is a subclass to A. This equation overrides the
corresponding (default) equation for A.x().
*Note!* This is equivalent to overriding method
implementations.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<B><a id="Shorthand"></a>Shorthand for synthesized
attributes</B>
</TD>
<TD></TD>
</TR>
<TR>
<TD WIDTH=266 HEIGHT=70>
<PRE>syn T A.x() = <I>Java-expr;</I></PRE>
</TD>
<TD HEIGHT=70>
The declaration of a synthesized attribute and the
(default) equation for it can be written in one clause. So
the clause to the left is equivalent to:
<PRE>syn T A.x();
eq A.x() = <I>Java-expression;</I></PRE>
</TD>
</TR>
</tbody>
</TABLE>
<TABLE BORDER=1>
<tbody>
<TR>
<TD WIDTH=266>
<B><a id="Inherited"></a>Inherited attributes</B>
</TD>
<TD>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T A.y();</PRE>
</TD>
<TD>
y is an inherited attribute in class A and of type T.
There must be equations defining y in all classes that have
children of type A. If a class has several children of type
A, there must be one equation for each of them.
Inherited attributes can be accessed in the same way as
synthesized attributes. I.e., the declaration generates the
following Java API:
<PRE>T A.y();</PRE>
<I>Note! </I>Inherited attributes differ from ordinary
virtual functions in that their definitions
(equations/method implementations) are located in the
<I>parent</I> AST node, rather than in the node itself.
<I>Note!</I> The concept of <I>inherited</I> attributes
in this Attribute Grammar sense is completely different from
object-oriented inheritance. Both attribute grammars and
object-orientation were invented in the late 60's and the
use of the same term "inheritance" is probably a mere
coincidence: In AGs, inheritance takes place between nodes
in a syntax tree. In OO, inheritance takes place between
classes in a class hierarchy.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq C.getA().y() = <I>Java-expr;</I></PRE>
</TD>
<TD>
This equation defines the value of the inherited attribute
y() of the A child of a C node.
<I>Note! </I>The Java-expression executes in the context of
C.
<I>Note!</I> The equation is similar to a method
implementation.
<I>Note!</I> The equation actually applies to all inherited
attributes y in the subtree rooted at A, provided that they
declare the y attribute. See below under broadcast
attributes.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq D.getA().y() = <I>Java-expr</I>;</PRE>
</TD>
<TD>
Suppose D is a subclass of C. In this case, the equation
overrides the previous one.
<I>Note!</I> This is analogous to overriding a virtual
method implementation.
</TD>
</TR>
</tbody>
</TABLE>
<TABLE BORDER=1>
<tbody>
<TR>
<TD WIDTH=266>
<B><a id="Method"></a>Method syntax</B>
</TD>
<TD>
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x() {
...
return <I>Java-expr</I>;
}</PRE>
</TD>
<TD>
It is possible to write the computation of an attribute value as a method body
instead of as a single expression. This may be convenient when the computation
is complex. Inside the method body it is possible to use ordinary imperative
Java code with local variables, assignments, loops, etc. However, the net
result of the computation must not have any side-effects. (Currently, JastAdd
does not check the absence of such side-effects, but future versions might do
so.)
</TD>
</TR>
<TR>
<TD WIDTH=266>
**<a id="Lazy"></a>Lazy attributes**<br /> (cached attributes)
</TD>
<TD>
An attribute can be declared <em>lazy</em> in order to speed up the evaluation.
An attribute that is declared lazy will automatically have its value is cached
after the first access to it. The next time the attribute is accessed, the
cached value is returned directly. We recommend that attributes that are
expensive to compute and that are accessed multiple times should be declared
lazy. For example, declaration bindings and type attributes are good candidates
for caching. JastAdd has facilities for automatically computing good cache
configurations based on profiling, but this is not yet documented here.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn lazy A.x();</PRE>
</TD>
<TD>
Here, the attribute x of class A is declared lazy.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<B><a id="RefineAttr"></a>Refine attribute</B>
</TD>
<TD> </TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>refine S eq B.x() = <I>Java-expr;</I></PRE>
</TD>
<TD>
Equations defined in one aspect can be refined in another aspect, in the same
way as methods can be refined, see [JastAdd aspect files](#Aspects). In this
example, the equation replaces the corresponding equation declared in the
aspect S. The value from the original equation in S can be accessed by the
expression S.B.x() (This feature is available in JastAdd version R20051107 and
later.)
</TD>
</TR>
</tbody>
</TABLE>
### <a id="Parameterized"></a>Parameterized attributes
<TABLE BORDER=1><tbody>
<TR>
<TD WIDTH=266>
<B>Parameterized attributes</B>
</TD>
<TD>
Attributes can have parameters. This is a bit unusual for attribute grammars,
but a natural generalization when you view attributes as virtual functions.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>syn T A.x(int a);
eq A.x(int a) {
return <I>Java-expr</I>;
}</PRE>
</TD>
<TD>
Here, x is a parameterized synthesized attribute. The equation is similar to a
method implementation and the argument values can be used in the computation of
the resulting value.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T A.y(int a);
eq C.getA().y(int a) {
return <I>Java-expr</I>;
}</PRE>
</TD>
<TD>
Here, y is a parameterized inherited attribute. The equation executes in the
context of C and can in addition access the arguments (a in this case).
</TD>
</TR></tbody>
</TABLE>
### <a id="Broadcasting"></a>Broadcasting inherited attributes
<TABLE BORDER=1><tbody>
<TR>
<TD WIDTH=266>
<B>Broadcasting inherited attributes</B>
</TD>
<TD>
Often, an inherited attribute is used in a number of places in a subtree. If
basic inherited attributes are used, the value needs to be copied explicitly
using inherited attributes in all the intermediate nodes. For convenience,
JastAdd supports another technique, namely broadcasting of an inherited
attribute to a complete subtree. An equation defining an inherited attribute
actually broadcasts the value to the complete subtree of the child. By using
this technique, no explicit copy attributes are needed.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>eq C.getA().y() = ...;
inh T A.y();</PRE>
</TD>
<TD>
Here, the equation defines an inherited attribute y() declared in the A child
of a C node. This equation actually applies not only to the inherited y()
attribute of the A child, but to all inherited y() attributes in the whole
subtree of A. In order to for a node N in the subtree to access y(), the
attribute must, however, be exposed by declaring y() as an inherited attribute
of N.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>inh T B.y();</PRE>
</TD>
<TD>
Here, the attribute y() is exposed in B by declaring it as an inherited
attribute there. If there is a B node that is in the subtree rooted at the A
that is a child of a C node, then the equation above will apply.
</TD>
</TR>
<TR>
<TD WIDTH=266 HEIGHT=22>
<B>Overruling broadcast definitions</B>
</TD>
<TD HEIGHT=22>
A broadcast definition of an attribute a() applies to all nodes in a subtree
rooted by N. If, however, there is a node in the subtree which has another
equation that defines a() for a child M, that equation will take precedence for
defining a() in M and its subtree.
</TD>
</TR>
<TR>
<TD WIDTH=266>
<B>Differentiating between children in a list</B>
</TD>
<TD>
When defining an inherited attribute of a child node that
is an element of a list, it is sometimes useful to know
which index the child node has. This can be done as
follows:
</TD>
</TR>
<TR>
<TD WIDTH=266>
<PRE>C ::= E*;
eq C.getE(int index).y() = ...index...</PRE>
</TD>
<TD>
Here, a C node has a list of E children. When defining the y() attribute of a
given (subtree of an) E child, the value might depend on the index of the
child. For example, if the E nodes are actual arguments of a procedure, we
might want to pass down the expected type of each argument.
The example equation shows how to declare the index as a parameter of the
getE() method, and to access the index in the equation body.
</TD>
</TR></tbody>
</TABLE>
### <a id="Rewrites"></a>Rewrites
<TABLE BORDER=1><tbody>
<TR>
<TD>
<B><a id="Unconditional"></a>Unconditional rewrite
rule</B>
</TD>
<TD> </TD>
</TR>
<TR>
<TD>
<PRE>rewrite A {
to B {
...
return <I>exp</I>;
}
}</PRE>
</TD>
<TD>
An A node will be replaced by the node specified in the Java expression
<I>exp</I>. This will happen as soon as the A node is accessed (by a get()
method from its parent), so if you traverse the tree you will only be able to
access the final rewritten nodes.
A and B must be AST classes.
The <I>exp</I> must be of type B.
Let the set S be the superclasses of A (including A) that occur on right-hand
sides of productions in the abstract syntax. B must be a subclass of all
classes in S. This guarantees that replacing an A node by a B node does not
break the rules in the abstract syntax.
The code in the body of the rewrite may access and rearrange the nodes in the
subtree rooted at A, but not any other nodes in the AST. Furthermore, the code
may not have any other side effects.
</TD>
</TR>
<TR>
<TD>
<B><a id="Conditional"></a>Conditional rewrite
rule</B>
</TD>
<TD>
</TD>
</TR>
<TR>
<TD>
<PRE>rewrite A {
when ( <I>condition</I> )
to B {
...
return <I>exp</I>;
}
}</PRE>
</TD>
<TD>
The conditional rewrite works in the same way as the unconditional one, but
performs the replacement only if the boolean expression <I>condition</I> is
true. The condition may access anything in the AST, e.g., attributes, other
tree nodes and their attributes, etc.
</TD>
</TR>
<TR>
<TD>
<B><a id="Iterative"></a>Iterative rewriting</B>
</TD>
<TD>
After a node has been replaced according to a rewrite rule, all conditional
rewrite rules are checked again, and a new rewrite may be performed. This is
iterated until no rule conditions hold.
</TD>
</TR>
<TR>
<TD>
<B><a id="Order"></a>Order of rewriting</B>
</TD>
<TD>
At each iteration of rewriting, the rule conditions are evaluated in a certain
order. The first condition that is true is used for rewriting in that
iteration. The order in which rule condition evaluation occurs is the
following:
* conditions in superclasses are evaluated before conditions in subclasses
* conditions within an aspect file are evaluated in lexical order
* conditions in different aspect files are evaluated in the order the files are
listed in the jastadd command.
</TR>
<TR>
<TD>
**<a id="Confluency"></a>Confluency**
</TD>
<TD>
If the order of rewriting of a node does not effect the final result, the rules
are said to be *confluent*. This is highly desirable, since it makes the
specification more readable to not have to take lexical order of rules into
account. However, JastAdd cannot check that the rules are confluent. In cases
where several conditions for a node are true at the same time, we recommend
that you contemplate the rules and try to find out if they could be
non-confluent. In that case, we recommend you to refine the conditions so that
only one can apply at a time. This makes your specification independent of
lexical order. Note that it is often useful to have several different rules
that apply at the same time for a given node, but which are confluent.
</TD>
</TR>
<TR>
<TD>
<B><a id="ShorthandRewrite"></a>Shorthand
notation</B>
</TD>
<TD> </TD>
</TR>
<TR>
<TD>
If you have several conditional rewrite rules, you may write them together. So,
e.g., writing
<PRE>rewrite A {
when ( <I>condition-1</I> )
to B {
...
return <I>exp-1</I>
}
when ( <I>condition-2</I> )
to C {
...
return <I>exp-2</I>
}
}</PRE>
</TD>
<TD>
... is equivalent to:
<PRE>rewrite A {
when <I>condition-1</I>
to B {
...
return <I>exp-1</I>
}
}
rewrite A {
when <I>condition-2</I>
to C {
...
return <I>exp-2</I>
}
}</PRE>
</TD>
</TR>
<TR>
<TD>
Sometimes you don't need a block for computing the resulting node. It may be
sufficient with an expression. In that case, you may simply write the
expression instead of the block, e.g., as follows:
<PRE>rewrite A {
when ( <I>condition-1</I> )
to B <I>exp-1</I>
when ( <I>condition-2</I> )
to C <I>exp-2</I>
}</PRE>
</TD>
<TD>
... which is equivalent to
<PRE>rewrite A {
when ( <I>condition-1</I> )
to B { return <I>exp-1</I> }
when ( <I>condition-2</I> )
to C { <I>return exp-2</I> }
}</PRE>
</TD>
</TR></tbody>
</TABLE>
### <a id="Circular"></a>Circular attributes
<TABLE BORDER=1><tbody>
<TR>
<TD>
<B>Circular attributes</B>
</TD>
<TD>
Attributes can be circularly defined. I.e., the value of the attribute can
depend (indirectly) on itself. Circular attributes are evaluated iteratively,
starting with a start value given in the declaration of the attribute. The
evaluation stops when the value equals that for the previous iteration.
Circular attributes are always cached. They do not need to be declared "lazy".
If a lazy attribute is circular, but not declared as such, this will be
detected at runtime, and an exception will be generated.<BR> To be sure that
the evaluation of circular attributes will converge, the values should be
arranged into lattices of finite height, the bottom values should be used as
starting values, and each equation on the cycle should be monotonic with
respect to the lattices.
</TD>
</TR>
<TR>
<TD>
<PRE>syn T A.x(int a) circular &#91;<span style="font-style: italic;">bv</span>&#93;;
eq A.x(int a) = <span style="font-style: italic;">rv</span>;</PRE>
</TD>
<TD>
Here, the attribute x is a circular attribute. The starting value is <span
style="font-style: italic;">bv</span> (a Java expression).
The equation defines x as having the value computed by the Java expression
`rv`. Note that `rv` may depend (directly or indirectly) on x.
</TD>
</TR></tbody>
</TABLE>
### <a id="Nonterminal"></a>Nonterminal attributes
<TABLE BORDER="1">
<tr>
<td>
**Newer syntax**
<pre>syn nta C A.anNTA() = new C();</pre>
</td>
<td>
Nonterminal attributes (NTAs) are nodes in the AST. Whereas normal AST nodes
are built by the parser, the NTAs are viewed as attributes and are defined by
equations.
* NTAs can be inherited or synthesized.
* The value in the equation should be a freshly built AST subtree. It should
be complete in the sense that all its children should also be freshly
created nodes (i.e., they are not allowed to be initialized to null).
* The NTA can itself have attributes that can be accessed like normal
attributes.
* If the NTA has inherited attributes, there must be equations for those
attributes in some ancestor, as for normal children.
</td>
</tr>
<tr>
<td>
**Older syntax**
</td>
<td>
In the older syntax, you introduce a nonterminal attribute as follows:
* Declare the NTA in the ast file, (See also [NTAs in the abstract syntax](#ASTNTAs)).
* Declare the NTA as an attribute in a jrag file. It can be declared as a
synthesized or an inherited attribute.
The name of the attribute should be the same as in the
[AST traversal API](#typedTraversalAPI), e.g., <em>getX</em> if the NTA
is called <em>X</em>.
* Add equations defining the NTA. The defining value should be a new AST of
the appropriate type, created using the [AST creation API](#creationAPI).
Note that if the NTA is a List or an Optional node, you need to create the
appropriate AST with a List or an Opt node as its root. See examples below.
</td>
</tr>
<tr>
<td>
**Simple synthesized NTA**
</td>
<td> </td>
</tr>
<tr>
<td>
*In an .ast file:*
<pre>A ::= B /C/;</pre>
<em>In a .jrag file:</em>
<pre>syn C A.getC() = new C();</pre>
</td>
<td>
The NTA *C* is declared in the .ast file. It is then declared as a
synthesized attribute *getC()* in the .jrag file. The equation is
provided directly in the declaration and creates a new *C* node.
</td>
</tr>
<tr>
<td>
**List NTA**
</td>
<td> </td>
</tr>
<tr>
<td>
*In an .ast file:*
<pre>A ::= B /C*/;</pre>
*In a .jrag file:*
<pre>syn C A.getCList() =
new List().
add(new C()).
add(new C());</pre>
</td>
<td>
The list NTA *C* is declared in the .ast file. It is then declared as a synthesized attribute *getCList()*
(the same name as in the [implementation level traversal API](#ListsAndOpts)) in the .jrag file.
The equation is provided directly in the declaration and creates a <em>List</em> node to which is added a number of
<em>C</em> nodes (two in this example).
</td>
</tr>
</TABLE>
### <a id="Collection">Collection attributes</a>
<TABLE BORDER="1">
<tr>
<td>
**Collection attributes**
</td>
<td>
Collection attributes have composite values that are defined by so called
<em>contributions</em> that each add a small piece to the composite value. The
contributions may be located in any nodes in the AST.
</td>
</tr>
<tr>
<td>
**Collection attribute declaration**
<pre>coll T A.c() [fresh] with m;</pre>
</td>
<td>
This example shows a declaration of the collection attribute c in nodetype A, and with type T.
* Within square brackets, a Java expression, <em>fresh</em>, should be
written that provides a fresh object of type T. For example, new T().
* The composite value will be built by the underlying JastAdd machinery by
calling the method m for each contribution.
* The method m, should be a one-argument method of T.
* The method m should mutate the T object by adding a contribution to it.
* The method m should be commutative, in the sense that the order of calling
m for different contributions should yield the same resulting T value.
</td>
</tr>
<tr>
<td>
**Contribution declaration**
<pre>N1 contributes value-exp
when cond-exp
to N2.a()
for N2-ref-exp;</pre>
</td>
<td>
This declares that the nodetype N1 contributes <em>value-exp</em> to a
collection attribute N2.a(), or more precisely, to the attribute a in the N2
object denoted by the expression <em>N2-ref-exp</em>.
* N<em>2-ref-exp</em> should be a Java expression denoting an object of type N2.
* The *value-exp* should be a Java expression of the argument type of the method m.
* The contribution is only applied when the boolean condition *cond-exp* is
true.
* The "when"-clause may be omitted.
</td>
</tr>
<tr>
<td>
**Contributions to a set of collections**
<pre>N1 contributes value-exp
to N2.a()
for each N2-ref-set-exp;</pre>
</td>
<td>
A contribution declaration can define that a certain value is contributed to
a whole set of collection attributes by using the "for each" form.
* N2-ref-set-exp should denote an object of the Java type java.lang.Iterable, which should contain objects of type N2.
* The contribution is added to each of these N2 objects.
</td>
</tr>
<tr>
<td>
**Scoped collections**
<pre>coll N1.a [fresh] with m root R</pre>
</td>
<td>
A collection may be scoped to a certain subtree of the AST. This means that
only contributions inside that subtree will be applied when constructing the
collection value.
* If R is the same nodetype as N1 (or a subtype of N1), then the subtree root will be the N1 object.
* If R is some other nodetype, the subtree root will be the closets object of type R on the way from N1 towards the AST root.
</td>
</tr>
</table>
## <a id="Command"></a>Running JastAdd from the command line
### Synopsis
<PRE>
java -jar jastadd2.jar <I>options arguments</I>
</PRE>
### Options
<PRE>
--help <I>(prints help text and stops)</I>
--version <I>(prints version information and stops)</I>
--package=PPP <I>(optional package for generated files, default is none)</I>
--o=DDD <I>(optional base output directory, default is current directory)</I>
--beaver <I>(use beaver base node)</I>
--jjtree <I>(use jjtree base node, this requires --grammar to be set)</I>
--grammar=GGG <I>(the parser for the grammar is called GGG, required when using jjtree)</I>
--rewrite <I>(enable ReRAGs support)</I>
--novisitcheck <I>(disable circularity check for attributes)</I>
--noCacheCycle <I>(disable cache cyle optimization for circular attributes)</I>
--java1.4 <I>(generate Java 1.4 source code, rather than Java 5)</I>
</PRE>
### Arguments
Names of .ast, .jrag and .jadd source files.
### Example
The following command generates classes according to the AST description in Toy.ast.
The generated classes are placed in the package ast. The specifications in the jrag and jadd
files are translated and woven into the generated classes.
<PRE>
java -jar jastadd2.jar --package=ast Toy.ast \
NameAnalysis.jrag TypeAnalysis.jrag PrettyPrinter.jadd
</PRE>
### ANT task
The options above are also available in an ANT task. For generating Java 1.4
source code, write "java14=true" (without the decimal point). For the other
options, use the same names as above.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>JastAdd2 Release Notes</title>
</head>
<body>
<h1>JastAdd2 Release Notes
</h1>
<h2>R20130412</h2>
<blockquote>
<h3>General:</h3>
<ul>
<li>Added option for indentation type in the JastAdd Ant Task</li>
<li>Moved JastAdd main class to the package <code>org.jastadd</code>
(but left a deprecated class with the same name as a working entry point
for backward compatibility)</li>
<li>Removed global static variables to allow concurrent JastAdd instances
in the same JVM</li>
<li>Added JastAdd entry points that allow custom output/error streams</li>
</ul>
<h3>Error handling:</h3>
<ul>
<li>Help text is printed to the standard out stream rather than the standard
error stream</li>
<li>Improved error handling for missing equations of synthesized attributes:
now only the minimum set of classes requiring an equation is reported</li>
</ul>
<h3>Performance:</h3>
<ul>
<li>Minimum list size now only affects <code>List</code> nodes (previously
also affected <code>Opt</code> nodes)</li>
<li>It is now possible to specify a custom minimum list size with the
<code>minListSize</code> option</li>
</ul>
</blockquote>
<h2>R20130312</h2>
<blockquote>
<h3>Incremental evaluation:</h3>
<ul>
<li>Merged Emma S&ouml;derberg's incremental evaluation features into JastAdd2</li>
<li>The new option <code>fullFlush</code> was added to enable more thorough flush behaviour (makes <code>flushCache</code> flush rewrites and NTAs)</li>
</ul>
<h3>Removed obsolete features:</h3>
<ul>
<li>Dropped doxygen support</li>
<li>Dropped J2ME code generation support</li>
<li>Dropped parent interface support (for inherited equation searching)</li>
</ul>
<h3>Internals:</h3>
<ul>
<li>Much of the JastAdd2 internals have been rewritten to improve readability</li>
</ul>
</blockquote>
<h2>R20130212</h2>
<blockquote>
<h3>Bug fixes:</h3>
<ul>
<li>Fixed bug concerning weaving interface refinements</li>
<li>Fixed various bugs</li>
<li>Fixed a code generation error in jjtree mode</li>
</ul>
<h3>Error handling:</h3>
<ul>
<li>Multiple equivalent declarations of an inherited attribute now only raise a warning, rather than an error</li>
<li>The warning for a duplicate inherited declaration includes the previous declaration location</li>
<li>Improved error messages for method/equation refinement errors</li>
<li>The path to the output directory is included in the error message for a missing output directory</li>
</ul>
<h3>API changes</h3>
<ul>
<li><code>ASTNode.copy()</code> now sets the parent pointer of the copy to <code>null</code></li>
<li>Removed the redundant static method <code>ASTNode.getChild(ASTNode,int)</code></li>
</ul>
<h3>Performance:</h3>
<ul>
<li>Removed redundant NTA child initialization</li>
<li>Increased minimum (non-empty) child array size from 1 to 4</li>
<li>The child array for non-List, non-Opt nodes is now initialized to fit all children in the node constructor (removes redundant child-array growing)</li>
</ul>
<h3>Other changes:</h3>
<ul>
<li>JastAdd2 no longer depends on AspectJ</li>
<li>The <code>--doxygen</code> option is now deprecated</li>
<li>Added the <code>--indent</code> command-line option which allows changing the indentation in generated code. Can be set to tabs or 2-, 4-, and 8 space indentation.</li>
</ul>
</blockquote>
<h2>R20121112</h2>
<blockquote>
<h3>Bugfix Release</h3>
<ul>
<li>Fixed error in fullCopy causing some non-NTA children to not be copied correctly. This bug sometimes caused NullPointerExceptions or faulty behaviour in generated code.
</ul>
</blockquote>
<h2>R20121112</h2>
<blockquote>
<h3>Bugfix Release</h3>
<ul>
<li>Fixed error in fullCopy causing some non-NTA children to not be copied correctly. This bug sometimes caused NullPointerExceptions or faulty behaviour in generated code.
</ul>
</blockquote>
<h2>R20121026</h2>
<blockquote>
<h3>Various bug fixes</h3>
<ul>
<li>Fixed bug on Windows - backslashes in file paths now work correctly.
<li>NTA children are no longer copied by fullCopy.
<li>Removed the generated method for accessing value maps of parameterized attributes.
<li>Fixed error related to two synthesized attributes with the same name but different parameters.
<li>It is now possible to use static import statements in aspect files.
<li>Added a method getNumXNoTransform to count the number of elements in a list child without triggering rewrites.
</ul>
</blockquote>
<h2>R20121011</h2>
<blockquote>
<h3>Various bug fixes</h3>
<ul>
<li>getChild now returns null if the children array is null
<li>inherited equations lacking a return statement now give compilation error
<li>improved recognition of the "refined" keyword inside Java code in equations.
<li>Synthesized NTA with parameters may now have null values
<li>fullCopy now sets the parent of the copied tree to null
<li>insertChild and removeChild now update the childIndex field correctly
<li>Fixed how debug code escapes file names, to work also for Windows OS.
<li>Fixed bug in code generation for Contributes-clauses without when-part.
<li>Circular attributes now generate Java 1.4 code when the java1.4 option is set.
</ul>
<h3>Improved output handling</h3>
<ul>
<li>Error messages, warnings, and help messages are now printed on stderr instead of on stdout.
<li>JastAdd now returns exit code zero when just printing version or help information.
</ul>
<h3>Improved option handling</h3>
<ul>
<li>The options --noComponentCheck, --lazyMaps, and --refineLegacy are now by default ON when running from the command line.
<li>The default behavior is now the same when running from the command line as when running through ANT.
<li>Command line options are no longer case sensitive.
<li>Some options are deprecated. A warning is printed if such an option is used.
<li>Warnings are printed for some other cases, like giving an option twice, giving an option without an expected argument, etc.
</ul>
</blockquote>
<h2>R20110902</h2>
<blockquote>
<h3>JavaDoc support</h3>
<p>JastAdd now generates Java files with JavaDoc comments for built-in APIs and APIs for attributes. See the upcoming RagDoll tool for more information.</p>
<h3>JDK7 compliance </h3>
<p>Code generated by older versions of JastAdd might give compile time errors when compiling using javac from JDK 7. This is because JastAdd previously generated code where private fields were accessed in an erroneous way according to the JLS. Previous javac versions accepted such code, but the bug has been fixed in JDK 7. This version of JastAdd generates code not giving this problem.</p>
</blockquote>
<h2>R20110506</h2>
</body>
</html>
JastAdd2 Release Notes
======================
R20130412
---------
### General
* Added option for indentation type in the JastAdd Ant Task
* Moved JastAdd main class to the package `org.jastadd`
(but left a deprecated class with the same name as a working entry point
for backward compatibility)
* Removed global static variables to allow concurrent JastAdd instances
in the same JVM
* Added JastAdd entry points that allow custom output/error streams
### Error handling
* Help text is printed to the standard out stream rather than the standard
error stream
* Improved error handling for missing equations of synthesized attributes:
now only the minimum set of classes requiring an equation is reported
### Performance
* Minimum list size now only affects `List` nodes (previously
also affected `Opt` nodes)
* It is now possible to specify a custom minimum list size with the
`minListSize` option
R20130312
---------
### Incremental evaluation
* Merged Emma S&ouml;derberg's incremental evaluation features into JastAdd2
* The new option `fullFlush` was added to enable more thorough flush behaviour (makes `flushCache` flush rewrites and NTAs)
### Removed obsolete features
* Dropped doxygen support
* Dropped J2ME code generation support
* Dropped parent interface support (for inherited equation searching)
### Internals
* Much of the JastAdd2 internals have been rewritten to improve readability
R20130212
---------
### Bug fixes
* Fixed bug concerning weaving interface refinements
* Fixed various bugs
* Fixed a code generation error in jjtree mode
### Error handling
* Multiple equivalent declarations of an inherited attribute now only raise a warning, rather than an error
* The warning for a duplicate inherited declaration includes the previous declaration location
* Improved error messages for method/equation refinement errors
* The path to the output directory is included in the error message for a missing output directory
### API changes
* `ASTNode.copy()` now sets the parent pointer of the copy to `null`
* Removed the redundant static method `ASTNode.getChild(ASTNode,int)`
### Performance
* Removed redundant NTA child initialization
* Increased minimum (non-empty) child array size from 1 to 4
* The child array for non-List, non-Opt nodes is now initialized to fit all children in the node constructor (removes redundant child-array growing)
### Other changes
* JastAdd2 no longer depends on AspectJ
* The `--doxygen` option is now deprecated
* Added the `--indent` command-line option which allows changing the indentation in generated code. Can be set to tabs or 2-, 4-, and 8 space indentation.
R20121112
---------
### Bugfix Release
* Fixed error in fullCopy causing some non-NTA children to not be copied correctly. This bug sometimes caused NullPointerExceptions or faulty behaviour in generated code.
R20121112
---------
### Bugfix Release
* Fixed error in fullCopy causing some non-NTA children to not be copied correctly. This bug sometimes caused NullPointerExceptions or faulty behaviour in generated code.
R20121026
---------
### Various bug fixes
* Fixed bug on Windows - backslashes in file paths now work correctly.
* NTA children are no longer copied by fullCopy.
* Removed the generated method for accessing value maps of parameterized attributes.
* Fixed error related to two synthesized attributes with the same name but different parameters.
* It is now possible to use static import statements in aspect files.
* Added a method getNumXNoTransform to count the number of elements in a list child without triggering rewrites.
R20121011
---------
### Various bug fixes
* getChild now returns null if the children array is null
* inherited equations lacking a return statement now give compilation error
* improved recognition of the "refined" keyword inside Java code in equations.
* Synthesized NTA with parameters may now have null values
* fullCopy now sets the parent of the copied tree to null
* insertChild and removeChild now update the childIndex field correctly
* Fixed how debug code escapes file names, to work also for Windows OS.
* Fixed bug in code generation for Contributes-clauses without when-part.
* Circular attributes now generate Java 1.4 code when the java1.4 option is set.
### Improved output handling
* Error messages, warnings, and help messages are now printed on stderr instead of on stdout.
* JastAdd now returns exit code zero when just printing version or help information.
### Improved option handling
* The options --noComponentCheck, --lazyMaps, and --refineLegacy are now by default ON when running from the command line.
* The default behavior is now the same when running from the command line as when running through ANT.
* Command line options are no longer case sensitive.
* Some options are deprecated. A warning is printed if such an option is used.
* Warnings are printed for some other cases, like giving an option twice, giving an option without an expected argument, etc.
R20110902
---------
### JavaDoc support
JastAdd now generates Java files with JavaDoc comments for built-in APIs and
APIs for attributes. See the upcoming RagDoll tool for more information.
### JDK7 compliance
Code generated by older versions of JastAdd might give compile time errors when
compiling using javac from JDK 7. This is because JastAdd previously generated
code where private fields were accessed in an erroneous way according to the
JLS. Previous javac versions accepted such code, but the bug has been fixed in
JDK 7. This version of JastAdd generates code not giving this problem.
#!/bin/bash #!/bin/bash
# set version string if [ $# -lt "1" ]; then
VERSION=R`date +%Y%m%d` echo "Usage: $0 VERSION"
exit 1
fi
echo "This will script will tag, build and upload JastAdd2 $VERSION" \ VERSION=$1
echo "This script will tag, build and upload JastAdd2 $VERSION" \
"to jastadd.org/releases/jastadd2/$VERSION" "to jastadd.org/releases/jastadd2/$VERSION"
echo echo
echo "IMPORTANT: Please update doc/release-notes.html before proceeding!" echo "IMPORTANT: Please update doc/release-notes.md before proceeding!"
echo echo
while true; do while true; do
read -p "Proceed? " yn read -p "Proceed? (yes/no) " yn
case $yn in case $yn in
[Yy]* ) break;; [Yy]* ) break;;
[Nn]* ) exit;; [Nn]* ) exit;;
...@@ -18,7 +22,7 @@ while true; do ...@@ -18,7 +22,7 @@ while true; do
esac esac
done done
echo "Building release..." echo "Building release $VERSION..."
ant release -Dversion=$VERSION ant release -Dversion=$VERSION
echo "Creating new directory at jastadd.org..." echo "Creating new directory at jastadd.org..."
...@@ -26,7 +30,7 @@ ssh login.cs.lth.se "mkdir /cs/jastadd/releases/jastadd2/$VERSION" ...@@ -26,7 +30,7 @@ ssh login.cs.lth.se "mkdir /cs/jastadd/releases/jastadd2/$VERSION"
echo "Uploading files to jastadd.org..." echo "Uploading files to jastadd.org..."
scp jastadd2-src.zip jastadd2-bin.zip doc/*.html doc/*.php \ scp jastadd2-src.zip jastadd2-bin.zip doc/*.html doc/*.php \
doc/*.md README.md login.cs.lth.se:/cs/jastadd/releases/jastadd2/${VERSION} README.md login.cs.lth.se:/cs/jastadd/releases/jastadd2/${VERSION}
echo "Setting group write permission for uploaded files..." echo "Setting group write permission for uploaded files..."
ssh login.cs.lth.se "chmod -R g+w /cs/jastadd/releases/jastadd2/$VERSION" ssh login.cs.lth.se "chmod -R g+w /cs/jastadd/releases/jastadd2/$VERSION"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment