(JVS);
+ * 28-May-2006 : Moved connectivity info from edge to graph (JVS);
+ *
+ */
+
+package org.broadinstitute.compositetask;
+
+import java.util.*;
+
+/**
+ * The root interface in the graph hierarchy. A mathematical graph-theory graph
+ * object G(V,E) contains a set V of vertices and a set
+ * E of edges. Each edge e=(v1,v2) in E connects vertex v1 to vertex v2.
+ * for more information about graphs and their related definitions see
+ * http://mathworld.wolfram.com/Graph.html .
+ *
+ * This library generally follows the terminology found at:
+ * http://mathworld.wolfram.com/topics/GraphTheory.html . Implementation of
+ * this interface can provide simple-graphs, multigraphs, pseudographs etc. The
+ * package org.jgrapht.graph provides a gallery of abstract and
+ * concrete graph implementations.
+ *
+ * This library works best when vertices represent arbitrary objects and
+ * edges represent the relationships between them. Vertex and edge instances may
+ * be shared by more than one graph.
+ *
+ * Through generics, a graph can be typed to specific classes for vertices
+ * V and edges E<T>. Such a graph can contain
+ * vertices of type V and all sub-types and Edges of type
+ * E and all sub-types.
+ *
+ * For guidelines on vertex and edge classes, see this wiki
+ * page .
+ *
+ * @author Barak Naveh
+ * @since Jul 14, 2003
+ */
+public interface Graph
+{
+ //~ Methods ----------------------------------------------------------------
+
+ /**
+ * Returns a set of all edges connecting source vertex to target vertex if
+ * such vertices exist in this graph. If any of the vertices does not exist
+ * or is null, returns null. If both vertices
+ * exist but no edges found, returns an empty set.
+ *
+ * In undirected graphs, some of the returned edges may have their source
+ * and target vertices in the opposite order. In simple graphs the returned
+ * set is either singleton set or empty set.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return a set of all edges connecting source vertex to target vertex.
+ */
+ public Set getAllEdges(V sourceVertex, V targetVertex);
+
+ /**
+ * Returns an edge connecting source vertex to target vertex if such
+ * vertices and such edge exist in this graph. Otherwise returns
+ * null. If any of the specified vertices is null
+ * returns null
+ *
+ * In undirected graphs, the returned edge may have its source and target
+ * vertices in the opposite order.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return an edge connecting source vertex to target vertex.
+ */
+ public E getEdge(V sourceVertex, V targetVertex);
+
+ /**
+ * Returns the edge factory using which this graph creates new edges. The
+ * edge factory is defined when the graph is constructed and must not be
+ * modified.
+ *
+ * @return the edge factory using which this graph creates new edges.
+ */
+ public EdgeFactory getEdgeFactory();
+
+ /**
+ * Creates a new edge in this graph, going from the source vertex to the
+ * target vertex, and returns the created edge. Some graphs do not allow
+ * edge-multiplicity. In such cases, if the graph already contains an edge
+ * from the specified source to the specified target, than this method does
+ * not change the graph and returns null.
+ *
+ * The source and target vertices must already be contained in this
+ * graph. If they are not found in graph IllegalArgumentException is
+ * thrown.
+ *
+ * This method creates the new edge e using this graph's
+ * EdgeFactory. For the new edge to be added e
+ * must not be equal to any other edge the graph (even if the graph
+ * allows edge-multiplicity). More formally, the graph must not contain any
+ * edge e2 such that e2.equals(e). If such
+ * e2 is found then the newly created edge e is
+ * abandoned, the method leaves this graph unchanged returns
+ * null.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return The newly created edge if added to the graph, otherwise
+ * null.
+ *
+ * @throws IllegalArgumentException if source or target vertices are not
+ * found in the graph.
+ * @throws NullPointerException if any of the specified vertices is
+ * null.
+ *
+ * @see #getEdgeFactory()
+ */
+ public E addEdge(V sourceVertex, V targetVertex);
+
+ /**
+ * Adds the specified edge to this graph, going from the source vertex to
+ * the target vertex. More formally, adds the specified edge,
+ * e, to this graph if this graph contains no edge e2
+ * such that e2.equals(e). If this graph already contains such
+ * an edge, the call leaves this graph unchanged and returns false .
+ * Some graphs do not allow edge-multiplicity. In such cases, if the graph
+ * already contains an edge from the specified source to the specified
+ * target, than this method does not change the graph and returns
+ * false. If the edge was added to the graph, returns
+ * true.
+ *
+ * The source and target vertices must already be contained in this
+ * graph. If they are not found in graph IllegalArgumentException is
+ * thrown.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ * @param e edge to be added to this graph.
+ *
+ * @return true if this graph did not already contain the specified
+ * edge.
+ *
+ * @throws IllegalArgumentException if source or target vertices are not
+ * found in the graph.
+ * @throws ClassCastException if the specified edge is not assignment
+ * compatible with the class of edges produced by the edge factory of this
+ * graph.
+ * @throws NullPointerException if any of the specified vertices is
+ * null.
+ *
+ * @see #addEdge(Object, Object)
+ * @see #getEdgeFactory()
+ */
+ public boolean addEdge(V sourceVertex, V targetVertex, E e);
+
+ /**
+ * Adds the specified vertex to this graph if not already present. More
+ * formally, adds the specified vertex, v, to this graph if
+ * this graph contains no vertex u such that
+ * u.equals(v). If this graph already contains such vertex, the call
+ * leaves this graph unchanged and returns false . In combination
+ * with the restriction on constructors, this ensures that graphs never
+ * contain duplicate vertices.
+ *
+ * @param v vertex to be added to this graph.
+ *
+ * @return true if this graph did not already contain the specified
+ * vertex.
+ *
+ * @throws NullPointerException if the specified vertex is
+ * null.
+ */
+ public boolean addVertex(V v);
+
+ /**
+ * Returns true if and only if this graph contains an edge going
+ * from the source vertex to the target vertex. In undirected graphs the
+ * same result is obtained when source and target are inverted. If any of
+ * the specified vertices does not exist in the graph, or if is
+ * null, returns false.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return true if this graph contains the specified edge.
+ */
+ public boolean containsEdge(V sourceVertex, V targetVertex);
+
+ /**
+ * Returns true if this graph contains the specified edge. More
+ * formally, returns true if and only if this graph contains an
+ * edge e2 such that e.equals(e2). If the
+ * specified edge is null returns false.
+ *
+ * @param e edge whose presence in this graph is to be tested.
+ *
+ * @return true if this graph contains the specified edge.
+ */
+ public boolean containsEdge(E e);
+
+ /**
+ * Returns true if this graph contains the specified vertex. More
+ * formally, returns true if and only if this graph contains a
+ * vertex u such that u.equals(v). If the
+ * specified vertex is null returns false.
+ *
+ * @param v vertex whose presence in this graph is to be tested.
+ *
+ * @return true if this graph contains the specified vertex.
+ */
+ public boolean containsVertex(V v);
+
+ /**
+ * Returns a set of the edges contained in this graph. The set is backed by
+ * the graph, so changes to the graph are reflected in the set. If the graph
+ * is modified while an iteration over the set is in progress, the results
+ * of the iteration are undefined.
+ *
+ * The graph implementation may maintain a particular set ordering (e.g.
+ * via {@link java.util.LinkedHashSet}) for deterministic iteration, but
+ * this is not required. It is the responsibility of callers who rely on
+ * this behavior to only use graph implementations which support it.
+ *
+ * @return a set of the edges contained in this graph.
+ */
+ public Set edgeSet();
+
+ /**
+ * Returns a set of all edges touching the specified vertex. If no edges are
+ * touching the specified vertex returns an empty set.
+ *
+ * @param vertex the vertex for which a set of touching edges is to be
+ * returned.
+ *
+ * @return a set of all edges touching the specified vertex.
+ *
+ * @throws IllegalArgumentException if vertex is not found in the graph.
+ * @throws NullPointerException if vertex is null.
+ */
+ public Set edgesOf(V vertex);
+
+ /**
+ * Removes all the edges in this graph that are also contained in the
+ * specified edge collection. After this call returns, this graph will
+ * contain no edges in common with the specified edges. This method will
+ * invoke the {@link #removeEdge(Object)} method.
+ *
+ * @param edges edges to be removed from this graph.
+ *
+ * @return true if this graph changed as a result of the call
+ *
+ * @throws NullPointerException if the specified edge collection is
+ * null .
+ *
+ * @see #removeEdge(Object)
+ * @see #containsEdge(Object)
+ */
+ public boolean removeAllEdges(Collection extends E> edges);
+
+ /**
+ * Removes all the edges going from the specified source vertex to the
+ * specified target vertex, and returns a set of all removed edges. Returns
+ * null if any of the specified vertices does not exist in the
+ * graph. If both vertices exist but no edge is found, returns an empty set.
+ * This method will either invoke the {@link #removeEdge(Object)} method, or
+ * the {@link #removeEdge(Object, Object)} method.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return the removed edges, or null if no either vertex not
+ * part of graph
+ */
+ public Set removeAllEdges(V sourceVertex, V targetVertex);
+
+ /**
+ * Removes all the vertices in this graph that are also contained in the
+ * specified vertex collection. After this call returns, this graph will
+ * contain no vertices in common with the specified vertices. This method
+ * will invoke the {@link #removeVertex(Object)} method.
+ *
+ * @param vertices vertices to be removed from this graph.
+ *
+ * @return true if this graph changed as a result of the call
+ *
+ * @throws NullPointerException if the specified vertex collection is
+ * null .
+ *
+ * @see #removeVertex(Object)
+ * @see #containsVertex(Object)
+ */
+ public boolean removeAllVertices(Collection extends V> vertices);
+
+ /**
+ * Removes an edge going from source vertex to target vertex, if such
+ * vertices and such edge exist in this graph. Returns the edge if removed
+ * or null otherwise.
+ *
+ * @param sourceVertex source vertex of the edge.
+ * @param targetVertex target vertex of the edge.
+ *
+ * @return The removed edge, or null if no edge removed.
+ */
+ public E removeEdge(V sourceVertex, V targetVertex);
+
+ /**
+ * Removes the specified edge from the graph. Removes the specified edge
+ * from this graph if it is present. More formally, removes an edge
+ * e2 such that e2.equals(e), if the graph contains such
+ * edge. Returns true if the graph contained the specified edge.
+ * (The graph will not contain the specified edge once the call returns).
+ *
+ * If the specified edge is null returns
+ * false.
+ *
+ * @param e edge to be removed from this graph, if present.
+ *
+ * @return true if and only if the graph contained the
+ * specified edge.
+ */
+ public boolean removeEdge(E e);
+
+ /**
+ * Removes the specified vertex from this graph including all its touching
+ * edges if present. More formally, if the graph contains a vertex
+ * u such that u.equals(v), the call removes all edges
+ * that touch u and then removes u itself. If no
+ * such u is found, the call leaves the graph unchanged.
+ * Returns true if the graph contained the specified vertex. (The
+ * graph will not contain the specified vertex once the call returns).
+ *
+ * If the specified vertex is null returns
+ * false.
+ *
+ * @param v vertex to be removed from this graph, if present.
+ *
+ * @return true if the graph contained the specified vertex;
+ * false otherwise.
+ */
+ public boolean removeVertex(V v);
+
+ /**
+ * Returns a set of the vertices contained in this graph. The set is backed
+ * by the graph, so changes to the graph are reflected in the set. If the
+ * graph is modified while an iteration over the set is in progress, the
+ * results of the iteration are undefined.
+ *
+ * The graph implementation may maintain a particular set ordering (e.g.
+ * via {@link java.util.LinkedHashSet}) for deterministic iteration, but
+ * this is not required. It is the responsibility of callers who rely on
+ * this behavior to only use graph implementations which support it.
+ *
+ * @return a set view of the vertices contained in this graph.
+ */
+ public Set vertexSet();
+
+ /**
+ * Returns the source vertex of an edge. For an undirected graph, source and
+ * target are distinguishable designations (but without any mathematical
+ * meaning).
+ *
+ * @param e edge of interest
+ *
+ * @return source vertex
+ */
+ public V getEdgeSource(E e);
+
+ /**
+ * Returns the target vertex of an edge. For an undirected graph, source and
+ * target are distinguishable designations (but without any mathematical
+ * meaning).
+ *
+ * @param e edge of interest
+ *
+ * @return target vertex
+ */
+ public V getEdgeTarget(E e);
+
+ /**
+ * Returns the weight assigned to a given edge. Unweighted graphs return 1.0
+ * (as defined by {@link WeightedGraph#DEFAULT_EDGE_WEIGHT}), allowing
+ * weighted-graph algorithms to apply to them where meaningful.
+ *
+ * @param e edge of interest
+ *
+ * @return edge weight
+ *
+ * @see WeightedGraph
+ */
+ public double getEdgeWeight(E e);
+}
+
+// End Graph.java
diff --git a/src/main/java/org/broadinstitute/compositetask/HtmlColorizer.java b/src/main/java/org/broadinstitute/compositetask/HtmlColorizer.java
new file mode 100644
index 0000000..c47db4c
--- /dev/null
+++ b/src/main/java/org/broadinstitute/compositetask/HtmlColorizer.java
@@ -0,0 +1,27 @@
+package org.broadinstitute.compositetask;
+
+public class HtmlColorizer implements CompositeTaskColorizer {
+ public String preamble() {
+ return "";
+ }
+
+ public String postamble() {
+ return "";
+ }
+
+ public String keyword(String str) {
+ return "" + str + " ";
+ }
+
+ public String string(String str) {
+ return "" + str + " ";
+ }
+
+ public String variable(String str) {
+ return "" + str + " ";
+ }
+
+ public String task(String str) {
+ return "" + str + " ";
+ }
+}
diff --git a/src/main/java/org/broadinstitute/compositetask/Lexer.java b/src/main/java/org/broadinstitute/compositetask/Lexer.java
new file mode 100644
index 0000000..3784700
--- /dev/null
+++ b/src/main/java/org/broadinstitute/compositetask/Lexer.java
@@ -0,0 +1,121 @@
+package org.broadinstitute.compositetask;
+
+import java.util.regex.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.nio.*;
+import java.nio.charset.*;
+import java.nio.channels.*;
+
+import org.broadinstitute.parser.*;
+
+class LexerMatch {
+ private Terminal terminal;
+ LexerMatch() { this.terminal = null; }
+ LexerMatch(Terminal terminal) { this.terminal = terminal; }
+ public Terminal getTerminal() { return this.terminal; }
+}
+
+class TokenLexer {
+ private Pattern regex;
+ private CompositeTaskParser.TerminalId terminal;
+
+ TokenLexer(Pattern regex, CompositeTaskParser.TerminalId terminal) {
+ this.regex = regex;
+ this.terminal = terminal;
+ }
+
+ LexerMatch match(SourceCode source) {
+ Matcher m = this.regex.matcher(source.getString());
+ LexerMatch rval = null;
+ if ( m.find() ) {
+ String sourceString = m.group();
+ if (this.terminal != null)
+ rval = new LexerMatch(new Terminal(this.terminal.id(), this.terminal.string(), sourceString, source.getResource(), source.getLine(), source.getColumn()));
+ else
+ rval = new LexerMatch();
+
+ source.advance(sourceString.length());
+ }
+ return rval;
+ }
+
+ public String toString() {
+ return "[TokenLexer regex="+regex+", terminal="+terminal+"]";
+ }
+}
+
+public class Lexer {
+
+ private ArrayList regex;
+
+ Lexer() {
+ this.regex = new ArrayList();
+ this.regex.add( new TokenLexer(Pattern.compile("^/\\*.*?\\*/", Pattern.DOTALL), null) );
+ this.regex.add( new TokenLexer(Pattern.compile("^//.*"), null) );
+ this.regex.add( new TokenLexer(Pattern.compile("^composite_task(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_COMPOSITE_TASK) );
+ this.regex.add( new TokenLexer(Pattern.compile("^output(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_OUTPUT) );
+ this.regex.add( new TokenLexer(Pattern.compile("^input(?=(\\s*:)|$)"), CompositeTaskParser.TerminalId.TERMINAL_INPUT) );
+ this.regex.add( new TokenLexer(Pattern.compile("^step(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_STEP) );
+ this.regex.add( new TokenLexer(Pattern.compile("^File(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FILE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^FirstLine(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FIRST_LINE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^for(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_FOR) );
+ this.regex.add( new TokenLexer(Pattern.compile("^as(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_AS) );
+ this.regex.add( new TokenLexer(Pattern.compile("^into(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_INTO) );
+ this.regex.add( new TokenLexer(Pattern.compile("^in(?=[^a-zA-Z0-9_]|$)"), CompositeTaskParser.TerminalId.TERMINAL_IN) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\."), CompositeTaskParser.TerminalId.TERMINAL_DOT) );
+ this.regex.add( new TokenLexer(Pattern.compile("^,"), CompositeTaskParser.TerminalId.TERMINAL_COMMA) );
+ this.regex.add( new TokenLexer(Pattern.compile("^:"), CompositeTaskParser.TerminalId.TERMINAL_COLON) );
+ this.regex.add( new TokenLexer(Pattern.compile("^;"), CompositeTaskParser.TerminalId.TERMINAL_SEMI) );
+ this.regex.add( new TokenLexer(Pattern.compile("^="), CompositeTaskParser.TerminalId.TERMINAL_ASSIGN) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\["), CompositeTaskParser.TerminalId.TERMINAL_LSQUARE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\]"), CompositeTaskParser.TerminalId.TERMINAL_RSQUARE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\{"), CompositeTaskParser.TerminalId.TERMINAL_LBRACE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\}"), CompositeTaskParser.TerminalId.TERMINAL_RBRACE) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\("), CompositeTaskParser.TerminalId.TERMINAL_LPAREN) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\)"), CompositeTaskParser.TerminalId.TERMINAL_RPAREN) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\"([^\\\\\"\\n]|\\[\\\"'nrbtfav\\?]|\\[0-7]{1,3}|\\\\x[0-9a-fA-F]+|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*\""), CompositeTaskParser.TerminalId.TERMINAL_STRING) );
+ this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z0-9_\\.])+(?=\\s*=)"), CompositeTaskParser.TerminalId.TERMINAL_IDENTIFIER) );
+ this.regex.add( new TokenLexer(Pattern.compile("^([a-zA-Z_]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)([a-zA-Z_0-9]|\\\\[uU]([0-9a-fA-F]{4})([0-9a-fA-F]{4})?)*"), CompositeTaskParser.TerminalId.TERMINAL_IDENTIFIER) );
+ this.regex.add( new TokenLexer(Pattern.compile("^[-]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)"), CompositeTaskParser.TerminalId.TERMINAL_NUMBER) );
+ this.regex.add( new TokenLexer(Pattern.compile("^\\s+"), null) );
+ }
+
+ public List getTokens(SourceCode code) {
+ ArrayList tokens = new ArrayList();
+ boolean progress = true;
+
+ while (progress) {
+ progress = false;
+ for ( TokenLexer lexer : regex ) {
+ LexerMatch match = lexer.match(code);
+ if (match != null) {
+ progress = true;
+ if (match.getTerminal() != null) {
+ tokens.add(match.getTerminal());
+ }
+ break;
+ }
+ }
+ }
+
+ return tokens;
+ }
+ public static void main(String[] args) {
+ try {
+ SourceCode code = new CompositeTaskSourceCode(new File(args[0]));
+ Lexer lexer = new Lexer();
+ List terminals = lexer.getTokens(code);
+ System.out.println("[");
+ System.out.println(Utility.join(terminals, ",\n"));
+ System.out.println("]");
+ } catch( IOException e ) {
+ System.err.println(e);
+ }
+ }
+}
diff --git a/src/main/java/org/broadinstitute/compositetask/Main.java b/src/main/java/org/broadinstitute/compositetask/Main.java
new file mode 100644
index 0000000..6296054
--- /dev/null
+++ b/src/main/java/org/broadinstitute/compositetask/Main.java
@@ -0,0 +1,112 @@
+package org.broadinstitute.compositetask;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.broadinstitute.parser.Utility;
+import org.broadinstitute.parser.Ast;
+import org.broadinstitute.parser.ParseTree;
+import org.broadinstitute.parser.SyntaxError;
+import org.broadinstitute.parser.Terminal;
+
+public class Main {
+
+ public static void usage() {
+ System.err.println("Usage: <.wdl file> ");
+ System.err.println();
+ System.err.println("Actions:");
+ System.err.println(" tokens: tokenize the source code");
+ System.err.println(" ast: parse source code and output an abstract syntax tree");
+ System.err.println(" parsetree: parse source code and output a parsetree");
+ System.err.println(" entities: output an abbreviated view of all entities and which scope they're nested in");
+ System.err.println(" graph: output the set of verticies and edges for the directed acyclic graph");
+ System.err.println(" format: reformat source code");
+ System.err.println(" format-ansi: reformat source code and colorize for the terminal");
+ System.err.println(" format-html: reformat source code and add HTML span tags");
+ System.exit(-1);
+ }
+
+ public static void main(String[] args) {
+
+ if (args.length < 2) {
+ usage();
+ }
+
+ try {
+
+ if ( args[1].equals("tokens") ) {
+ Lexer lexer = new Lexer();
+ List terminals = lexer.getTokens(new CompositeTaskSourceCode(new File(args[0])));
+ for ( Terminal terminal : terminals ) {
+ System.out.println(terminal);
+ }
+ System.exit(0);
+ }
+
+ CompositeTask ctask = new CompositeTask(new File(args[0]));
+
+ if ( args[1].equals("ast") ) {
+ Ast ast = ctask.getAst();
+ System.out.println(ast.toPrettyString());
+ } else if ( args[1].equals("parsetree") ) {
+ ParseTree tree = ctask.getParseTree();
+ System.out.println(tree.toPrettyString());
+ } else if ( args[1].equals("entities") ) {
+ print_tree(ctask);
+ } else if ( args[1].equals("graph") ) {
+ CompositeTaskGraph graph = ctask.getGraph();
+
+ System.out.println("VERTICIES");
+ System.out.println("---------");
+ for ( CompositeTaskVertex v : graph.vertexSet() ) {
+ System.out.println(v);
+ }
+ System.out.println("");
+
+ System.out.println("EDGES");
+ System.out.println("-----");
+ for ( CompositeTaskEdge v : graph.edgeSet() ) {
+ System.out.println(v);
+ }
+
+ } else if ( args[1].equals("format-ansi") ) {
+ CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(new AnsiColorizer());
+ String formatted = formatter.format(ctask);
+ System.out.println(formatted);
+ } else if ( args[1].equals("format-html") ) {
+ CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter(new HtmlColorizer());
+ String formatted = formatter.format(ctask);
+ System.out.println(formatted);
+ } else if ( args[1].equals("format") ) {
+ CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter();
+ String formatted = formatter.format(ctask);
+ System.out.println(formatted);
+ } else {
+ usage();
+ }
+ } catch (IOException error) {
+ System.err.println(error);
+ System.exit(-1);
+ } catch (SyntaxError error) {
+ System.err.println(error);
+ System.exit(-1);
+ }
+ }
+
+ public static void print_tree(CompositeTask ctask) {
+ print_tree(ctask, 0);
+ }
+
+ public static void print_tree(CompositeTaskScope scope, int depth) {
+ Set nodes = scope.getNodes();
+ for ( CompositeTaskNode node : nodes ) {
+ System.out.println(Utility.getIndentString(depth) + node);
+ if ( node instanceof CompositeTaskScope ) {
+ print_tree((CompositeTaskScope) node, depth + 2);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/broadinstitute/compositetask/NullColorizer.java b/src/main/java/org/broadinstitute/compositetask/NullColorizer.java
new file mode 100644
index 0000000..40b801e
--- /dev/null
+++ b/src/main/java/org/broadinstitute/compositetask/NullColorizer.java
@@ -0,0 +1,27 @@
+package org.broadinstitute.compositetask;
+
+public class NullColorizer implements CompositeTaskColorizer {
+ public String preamble() {
+ return "";
+ }
+
+ public String postamble() {
+ return "";
+ }
+
+ public String keyword(String str) {
+ return str;
+ }
+
+ public String string(String str) {
+ return str;
+ }
+
+ public String variable(String str) {
+ return str;
+ }
+
+ public String task(String str) {
+ return str;
+ }
+}
diff --git a/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java
new file mode 100644
index 0000000..fdb53f8
--- /dev/null
+++ b/src/main/java/org/broadinstitute/compositetask/WdlSyntaxErrorFormatter.java
@@ -0,0 +1,102 @@
+package org.broadinstitute.compositetask;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.broadinstitute.parser.SyntaxErrorFormatter;
+import org.broadinstitute.parser.SourceCode;
+import org.broadinstitute.parser.Terminal;
+import org.broadinstitute.parser.TerminalIdentifier;
+import org.broadinstitute.parser.Utility;
+
+public class WdlSyntaxErrorFormatter implements SyntaxErrorFormatter {
+ private SourceCode code;
+ public void setSourceCode(SourceCode code) {
+ this.code = code;
+ }
+
+ public String unexpected_eof(String method, List expected, List nt_rules) {
+ ArrayList expected_terminals = new ArrayList();
+ if ( expected != null && expected.size() > 0 ) {
+ for ( TerminalIdentifier e : expected ) {
+ expected_terminals.add(e.string());
+ }
+ }
+ return "Unexpected end of file when parsing " + method + "\n\nExpecting one of: " + Utility.join(expected_terminals, ", ") + "\nPossible rules:\n" + Utility.join(nt_rules, "\n");
+ }
+
+ public String excess_tokens(String method, Terminal terminal) {
+ String msg = "Finished parsing without consuming all tokens";
+ msg += "\nLocation: " + terminal.getResource() + " @ line " + terminal.getLine() + ", column " + terminal.getColumn();
+ return msg;
+ }
+
+ public String unexpected_symbol(String method, Terminal actual, List expected, String rule) {
+ String msg = "Unexpected symbol " + actual.getTerminalStr();
+
+ if ( expected != null && expected.size() > 0 ) {
+ ArrayList expected_terminals = new ArrayList();
+ for ( TerminalIdentifier e : expected ) {
+ expected_terminals.add(e.string());
+ }
+ msg += ". Expecting " + Utility.join(expected_terminals, ", ") + ".";
+ }
+
+ msg += "\nRule: " + rule;
+ msg += "\nLocation: " + actual.getResource() + " @ line " + actual.getLine() + ", column " + actual.getColumn() + ":\n\n";
+ msg += code.getLine(actual.getLine()) + "\n";
+ msg += Utility.getIndentString(actual.getColumn()-1) + "^\n";
+ return msg;
+ }
+
+ public String no_more_tokens(String method, TerminalIdentifier expecting, Terminal last) {
+ return "No more tokens when parsing " + method + "\n" +
+ "Expecting: " + expecting.string() + "\n" +
+ "Location: " + last.getResource() + " @ line " + last.getLine() + ", column " + last.getColumn() + ":\n\n" +
+ this.code.getLine(last.getLine()) + "\n" +
+ Utility.getIndentString(last.getColumn()-1) + "^\n";
+ }
+
+ public String invalid_terminal(String method, Terminal invalid) {
+ return "Invalid symbol ID: "+invalid.getId()+" ("+invalid.getTerminalStr()+")";
+ }
+
+ public String missing_version(Terminal task_name) {
+ return "Version information missing for task " + task_name.getSourceString() + "\n" +
+ "Location: " + task_name.getResource() + " @ line " + task_name.getLine() + ", column " + task_name.getColumn() + ":\n\n" +
+ this.code.getLine(task_name.getLine()) + "\n" + Utility.getIndentString(task_name.getColumn()-1) + "^\n";
+ }
+
+ public String duplicate_output_variable(Terminal duplicate, Terminal previous) {
+ return "Two steps output to the same variable: " + duplicate.getSourceString() + "\n" +
+ "Location: " + duplicate.getResource() + " @ line " + duplicate.getLine() + ", column " + duplicate.getColumn() + ":\n\n" +
+ this.code.getLine(duplicate.getLine()) + "\n" + Utility.getIndentString(duplicate.getColumn()-1) + "^\n" +
+ "Previous output for variable was @ line " + previous.getLine() + ", column " + previous.getColumn() + ":\n\n" +
+ this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n";
+ }
+
+ public String duplicate_output_file(Terminal duplicate, Terminal previous) {
+ return "Two steps output to the same file: " + duplicate.getSourceString() + "\n" +
+ "Location: " + duplicate.getResource() + " @ line " + duplicate.getLine() + ", column " + duplicate.getColumn() + ":\n\n" +
+ this.code.getLine(duplicate.getLine()) + "\n" + Utility.getIndentString(duplicate.getColumn()-1) + "^\n" +
+ "Previous output for file was @ line " + previous.getLine() + ", column " + previous.getColumn() + ":\n\n" +
+ this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n";
+ }
+
+ public String duplicate_step_names(Terminal duplicate, Terminal previous) {
+ return "Two steps have the same name: " + duplicate.getSourceString() + "\n" +
+ "Location: " + duplicate.getResource() + " @ line " + duplicate.getLine() + ", column " + duplicate.getColumn() + ":\n\n" +
+ this.code.getLine(duplicate.getLine()) + "\n" + Utility.getIndentString(duplicate.getColumn()-1) + "^\n" +
+ "Previous step was defined @ line " + previous.getLine() + ", column " + previous.getColumn() + ":\n\n" +
+ this.code.getLine(previous.getLine()) + "\n" + Utility.getIndentString(previous.getColumn()-1) + "^\n";
+ }
+
+ public String step_doesnt_use_loop_iterator(Terminal loop_iterator, Terminal step_name) {
+ return "Step '" + step_name.getSourceString() + "' inside for loop doesn't use loop iterator: " + loop_iterator.getSourceString() + "\n" +
+ "Location: " + step_name.getResource() + " @ line " + step_name.getLine() + ", column " + step_name.getColumn() + ":\n\n" +
+ this.code.getLine(step_name.getLine()) + "\n" + Utility.getIndentString(step_name.getColumn()-1) + "^\n" +
+ "Loop iterator is declared @ line " + loop_iterator.getLine() + ", column " + loop_iterator.getColumn() + ":\n\n" +
+ this.code.getLine(loop_iterator.getLine()) + "\n" + Utility.getIndentString(loop_iterator.getColumn()-1) + "^\n";
+ }
+
+}
diff --git a/src/main/java/org/broadinstitute/parser/Ast.java b/src/main/java/org/broadinstitute/parser/Ast.java
new file mode 100644
index 0000000..98c53a8
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/Ast.java
@@ -0,0 +1,48 @@
+
+package org.broadinstitute.parser;
+import java.util.Map;
+import java.util.LinkedList;
+import java.util.Formatter;
+import java.util.Locale;
+import java.util.ArrayList;
+public class Ast implements AstNode {
+ private String name;
+ private Map attributes;
+ Ast(String name, Map attributes) {
+ this.name = name;
+ this.attributes = attributes;
+ }
+ public AstNode getAttribute(String name) {
+ return this.attributes.get(name);
+ }
+ public Map getAttributes() {
+ return this.attributes;
+ }
+ public String getName() {
+ return this.name;
+ }
+ public String toString() {
+ Formatter formatter = new Formatter(new StringBuilder(), Locale.US);
+ LinkedList attributes = new LinkedList();
+ for (final Map.Entry attribute : this.attributes.entrySet()) {
+ final String name = attribute.getKey();
+ final AstNode node = attribute.getValue();
+ final String nodeStr = (node == null) ? "None" : node.toString();
+ attributes.add(name + "=" + nodeStr);
+ }
+ formatter.format("(%s: %s)", this.name, Utility.join(attributes, ", "));
+ return formatter.toString();
+ }
+ public String toPrettyString() {
+ return toPrettyString(0);
+ }
+ public String toPrettyString(int indent) {
+ String spaces = Utility.getIndentString(indent);
+ ArrayList children = new ArrayList();
+ for( Map.Entry attribute : this.attributes.entrySet() ) {
+ String valueString = attribute.getValue() == null ? "None" : attribute.getValue().toPrettyString(indent + 2).trim();
+ children.add(spaces + " " + attribute.getKey() + "=" + valueString);
+ }
+ return spaces + "(" + this.name + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")";
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/AstList.java b/src/main/java/org/broadinstitute/parser/AstList.java
new file mode 100644
index 0000000..fb6ca4d
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/AstList.java
@@ -0,0 +1,22 @@
+
+package org.broadinstitute.parser;
+import java.util.ArrayList;
+public class AstList extends ArrayList implements AstNode {
+ public String toString() {
+ return "[" + Utility.join(this, ", ") + "]";
+ }
+ public String toPrettyString() {
+ return toPrettyString(0);
+ }
+ public String toPrettyString(int indent) {
+ String spaces = Utility.getIndentString(indent);
+ if (this.size() == 0) {
+ return spaces + "[]";
+ }
+ ArrayList elements = new ArrayList();
+ for ( AstNode node : this ) {
+ elements.add(node.toPrettyString(indent + 2));
+ }
+ return spaces + "[\n" + Utility.join(elements, ",\n") + "\n" + spaces + "]";
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/AstNode.java b/src/main/java/org/broadinstitute/parser/AstNode.java
new file mode 100644
index 0000000..2023534
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/AstNode.java
@@ -0,0 +1,7 @@
+
+package org.broadinstitute.parser;
+public interface AstNode {
+ public String toString();
+ public String toPrettyString();
+ public String toPrettyString(int indent);
+}
diff --git a/src/main/java/org/broadinstitute/parser/AstTransform.java b/src/main/java/org/broadinstitute/parser/AstTransform.java
new file mode 100644
index 0000000..7ca7cce
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/AstTransform.java
@@ -0,0 +1,3 @@
+
+package org.broadinstitute.parser;
+public interface AstTransform {}
diff --git a/src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java b/src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java
new file mode 100644
index 0000000..8ecf41d
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/AstTransformNodeCreator.java
@@ -0,0 +1,26 @@
+
+package org.broadinstitute.parser;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+public class AstTransformNodeCreator implements AstTransform {
+ private String name;
+ private LinkedHashMap parameters;
+ AstTransformNodeCreator(String name, LinkedHashMap parameters) {
+ this.name = name;
+ this.parameters = parameters;
+ }
+ public Map getParameters() {
+ return this.parameters;
+ }
+ public String getName() {
+ return this.name;
+ }
+ public String toString() {
+ LinkedList items = new LinkedList();
+ for (final Map.Entry entry : this.parameters.entrySet()) {
+ items.add(entry.getKey() + "=$" + entry.getValue().toString());
+ }
+ return "AstNodeCreator: " + this.name + "( " + Utility.join(items, ", ") + " )";
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java b/src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java
new file mode 100644
index 0000000..f4dcbcb
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/AstTransformSubstitution.java
@@ -0,0 +1,14 @@
+
+package org.broadinstitute.parser;
+public class AstTransformSubstitution implements AstTransform {
+ private int index;
+ AstTransformSubstitution(int index) {
+ this.index = index;
+ }
+ public int getIndex() {
+ return this.index;
+ }
+ public String toString() {
+ return "AstSubstitution: $" + Integer.toString(this.index);
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java
new file mode 100644
index 0000000..734866d
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/CompositeTaskParser.java
@@ -0,0 +1,1363 @@
+
+package org.broadinstitute.parser;
+import java.util.*;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Arrays;
+public class CompositeTaskParser implements Parser {
+ private TokenStream tokens;
+ private HashMap expressionParsers;
+ private SyntaxErrorFormatter syntaxErrorFormatter;
+ private Map first;
+ private Map follow;
+ private Map> nonterminal_rules;
+ private Map rules;
+ /* table[nonterminal][terminal] = rule */
+ private static final int[][] table = {
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1 },
+ { -1, -1, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1 },
+ { 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 42, -1 },
+ { -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, 0, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, 8, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1 },
+ { -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1 },
+ { -1, 43, -1, -1, -1, -1, -1, -1, 16, -1, 16, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, 13, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 18, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20 },
+ { -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, 41, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ };
+ public enum TerminalId implements TerminalIdentifier {
+ TERMINAL_RSQUARE(0, "rsquare"),
+ TERMINAL_RBRACE(1, "rbrace"),
+ TERMINAL_DOT(2, "dot"),
+ TERMINAL_FILE(3, "file"),
+ TERMINAL_COMMA(4, "comma"),
+ TERMINAL_OUTPUT(5, "output"),
+ TERMINAL_LBRACE(6, "lbrace"),
+ TERMINAL_INTO(7, "into"),
+ TERMINAL_FOR(8, "for"),
+ TERMINAL_STRING(9, "string"),
+ TERMINAL_COMPOSITE_TASK(10, "composite_task"),
+ TERMINAL_IDENTIFIER(11, "identifier"),
+ TERMINAL_IN(12, "in"),
+ TERMINAL_RPAREN(13, "rparen"),
+ TERMINAL_STEP(14, "step"),
+ TERMINAL_NUMBER(15, "number"),
+ TERMINAL_LPAREN(16, "lparen"),
+ TERMINAL_SEMI(17, "semi"),
+ TERMINAL_FIRST_LINE(18, "first_line"),
+ TERMINAL_LSQUARE(19, "lsquare"),
+ TERMINAL_COLON(20, "colon"),
+ TERMINAL_ASSIGN(21, "assign"),
+ TERMINAL_AS(22, "as"),
+ TERMINAL_INPUT(23, "input");
+ private final int id;
+ private final String string;
+ TerminalId(int id, String string) {
+ this.id = id;
+ this.string = string;
+ }
+ public int id() {return id;}
+ public String string() {return string;}
+ }
+ private class CompositeTaskTerminalMap implements TerminalMap {
+ private Map id_to_str;
+ private Map str_to_id;
+ CompositeTaskTerminalMap(TerminalId[] terminals) {
+ id_to_str = new HashMap();
+ str_to_id = new HashMap();
+ for( TerminalId terminal : terminals ) {
+ Integer id = new Integer(terminal.id());
+ String str = terminal.string();
+ id_to_str.put(id, str);
+ str_to_id.put(str, id);
+ }
+ }
+ public int get(String string) { return this.str_to_id.get(string); }
+ public String get(int id) { return this.id_to_str.get(id); }
+ public boolean isValid(String string) { return this.str_to_id.containsKey(string); }
+ public boolean isValid(int id) { return this.id_to_str.containsKey(id); }
+ }
+ public CompositeTaskParser(SyntaxErrorFormatter syntaxErrorFormatter) {
+ this.syntaxErrorFormatter = syntaxErrorFormatter;
+ this.expressionParsers = new HashMap();
+ this.first = new HashMap();
+ this.follow = new HashMap();
+ this.nonterminal_rules = new HashMap>();
+ this.rules = new HashMap();
+ ArrayList list;
+ String rule;
+ this.nonterminal_rules.put("_gen6", new ArrayList());
+ this.nonterminal_rules.put("step_name", new ArrayList());
+ this.nonterminal_rules.put("_gen2", new ArrayList());
+ this.nonterminal_rules.put("task_attr", new ArrayList());
+ this.nonterminal_rules.put("variable", new ArrayList());
+ this.nonterminal_rules.put("step_output", new ArrayList());
+ this.nonterminal_rules.put("_gen5", new ArrayList());
+ this.nonterminal_rules.put("_gen4", new ArrayList());
+ this.nonterminal_rules.put("step_output_list", new ArrayList());
+ this.nonterminal_rules.put("_gen10", new ArrayList());
+ this.nonterminal_rules.put("step", new ArrayList());
+ this.nonterminal_rules.put("task_attr_value", new ArrayList());
+ this.nonterminal_rules.put("wdl_entity", new ArrayList());
+ this.nonterminal_rules.put("step_output_location", new ArrayList());
+ this.nonterminal_rules.put("step_attr", new ArrayList());
+ this.nonterminal_rules.put("_gen0", new ArrayList());
+ this.nonterminal_rules.put("step_output_mode", new ArrayList());
+ this.nonterminal_rules.put("_gen1", new ArrayList());
+ this.nonterminal_rules.put("wdl", new ArrayList());
+ this.nonterminal_rules.put("composite_task_entity", new ArrayList());
+ this.nonterminal_rules.put("step_input", new ArrayList());
+ this.nonterminal_rules.put("_gen8", new ArrayList());
+ this.nonterminal_rules.put("step_input_list", new ArrayList());
+ this.nonterminal_rules.put("_gen9", new ArrayList());
+ this.nonterminal_rules.put("for_loop", new ArrayList());
+ this.nonterminal_rules.put("task_identifier", new ArrayList());
+ this.nonterminal_rules.put("_gen3", new ArrayList());
+ this.nonterminal_rules.put("task_attrs", new ArrayList());
+ this.nonterminal_rules.put("composite_task", new ArrayList());
+ this.nonterminal_rules.put("_gen7", new ArrayList());
+ this.nonterminal_rules.put("variable_member", new ArrayList());
+ rule = "_gen10 := variable_member";
+ this.nonterminal_rules.get("_gen10").add(rule);
+ this.rules.put(new Integer(0), rule);
+ rule = "step_output_list := 'output' 'colon' _gen8 'semi' -> StepOutputList( outputs=$2 )";
+ this.nonterminal_rules.get("step_output_list").add(rule);
+ this.rules.put(new Integer(1), rule);
+ rule = "step_input := 'identifier' 'assign' variable -> StepInput( parameter=$0, value=$2 )";
+ this.nonterminal_rules.get("step_input").add(rule);
+ this.rules.put(new Integer(2), rule);
+ rule = "_gen4 := task_attrs";
+ this.nonterminal_rules.get("_gen4").add(rule);
+ this.rules.put(new Integer(3), rule);
+ rule = "wdl_entity := composite_task";
+ this.nonterminal_rules.get("wdl_entity").add(rule);
+ this.rules.put(new Integer(4), rule);
+ rule = "step := 'step' task_identifier _gen2 'lbrace' _gen3 'rbrace' -> Step( task=$1, name=$2, body=$4 )";
+ this.nonterminal_rules.get("step").add(rule);
+ this.rules.put(new Integer(5), rule);
+ rule = "step_output_location := 'as' variable -> OutputVariable( var=$1 )";
+ this.nonterminal_rules.get("step_output_location").add(rule);
+ this.rules.put(new Integer(6), rule);
+ rule = "_gen5 := task_attr _gen5";
+ this.nonterminal_rules.get("_gen5").add(rule);
+ this.rules.put(new Integer(7), rule);
+ rule = "task_attr_value := 'identifier'";
+ this.nonterminal_rules.get("task_attr_value").add(rule);
+ this.rules.put(new Integer(8), rule);
+ rule = "_gen3 := step_attr _gen3";
+ this.nonterminal_rules.get("_gen3").add(rule);
+ this.rules.put(new Integer(9), rule);
+ rule = "step_output := step_output_mode 'lparen' 'string' 'rparen' step_output_location -> StepOutput( mode=$0, expression=$2, var=$4 )";
+ this.nonterminal_rules.get("step_output").add(rule);
+ this.rules.put(new Integer(10), rule);
+ rule = "_gen5 := ε";
+ this.nonterminal_rules.get("_gen5").add(rule);
+ this.rules.put(new Integer(11), rule);
+ rule = "task_identifier := 'identifier' _gen4 -> Task( name=$0, attributes=$1 )";
+ this.nonterminal_rules.get("task_identifier").add(rule);
+ this.rules.put(new Integer(12), rule);
+ rule = "composite_task_entity := composite_task";
+ this.nonterminal_rules.get("composite_task_entity").add(rule);
+ this.rules.put(new Integer(13), rule);
+ rule = "composite_task_entity := for_loop";
+ this.nonterminal_rules.get("composite_task_entity").add(rule);
+ this.rules.put(new Integer(14), rule);
+ rule = "task_attr_value := 'number'";
+ this.nonterminal_rules.get("task_attr_value").add(rule);
+ this.rules.put(new Integer(15), rule);
+ rule = "_gen1 := composite_task_entity _gen1";
+ this.nonterminal_rules.get("_gen1").add(rule);
+ this.rules.put(new Integer(16), rule);
+ rule = "step_name := 'as' 'identifier' -> $1";
+ this.nonterminal_rules.get("step_name").add(rule);
+ this.rules.put(new Integer(17), rule);
+ rule = "_gen8 := step_output _gen9";
+ this.nonterminal_rules.get("_gen8").add(rule);
+ this.rules.put(new Integer(18), rule);
+ rule = "variable := 'identifier' _gen10 -> Variable( name=$0, member=$1 )";
+ this.nonterminal_rules.get("variable").add(rule);
+ this.rules.put(new Integer(19), rule);
+ rule = "step_input_list := 'input' 'colon' _gen6 'semi' -> StepInputList( inputs=$2 )";
+ this.nonterminal_rules.get("step_input_list").add(rule);
+ this.rules.put(new Integer(20), rule);
+ rule = "task_attrs := 'lsquare' _gen5 'rsquare' -> $1";
+ this.nonterminal_rules.get("task_attrs").add(rule);
+ this.rules.put(new Integer(21), rule);
+ rule = "_gen9 := 'comma' step_output _gen9";
+ this.nonterminal_rules.get("_gen9").add(rule);
+ this.rules.put(new Integer(22), rule);
+ rule = "for_loop := 'for' 'lparen' 'identifier' 'in' 'identifier' 'rparen' 'lbrace' _gen1 'rbrace' -> ForLoop( collection=$4, item=$2, body=$7 )";
+ this.nonterminal_rules.get("for_loop").add(rule);
+ this.rules.put(new Integer(23), rule);
+ rule = "task_attr := 'identifier' 'assign' task_attr_value -> TaskAttribute( key=$0, value=$2 )";
+ this.nonterminal_rules.get("task_attr").add(rule);
+ this.rules.put(new Integer(24), rule);
+ rule = "wdl := _gen0";
+ this.nonterminal_rules.get("wdl").add(rule);
+ this.rules.put(new Integer(25), rule);
+ rule = "_gen9 := ε";
+ this.nonterminal_rules.get("_gen9").add(rule);
+ this.rules.put(new Integer(26), rule);
+ rule = "_gen0 := wdl_entity _gen0";
+ this.nonterminal_rules.get("_gen0").add(rule);
+ this.rules.put(new Integer(27), rule);
+ rule = "_gen6 := step_input _gen7";
+ this.nonterminal_rules.get("_gen6").add(rule);
+ this.rules.put(new Integer(28), rule);
+ rule = "composite_task := 'composite_task' 'identifier' 'lbrace' _gen1 'rbrace' -> CompositeTask( name=$1, body=$3 )";
+ this.nonterminal_rules.get("composite_task").add(rule);
+ this.rules.put(new Integer(29), rule);
+ rule = "_gen8 := ε";
+ this.nonterminal_rules.get("_gen8").add(rule);
+ this.rules.put(new Integer(30), rule);
+ rule = "step_output_location := 'into' variable -> OutputListAppend( var=$1 )";
+ this.nonterminal_rules.get("step_output_location").add(rule);
+ this.rules.put(new Integer(31), rule);
+ rule = "variable_member := 'dot' 'identifier' -> $1";
+ this.nonterminal_rules.get("variable_member").add(rule);
+ this.rules.put(new Integer(32), rule);
+ rule = "composite_task_entity := step";
+ this.nonterminal_rules.get("composite_task_entity").add(rule);
+ this.rules.put(new Integer(33), rule);
+ rule = "_gen7 := ε";
+ this.nonterminal_rules.get("_gen7").add(rule);
+ this.rules.put(new Integer(34), rule);
+ rule = "_gen6 := ε";
+ this.nonterminal_rules.get("_gen6").add(rule);
+ this.rules.put(new Integer(35), rule);
+ rule = "step_output_mode := 'first_line'";
+ this.nonterminal_rules.get("step_output_mode").add(rule);
+ this.rules.put(new Integer(36), rule);
+ rule = "_gen0 := ε";
+ this.nonterminal_rules.get("_gen0").add(rule);
+ this.rules.put(new Integer(37), rule);
+ rule = "step_output_mode := 'file'";
+ this.nonterminal_rules.get("step_output_mode").add(rule);
+ this.rules.put(new Integer(38), rule);
+ rule = "_gen2 := step_name";
+ this.nonterminal_rules.get("_gen2").add(rule);
+ this.rules.put(new Integer(39), rule);
+ rule = "_gen10 := ε";
+ this.nonterminal_rules.get("_gen10").add(rule);
+ this.rules.put(new Integer(40), rule);
+ rule = "_gen3 := ε";
+ this.nonterminal_rules.get("_gen3").add(rule);
+ this.rules.put(new Integer(41), rule);
+ rule = "_gen4 := ε";
+ this.nonterminal_rules.get("_gen4").add(rule);
+ this.rules.put(new Integer(42), rule);
+ rule = "_gen1 := ε";
+ this.nonterminal_rules.get("_gen1").add(rule);
+ this.rules.put(new Integer(43), rule);
+ rule = "task_attr_value := 'string'";
+ this.nonterminal_rules.get("task_attr_value").add(rule);
+ this.rules.put(new Integer(44), rule);
+ rule = "step_attr := step_input_list";
+ this.nonterminal_rules.get("step_attr").add(rule);
+ this.rules.put(new Integer(45), rule);
+ rule = "step_attr := step_output_list";
+ this.nonterminal_rules.get("step_attr").add(rule);
+ this.rules.put(new Integer(46), rule);
+ rule = "_gen2 := ε";
+ this.nonterminal_rules.get("_gen2").add(rule);
+ this.rules.put(new Integer(47), rule);
+ rule = "_gen7 := 'comma' step_input _gen7";
+ this.nonterminal_rules.get("_gen7").add(rule);
+ this.rules.put(new Integer(48), rule);
+ this.first.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("step_name", new TerminalId[] { TerminalId.TERMINAL_AS });
+ this.first.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_AS });
+ this.first.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("variable", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("step_output", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE });
+ this.first.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_LSQUARE });
+ this.first.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_OUTPUT });
+ this.first.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_DOT });
+ this.first.put("step", new TerminalId[] { TerminalId.TERMINAL_STEP });
+ this.first.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_NUMBER, TerminalId.TERMINAL_STRING });
+ this.first.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK });
+ this.first.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_INTO, TerminalId.TERMINAL_AS });
+ this.first.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT });
+ this.first.put("_gen0", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK });
+ this.first.put("step_output_mode", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE });
+ this.first.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP });
+ this.first.put("wdl", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK });
+ this.first.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP });
+ this.first.put("step_input", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_FILE, TerminalId.TERMINAL_FIRST_LINE });
+ this.first.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT });
+ this.first.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_COMMA });
+ this.first.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_FOR });
+ this.first.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER });
+ this.first.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT });
+ this.first.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_LSQUARE });
+ this.first.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK });
+ this.first.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_COMMA });
+ this.first.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_DOT });
+ this.follow.put("_gen6", new TerminalId[] { TerminalId.TERMINAL_SEMI });
+ this.follow.put("step_name", new TerminalId[] { TerminalId.TERMINAL_LBRACE });
+ this.follow.put("_gen2", new TerminalId[] { TerminalId.TERMINAL_LBRACE });
+ this.follow.put("task_attr", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE });
+ this.follow.put("variable", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ this.follow.put("step_output", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ this.follow.put("_gen5", new TerminalId[] { TerminalId.TERMINAL_RSQUARE });
+ this.follow.put("_gen4", new TerminalId[] { TerminalId.TERMINAL_AS });
+ this.follow.put("step_output_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("_gen10", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ this.follow.put("step", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("task_attr_value", new TerminalId[] { TerminalId.TERMINAL_IDENTIFIER, TerminalId.TERMINAL_RSQUARE });
+ this.follow.put("wdl_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK });
+ this.follow.put("step_output_location", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ this.follow.put("step_attr", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("_gen0", new TerminalId[] { });
+ this.follow.put("step_output_mode", new TerminalId[] { TerminalId.TERMINAL_LPAREN });
+ this.follow.put("_gen1", new TerminalId[] { TerminalId.TERMINAL_RBRACE });
+ this.follow.put("wdl", new TerminalId[] { });
+ this.follow.put("composite_task_entity", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("step_input", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ this.follow.put("_gen8", new TerminalId[] { TerminalId.TERMINAL_SEMI });
+ this.follow.put("step_input_list", new TerminalId[] { TerminalId.TERMINAL_INPUT, TerminalId.TERMINAL_OUTPUT, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("_gen9", new TerminalId[] { TerminalId.TERMINAL_SEMI });
+ this.follow.put("for_loop", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("task_identifier", new TerminalId[] { TerminalId.TERMINAL_AS });
+ this.follow.put("_gen3", new TerminalId[] { TerminalId.TERMINAL_RBRACE });
+ this.follow.put("task_attrs", new TerminalId[] { TerminalId.TERMINAL_AS });
+ this.follow.put("composite_task", new TerminalId[] { TerminalId.TERMINAL_COMPOSITE_TASK, TerminalId.TERMINAL_FOR, TerminalId.TERMINAL_STEP, TerminalId.TERMINAL_RBRACE });
+ this.follow.put("_gen7", new TerminalId[] { TerminalId.TERMINAL_SEMI });
+ this.follow.put("variable_member", new TerminalId[] { TerminalId.TERMINAL_SEMI, TerminalId.TERMINAL_COMMA });
+ }
+ public TerminalMap getTerminalMap() {
+ return new CompositeTaskTerminalMap(TerminalId.values());
+ }
+ public ParseTree parse(TokenStream tokens) throws SyntaxError {
+ this.tokens = tokens;
+ this.tokens.setSyntaxErrorFormatter(this.syntaxErrorFormatter);
+ this.tokens.setTerminalMap(this.getTerminalMap());
+ ParseTree tree = this.parse_wdl();
+ if (this.tokens.current() != null) {
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+ throw new SyntaxError(this.syntaxErrorFormatter.excess_tokens(stack[1].getMethodName(), this.tokens.current()));
+ }
+ return tree;
+ }
+ private boolean isTerminal(TerminalId terminal) {
+ return (0 <= terminal.id() && terminal.id() <= 23);
+ }
+ private boolean isNonTerminal(TerminalId terminal) {
+ return (24 <= terminal.id() && terminal.id() <= 54);
+ }
+ private boolean isTerminal(int terminal) {
+ return (0 <= terminal && terminal <= 23);
+ }
+ private boolean isNonTerminal(int terminal) {
+ return (24 <= terminal && terminal <= 54);
+ }
+ private ParseTree parse__gen6() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[0][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(24, "_gen6"));
+ tree.setList("slist");
+ if ( current != null ) {
+ if (current.getId() == 17) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 28) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_input();
+ tree.add( subtree);
+ subtree = this.parse__gen7();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_step_name() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[1][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(25, "step_name"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_name",
+ Arrays.asList(this.first.get("step_name")),
+ this.nonterminal_rules.get("step_name")
+ ));
+ }
+ if (rule == 17) {
+ tree.setAstTransformation(new AstTransformSubstitution(1));
+ next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_name", this.rules.get(17));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_name", this.rules.get(17));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_name"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_name",
+ current,
+ Arrays.asList(this.first.get("step_name")),
+ this.rules.get(17)
+ ));
+ }
+ private ParseTree parse__gen2() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[2][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(26, "_gen2"));
+ tree.setList(null);
+ if ( current != null ) {
+ if (current.getId() == 6) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 39) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_name();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_task_attr() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[3][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(27, "task_attr"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "task_attr",
+ Arrays.asList(this.first.get("task_attr")),
+ this.nonterminal_rules.get("task_attr")
+ ));
+ }
+ if (rule == 24) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("key", 0);
+ parameters.put("value", 2);
+ tree.setAstTransformation(new AstTransformNodeCreator("TaskAttribute", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr", this.rules.get(24));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "task_attr", this.rules.get(24));
+ tree.add(next);
+ subtree = this.parse_task_attr_value();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("task_attr"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "task_attr",
+ current,
+ Arrays.asList(this.first.get("task_attr")),
+ this.rules.get(24)
+ ));
+ }
+ private ParseTree parse_variable() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[4][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(28, "variable"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "variable",
+ Arrays.asList(this.first.get("variable")),
+ this.nonterminal_rules.get("variable")
+ ));
+ }
+ if (rule == 19) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("name", 0);
+ parameters.put("member", 1);
+ tree.setAstTransformation(new AstTransformNodeCreator("Variable", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable", this.rules.get(19));
+ tree.add(next);
+ subtree = this.parse__gen10();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("variable"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "variable",
+ current,
+ Arrays.asList(this.first.get("variable")),
+ this.rules.get(19)
+ ));
+ }
+ private ParseTree parse_step_output() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[5][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(29, "step_output"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_output",
+ Arrays.asList(this.first.get("step_output")),
+ this.nonterminal_rules.get("step_output")
+ ));
+ }
+ if (rule == 10) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("mode", 0);
+ parameters.put("expression", 2);
+ parameters.put("var", 4);
+ tree.setAstTransformation(new AstTransformNodeCreator("StepOutput", parameters));
+ subtree = this.parse_step_output_mode();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "step_output", this.rules.get(10));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_STRING, "step_output", this.rules.get(10));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "step_output", this.rules.get(10));
+ tree.add(next);
+ subtree = this.parse_step_output_location();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_output"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_output",
+ current,
+ Arrays.asList(this.first.get("step_output")),
+ this.rules.get(10)
+ ));
+ }
+ private ParseTree parse__gen5() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[6][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(30, "_gen5"));
+ tree.setList("nlist");
+ if ( current != null ) {
+ if (current.getId() == 0) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 7) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_task_attr();
+ tree.add( subtree);
+ subtree = this.parse__gen5();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse__gen4() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[7][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(31, "_gen4"));
+ tree.setList(null);
+ if ( current != null ) {
+ if (current.getId() == 22) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 3) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_task_attrs();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_step_output_list() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[8][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(32, "step_output_list"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_output_list",
+ Arrays.asList(this.first.get("step_output_list")),
+ this.nonterminal_rules.get("step_output_list")
+ ));
+ }
+ if (rule == 1) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("outputs", 2);
+ tree.setAstTransformation(new AstTransformNodeCreator("StepOutputList", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_OUTPUT, "step_output_list", this.rules.get(1));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_output_list", this.rules.get(1));
+ tree.add(next);
+ subtree = this.parse__gen8();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_output_list", this.rules.get(1));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_output_list"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_output_list",
+ current,
+ Arrays.asList(this.first.get("step_output_list")),
+ this.rules.get(1)
+ ));
+ }
+ private ParseTree parse__gen10() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[9][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(33, "_gen10"));
+ tree.setList(null);
+ if ( current != null ) {
+ if (current.getId() == 17 || current.getId() == 4) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 0) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_variable_member();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_step() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[10][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(34, "step"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step",
+ Arrays.asList(this.first.get("step")),
+ this.nonterminal_rules.get("step")
+ ));
+ }
+ if (rule == 5) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("task", 1);
+ parameters.put("name", 2);
+ parameters.put("body", 4);
+ tree.setAstTransformation(new AstTransformNodeCreator("Step", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_STEP, "step", this.rules.get(5));
+ tree.add(next);
+ subtree = this.parse_task_identifier();
+ tree.add( subtree);
+ subtree = this.parse__gen2();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "step", this.rules.get(5));
+ tree.add(next);
+ subtree = this.parse__gen3();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "step", this.rules.get(5));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step",
+ current,
+ Arrays.asList(this.first.get("step")),
+ this.rules.get(5)
+ ));
+ }
+ private ParseTree parse_task_attr_value() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[11][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(35, "task_attr_value"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "task_attr_value",
+ Arrays.asList(this.first.get("task_attr_value")),
+ this.nonterminal_rules.get("task_attr_value")
+ ));
+ }
+ if (rule == 8) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_attr_value", this.rules.get(8));
+ tree.add(next);
+ return tree;
+ }
+ else if (rule == 15) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_NUMBER, "task_attr_value", this.rules.get(15));
+ tree.add(next);
+ return tree;
+ }
+ else if (rule == 44) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_STRING, "task_attr_value", this.rules.get(44));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("task_attr_value"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "task_attr_value",
+ current,
+ Arrays.asList(this.first.get("task_attr_value")),
+ this.rules.get(44)
+ ));
+ }
+ private ParseTree parse_wdl_entity() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[12][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(36, "wdl_entity"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "wdl_entity",
+ Arrays.asList(this.first.get("wdl_entity")),
+ this.nonterminal_rules.get("wdl_entity")
+ ));
+ }
+ if (rule == 4) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_composite_task();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("wdl_entity"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "wdl_entity",
+ current,
+ Arrays.asList(this.first.get("wdl_entity")),
+ this.rules.get(4)
+ ));
+ }
+ private ParseTree parse_step_output_location() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[13][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(37, "step_output_location"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_output_location",
+ Arrays.asList(this.first.get("step_output_location")),
+ this.nonterminal_rules.get("step_output_location")
+ ));
+ }
+ if (rule == 6) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("var", 1);
+ tree.setAstTransformation(new AstTransformNodeCreator("OutputVariable", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_AS, "step_output_location", this.rules.get(6));
+ tree.add(next);
+ subtree = this.parse_variable();
+ tree.add( subtree);
+ return tree;
+ }
+ else if (rule == 31) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("var", 1);
+ tree.setAstTransformation(new AstTransformNodeCreator("OutputListAppend", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_INTO, "step_output_location", this.rules.get(31));
+ tree.add(next);
+ subtree = this.parse_variable();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_output_location"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_output_location",
+ current,
+ Arrays.asList(this.first.get("step_output_location")),
+ this.rules.get(31)
+ ));
+ }
+ private ParseTree parse_step_attr() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[14][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(38, "step_attr"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_attr",
+ Arrays.asList(this.first.get("step_attr")),
+ this.nonterminal_rules.get("step_attr")
+ ));
+ }
+ if (rule == 45) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_input_list();
+ tree.add( subtree);
+ return tree;
+ }
+ else if (rule == 46) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_output_list();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_attr"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_attr",
+ current,
+ Arrays.asList(this.first.get("step_attr")),
+ this.rules.get(46)
+ ));
+ }
+ private ParseTree parse__gen0() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[15][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(39, "_gen0"));
+ tree.setList("nlist");
+ if ( current != null ) {
+ if (current.getId() == -1) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 27) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_wdl_entity();
+ tree.add( subtree);
+ subtree = this.parse__gen0();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_step_output_mode() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[16][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(40, "step_output_mode"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_output_mode",
+ Arrays.asList(this.first.get("step_output_mode")),
+ this.nonterminal_rules.get("step_output_mode")
+ ));
+ }
+ if (rule == 36) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_FIRST_LINE, "step_output_mode", this.rules.get(36));
+ tree.add(next);
+ return tree;
+ }
+ else if (rule == 38) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_FILE, "step_output_mode", this.rules.get(38));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_output_mode"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_output_mode",
+ current,
+ Arrays.asList(this.first.get("step_output_mode")),
+ this.rules.get(38)
+ ));
+ }
+ private ParseTree parse__gen1() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[17][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(41, "_gen1"));
+ tree.setList("nlist");
+ if ( current != null ) {
+ if (current.getId() == 1) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 16) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_composite_task_entity();
+ tree.add( subtree);
+ subtree = this.parse__gen1();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_wdl() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[18][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(42, "wdl"));
+ tree.setList(null);
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 25) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse__gen0();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("wdl"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "wdl",
+ current,
+ Arrays.asList(this.first.get("wdl")),
+ this.rules.get(25)
+ ));
+ }
+ private ParseTree parse_composite_task_entity() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[19][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(43, "composite_task_entity"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "composite_task_entity",
+ Arrays.asList(this.first.get("composite_task_entity")),
+ this.nonterminal_rules.get("composite_task_entity")
+ ));
+ }
+ if (rule == 13) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_composite_task();
+ tree.add( subtree);
+ return tree;
+ }
+ else if (rule == 14) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_for_loop();
+ tree.add( subtree);
+ return tree;
+ }
+ else if (rule == 33) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("composite_task_entity"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "composite_task_entity",
+ current,
+ Arrays.asList(this.first.get("composite_task_entity")),
+ this.rules.get(33)
+ ));
+ }
+ private ParseTree parse_step_input() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[20][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(44, "step_input"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_input",
+ Arrays.asList(this.first.get("step_input")),
+ this.nonterminal_rules.get("step_input")
+ ));
+ }
+ if (rule == 2) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("parameter", 0);
+ parameters.put("value", 2);
+ tree.setAstTransformation(new AstTransformNodeCreator("StepInput", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "step_input", this.rules.get(2));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_ASSIGN, "step_input", this.rules.get(2));
+ tree.add(next);
+ subtree = this.parse_variable();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_input"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_input",
+ current,
+ Arrays.asList(this.first.get("step_input")),
+ this.rules.get(2)
+ ));
+ }
+ private ParseTree parse__gen8() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[21][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(45, "_gen8"));
+ tree.setList("slist");
+ if ( current != null ) {
+ if (current.getId() == 17) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 18) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_output();
+ tree.add( subtree);
+ subtree = this.parse__gen9();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_step_input_list() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[22][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(46, "step_input_list"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "step_input_list",
+ Arrays.asList(this.first.get("step_input_list")),
+ this.nonterminal_rules.get("step_input_list")
+ ));
+ }
+ if (rule == 20) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("inputs", 2);
+ tree.setAstTransformation(new AstTransformNodeCreator("StepInputList", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_INPUT, "step_input_list", this.rules.get(20));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_COLON, "step_input_list", this.rules.get(20));
+ tree.add(next);
+ subtree = this.parse__gen6();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_SEMI, "step_input_list", this.rules.get(20));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("step_input_list"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "step_input_list",
+ current,
+ Arrays.asList(this.first.get("step_input_list")),
+ this.rules.get(20)
+ ));
+ }
+ private ParseTree parse__gen9() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[23][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(47, "_gen9"));
+ tree.setList("slist");
+ if ( current != null ) {
+ if (current.getId() == 17) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 22) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen9", this.rules.get(22));
+ tree.add(next);
+ tree.setListSeparator(next);
+ subtree = this.parse_step_output();
+ tree.add( subtree);
+ subtree = this.parse__gen9();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_for_loop() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[24][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(48, "for_loop"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "for_loop",
+ Arrays.asList(this.first.get("for_loop")),
+ this.nonterminal_rules.get("for_loop")
+ ));
+ }
+ if (rule == 23) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("collection", 4);
+ parameters.put("item", 2);
+ parameters.put("body", 7);
+ tree.setAstTransformation(new AstTransformNodeCreator("ForLoop", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_FOR, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_LPAREN, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IN, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_RPAREN, "for_loop", this.rules.get(23));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "for_loop", this.rules.get(23));
+ tree.add(next);
+ subtree = this.parse__gen1();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "for_loop", this.rules.get(23));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("for_loop"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "for_loop",
+ current,
+ Arrays.asList(this.first.get("for_loop")),
+ this.rules.get(23)
+ ));
+ }
+ private ParseTree parse_task_identifier() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[25][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(49, "task_identifier"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "task_identifier",
+ Arrays.asList(this.first.get("task_identifier")),
+ this.nonterminal_rules.get("task_identifier")
+ ));
+ }
+ if (rule == 12) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("name", 0);
+ parameters.put("attributes", 1);
+ tree.setAstTransformation(new AstTransformNodeCreator("Task", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "task_identifier", this.rules.get(12));
+ tree.add(next);
+ subtree = this.parse__gen4();
+ tree.add( subtree);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("task_identifier"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "task_identifier",
+ current,
+ Arrays.asList(this.first.get("task_identifier")),
+ this.rules.get(12)
+ ));
+ }
+ private ParseTree parse__gen3() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[26][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(50, "_gen3"));
+ tree.setList("nlist");
+ if ( current != null ) {
+ if (current.getId() == 1) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 9) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ subtree = this.parse_step_attr();
+ tree.add( subtree);
+ subtree = this.parse__gen3();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_task_attrs() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[27][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(51, "task_attrs"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "task_attrs",
+ Arrays.asList(this.first.get("task_attrs")),
+ this.nonterminal_rules.get("task_attrs")
+ ));
+ }
+ if (rule == 21) {
+ tree.setAstTransformation(new AstTransformSubstitution(1));
+ next = this.tokens.expect(TerminalId.TERMINAL_LSQUARE, "task_attrs", this.rules.get(21));
+ tree.add(next);
+ subtree = this.parse__gen5();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_RSQUARE, "task_attrs", this.rules.get(21));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("task_attrs"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "task_attrs",
+ current,
+ Arrays.asList(this.first.get("task_attrs")),
+ this.rules.get(21)
+ ));
+ }
+ private ParseTree parse_composite_task() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[28][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(52, "composite_task"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "composite_task",
+ Arrays.asList(this.first.get("composite_task")),
+ this.nonterminal_rules.get("composite_task")
+ ));
+ }
+ if (rule == 29) {
+ LinkedHashMap parameters = new LinkedHashMap();
+ parameters.put("name", 1);
+ parameters.put("body", 3);
+ tree.setAstTransformation(new AstTransformNodeCreator("CompositeTask", parameters));
+ next = this.tokens.expect(TerminalId.TERMINAL_COMPOSITE_TASK, "composite_task", this.rules.get(29));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "composite_task", this.rules.get(29));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_LBRACE, "composite_task", this.rules.get(29));
+ tree.add(next);
+ subtree = this.parse__gen1();
+ tree.add( subtree);
+ next = this.tokens.expect(TerminalId.TERMINAL_RBRACE, "composite_task", this.rules.get(29));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("composite_task"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "composite_task",
+ current,
+ Arrays.asList(this.first.get("composite_task")),
+ this.rules.get(29)
+ ));
+ }
+ private ParseTree parse__gen7() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[29][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(53, "_gen7"));
+ tree.setList("slist");
+ if ( current != null ) {
+ if (current.getId() == 17) {
+ return tree;
+ }
+ }
+ if (current == null) {
+ return tree;
+ }
+ if (rule == 48) {
+ tree.setAstTransformation(new AstTransformSubstitution(0));
+ next = this.tokens.expect(TerminalId.TERMINAL_COMMA, "_gen7", this.rules.get(48));
+ tree.add(next);
+ tree.setListSeparator(next);
+ subtree = this.parse_step_input();
+ tree.add( subtree);
+ subtree = this.parse__gen7();
+ tree.add( subtree);
+ return tree;
+ }
+ return tree;
+ }
+ private ParseTree parse_variable_member() throws SyntaxError {
+ Terminal current = this.tokens.current();
+ Terminal next;
+ ParseTree subtree;
+ int rule = current != null ? this.table[30][current.getId()] : -1;
+ ParseTree tree = new ParseTree( new NonTerminal(54, "variable_member"));
+ tree.setList(null);
+ if (current == null) {
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_eof(
+ "variable_member",
+ Arrays.asList(this.first.get("variable_member")),
+ this.nonterminal_rules.get("variable_member")
+ ));
+ }
+ if (rule == 32) {
+ tree.setAstTransformation(new AstTransformSubstitution(1));
+ next = this.tokens.expect(TerminalId.TERMINAL_DOT, "variable_member", this.rules.get(32));
+ tree.add(next);
+ next = this.tokens.expect(TerminalId.TERMINAL_IDENTIFIER, "variable_member", this.rules.get(32));
+ tree.add(next);
+ return tree;
+ }
+ List terminals = Arrays.asList(this.first.get("variable_member"));
+ throw new SyntaxError(this.syntaxErrorFormatter.unexpected_symbol(
+ "variable_member",
+ current,
+ Arrays.asList(this.first.get("variable_member")),
+ this.rules.get(32)
+ ));
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/ExpressionParser.java b/src/main/java/org/broadinstitute/parser/ExpressionParser.java
new file mode 100644
index 0000000..e27ca16
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/ExpressionParser.java
@@ -0,0 +1,5 @@
+
+package org.broadinstitute.parser;
+public interface ExpressionParser extends Parser {
+ ParseTree parse(TokenStream tokens, int rbp) throws SyntaxError;
+}
diff --git a/src/main/java/org/broadinstitute/parser/NonTerminal.java b/src/main/java/org/broadinstitute/parser/NonTerminal.java
new file mode 100644
index 0000000..613898f
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/NonTerminal.java
@@ -0,0 +1,19 @@
+
+package org.broadinstitute.parser;
+public class NonTerminal {
+ private int id;
+ private String string;
+ NonTerminal(int id, String string) {
+ this.id = id;
+ this.string = string;
+ }
+ public int getId() {
+ return this.id;
+ }
+ public String getString() {
+ return this.string;
+ }
+ public String toString() {
+ return this.string;
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/ParseTree.java b/src/main/java/org/broadinstitute/parser/ParseTree.java
new file mode 100644
index 0000000..060dcb0
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/ParseTree.java
@@ -0,0 +1,161 @@
+
+package org.broadinstitute.parser;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.List;
+import java.util.LinkedHashMap;
+public class ParseTree implements ParseTreeNode {
+ private NonTerminal nonterminal;
+ private ArrayList children;
+ private boolean isExpr, isNud, isPrefix, isInfix, isExprNud;
+ private int nudMorphemeCount;
+ private Terminal listSeparator;
+ private String list;
+ private AstTransform astTransform;
+ ParseTree(NonTerminal nonterminal) {
+ this.nonterminal = nonterminal;
+ this.children = new ArrayList();
+ this.astTransform = null;
+ this.isExpr = false;
+ this.isNud = false;
+ this.isPrefix = false;
+ this.isInfix = false;
+ this.isExprNud = false;
+ this.nudMorphemeCount = 0;
+ this.listSeparator = null;
+ this.list = "";
+ }
+ public void setExpr(boolean value) { this.isExpr = value; }
+ public void setNud(boolean value) { this.isNud = value; }
+ public void setPrefix(boolean value) { this.isPrefix = value; }
+ public void setInfix(boolean value) { this.isInfix = value; }
+ public void setExprNud(boolean value) { this.isExprNud = value; }
+ public void setAstTransformation(AstTransform value) { this.astTransform = value; }
+ public void setNudMorphemeCount(int value) { this.nudMorphemeCount = value; }
+ public void setList(String value) { this.list = value; }
+ public void setListSeparator(Terminal value) { this.listSeparator = value; }
+ public int getNudMorphemeCount() { return this.nudMorphemeCount; }
+ public List getChildren() { return this.children; }
+ public boolean isInfix() { return this.isInfix; }
+ public boolean isPrefix() { return this.isPrefix; }
+ public boolean isExpr() { return this.isExpr; }
+ public boolean isNud() { return this.isNud; }
+ public boolean isExprNud() { return this.isExprNud; }
+ public void add(ParseTreeNode tree) {
+ if (this.children == null) {
+ this.children = new ArrayList();
+ }
+ this.children.add(tree);
+ }
+ private boolean isCompoundNud() {
+ if ( this.children.size() > 0 && this.children.get(0) instanceof ParseTree ) {
+ ParseTree child = (ParseTree) this.children.get(0);
+ if ( child.isNud() && !child.isPrefix() && !this.isExprNud() && !this.isInfix() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public AstNode toAst() {
+ if ( this.list == "slist" || this.list == "nlist" ) {
+ int offset = (this.children.size() > 0 && this.children.get(0) == this.listSeparator) ? 1 : 0;
+ AstList astList = new AstList();
+ if ( this.children.size() == 0 ) {
+ return astList;
+ }
+ astList.add(this.children.get(offset).toAst());
+ astList.addAll((AstList) this.children.get(offset + 1).toAst());
+ return astList;
+ } else if ( this.list == "tlist" ) {
+ AstList astList = new AstList();
+ if ( this.children.size() == 0 ) {
+ return astList;
+ }
+ astList.add(this.children.get(0).toAst());
+ astList.addAll((AstList) this.children.get(2).toAst());
+ return astList;
+ } else if ( this.list == "mlist" ) {
+ AstList astList = new AstList();
+ int lastElement = this.children.size() - 1;
+ if ( this.children.size() == 0 ) {
+ return astList;
+ }
+ for (int i = 0; i < lastElement; i++) {
+ astList.add(this.children.get(i).toAst());
+ }
+ astList.addAll((AstList) this.children.get(this.children.size() - 1).toAst());
+ return astList;
+ } else if ( this.isExpr ) {
+ if ( this.astTransform instanceof AstTransformSubstitution ) {
+ AstTransformSubstitution astSubstitution = (AstTransformSubstitution) astTransform;
+ return this.children.get(astSubstitution.getIndex()).toAst();
+ } else if ( this.astTransform instanceof AstTransformNodeCreator ) {
+ AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) this.astTransform;
+ LinkedHashMap parameters = new LinkedHashMap();
+ ParseTreeNode child;
+ for ( final Map.Entry parameter : astNodeCreator.getParameters().entrySet() ) {
+ String name = parameter.getKey();
+ int index = parameter.getValue().intValue();
+ if ( index == '$' ) {
+ child = this.children.get(0);
+ } else if ( this.isCompoundNud() ) {
+ ParseTree firstChild = (ParseTree) this.children.get(0);
+ if ( index < firstChild.getNudMorphemeCount() ) {
+ child = firstChild.getChildren().get(index);
+ } else {
+ index = index - firstChild.getNudMorphemeCount() + 1;
+ child = this.children.get(index);
+ }
+ } else if ( this.children.size() == 1 && !(this.children.get(0) instanceof ParseTree) && !(this.children.get(0) instanceof List) ) {
+ // TODO: I don't think this should ever be called
+ child = this.children.get(0);
+ } else {
+ child = this.children.get(index);
+ }
+ parameters.put(name, child.toAst());
+ }
+ return new Ast(astNodeCreator.getName(), parameters);
+ }
+ } else {
+ AstTransformSubstitution defaultAction = new AstTransformSubstitution(0);
+ AstTransform action = this.astTransform != null ? this.astTransform : defaultAction;
+ if (this.children.size() == 0) return null;
+ if (action instanceof AstTransformSubstitution) {
+ AstTransformSubstitution astSubstitution = (AstTransformSubstitution) action;
+ return this.children.get(astSubstitution.getIndex()).toAst();
+ } else if (action instanceof AstTransformNodeCreator) {
+ AstTransformNodeCreator astNodeCreator = (AstTransformNodeCreator) action;
+ LinkedHashMap evaluatedParameters = new LinkedHashMap();
+ for ( Map.Entry baseParameter : astNodeCreator.getParameters().entrySet() ) {
+ String name = baseParameter.getKey();
+ int index2 = baseParameter.getValue().intValue();
+ evaluatedParameters.put(name, this.children.get(index2).toAst());
+ }
+ return new Ast(astNodeCreator.getName(), evaluatedParameters);
+ }
+ }
+ return null;
+ }
+ public String toString() {
+ ArrayList children = new ArrayList();
+ for (ParseTreeNode child : this.children) {
+ children.add(child.toString());
+ }
+ return "(" + this.nonterminal.getString() + ": " + Utility.join(children, ", ") + ")";
+ }
+ public String toPrettyString() {
+ return toPrettyString(0);
+ }
+ public String toPrettyString(int indent) {
+ if (this.children.size() == 0) {
+ return "(" + this.nonterminal.toString() + ": )";
+ }
+ String spaces = Utility.getIndentString(indent);
+ ArrayList children = new ArrayList();
+ for ( ParseTreeNode node : this.children ) {
+ String sub = node.toPrettyString(indent + 2).trim();
+ children.add(spaces + " " + sub);
+ }
+ return spaces + "(" + this.nonterminal.toString() + ":\n" + Utility.join(children, ",\n") + "\n" + spaces + ")";
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/ParseTreeNode.java b/src/main/java/org/broadinstitute/parser/ParseTreeNode.java
new file mode 100644
index 0000000..a3a530e
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/ParseTreeNode.java
@@ -0,0 +1,8 @@
+
+package org.broadinstitute.parser;
+public interface ParseTreeNode {
+ public AstNode toAst();
+ public String toString();
+ public String toPrettyString();
+ public String toPrettyString(int indent);
+}
diff --git a/src/main/java/org/broadinstitute/parser/Parser.java b/src/main/java/org/broadinstitute/parser/Parser.java
new file mode 100644
index 0000000..e83aa2e
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/Parser.java
@@ -0,0 +1,6 @@
+
+package org.broadinstitute.parser;
+public interface Parser {
+ ParseTree parse(TokenStream tokens) throws SyntaxError;
+ TerminalMap getTerminalMap();
+}
diff --git a/src/main/java/org/broadinstitute/parser/SourceCode.java b/src/main/java/org/broadinstitute/parser/SourceCode.java
new file mode 100644
index 0000000..0e101ff
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/SourceCode.java
@@ -0,0 +1,12 @@
+
+package org.broadinstitute.parser;
+import java.util.List;
+public interface SourceCode {
+ public void advance(int amount);
+ public List getLines();
+ public String getLine(int lineno);
+ public String getString();
+ public int getLine();
+ public int getColumn();
+ public String getResource();
+}
diff --git a/src/main/java/org/broadinstitute/parser/SyntaxError.java b/src/main/java/org/broadinstitute/parser/SyntaxError.java
new file mode 100644
index 0000000..caae11e
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/SyntaxError.java
@@ -0,0 +1,7 @@
+
+package org.broadinstitute.parser;
+public class SyntaxError extends Exception {
+ public SyntaxError(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java b/src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java
new file mode 100644
index 0000000..aa6dda7
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/SyntaxErrorFormatter.java
@@ -0,0 +1,15 @@
+
+package org.broadinstitute.parser;
+import java.util.List;
+public interface SyntaxErrorFormatter {
+ /* Called when the parser runs out of tokens but isn't finished parsing. */
+ String unexpected_eof(String method, List expected, List nt_rules);
+ /* Called when the parser finished parsing but there are still tokens left in the stream. */
+ String excess_tokens(String method, Terminal terminal);
+ /* Called when the parser is expecting one token and gets another. */
+ String unexpected_symbol(String method, Terminal actual, List expected, String rule);
+ /* Called when the parser is expecing a tokens but there are no more tokens. */
+ String no_more_tokens(String method, TerminalIdentifier expecting, Terminal last);
+ /* Invalid terminal is found in the token stream. */
+ String invalid_terminal(String method, Terminal invalid);
+}
diff --git a/src/main/java/org/broadinstitute/parser/Terminal.java b/src/main/java/org/broadinstitute/parser/Terminal.java
new file mode 100644
index 0000000..28034f8
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/Terminal.java
@@ -0,0 +1,53 @@
+
+package org.broadinstitute.parser;
+import java.util.Formatter;
+import java.util.Locale;
+public class Terminal implements AstNode, ParseTreeNode
+{
+ private int id;
+ private String terminal_str;
+ private String source_string;
+ private String resource;
+ private int line;
+ private int col;
+ public Terminal(int id, String terminal_str, String source_string, String resource, int line, int col) {
+ this.id = id;
+ this.terminal_str = terminal_str;
+ this.source_string = source_string;
+ this.resource = resource;
+ this.line = line;
+ this.col = col;
+ }
+ public int getId() {
+ return this.id;
+ }
+ public String getTerminalStr() {
+ return this.terminal_str;
+ }
+ public String getSourceString() {
+ return this.source_string;
+ }
+ public String getResource() {
+ return this.resource;
+ }
+ public int getLine() {
+ return this.line;
+ }
+ public int getColumn() {
+ return this.col;
+ }
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Formatter formatter = new Formatter(sb, Locale.US);
+ formatter.format("{\"terminal\": \"%s\", \"line\": %d, \"col\": %d, \"resource\": \"%s\", \"source_string\": \"%s\"}", this.getTerminalStr(), this.getLine(), this.getColumn(), this.getResource(), Utility.base64_encode(this.getSourceString().getBytes()));
+ return formatter.toString();
+ }
+ public String toPrettyString() {
+ return toPrettyString(0);
+ }
+ public String toPrettyString(int indent) {
+ String spaces = Utility.getIndentString(indent);
+ return spaces + this.getTerminalStr();
+ }
+ public AstNode toAst() { return this; }
+}
diff --git a/src/main/java/org/broadinstitute/parser/TerminalIdentifier.java b/src/main/java/org/broadinstitute/parser/TerminalIdentifier.java
new file mode 100644
index 0000000..5690697
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/TerminalIdentifier.java
@@ -0,0 +1,6 @@
+
+package org.broadinstitute.parser;
+public interface TerminalIdentifier {
+ public int id();
+ public String string();
+}
diff --git a/src/main/java/org/broadinstitute/parser/TerminalMap.java b/src/main/java/org/broadinstitute/parser/TerminalMap.java
new file mode 100644
index 0000000..3cf3fa4
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/TerminalMap.java
@@ -0,0 +1,8 @@
+
+package org.broadinstitute.parser;
+public interface TerminalMap {
+ int get(String string);
+ String get(int id);
+ boolean isValid(String string);
+ boolean isValid(int id);
+}
diff --git a/src/main/java/org/broadinstitute/parser/TokenStream.java b/src/main/java/org/broadinstitute/parser/TokenStream.java
new file mode 100644
index 0000000..5a81fa9
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/TokenStream.java
@@ -0,0 +1,57 @@
+
+package org.broadinstitute.parser;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Formatter;
+import java.util.Locale;
+public class TokenStream extends ArrayList {
+ private int index;
+ private TerminalMap terminals;
+ private SyntaxErrorFormatter syntaxErrorFormatter;
+ public TokenStream(List terminals) {
+ super(terminals);
+ reset();
+ }
+ public TokenStream() {
+ reset();
+ }
+ public void setTerminalMap(TerminalMap terminals) {
+ this.terminals = terminals;
+ }
+ public void setSyntaxErrorFormatter(SyntaxErrorFormatter syntaxErrorFormatter) {
+ this.syntaxErrorFormatter = syntaxErrorFormatter;
+ }
+ public void reset() {
+ this.index = 0;
+ }
+ public Terminal advance() {
+ this.index += 1;
+ return this.current();
+ }
+ public Terminal current() {
+ try {
+ return this.get(this.index);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+ public Terminal last() {
+ return this.get(this.size() - 1);
+ }
+ public Terminal expect(TerminalIdentifier expecting, String nonterminal, String rule) throws SyntaxError {
+ Terminal current = current();
+ if (current == null) {
+ throw new SyntaxError(syntaxErrorFormatter.no_more_tokens(nonterminal, expecting, last()));
+ }
+ if (current.getId() != expecting.id()) {
+ ArrayList expectedList = new ArrayList();
+ expectedList.add(expecting);
+ throw new SyntaxError(syntaxErrorFormatter.unexpected_symbol(nonterminal, current, expectedList, rule));
+ }
+ Terminal next = advance();
+ if ( next != null && !this.terminals.isValid(next.getId()) ) {
+ throw new SyntaxError(syntaxErrorFormatter.invalid_terminal(nonterminal, next));
+ }
+ return current;
+ }
+}
diff --git a/src/main/java/org/broadinstitute/parser/Utility.java b/src/main/java/org/broadinstitute/parser/Utility.java
new file mode 100644
index 0000000..0b87903
--- /dev/null
+++ b/src/main/java/org/broadinstitute/parser/Utility.java
@@ -0,0 +1,83 @@
+
+package org.broadinstitute.parser;
+import java.util.Collection;
+import java.util.Iterator;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.nio.*;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+public class Utility {
+ public static String join(Collection> s, String delimiter) {
+ StringBuilder builder = new StringBuilder();
+ Iterator iter = s.iterator();
+ while (iter.hasNext()) {
+ builder.append(iter.next());
+ if (!iter.hasNext()) {
+ break;
+ }
+ builder.append(delimiter);
+ }
+ return builder.toString();
+ }
+ public static String getIndentString(int spaces) {
+ StringBuilder sb = new StringBuilder();
+ for(int i = 0; i < spaces; i++) {
+ sb.append(' ');
+ }
+ return sb.toString();
+ }
+ public static String base64_encode(byte[] bytes) {
+ int b64_len = ((bytes.length + ( (bytes.length % 3 != 0) ? (3 - (bytes.length % 3)) : 0) ) / 3) * 4;
+ int cycle = 0, b64_index = 0;
+ byte[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes();
+ byte[] b64 = new byte[b64_len];
+ byte[] buffer = new byte[3];
+ Arrays.fill(buffer, (byte) -1);
+ for (byte b : bytes) {
+ int index = cycle % 3;
+ buffer[index] = b;
+ boolean last = (cycle == (bytes.length - 1));
+ if ( index == 2 || last ) {
+ if ( last ) {
+ if ( buffer[1] == -1 ) buffer[1] = 0;
+ if ( buffer[2] == -1 ) buffer[2] = 0;
+ }
+ b64[b64_index++] = alphabet[buffer[0] >> 2];
+ b64[b64_index++] = alphabet[((buffer[0] & 0x3) << 4) | ((buffer[1] >> 4) & 0xf)];
+ b64[b64_index++] = alphabet[((buffer[1] & 0xf) << 2) | ((buffer[2] >> 6) & 0x3)];
+ b64[b64_index++] = alphabet[buffer[2] & 0x3f];
+ if ( buffer[1] == 0 ) b64[b64_index - 2] = (byte) '=';
+ if ( buffer[2] == 0 ) b64[b64_index - 1] = (byte) '=';
+ Arrays.fill(buffer, (byte) -1);
+ }
+ cycle++;
+ }
+ return new String(b64);
+ }
+ public static String readStdin() throws IOException {
+ InputStreamReader stream = new InputStreamReader(System.in, "utf-8");
+ char buffer[] = new char[System.in.available()];
+ try {
+ stream.read(buffer, 0, System.in.available());
+ } finally {
+ stream.close();
+ }
+ return new String(buffer);
+ }
+ public static String readFile(String path) throws IOException {
+ FileInputStream stream = new FileInputStream(new File(path));
+ try {
+ FileChannel fc = stream.getChannel();
+ MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+ /* Instead of using default, pass in a decoder. */
+ return Charset.defaultCharset().decode(bb).toString();
+ }
+ finally {
+ stream.close();
+ }
+ }
+}
diff --git a/src/test/java/org/broadinstitute/compositetask/ApiTest.java b/src/test/java/org/broadinstitute/compositetask/ApiTest.java
new file mode 100644
index 0000000..133ede6
--- /dev/null
+++ b/src/test/java/org/broadinstitute/compositetask/ApiTest.java
@@ -0,0 +1,85 @@
+package org.broadinstitute.compositetask;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+import org.testng.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Set;
+
+import org.broadinstitute.parser.SyntaxError;
+
+import org.broadinstitute.compositetask.CompositeTask;
+
+public class ApiTest
+{
+ private CompositeTask task;
+
+ @BeforeClass
+ private void createCompositeTaskObject() {
+ try {
+ File source = new File("test-files/api/0.wdl");
+ String relative = new File(".").toURI().relativize(source.toURI()).getPath();
+ this.task = new CompositeTask(source, relative);
+ } catch(IOException error) {
+ Assert.fail("IOException reading file: " + error);
+ } catch(SyntaxError error) {
+ Assert.fail("Not expecting syntax error: " + error);
+ }
+ }
+
+ @Test
+ public void testGetNodesMethodReturnsTheRightNumberOfNodes() {
+ Assert.assertEquals(this.task.getNodes().size(), 2, "Expecting 2 nodes, found " + this.task.getNodes().size());
+ }
+
+ @Test
+ public void testGetStepMethodReturnsTheCorrectTopLevelStep() {
+ CompositeTaskStep step = this.task.getStep("atask");
+ Assert.assertNotNull(step, "Expected one step with name 'atask'");
+ Assert.assertEquals(step.getName(), "atask", "Expecting one step with name 'atask'");
+ Assert.assertEquals(step.getParent(), this.task, "Expecting the parent of 'atask' step to be the composite task");
+ }
+
+ @Test
+ public void testTopLevelStepHasCorrectOutputMappingsToVariableX() {
+ CompositeTaskStep step = this.task.getStep("atask");
+ boolean found = false;
+ for ( CompositeTaskStepOutput output : step.getOutputs() ) {
+ if ( output.getVariable().getName().equals("x") ) {
+ found = true;
+ Assert.assertEquals(output.getType(), "File", "Expected the variable 'x' to be a File mapping");
+ Assert.assertEquals(output.getMethod(), "assign", "Expected the mapping method to be 'assign'");
+ Assert.assertEquals(output.getPath(), "foo.txt", "Expected the output file path to be 'foo.txt'");
+ }
+ }
+ if ( !found ) Assert.fail("Expected to find one output to 'atask' to variable 'x'");
+ }
+
+ @Test
+ public void testTopLevelStepHasCorrectOutputMappingsToVariableY() {
+ CompositeTaskStep step = this.task.getStep("atask");
+ boolean found = false;
+ for ( CompositeTaskStepOutput output : step.getOutputs() ) {
+ if ( output.getVariable().getName().equals("y") ) {
+ found = true;
+ Assert.assertEquals(output.getType(), "FirstLine", "Expected the variable 'y' to be a File mapping");
+ Assert.assertEquals(output.getMethod(), "assign", "Expected the mapping method to be 'assign'");
+ Assert.assertEquals(output.getPath(), "bar.txt", "Expected the output file path to be 'bar.txt'");
+ }
+ }
+ if ( !found ) Assert.fail("Expected to find one output to 'atask' to variable 'y'");
+ }
+
+ @Test
+ public void testSingleTopLevelForLoopExistsWithSubTask() {
+ Set nodes = this.task.getNodes();
+ CompositeTaskStep innerStep = this.task.getStep("btask");
+ Assert.assertNotNull(innerStep, "Expected a step with name 'btask' to exist");
+ CompositeTaskForLoop loop = (CompositeTaskForLoop) innerStep.getParent();
+ Assert.assertEquals(loop.getParent(), this.task, "Expected the loop's parent node to be the composite task");
+ Assert.assertEquals(loop.getCollection().getName(), "foobar", "Expecting one loop with a collection called 'foobar'");
+ Assert.assertEquals(loop.getVariable().getName(), "item", "Expecting one loop with a variable called 'item'");
+ }
+}
diff --git a/src/test/java/org/broadinstitute/compositetask/ParsingTest.java b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java
new file mode 100644
index 0000000..452d404
--- /dev/null
+++ b/src/test/java/org/broadinstitute/compositetask/ParsingTest.java
@@ -0,0 +1,222 @@
+package org.broadinstitute.compositetask;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.Assert;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.broadinstitute.parser.SyntaxError;
+import org.broadinstitute.parser.SourceCode;
+import org.broadinstitute.parser.Terminal;
+import org.broadinstitute.parser.Utility;
+
+import org.broadinstitute.compositetask.CompositeTask;
+import org.broadinstitute.compositetask.CompositeTaskSourceCode;
+import org.broadinstitute.compositetask.Lexer;
+
+public class ParsingTest
+{
+ @DataProvider(name="parsingTests")
+ public Object[][] parsingTests() {
+ File parsingTestDir = new File("test-files", "parsing");
+ Collection composite_tasks = new ArrayList();
+
+ for ( String subDir : parsingTestDir.list() ) {
+ File testDir = new File(parsingTestDir, subDir);
+ File skipFile = new File(testDir, "skip");
+ if ( ! skipFile.exists() ) {
+ composite_tasks.add(new Object[] { testDir });
+ }
+ }
+
+ return composite_tasks.toArray(new Object[0][]);
+ }
+
+ private CompositeTask getCompositeTask(File source) {
+ try {
+ String relative = new File(".").toURI().relativize(source.toURI()).getPath();
+ return new CompositeTask(source, relative);
+ } catch(IOException error) {
+ Assert.fail("IOException reading file: " + error);
+ } catch(SyntaxError error) {
+ Assert.fail("Not expecting syntax error: " + error);
+ }
+
+ return null;
+ }
+
+ @Test(dataProvider="parsingTests")
+ public void testLexicalAnalysis(File dir) {
+ File tokens = new File(dir, "tokens");
+ File source = new File(dir, "source.wdl");
+ String actual = null;
+
+ try {
+ String relative = new File(".").toURI().relativize(source.toURI()).getPath();
+ SourceCode code = new CompositeTaskSourceCode(source, relative);
+ Lexer lexer = new Lexer();
+ List terminals = lexer.getTokens(code);
+ actual = "[\n " + Utility.join(terminals, ",\n ") + "\n]\n";
+ } catch (IOException error) {
+ Assert.fail("Could not read source code: " + error);
+ }
+
+ if ( !tokens.exists() ) {
+ try {
+ FileWriter out = new FileWriter(tokens);
+ out.write(actual);
+ out.close();
+ } catch (IOException error) {
+ Assert.fail("Could not write tokens file: " + error);
+ }
+
+ System.out.println("Created " + tokens);
+ }
+
+ try {
+ String expected = Utility.readFile(tokens.getAbsolutePath());
+ Assert.assertEquals(actual, expected, "Tokens list did not match.");
+ } catch (IOException error) {
+ Assert.fail("Cannot read " + tokens.getAbsolutePath());
+ }
+ }
+
+ @Test(dataProvider="parsingTests")
+ public void testParseTreeIsGeneratedFromSourceCodeCorrectly(File dir) {
+ File source = new File(dir, "source.wdl");
+ File parsetree = new File(dir, "parsetree");
+ CompositeTask ctask = getCompositeTask(source);
+ String actual = ctask.getParseTree().toPrettyString();
+
+ if ( ctask == null ) {
+ Assert.fail("Null Composite Task");
+ }
+
+ if ( !parsetree.exists() ) {
+ try {
+ FileWriter out = new FileWriter(parsetree);
+ out.write(actual);
+ out.close();
+ } catch (IOException error) {
+ Assert.fail("Could not write " + parsetree + ": " + error);
+ }
+
+ System.out.println("Created " + parsetree);
+ }
+
+ try {
+ String expected = Utility.readFile(parsetree.getAbsolutePath());
+ Assert.assertEquals(actual, expected, "Parse trees did not match");
+ } catch (IOException error) {
+ Assert.fail("Cannot read " + parsetree.getAbsolutePath());
+ }
+ }
+
+ @Test(dataProvider="parsingTests")
+ public void testAbstractSyntaxTreeIsGeneratedFromSourceCodeCorrectly(File dir) {
+ File source = new File(dir, "source.wdl");
+ File ast = new File(dir, "ast");
+ CompositeTask ctask = getCompositeTask(source);
+ String actual = ctask.getAst().toPrettyString();
+
+ if ( !ast.exists() ) {
+ try {
+ FileWriter out = new FileWriter(ast);
+ out.write(actual);
+ out.close();
+ } catch (IOException error) {
+ Assert.fail("Could not write " + ast + ": " + error);
+ }
+
+ System.out.println("Created " + ast);
+ }
+
+ try {
+ String expected = Utility.readFile(ast.getAbsolutePath());
+ Assert.assertEquals(actual, expected, "Abstract syntax trees did not match");
+ } catch (IOException error) {
+ Assert.fail("Cannot read " + ast.getAbsolutePath());
+ }
+ }
+
+ @Test(dataProvider="parsingTests")
+ public void testSourceFormatterOutputsCorrectlyFormattedSourceCode(File dir) {
+ File source = new File(dir, "source.wdl");
+ File formatted_file = new File(dir, "formatted");
+ CompositeTask ctask = getCompositeTask(source);
+ CompositeTaskSourceCodeFormatter formatter = new CompositeTaskSourceCodeFormatter();
+ String actual = formatter.format(ctask);
+
+ if ( !formatted_file.exists() ) {
+ try {
+ FileWriter out = new FileWriter(formatted_file);
+ out.write(actual);
+ out.close();
+ } catch (IOException error) {
+ Assert.fail("Could not write " + formatted_file + ": " + error);
+ }
+
+ System.out.println("Created " + formatted_file);
+ }
+
+ try {
+ String expected = Utility.readFile(formatted_file.getAbsolutePath());
+ Assert.assertEquals(actual, expected, "Formatted source code files did not match");
+ } catch (IOException error) {
+ Assert.fail("Cannot read " + formatted_file.getAbsolutePath());
+ }
+ }
+
+ public static > List asSortedList(Collection c) {
+ List