| ### Pops | ||
| -Stack pops (`^`) switch context to a previous element. Multiple pops | ||
| -per line are permitted; extraneous pops are silently ignored: context | ||
| -never traverses beyond the root node. | ||
| +Stack pops (`^`) switch context to a previous element. Multiple consecutive | ||
| +pops are permitted; extraneous pops are silently ignored: context never | ||
| +traverses beyond the root node. | ||
| ### Globs |
| import com.whitemagicsoftware.rxm.grammar.QueryParser; | ||
| -import java.nio.CharBuffer; | ||
| +import com.whitemagicsoftware.rxm.tree.Tree; | ||
| +import com.whitemagicsoftware.rxm.tree.XMLQueryTree; | ||
| import org.antlr.v4.runtime.ANTLRInputStream; | ||
| */ | ||
| public class Parser extends QueryBaseListener { | ||
| - private static int INDENT = 2; | ||
| - | ||
| /** Map for containing modules. */ | ||
| private RXM rxm; | ||
| @Override | ||
| public synchronized void enterTableMap( QueryParser.TableMapContext ctx ) { | ||
| - Tree<ParserRuleContext> tree = createTree( ctx ); | ||
| - getContextTree().addLeaf( tree ); | ||
| - | ||
| - setContextTree( tree ); | ||
| - } | ||
| - | ||
| - private String getText() { | ||
| - return getContextTree().getPayload().getText(); | ||
| + setContextTree( addLeaf( ctx ) ); | ||
| } | ||
| /** | ||
| * Invoked when parsing <code>column > node</code>. Adds a new leaf to | ||
| * the context tree. | ||
| */ | ||
| @Override | ||
| public synchronized void enterColumnMap( QueryParser.ColumnMapContext ctx ) { | ||
| - Tree<ParserRuleContext> tree = createTree( ctx ); | ||
| - getContextTree().addLeaf( tree ); | ||
| + addLeaf( ctx ); | ||
| } | ||
| push( s ); | ||
| */ | ||
| - | ||
| - System.out.println( toString() ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Performs a depth-first traversal to generate a printable string. | ||
| - */ | ||
| - @Override | ||
| - public String toString() { | ||
| - return toString( getContextTree().getRoot(), INDENT ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Depth-first traversal. | ||
| - */ | ||
| - private String toString( Tree<ParserRuleContext> tree, int increment ) { | ||
| - String s = indent( increment ) + tree.getPayload().getText(); | ||
| - | ||
| - for( Tree<ParserRuleContext> child : tree.getLeaves() ) { | ||
| - s += String.format( "%n%s", toString( child, increment + INDENT ) ); | ||
| - } | ||
| - return s; | ||
| + System.out.println( getContextTree().getRoot().toString() ); | ||
| } | ||
| /** | ||
| - * Creates a string of spaces that is spaces spaces long. | ||
| + * Adds the given parser rule context to the current context tree. | ||
| * | ||
| - * @param spaces The number of spaces to add to the string. | ||
| + * @param ctx The parser rule context to add as a leaf to the context tree. | ||
| + * @return The leaf (tree) that was added. | ||
| */ | ||
| - private String indent( int spaces ) { | ||
| - String empty = CharBuffer.allocate( spaces ).toString(); | ||
| - return empty.replace( '\0', ' ' ); | ||
| + private Tree<ParserRuleContext> addLeaf( ParserRuleContext ctx ) { | ||
| + return getContextTree().addLeaf( createTree( ctx ) ); | ||
| } | ||
| */ | ||
| private Tree<ParserRuleContext> createTree( ParserRuleContext payload ) { | ||
| - return new Tree<ParserRuleContext>( payload ); | ||
| + return new XMLQueryTree<ParserRuleContext>( payload ); | ||
| } | ||
| } | ||
| -package com.whitemagicsoftware.rxm; | ||
| - | ||
| -import java.util.ArrayList; | ||
| -import java.util.List; | ||
| - | ||
| -/** | ||
| - * Stores a tree of values. | ||
| - * | ||
| - * @param <T> The tree's playload. | ||
| - */ | ||
| -public class Tree<T> { | ||
| - /** Data associated with this leaf. */ | ||
| - private T payload; | ||
| - | ||
| - /** Root of this tree, possibly null. */ | ||
| - private Tree<T> parent; | ||
| - | ||
| - /** Child trees of this tree, possibly empty. */ | ||
| - private List<Tree<T>> leaves = new ArrayList<Tree<T>>(); | ||
| - | ||
| - /** | ||
| - * Constructs a new tree, ready to have leaves added. | ||
| - * | ||
| - * @param payload The data associated with this tree leaf (must not | ||
| - * be null). | ||
| - */ | ||
| - public Tree( T payload ) { | ||
| - setPayload( payload ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Adds the given tree to the list of this tree's leaves. This will also | ||
| - * set the parent of the given tree to this tree instance. | ||
| - * | ||
| - * @param tree The tree to append to the list of leaves. | ||
| - * @return The tree that was added (i.e., the tree parameter). | ||
| - */ | ||
| - public Tree<T> addLeaf( Tree<T> tree ) { | ||
| - getLeaves().add( tree ); | ||
| - | ||
| - return tree.setParent( this ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Finds the root to this tree by iterating over this tree's parent nodes. | ||
| - * | ||
| - * @return The root of this tree. | ||
| - */ | ||
| - public Tree<T> getRoot() { | ||
| - Tree<T> root = this; | ||
| - | ||
| - // Traverse until there are no more parents. | ||
| - while( root.getParent() != null ) { | ||
| - root = root.getParent(); | ||
| - } | ||
| - | ||
| - return root; | ||
| - } | ||
| - | ||
| - /** | ||
| - * Sets the parent tree to this tree. | ||
| - * | ||
| - * @param parent The root for this tree. | ||
| - * @return The root for this tree. | ||
| - */ | ||
| - private Tree<T> setParent( Tree<T> parent ) { | ||
| - return this.parent = parent; | ||
| - } | ||
| - | ||
| - /** | ||
| - * Returns the parent tree to this tree, or null if this is the tree top. | ||
| - * | ||
| - * @return The root of this tree, or null if no more trees exist above. | ||
| - */ | ||
| - public Tree<T> getParent() { | ||
| - return this.parent; | ||
| - } | ||
| - | ||
| - /** | ||
| - * Sets the data for this leaf in the tree. | ||
| - * | ||
| - * @param payload The data to associate with this leaf. | ||
| - */ | ||
| - private void setPayload( T payload ) { | ||
| - this.payload = payload; | ||
| - } | ||
| - | ||
| - /** | ||
| - * Returns the data held at this position in the tree. | ||
| - * | ||
| - * @return A non-null payload. | ||
| - */ | ||
| - public T getPayload() { | ||
| - return this.payload; | ||
| - } | ||
| - | ||
| - /** | ||
| - * Returns the list of leaves for this tree. | ||
| - * | ||
| - * @return A non-null, but possibly empty, list of leaves. | ||
| - */ | ||
| - public List<Tree<T>> getLeaves() { | ||
| - return this.leaves; | ||
| - } | ||
| -} | ||
| - | ||
| +package com.whitemagicsoftware.rxm.tree; | ||
| + | ||
| +import java.nio.CharBuffer; | ||
| + | ||
| +/** | ||
| + * A tree that can transform itself from its data structure into a string. | ||
| + * The string is based on the tree's payload. | ||
| + */ | ||
| +public class TransformationTree<T> extends Tree<T> { | ||
| + private static int INDENT = 2; | ||
| + | ||
| + /** | ||
| + * Constructs a new tree, ready to have leaves added. | ||
| + * | ||
| + * @param payload The data associated with this tree leaf (must not | ||
| + * be null). | ||
| + */ | ||
| + public TransformationTree( T payload ) { | ||
| + super( payload ); | ||
| + } | ||
| + | ||
| + public String toString() { | ||
| + return toString( this, 0 ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Depth-first traversal. | ||
| + */ | ||
| + protected String toString( Tree<T> tree, int depth ) { | ||
| + String s = indent( depth ) + tree.getPayload().toString(); | ||
| + | ||
| + for( Tree<T> branch : tree.getLeaves() ) { | ||
| + s += String.format( "%n%s", toString( branch, depth + getIndent() ) ); | ||
| + } | ||
| + | ||
| + return s; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Creates a string of spaces that is spaces spaces long. | ||
| + * | ||
| + * @param spaces The number of spaces to add to the string. | ||
| + */ | ||
| + private String indent( int spaces ) { | ||
| + String empty = CharBuffer.allocate( spaces ).toString(); | ||
| + return empty.replace( '\0', ' ' ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the indent value. | ||
| + * | ||
| + * @return 2 (by default) | ||
| + */ | ||
| + protected int getIndent() { | ||
| + return INDENT; | ||
| + } | ||
| +} | ||
| + | ||
| +package com.whitemagicsoftware.rxm.tree; | ||
| + | ||
| +import java.util.ArrayList; | ||
| +import java.util.List; | ||
| + | ||
| +/** | ||
| + * Stores a tree of values. | ||
| + * | ||
| + * @param <T> The tree's playload. | ||
| + */ | ||
| +public class Tree<T> { | ||
| + /** Data associated with this leaf. */ | ||
| + private T payload; | ||
| + | ||
| + /** Root of this tree, possibly null. */ | ||
| + private Tree<T> parent; | ||
| + | ||
| + /** Child trees of this tree, possibly empty. */ | ||
| + private List<Tree<T>> leaves = new ArrayList<Tree<T>>(); | ||
| + | ||
| + /** | ||
| + * Constructs a new tree, ready to have leaves added. | ||
| + * | ||
| + * @param payload The data associated with this tree leaf (must not | ||
| + * be null). | ||
| + */ | ||
| + public Tree( T payload ) { | ||
| + setPayload( payload ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Adds the given tree to the list of this tree's leaves. This will also | ||
| + * set the parent of the given tree to this tree instance. | ||
| + * | ||
| + * @param tree The tree to append to the list of leaves. | ||
| + * @return The tree that was added (i.e., the tree parameter). | ||
| + */ | ||
| + public Tree<T> addLeaf( Tree<T> tree ) { | ||
| + getLeaves().add( tree ); | ||
| + tree.setParent( this ); | ||
| + return tree; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Finds the root to this tree by iterating over this tree's parent nodes. | ||
| + * | ||
| + * @return The root of this tree. | ||
| + */ | ||
| + public Tree<T> getRoot() { | ||
| + Tree<T> root = this; | ||
| + | ||
| + // Traverse until there are no more parents. | ||
| + while( root.getParent() != null ) { | ||
| + root = root.getParent(); | ||
| + } | ||
| + | ||
| + return root; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Sets the parent tree to this tree. | ||
| + * | ||
| + * @param parent The root for this tree. | ||
| + */ | ||
| + private void setParent( Tree<T> parent ) { | ||
| + this.parent = parent; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the parent tree to this tree, or null if this is the tree top. | ||
| + * | ||
| + * @return The root of this tree, or null if no more trees exist above. | ||
| + */ | ||
| + public Tree<T> getParent() { | ||
| + return this.parent; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Sets the data for this leaf in the tree. | ||
| + * | ||
| + * @param payload The data to associate with this leaf. | ||
| + */ | ||
| + private void setPayload( T payload ) { | ||
| + this.payload = payload; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the data held at this position in the tree. | ||
| + * | ||
| + * @return A non-null payload. | ||
| + */ | ||
| + public T getPayload() { | ||
| + return this.payload; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the list of leaves for this tree. | ||
| + * | ||
| + * @return A non-null, but possibly empty, list of leaves. | ||
| + */ | ||
| + public List<Tree<T>> getLeaves() { | ||
| + return this.leaves; | ||
| + } | ||
| +} | ||
| + | ||
| +package com.whitemagicsoftware.rxm.tree; | ||
| + | ||
| +import org.antlr.v4.runtime.ParserRuleContext; | ||
| + | ||
| +/** | ||
| + * Stores a tree of ParserRuleContext instances. | ||
| + */ | ||
| +public class XMLQueryTree<T extends ParserRuleContext> | ||
| + extends TransformationTree<T> { | ||
| + /** | ||
| + * Constructs a new tree, ready to have leaves added. | ||
| + * | ||
| + * @param payload The data associated with this tree leaf (must not | ||
| + * be null). | ||
| + */ | ||
| + public XMLQueryTree( T payload ) { | ||
| + super( payload ); | ||
| + } | ||
| +} | ||
| + | ||
| Author | Dave Jarvis <email> |
|---|---|
| Date | 2015-03-07 11:12:07 GMT-0800 |
| Commit | baa7be9c87dd76e4963e3c4605a07250be6000d2 |
| Parent | a4a0e10 |
| Delta | 197 lines added, 150 lines removed, 47-line increase |