Skip to content

Commit

Permalink
Switch to JavaCC-based parser (was JavaCUP).
Browse files Browse the repository at this point in the history
Add DrillThroughNode.
Plus a couple of cosmetic changes.


git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@512 c6a108a4-781c-0410-a6c6-c2d559e19af0
  • Loading branch information
julianhyde committed Feb 27, 2012
1 parent cc74e15 commit ff570b4
Show file tree
Hide file tree
Showing 16 changed files with 1,978 additions and 77 deletions.
20 changes: 17 additions & 3 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@
<property name="generated.java.files"
value="
${src.dir}/org/olap4j/mdx/parser/impl/DefaultMdxParser.java,
${src.dir}/org/olap4j/mdx/parser/impl/DefaultMdxParserSym.java" />
${src.dir}/org/olap4j/mdx/parser/impl/DefaultMdxParserSym.java,
${src.dir}/org/olap4j/mdx/parser/impl/MdxParserImpl.java,
${src.dir}/org/olap4j/mdx/parser/impl/MdxParserImplTokenManager.java,
${src.dir}/org/olap4j/mdx/parser/impl/ParseException.java,
${src.dir}/org/olap4j/mdx/parser/impl/SimpleCharStream.java,
${src.dir}/org/olap4j/mdx/parser/impl/Token.java,
${src.dir}/org/olap4j/mdx/parser/impl/TokenMgrError.java" />

<target name="checkIsJdk15" if="jdk15.not.present">
<fail message="The 'jar' target (and dependent targets 'release', 'binzip') must be run under JDK 1.5." />
Expand Down Expand Up @@ -254,13 +260,21 @@ class XmlaOlap4jDriverVersion {
// End XmlaOlap4jDriverVersion.java</echo>
</target>

<target name="parser" depends="resolve">
<target name="define-tasks">
<taskdef name="javacup" classname="java_cup.JavaCUPTask">
<classpath refid="classpath" />
<classpath refid="classpath"/>
</taskdef>
</target>

<target name="parser" depends="resolve,define-tasks">
<!-- Old parser. -->
<javacup srcdir="${src.dir}"
input="${src.dir}/org/olap4j/mdx/parser/impl/DefaultMdxParser.cup"
expect="61" interface="true" />
<!-- New parser. -->
<javacc
target="${src.dir}/org/olap4j/mdx/parser/impl/MdxParser.jj"
javacchome="${lib.dir}"/>
</target>

<target name="clean-tests" depends="subfloor.clean-tests">
Expand Down
2 changes: 2 additions & 0 deletions ivy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
<dependency org="net.sf" name="pdfdoclet" rev="1.0.2"
conf="codegen->default" />

<dependency org="net.java.dev.javacc" name="javacc" rev="5.0"/>

</dependencies>
</ivy-module>

Expand Down
7 changes: 7 additions & 0 deletions src/org/olap4j/mdx/DefaultMdxValidatorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ public ParseTreeNode visit(PropertyValueNode propertyValueNode) {
throw new UnsupportedOperationException();
}

public ParseTreeNode visit(DrillThroughNode drillThroughNode) {
if (false) {
return null;
}
throw new UnsupportedOperationException();
}

public void accept(AxisNode axis) {
ParseTreeNode exp = axis.getExpression().accept(this);
final Type type = exp.getType();
Expand Down
113 changes: 113 additions & 0 deletions src/org/olap4j/mdx/DrillThroughNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
// $Id$
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package org.olap4j.mdx;

import org.olap4j.type.Type;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

/**
* Parse tree model for an MDX {@code DRILLTHROUGH} statement.
*
* @author jhyde
* @version $Id$
* @since Feb 24, 2012
*/
public class DrillThroughNode implements ParseTreeNode {
private final ParseRegion region;
private final SelectNode select;
private final int maxRowCount;
private final int firstRowOrdinal;
private final List<ParseTreeNode> returnList;

/**
* Creates a DrillThroughNode.
*
* @param region Region of source code from which this node was created
* @param select Select statement
* @param maxRowCount Maximum number of rows to return, or -1
* @param firstRowOrdinal Ordinal of first row to return, or -1
* @param returnList List of columns to return
*/
public DrillThroughNode(
ParseRegion region,
SelectNode select,
int maxRowCount,
int firstRowOrdinal,
List<ParseTreeNode> returnList)
{
this.region = region;
this.select = select;
this.maxRowCount = maxRowCount;
this.firstRowOrdinal = firstRowOrdinal;
this.returnList = returnList;
}

public ParseRegion getRegion() {
return region;
}

public <T> T accept(ParseTreeVisitor<T> visitor) {
return visitor.visit(this);
}

public Type getType() {
// not an expression, so has no type
return null;
}

public String toString() {
StringWriter sw = new StringWriter();
ParseTreeWriter pw = new ParseTreeWriter(sw);
unparse(pw);
return sw.toString();
}

public void unparse(ParseTreeWriter writer) {
final PrintWriter pw = writer.getPrintWriter();
pw.print("DRILLTHROUGH");
if (maxRowCount >= 0) {
pw.print(" MAXROWS ");
pw.print(maxRowCount);
}
if (firstRowOrdinal >= 0) {
pw.print(" FIRSTROWSET ");
pw.print(firstRowOrdinal);
}
pw.print(" ");
select.unparse(writer);
if (returnList != null) {
MdxUtil.unparseList(writer, returnList, " RETURN ", ", ", "");
}
}

public DrillThroughNode deepCopy() {
return new DrillThroughNode(
region,
select.deepCopy(),
maxRowCount,
firstRowOrdinal,
MdxUtil.deepCopyList(returnList));
}
}

// End DrillThroughNode.java
19 changes: 19 additions & 0 deletions src/org/olap4j/mdx/MdxUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
package org.olap4j.mdx;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -96,6 +97,24 @@ static <E extends ParseTreeNode> List<E> deepCopyList(List<E> list) {
}
return listCopy;
}

static void unparseList(
ParseTreeWriter writer,
List<ParseTreeNode> argList,
String start,
String mid,
String end)
{
final PrintWriter pw = writer.getPrintWriter();
pw.print(start);
for (int i = 0; i < argList.size(); i++) {
if (i > 0) {
pw.print(mid);
}
argList.get(i).unparse(writer);
}
pw.print(end);
}
}

// End MdxUtil.java
61 changes: 59 additions & 2 deletions src/org/olap4j/mdx/ParseRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
*/
package org.olap4j.mdx;

import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;

/**
* Region of parser source code.
*
Expand Down Expand Up @@ -48,8 +52,6 @@ public class ParseRegion {
private final int endLine;
private final int endColumn;

private static final String NL = System.getProperty("line.separator");

/**
* Creates a ParseRegion.
*
Expand Down Expand Up @@ -171,6 +173,61 @@ public boolean equals(Object obj) {
}
}

/**
* Combines this region with other regions.
*
* @param nodes Source code regions
* @return region which represents the span of the given regions
*/
public ParseRegion plus(final ParseTreeNode... nodes)
{
return plusAll(
new AbstractList<ParseRegion>() {
public ParseRegion get(int index) {
final ParseTreeNode node = nodes[index];
if (node == null) {
return null;
}
return node.getRegion();
}

public int size() {
return nodes.length;
}
});
}

public ParseRegion plus(final List<? extends ParseTreeNode> nodes) {
if (nodes == null) {
return this;
}
return plusAll(
new AbstractList<ParseRegion>() {
public ParseRegion get(int index) {
final ParseTreeNode node = nodes.get(index);
if (node == null) {
return null;
}
return node.getRegion();
}

public int size() {
return nodes.size();
}
});
}

/**
* Combines this region with other regions.
*
* @param regions Source code regions
* @return region which represents the span of the given regions
*/
public ParseRegion plus(ParseRegion... regions)
{
return plusAll(Arrays.asList(regions));
}

/**
* Combines this region with a list of parse tree nodes to create a
* region which spans from the first point in the first to the last point
Expand Down
11 changes: 11 additions & 0 deletions src/org/olap4j/mdx/ParseTreeVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,17 @@ public interface ParseTreeVisitor<T> {
* @see PropertyValueNode#accept(ParseTreeVisitor)
*/
T visit(PropertyValueNode propertyValueNode);

/**
* Visits a property-value pair.
*
* @param drillThroughNode Node representing a drill-through statement
*
* @return value yielded by visiting the node
*
* @see DrillThroughNode#accept(ParseTreeVisitor)
*/
T visit(DrillThroughNode drillThroughNode);
}

// End ParseTreeVisitor.java
50 changes: 30 additions & 20 deletions src/org/olap4j/mdx/Syntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.io.PrintWriter;
import java.util.List;

import static org.olap4j.mdx.MdxUtil.unparseList;

/**
* Enumerated values describing the syntax of an expression.
*
Expand Down Expand Up @@ -297,13 +299,39 @@ public void unparse(
* Defines syntax for expression invoked <code>object&#46;&PROPERTY</code>
* (a variant of {@link #Property}).
*/
QuotedProperty,
QuotedProperty {
public void unparse(
String operatorName,
List<ParseTreeNode> argList,
ParseTreeWriter writer)
{
assert argList.size() == 1;
argList.get(0).unparse(writer); // 'this'
final PrintWriter pw = writer.getPrintWriter();
pw.print(".[");
pw.print(operatorName);
pw.print("]");
}
},

/**
* Defines syntax for expression invoked <code>object&#46;[&PROPERTY]</code>
* (a variant of {@link #Property}).
*/
AmpersandQuotedProperty,
AmpersandQuotedProperty {
public void unparse(
String operatorName,
List<ParseTreeNode> argList,
ParseTreeWriter writer)
{
assert argList.size() == 1;
argList.get(0).unparse(writer); // 'this'
final PrintWriter pw = writer.getPrintWriter();
pw.print(".&[");
pw.print(operatorName);
pw.print("]");
}
},

/**
* Defines the syntax for an empty expression. Empty expressions can occur
Expand Down Expand Up @@ -352,24 +380,6 @@ private static boolean needParen(List<ParseTreeNode> args) {
&& args.get(0) instanceof CallNode
&& ((CallNode) args.get(0)).getSyntax() == Parentheses);
}

private static void unparseList(
ParseTreeWriter writer,
List<ParseTreeNode> argList,
String start,
String mid,
String end)
{
final PrintWriter pw = writer.getPrintWriter();
pw.print(start);
for (int i = 0; i < argList.size(); i++) {
if (i > 0) {
pw.print(mid);
}
argList.get(i).unparse(writer);
}
pw.print(end);
}
}

// End Syntax.java
Loading

0 comments on commit ff570b4

Please sign in to comment.