Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/rxm.git

Revised BNF to clarify context for different types of maps. Added a tree that is populated while walking through the map. The tree, eventually, will employ a wrapper around elements that can generate the appropriate SQL code.

AuthorDave Jarvis <email>
Date2015-03-05 20:00:56 GMT-0800
Commitc717449daad8dc44a57a52571b86023d40dca61e
Parentf79fa77
source/grammar/Query.g
/* Define the root, line map, and JOIN clauses.
*/
-start: (root | module) T_EOL ;
-root : T_ROOT T_MAP element ;
+start : (root | module) T_EOL ;
+root : T_ROOT T_MAP element ;
+module: T_MODULE T_ID ;
-statement: (pop | glob | map | innerJoin | outerJoin | include) T_EOL ;
+statement: (pop | glob | map | include) T_EOL ;
pop : T_POP ;
glob : T_GLOB ;
-map : entity T_MAP node ;
-innerJoin: tableColumn T_INNER tableColumn ;
-outerJoin: tableColumn T_OUTER tableColumn ;
+
+map : tableMap | columnMap | innerMap | outerMap;
+columnMap: column T_MAP node ;
+tableMap : table T_MAP node ;
+innerMap : tableColumn T_INNER tableColumn ;
+outerMap : tableColumn T_OUTER tableColumn ;
+
include : T_IMPORT T_ID ;
-module : T_MODULE T_ID ;
table : T_ID ;
column : T_PERIOD T_ID ;
tableColumn: table column ;
attribute : T_AT T_ID ;
element : T_ID ;
path : element T_SLASH element ;
-entity : table | column ;
node : element | attribute | path ;
source/java/com/whitemagicsoftware/rxm/Parser.java
*/
public class Parser extends QueryBaseListener {
+ private static int INDENT = 2;
+
private RXM rxm;
/** Used to convert linear map to hierarchical form. */
private List<String> statements = new ArrayList<String>();
/** Tracks the SQL statement insertion point. */
private int depth = 0;
- private Tree<ParserRuleContext> tree;
+ /** The tree constructed while walking the <b>rxm</b>. */
+ private Tree<ParserRuleContext> queryTree;
+
+ /** Current context within queryTree. */
+ private Tree<ParserRuleContext> contextTree;
/**
- * Creates a Parser instance that parses a given <b>rxm</b> string.
+ * Creates a Parser instance that parses a given <b>rxm</b>.
*
* @param rxm The <b>rxm</b> instance responsible for receiving information
@Override
public synchronized void enterQuery( QueryParser.QueryContext ctx ) {
- setTree( new Tree<ParserRuleContext>( ctx ) );
+ setQueryTree( createTree( ctx ) );
}
@Override
public synchronized void enterRoot( QueryParser.RootContext ctx ) {
- String root = ctx.getChild(2).getText();
-
- push( "XMLROOT(" );
- push( String.format( "XMLELEMENT( NAME \"%s\"", root ) );
+ setContextTree( getQueryTree().addLeaf( ctx ) );
+ }
- decreaseDepth();
- push( ")" );
- decreaseDepth();
- push( ", VERSION '1.0', STANDALONE YES)" );
+ @Override
+ public synchronized void enterTableMap( QueryParser.TableMapContext ctx ) {
+ setContextTree( getContextTree().addLeaf( ctx ) );
}
@Override
- public synchronized void enterMap( QueryParser.MapContext ctx ) {
+ public synchronized void enterColumnMap( QueryParser.ColumnMapContext ctx ) {
+ getContextTree().addLeaf( ctx );
}
@Override
- public synchronized void exitMap( QueryParser.MapContext ctx ) {
+ public synchronized void enterPop( QueryParser.PopContext ctx ) {
+ setContextTree( getContextTree().getParent() );
}
@Override
- public synchronized void enterElement( QueryParser.ElementContext ctx ) {
+ public synchronized void exitQuery( QueryParser.QueryContext ctx ) {
+ /*
+ push( "XMLROOT(" );
+ push( String.format( "XMLELEMENT( NAME \"%s\"", root ) );
+
+ push( ")" );
+ push( ", VERSION '1.0', STANDALONE YES)" );
+
String s = String.format( "XMLELEMENT( \"%s\" AS %s )",
ctx.getText(), "COLUMN" );
push( s );
- }
-
- @Override
- public synchronized void enterAttribute( QueryParser.AttributeContext ctx ) {
String s = String.format( "XMLATTRIBUTES( %s AS \"%s\" )",
"COLUMN", ctx.getText().substring(1) );
push( s );
+ */
+
+ System.out.println( toString() );
}
+ /**
+ * Performs a depth-first traversal to generate a printable string.
+ */
@Override
- public synchronized void exitQuery( QueryParser.QueryContext ctx ) {
- // Traverse the stack in order.
- for( String s : getStatements() ) {
- System.out.println( s );
- }
+ public String toString() {
+ return toString( getQueryTree().getLeaves().get(0), INDENT );
}
- private void push( String s ) {
- getStatements().add( getDepth() + "." + createIndent() + s );
- increaseDepth();
- }
+ /**
+ * Depth-first traversal.
+ */
+ private String toString( Tree<ParserRuleContext> tree, int increment ) {
+ String s = indent( increment ) + tree.getPayload().getText();
- private String createIndent() {
- String empty = CharBuffer.allocate( getDepth() * 2 ).toString();
- return empty.replace( '\0', ' ' );
- }
+ for( Tree<ParserRuleContext> child : tree.getLeaves() ) {
+ s += String.format( "%n%s", toString( child, increment + INDENT ) );
+ }
- private void increaseDepth() {
- setDepth( getDepth() + 1 );
+ return s;
}
- private void decreaseDepth() {
- setDepth( getDepth() - 1 );
+ private String indent( int spaces ) {
+ String empty = CharBuffer.allocate( spaces ).toString();
+ return empty.replace( '\0', ' ' );
}
}
- private void setDepth( int depth ) {
- this.depth = depth;
+ private void setContextTree( Tree<ParserRuleContext> contextTree ) {
+ this.contextTree = contextTree;
}
- private int getDepth() {
- return this.depth;
+ private Tree<ParserRuleContext> getContextTree() {
+ return this.contextTree;
}
- private void setTree( Tree<ParserRuleContext> tree ) {
- this.tree = tree;
+ private void setQueryTree( Tree<ParserRuleContext> queryTree ) {
+ this.queryTree = queryTree;
}
- private Tree<ParserRuleContext> getTree() {
- return this.tree;
+ private Tree<ParserRuleContext> getQueryTree() {
+ return this.queryTree;
+ }
+
+ /**
+ * Creates a new tree with the given payload.
+ */
+ private Tree<ParserRuleContext> createTree( ParserRuleContext payload ) {
+ return new Tree<ParserRuleContext>( payload );
}
}
source/java/com/whitemagicsoftware/rxm/Tree.java
import java.util.Map;
+import java.nio.CharBuffer;
+
/**
* Stores a tree of values.
private Map<T, Tree<T>> map = new HashMap<T, 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 );
put( payload, this );
}
- public Tree<T> addLeaf( T leaf ) {
- Tree<T> tree = new Tree<T>( leaf );
+ /**
+ * Adds a new leaf to this tree.
+ *
+ * @param payload The data to add to the leaf.
+ * @return The tree containing the given payload.
+ */
+ public Tree<T> addLeaf( T payload ) {
+ Tree<T> tree = createTree( payload );
+
add( tree );
+ put( payload, tree );
- put( leaf, tree );
return tree;
}
- public void addLeaf( T root, T leaf ) {
- if( contains( root ) ) {
- get( root ).addLeaf( leaf );
- }
- else {
- addLeaf( root ).addLeaf( leaf );
- }
+ /**
+ * Adds a new leaf to the given root. If the root is not already
+ * part of this tree, it is added as a leaf.
+ *
+ * @param root The payload for the root tree to which the given payload
+ * is added.
+ * @param payload The payload to add to the given root.
+ */
+ public void addLeaf( T root, T payload ) {
+ (contains( root ) ? get( root ) : addLeaf( root )).addLeaf( payload );
}
private void add( Tree<T> tree ) {
getLeaves().add( tree );
tree.setParent( this );
tree.setMap( getMap() );
}
- private boolean contains( T root ) {
- return getMap().containsKey( root );
+ private boolean contains( T payload ) {
+ return getMap().containsKey( payload );
}
}
- private Tree<T> getParent() {
+ public Tree<T> getParent() {
return this.parent;
}
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;
}
- private List<Tree<T>> getLeaves() {
+ /**
+ * 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;
+ }
+
+ /**
+ * Creates a new tree starting with the given payload.
+ *
+ * @param payload The data at the root to create.
+ * @return The tree containing the given payload.
+ */
+ protected Tree<T> createTree( T payload ) {
+ return new Tree<T>( payload );
}
}
Delta124 lines added, 65 lines removed, 59-line increase