You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2004/12/22 19:15:07 UTC

svn commit: r123135 - in incubator/jackrabbit/trunk: . src/grammar src/grammar/sql src/grammar/xpath src/java/org/apache/jackrabbit/core src/java/org/apache/jackrabbit/core/search src/java/org/apache/jackrabbit/core/search/jcrql src/java/org/apache/jackrabbit/core/search/lucene src/java/org/apache/jackrabbit/core/search/sql src/java/org/apache/jackrabbit/core/search/xpath src/test/org/apache/jackrabbit/test/search

Author: mreutegg
Date: Wed Dec 22 10:15:05 2004
New Revision: 123135

URL: http://svn.apache.org/viewcvs?view=rev&rev=123135
Log:
Added SQL and XPath query implementation. The implementation is not complete yet. Only basic operations are supported.
Also added postGoals to the maven.xml to generate the parser classes for SQL XPath.
Added:
   incubator/jackrabbit/trunk/src/grammar/
   incubator/jackrabbit/trunk/src/grammar/sql/
   incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/   (props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/grammar.dtd   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/javacc.xsl   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/jjtree-jackrabbit.xsl   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/jjtree.xsl   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/strip.xsl   (contents, props changed)
   incubator/jackrabbit/trunk/src/grammar/xpath/xpath-grammar.xml   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/ChildAxisQuery.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/DescendantSelfAxisQuery.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/   (props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTLiteral.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/DefaultParserVisitor.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/   (props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/SimpleNode.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SQLTest.java   (contents, props changed)
Removed:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredScorer.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LocationStepQuery.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PackageFilter.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilter.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilterQuery.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathQuery.java
Modified:
   incubator/jackrabbit/trunk/maven.xml
   incubator/jackrabbit/trunk/project.xml
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java

Modified: incubator/jackrabbit/trunk/maven.xml
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/maven.xml?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/maven.xml&r1=123134&p2=incubator/jackrabbit/trunk/maven.xml&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/maven.xml	(original)
+++ incubator/jackrabbit/trunk/maven.xml	Wed Dec 22 10:15:05 2004
@@ -48,9 +48,78 @@
    
    <!-- Additionally cleans the test data created -->
    <postGoal name="clean">
+      <attainGoal name="test:clean"/>
+   </postGoal>
+   
+   <!-- deletes the test data -->
+   <goal name="test:clean">
       <ant:delete dir="applications/test/repository"/>
       <ant:delete dir="applications/test/tx"/>
       <ant:delete dir="applications/test/workspaces"/>
+   </goal>
+   
+   <postGoal name="java:prepare-filesystem">
+      <attainGoal name="jackrabbit:generate-parsers"/>
    </postGoal>
+   
+   <goal name="jackrabbit:generate-parsers">
+      <!-- SQL Parser -->
+      <ant:java classname="jjtree" fork="true">
+         <arg value="-OUTPUT_DIRECTORY=src/java/org/apache/jackrabbit/core/search/sql"/>
+         <arg value="src/grammar/sql/JCRSQL.jjt"/>
+         <classpath>
+            <fileset dir="${maven.repo.local}/javacc/jars">
+               <include name="javacc-3.2.jar"/>
+            </fileset>
+         </classpath>
+      </ant:java>
+      <ant:java classname="javacc" fork="true">
+         <arg value="-OUTPUT_DIRECTORY=src/java/org/apache/jackrabbit/core/search/sql"/>
+         <arg value="src/java/org/apache/jackrabbit/core/search/sql/JCRSQL.jj"/>
+         <classpath>
+            <fileset dir="${maven.repo.local}/javacc/jars">
+               <include name="javacc-3.2.jar"/>
+            </fileset>
+         </classpath>
+      </ant:java>
+
+
+      <!-- XPath Parser -->
+      <!-- The following is a hack to get xslt work with maven (See: http://maven.apache.org/faq.html#BadXSLT ) -->
+      ${systemScope.setProperty('javax.xml.transform.TransformerFactory','org.apache.xalan.processor.TransformerFactoryImpl')}
+      
+      <ant:xslt style="src/grammar/xpath/strip.xsl"
+             in="src/grammar/xpath/xpath-grammar.xml"
+             out="src/grammar/xpath/stripped-xpath-grammar.xml"
+             force="yes">
+      </ant:xslt>
+      <ant:xslt style="src/grammar/xpath/jjtree-jackrabbit.xsl"
+             in="src/grammar/xpath/stripped-xpath-grammar.xml"
+             out="src/grammar/xpath/XPath.jjt"
+             force="yes">
+      </ant:xslt>
+
+
+      <ant:java classname="jjtree" fork="true">
+         <arg value="-OUTPUT_DIRECTORY=src/java/org/apache/jackrabbit/core/search/xpath"/>
+         <arg value="src/grammar/xpath/XPath.jjt"/>
+         <classpath>
+            <fileset dir="${maven.repo.local}/javacc/jars">
+               <include name="javacc-3.2.jar"/>
+            </fileset>
+         </classpath>
+      </ant:java>
+      <ant:java classname="javacc" fork="true">
+         <arg value="-OUTPUT_DIRECTORY=src/java/org/apache/jackrabbit/core/search/xpath"/>
+         <arg value="-UNICODE_INPUT=true"/>
+         <arg value="src/java/org/apache/jackrabbit/core/search/xpath/XPath.jj"/>
+         <classpath>
+            <fileset dir="${maven.repo.local}/javacc/jars">
+               <include name="javacc-3.2.jar"/>
+            </fileset>
+         </classpath>
+      </ant:java>
+
+   </goal>
 
 </project>

Modified: incubator/jackrabbit/trunk/project.xml
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/project.xml?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/project.xml&r1=123134&p2=incubator/jackrabbit/trunk/project.xml&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/project.xml	(original)
+++ incubator/jackrabbit/trunk/project.xml	Wed Dec 22 10:15:05 2004
@@ -233,6 +233,10 @@
       <version>1.0</version>
     </dependency>
     <dependency>
+      <id>javacc</id>
+      <version>3.2</version>
+    </dependency>
+    <dependency>
       <groupId>geronimo-spec</groupId>
       <artifactId>geronimo-spec-jta</artifactId>
       <version>1.0-M1</version>

Added: incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,499 @@
+options {
+  LOOKAHEAD = 1;
+  CHOICE_AMBIGUITY_CHECK = 5;
+  OTHER_AMBIGUITY_CHECK = 2;
+  STATIC = false;
+  //DEBUG_PARSER = true;
+  //DEBUG_LOOKAHEAD = false;
+  //DEBUG_TOKEN_MANAGER = true;
+  ERROR_REPORTING = true;
+  JAVA_UNICODE_ESCAPE = false;
+  UNICODE_INPUT = true;
+  IGNORE_CASE = false;
+  USER_TOKEN_MANAGER = false;
+  USER_CHAR_STREAM = false;
+  BUILD_PARSER = true;
+  BUILD_TOKEN_MANAGER = true;
+  SANITY_CHECK = true;
+  FORCE_LA_CHECK = true;
+
+  MULTI = true;
+  NODE_PACKAGE = "org.apache.jackrabbit.core.search.sql";
+  VISITOR = true;
+}
+
+PARSER_BEGIN(JCRSQLParser)
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+import org.apache.jackrabbit.core.search.Constants;
+
+public class JCRSQLParser {
+
+  private String statement;
+
+  public static void main(String args[]) throws ParseException {
+  	JCRSQLParser parser = new JCRSQLParser(System.in);
+  	parser.Query().dump("");
+  }
+
+  public static ASTQuery parse(String statement) throws ParseException {
+  	java.io.StringReader sReader = new java.io.StringReader(statement);
+  	JCRSQLParser parser = new JCRSQLParser(sReader);
+  	return parser.Query();
+  }
+
+}
+
+PARSER_END(JCRSQLParser)
+
+SKIP :
+{
+  " "
+| "\r"
+| "\n"
+| "\t"
+| < COMMENT: <COMMENT_INTRO> (<COMMENT_CHAR>)* "\n" >
+| < #COMMENT_CHAR: <NON_QUOTE_CHAR> | <QUOTE> >
+| < #NON_QUOTE_CHAR: ~["'"] > // syntax rules
+| < #COMMENT_INTRO: <MINUS_SIGN> <MINUS_SIGN> (<MINUS_SIGN>)* >
+}
+
+// KEY WORDS
+TOKEN [ IGNORE_CASE ] :
+{
+  < BY: "BY" >
+| < IN: "IN" >
+| < OR: "OR" >
+| < IS: "IS" >
+| < AND: "AND" >
+| < NOT: "NOT" >
+| < LIKE: "LIKE" >
+| < NULL: "NULL" >
+| < FROM: "FROM" >
+| < ORDER: "ORDER" >
+| < WHERE: "WHERE" >
+| < SELECT: "SELECT" >
+| < BETWEEN: "BETWEEN" >
+| < CONTAINS: "CONTAINS" >
+}
+
+
+
+TOKEN:
+{
+  < #SIMPLE_LATIN_LETTER: <SIMPLE_LATIN_UPPER_CASE_LETTER> | <SIMPLE_LATIN_LOWER_CASE_LETTER> >
+| < #SIMPLE_LATIN_UPPER_CASE_LETTER: (["A"-"Z"]) >
+| < #SIMPLE_LATIN_LOWER_CASE_LETTER: (["a"-"z"]) >
+
+| < #LETTER: <BASE_CHAR> | <IDEOGRAPHIC> >
+
+| < #BASE_CHAR:
+          ["\u0041"-"\u005A"] | ["\u0061"-"\u007A"] | ["\u00C0"-"\u00D6"] | ["\u00D8"-"\u00F6"]
+        | ["\u00F8"-"\u00FF"] | ["\u0100"-"\u0131"] | ["\u0134"-"\u013E"] | ["\u0141"-"\u0148"]
+        | ["\u014A"-"\u017E"] | ["\u0180"-"\u01C3"] | ["\u01CD"-"\u01F0"] | ["\u01F4"-"\u01F5"]
+        | ["\u01FA"-"\u0217"] | ["\u0250"-"\u02A8"] | ["\u02BB"-"\u02C1"] | "\u0386" | ["\u0388"-"\u038A"]
+        | "\u038C" | ["\u038E"-"\u03A1"] | ["\u03A3"-"\u03CE"] | ["\u03D0"-"\u03D6"] | "\u03DA"
+        | "\u03DC" | "\u03DE" | "\u03E0" | ["\u03E2"-"\u03F3"] | ["\u0401"-"\u040C"] | ["\u040E"-"\u044F"]
+        | ["\u0451"-"\u045C"] | ["\u045E"-"\u0481"] | ["\u0490"-"\u04C4"] | ["\u04C7"-"\u04C8"]
+        | ["\u04CB"-"\u04CC"] | ["\u04D0"-"\u04EB"] | ["\u04EE"-"\u04F5"] | ["\u04F8"-"\u04F9"]
+        | ["\u0531"-"\u0556"] | "\u0559" | ["\u0561"-"\u0586"] | ["\u05D0"-"\u05EA"] | ["\u05F0"-"\u05F2"]
+        | ["\u0621"-"\u063A"] | ["\u0641"-"\u064A"] | ["\u0671"-"\u06B7"] | ["\u06BA"-"\u06BE"]
+        | ["\u06C0"-"\u06CE"] | ["\u06D0"-"\u06D3"] | "\u06D5" | ["\u06E5"-"\u06E6"] | ["\u0905"-"\u0939"]
+        | "\u093D" | ["\u0958"-"\u0961"] | ["\u0985"-"\u098C"] | ["\u098F"-"\u0990"] | ["\u0993"-"\u09A8"]
+        | ["\u09AA"-"\u09B0"] | "\u09B2" | ["\u09B6"-"\u09B9"] | ["\u09DC"-"\u09DD"] | ["\u09DF"-"\u09E1"]
+        | ["\u09F0"-"\u09F1"] | ["\u0A05"-"\u0A0A"] | ["\u0A0F"-"\u0A10"] | ["\u0A13"-"\u0A28"]
+        | ["\u0A2A"-"\u0A30"] | ["\u0A32"-"\u0A33"] | ["\u0A35"-"\u0A36"] | ["\u0A38"-"\u0A39"]
+        | ["\u0A59"-"\u0A5C"] | "\u0A5E" | ["\u0A72"-"\u0A74"] | ["\u0A85"-"\u0A8B"] | "\u0A8D"
+        | ["\u0A8F"-"\u0A91"] | ["\u0A93"-"\u0AA8"] | ["\u0AAA"-"\u0AB0"] | ["\u0AB2"-"\u0AB3"]
+        | ["\u0AB5"-"\u0AB9"] | "\u0ABD" | "\u0AE0" | ["\u0B05"-"\u0B0C"] | ["\u0B0F"-"\u0B10"]
+        | ["\u0B13"-"\u0B28"] | ["\u0B2A"-"\u0B30"] | ["\u0B32"-"\u0B33"] | ["\u0B36"-"\u0B39"]
+        | "\u0B3D" | ["\u0B5C"-"\u0B5D"] | ["\u0B5F"-"\u0B61"] | ["\u0B85"-"\u0B8A"]
+        | ["\u0B8E"-"\u0B90"] | ["\u0B92"-"\u0B95"] | ["\u0B99"-"\u0B9A"] | "\u0B9C" | ["\u0B9E"-"\u0B9F"]
+        | ["\u0BA3"-"\u0BA4"] | ["\u0BA8"-"\u0BAA"] | ["\u0BAE"-"\u0BB5"] | ["\u0BB7"-"\u0BB9"]
+        | ["\u0C05"-"\u0C0C"] | ["\u0C0E"-"\u0C10"] | ["\u0C12"-"\u0C28"] | ["\u0C2A"-"\u0C33"]
+        | ["\u0C35"-"\u0C39"] | ["\u0C60"-"\u0C61"] | ["\u0C85"-"\u0C8C"] | ["\u0C8E"-"\u0C90"]
+        | ["\u0C92"-"\u0CA8"] | ["\u0CAA"-"\u0CB3"] | ["\u0CB5"-"\u0CB9"] | "\u0CDE" | ["\u0CE0"-"\u0CE1"]
+        | ["\u0D05"-"\u0D0C"] | ["\u0D0E"-"\u0D10"] | ["\u0D12"-"\u0D28"] | ["\u0D2A"-"\u0D39"]
+        | ["\u0D60"-"\u0D61"] | ["\u0E01"-"\u0E2E"] | "\u0E30" | ["\u0E32"-"\u0E33"] | ["\u0E40"-"\u0E45"]
+        | ["\u0E81"-"\u0E82"] | "\u0E84" | ["\u0E87"-"\u0E88"] | "\u0E8A" | "\u0E8D" | ["\u0E94"-"\u0E97"]
+        | ["\u0E99"-"\u0E9F"] | ["\u0EA1"-"\u0EA3"] | "\u0EA5" | "\u0EA7" | ["\u0EAA"-"\u0EAB"]
+        | ["\u0EAD"-"\u0EAE"] | "\u0EB0" | ["\u0EB2"-"\u0EB3"] | "\u0EBD" | ["\u0EC0"-"\u0EC4"]
+        | ["\u0F40"-"\u0F47"] | ["\u0F49"-"\u0F69"] | ["\u10A0"-"\u10C5"] | ["\u10D0"-"\u10F6"] | "\u1100"
+        | ["\u1102"-"\u1103"] | ["\u1105"-"\u1107"] | "\u1109" | ["\u110B"-"\u110C"] | ["\u110E"-"\u1112"]
+        | "\u113C" | "\u113E" | "\u1140" | "\u114C" | "\u114E" | "\u1150" | ["\u1154"-"\u1155"] | "\u1159"
+        | ["\u115F"-"\u1161"] | "\u1163" | "\u1165" | "\u1167" | "\u1169" | ["\u116D"-"\u116E"]
+        | ["\u1172"-"\u1173"] | "\u1175" | "\u119E" | "\u11A8" | "\u11AB" | ["\u11AE"-"\u11AF"]
+        | ["\u11B7"-"\u11B8"] | "\u11BA" | ["\u11BC"-"\u11C2"] | "\u11EB" | "\u11F0" | "\u11F9"
+        | ["\u1E00"-"\u1E9B"] | ["\u1EA0"-"\u1EF9"] | ["\u1F00"-"\u1F15"] | ["\u1F18"-"\u1F1D"]
+        | ["\u1F20"-"\u1F45"] | ["\u1F48"-"\u1F4D"] | ["\u1F50"-"\u1F57"] | "\u1F59" | "\u1F5B" | "\u1F5D"
+        | ["\u1F5F"-"\u1F7D"] | ["\u1F80"-"\u1FB4"] | ["\u1FB6"-"\u1FBC"] | "\u1FBE" | ["\u1FC2"-"\u1FC4"]
+        | ["\u1FC6"-"\u1FCC"] | ["\u1FD0"-"\u1FD3"] | ["\u1FD6"-"\u1FDB"] | ["\u1FE0"-"\u1FEC"]
+        | ["\u1FF2"-"\u1FF4"] | ["\u1FF6"-"\u1FFC"] | "\u2126" | ["\u212A"-"\u212B"] | "\u212E"
+        | ["\u2180"-"\u2182"] | ["\u3041"-"\u3094"] | ["\u30A1"-"\u30FA"] | ["\u3105"-"\u312C"]
+        | ["\uAC00"-"\uD7A3"] >
+| < #IDEOGRAPHIC :
+          ["\u4E00"-"\u9FA5"] | "\u3007" | ["\u3021"-"\u3029"] >
+
+| < #DIGIT: (["0"-"9"]) >
+
+
+| < DOUBLE_QUOTE: "\"" >
+| < PERCENT: "%" >
+| < AMPERSAND: "&" >
+| < QUOTE: "'" >
+| < LEFT_PAREN: "(" >
+| < RIGHT_PAREN: ")" >
+| < ASTERISK: "*" >
+| < PLUS_SIGN: "+" >
+| < COMMA: "," >
+| < MINUS_SIGN: "-" >
+| < PERIOD: "." >
+| < SOLIDUS: "/" >
+| < COLON: ":" >
+| < SEMICOLON: ";" >
+| < LT_OPERATOR: "<" >
+| < EQ_OPERATOR: "=" >
+| < GT_OPERATOR: ">" >
+| < QUESTION_MARK: "?" >
+| < UNDERSCORE: "_" >
+| < VERTICAL_BAR: "|" >
+
+| < LEFT_BRACKET: "[" >  // also special char?
+| < RIGHT_BRACKET: "]" > // also special char?
+
+
+| < REGULAR_IDENTIFIER: <IDENTIFIER_BODY> >
+| < #IDENTIFIER_BODY: <IDENTIFIER_START> (<UNDERSCORE> | <IDENTIFIER_PART>)* >
+| < #IDENTIFIER_START: <LETTER> > // syntax rules 5.2
+| < #IDENTIFIER_PART: <IDENTIFIER_START> | <DIGIT> >
+
+| < DELIMITED_IDENTIFIER: <DOUBLE_QUOTE> <DELIMITED_IDENTIFIER_BODY> <DOUBLE_QUOTE> >
+| < #DELIMITED_IDENTIFIER_BODY: (<DELIMITED_IDENTIFIER_PART>)+ >
+| < #DELIMITED_IDENTIFIER_PART: <NON_DOUBLE_QUOTE_CHAR> | <DOUBLE_QUOTE_SYMBOL> >
+| < #NON_DOUBLE_QUOTE_CHAR: ~["\""] > // syntax rules 5.2
+| < #DOUBLE_QUOTE_SYMBOL: <DOUBLE_QUOTE><DOUBLE_QUOTE> >
+
+| < NE_OPERATOR: "<>" >
+| < GE_OPERATOR: ">=" >
+| < LE_OPERATOR: "<=" >
+| < CONCAT_OPERATOR: "||" >
+| < DOUBLE_PERIOD: ".." >
+
+/*
+| < COMMENT: <COMMENT_INTRO> (<COMMENT_CHAR>)* "\n" >
+| < #COMMENT_CHAR: <NON_QUOTE_CHAR> | <QUOTE> >
+| < #NON_QUOTE_CHAR: ~["'"] > // syntax rules
+| < #COMMENT_INTRO: <MINUS_SIGN> <MINUS_SIGN> (<MINUS_SIGN>)* >
+*/
+
+/* Literals */
+
+| < EXACT_NUMERIC_LITERAL: (<SIGN>)? (<UNSIGNED_INTEGER> (<PERIOD> (<UNSIGNED_INTEGER>)?)?) | (<PERIOD> <UNSIGNED_INTEGER>) >
+| < #SIGN: <PLUS_SIGN> | <MINUS_SIGN> >
+| < APPROXIMATE_NUMERIC_LITERAL: <MANTISSA> ("E" | "e") <EXPONENT> >
+| < #MANTISSA: <EXACT_NUMERIC_LITERAL> >
+| < #EXPONENT: <SIGNED_INTEGER> >
+| < #SIGNED_INTEGER: (<SIGN>)? <UNSIGNED_INTEGER> >
+| < #UNSIGNED_INTEGER: (<DIGIT>)+ >
+| < DATETIME_LITERAL: <DATE_LITERAL> | /* <TIME_LITERAL> | */ <TIMESTAMP_LITERAL> >
+| < DATE_LITERAL: "DATE" (" ")+ <DATE_STRING> >
+//| < TIME_LITERAL: "TIME" (" ")+ <TIME_STRING> >  // not supported in jcr
+| < TIMESTAMP_LITERAL: "TIMESTAMP" (" ")+ <TIMESTAMP_STRING> >
+| < #DATE_STRING: <QUOTE> <DATE_VALUE> <QUOTE> >
+// | < #TIME_STRING: <QUOTE> <TIME_VALUE> (<TIME_ZONE_INTERVAL>)? <QUOTE> > // not supported in jcr
+| < #TIMESTAMP_STRING: <QUOTE> <DATE_VALUE> (" "|"T") <TIME_VALUE> (<TIME_ZONE_INTERVAL>)? <QUOTE> >
+| < #TIME_ZONE_INTERVAL: "Z" | (<SIGN> <HOURS_VALUE> <COLON> <MINUTES_VALUE>) >
+| < #DATE_VALUE: <YEARS_VALUE> <MINUS_SIGN> <MONTHS_VALUE> <MINUS_SIGN> <DAYS_VALUE> >
+| < #TIME_VALUE: <HOURS_VALUE> <COLON> <MINUTES_VALUE> <COLON> <SECONDS_VALUE> >
+| < #YEARS_VALUE: <DATETIME_VALUE> >
+| < #MONTHS_VALUE: <DATETIME_VALUE> >
+| < #DAYS_VALUE: <DATETIME_VALUE> >
+| < #HOURS_VALUE: <DATETIME_VALUE> >
+| < #MINUTES_VALUE: <DATETIME_VALUE> >
+| < #SECONDS_VALUE: <SECONDS_INTEGER_VALUE> (<PERIOD> (<SECONDS_FRACTION>)?)? >
+| < #SECONDS_INTEGER_VALUE: <UNSIGNED_INTEGER> >
+| < #SECONDS_FRACTION: <UNSIGNED_INTEGER> >
+| < #DATETIME_VALUE: <UNSIGNED_INTEGER> >
+
+| < CHAR_STRING_LITERAL: <QUOTE> (<CHAR_REPRESENTATION>)* <QUOTE> >
+| < #CHAR_REPRESENTATION: <NON_QUOTE_CHAR> | (<QUOTE_SYMBOL>) >
+| < #QUOTE_SYMBOL: <QUOTE><QUOTE> >
+}
+
+
+
+
+// QUERY EXPRESSIONS, 7
+
+ASTQuery Query() :
+{}
+{
+  <SELECT>
+  SelectList()
+  TableExpression()
+  [ OrderByClause() ]
+  <EOF>
+  { return jjtThis; }
+}
+
+void SelectList() :
+{}
+{
+    (<ASTERISK>)
+  | (Identifier() (<COMMA> Identifier())*)
+}
+
+void TableExpression() #void :
+{}
+{
+  FromClause()
+  [ WhereClause() ]
+}
+
+void FromClause() :
+{}
+{
+  <FROM> Identifier() (<COMMA> Identifier())*
+}
+
+void WhereClause() :
+{}
+{
+  <WHERE> SearchCondition()
+}
+
+// PREDICATES 8.1
+void Predicate() :
+{
+  int operationType;
+  String identifier;
+  Token t;
+  String value;
+}
+{
+  identifier = Identifier() { jjtThis.setIdentifier(identifier); }
+  (
+    (
+      operationType = ComparisonOperation() { jjtThis.setOperationType(operationType); }
+      (Literal() | identifier = Identifier() { jjtThis.setIdentifier(identifier); } )
+    )
+  |
+    ((<NOT> { jjtThis.setNegate(true); })?
+      (
+        (<BETWEEN> { jjtThis.setOperationType(Constants.OPERATION_BETWEEN); } Literal() <AND> Literal())
+      |
+        (<IN> { jjtThis.setOperationType(Constants.OPERATION_IN); } <LEFT_PAREN> Literal() (<COMMA> Literal())* <RIGHT_PAREN>)
+      |
+        (
+          <LIKE> { jjtThis.setOperationType(Constants.OPERATION_LIKE); } value = CharStringLiteral()
+          {
+            ASTLiteral s = new ASTLiteral(JJTLITERAL);
+            s.setType(Constants.TYPE_STRING);
+            s.setValue(value);
+            s.jjtSetParent(jjtThis);
+            jjtThis.jjtAddChild(s, jjtThis.jjtGetNumChildren());
+          }
+        )
+      )
+    )
+  |
+    (<IS> (<NOT> { jjtThis.setNegate(true); })? <NULL> { jjtThis.setOperationType(Constants.OPERATION_NULL); } )
+  )
+}
+
+
+int ComparisonOperation() #void :
+{
+  int operationType;
+}
+{
+  (
+      <EQ_OPERATOR> { operationType = Constants.OPERATION_EQ; }
+    | <NE_OPERATOR> { operationType = Constants.OPERATION_NE; }
+    | <LT_OPERATOR> { operationType = Constants.OPERATION_LT; }
+    | <GT_OPERATOR> { operationType = Constants.OPERATION_GT; }
+    | <LE_OPERATOR> { operationType = Constants.OPERATION_LE; }
+    | <GE_OPERATOR> { operationType = Constants.OPERATION_GE; }
+  )
+  {
+    return operationType;
+  }
+}
+
+
+// SEARCH CONDITION 8.12
+void SearchCondition() #void :
+{}
+{
+  OrExpression()
+}
+
+void OrExpression() #void :
+{}
+{
+  (
+    AndExpression() (<OR> AndExpression())*
+  ) #OrExpression(>1)
+}
+
+void AndExpression() #void :
+{}
+{
+  (
+    UnaryExpression() (<AND> UnaryExpression())*
+  ) #AndExpression(>1)
+}
+
+void UnaryExpression() #void :
+{}
+{
+  (
+    <NOT> UnaryExpression()
+  ) #NotExpression()
+|
+  (
+    PrimaryExpression()
+  )
+}
+
+void PrimaryExpression() #void :
+{}
+{
+  (
+    Predicate()
+  )
+|
+  (
+    BracketExpression()
+  )
+|
+  (
+    ContainsExpression()
+  )
+}
+
+void BracketExpression() :
+{}
+{
+  <LEFT_PAREN> SearchCondition() <RIGHT_PAREN>
+}
+
+void ContainsExpression() :
+{
+  Token t = null;
+}
+{
+  <CONTAINS> <LEFT_PAREN> t = <CHAR_STRING_LITERAL> { jjtThis.setQuery(t.image.substring(1, t.image.length() - 1).replaceAll("''", "'")); } <RIGHT_PAREN>
+}
+
+void Literal() :
+{
+  Token t = null;
+  String value;
+}
+{
+  (
+    t = <APPROXIMATE_NUMERIC_LITERAL> { jjtThis.setType(Constants.TYPE_DOUBLE); jjtThis.setValue(t.image); }
+  |
+    // can contain a dot -> use double
+    t = <EXACT_NUMERIC_LITERAL>
+    {
+      if (t.image.indexOf('.') > -1) {
+        jjtThis.setType(Constants.TYPE_DOUBLE);
+      } else {
+        jjtThis.setType(Constants.TYPE_LONG);
+      }
+      jjtThis.setValue(t.image);
+    }
+  |
+    value = CharStringLiteral() { jjtThis.setType(Constants.TYPE_STRING); jjtThis.setValue(value); }
+  |
+    t = <DATETIME_LITERAL>
+    {
+      if (t.image.startsWith("TIMESTAMP")) {
+        jjtThis.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
+        jjtThis.setType(Constants.TYPE_TIMESTAMP);
+      /*
+      } else if (t.image.startsWith("TIME")) {
+        jjtThis.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
+        jjtThis.setType(Constants.TYPE_TIME);
+      */
+      } else {
+        jjtThis.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
+        jjtThis.setType(Constants.TYPE_DATE);
+      }
+    }
+  )
+}
+
+String CharStringLiteral() #void :
+{
+  Token t;
+  String value = "";
+}
+{
+  (
+    t = <CHAR_STRING_LITERAL> { value += t.image.substring(1, t.image.length() - 1); } ( t = <CHAR_STRING_LITERAL> { value += t.image.substring(1, t.image.length() - 1); } )*
+  )
+  {
+    // strip any quote escapes
+    return value.replaceAll("''", "'");
+  }
+}
+
+String Identifier() :
+{
+  Token t = null;
+  String name = null;
+}
+{
+  (
+    t = <REGULAR_IDENTIFIER> { jjtThis.setName(t.image); }
+  |
+    t = <DELIMITED_IDENTIFIER> { jjtThis.setName(t.image.substring(1, t.image.length()-1)); }
+  |
+    (
+      (
+        // or any keyword
+          t = <BY>
+        | t = <IN>
+        | t = <OR>
+        | t = <IS>
+        | t = <AND>
+        /*| <NOT>*/
+        | t = <LIKE>
+        | t = <NULL>
+        | t = <FROM>
+        | t = <ORDER>
+        | t = <WHERE>
+        | t = <SELECT>
+        | t = <BETWEEN>
+      )
+      { jjtThis.setName(t.image); }
+    )
+  )
+  {
+    return name;
+  }
+}
+
+void OrderByClause() :
+{}
+{
+  <ORDER> <BY> Identifier() (<COMMA> Identifier())*
+}
\ No newline at end of file

Added: incubator/jackrabbit/trunk/src/grammar/xpath/grammar.dtd
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/grammar.dtd?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/grammar.dtd	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,410 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--========================================================================
+    DTD (Document Type Definition) for grammar definition originally created 
+    by James Clark.  The idea is to define an abstract grammar in XML than 
+    may then be used by documentation, directly by parser generators, 
+    or via an XSLT stylesheet or other transformation, may generate 
+    a parser compiler specification such as for YACC or JavaCC.
+
+Norm and Scott moved this file, and added an explicit prefix, as part of the
+transition toward a unified build process for last call and beyond. This involved
+moving the location of the CVS repository, For earlier history information,
+see /WWW/XML/Group/xpath-query-src/grammar.dtd
+
+=========================================================================-->
+<!-- The root element of the definition -->
+<!ELEMENT g:grammar ((g:language)+, (g:start)+, (g:token | g:skip)*, (g:state-list)?,
+                   (g:exprProduction | g:production | g:exposition-production)+)>
+<!ATTLIST g:grammar
+  xmlns:g CDATA #FIXED "http://www.w3.org/2001/03/XPath/grammar"
+>
+
+<!-- Declare a language subset or superset, if they are used in the 
+     if attributes.
+     Attributes:
+         id -> the id of the language. 'if' attributes should map to these ids.
+         display-name -> The name to use for the descriptive name of the language.
+-->
+<!ELEMENT g:language EMPTY>
+<!ATTLIST g:language
+  id ID #REQUIRED
+  if IDREFS #IMPLIED
+  display-name CDATA #REQUIRED
+>
+
+<!-- The grammar must say where the start point is.
+     Attributes:
+         name -> the name of the starting production. 
+         state -> the start state for lexical matching.
+         if -> space separated list of tokens for conditional processing.
+-->
+<!ELEMENT g:start EMPTY>
+<!ATTLIST g:start
+  name IDREF #REQUIRED
+  state CDATA #IMPLIED
+  if IDREFS #IMPLIED
+  sub-spec CDATA #IMPLIED
+>
+
+<!-- ============= Lexical Specifications (terminals) ==============-->
+<!-- Define a token.
+     Attributes:
+         name -> the name of the token. 
+         if -> space separated list of tokens for conditional processing.
+         inline -> tell if the BNF description should expand this token inline.
+         override -> (not sure what this does yet. -sb)
+         recognize -> The state where this token will be recognized.
+         is-macro -> "yes" if this token can be used just as a macro, 
+                     and not as a true token.
+         value-type -> If just a grammatical token, use "none", 
+                       or use "string" for a string value
+                       or use "number" for a number value
+                       or use "id" if it is a token value with meaning.
+-->
+<!ELEMENT g:token (g:string | g:emph | g:zeroOrMore | g:charClass | g:char | g:requiredSkip | g:optional | g:ref | g:xref | g:choice | g:optionalSkip | g:oneOrMore | g:sequence | g:complement)*>
+<!ATTLIST g:token
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  inline CDATA #IMPLIED
+  override (no | yes) #IMPLIED
+  recognize CDATA #IMPLIED
+  is-macro (yes | no) #IMPLIED
+  is-xml (yes | no) #IMPLIED
+  xhref CDATA #IMPLIED
+  special (no | yes) #IMPLIED
+  more (no | yes) #IMPLIED
+  skip (no | yes) #IMPLIED
+  value-type (none | string | number | id) #IMPLIED
+  type (none | literal | skip-token) #IMPLIED
+  whitespace-spec (not-significant | significant | explicit) #IMPLIED
+  node-type CDATA #IMPLIED
+  show (yes | no) #IMPLIED
+  visible (true | false) #IMPLIED
+  force-delimiting (yes | no) #IMPLIED
+  sub-spec CDATA #IMPLIED
+  alias-for IDREF #IMPLIED
+  subtract-reg-expr CDATA #IMPLIED
+  comment-id CDATA #IMPLIED
+  exposition-only (no | yes) #IMPLIED
+>
+
+<!-- Specification of a single character token. -->
+<!ELEMENT g:char (#PCDATA)>
+<!ATTLIST g:char
+  if IDREFS #IMPLIED
+  complement (no | yes) #IMPLIED
+  force-quote (single | double) #IMPLIED
+>
+
+<!-- SGML mode in emacs doesn't like this, so I'm avoiding it for now. -->
+<!-- ATTLIST char
+	xml:space CDATA #IMPLIED
+-->
+
+<!ELEMENT g:charClass (g:charCode | g:char | g:charCodeRange | g:charRange)+>
+<!ATTLIST g:charClass
+  if IDREFS #IMPLIED
+>
+<!ELEMENT g:charCode EMPTY>
+<!ATTLIST g:charCode
+  value CDATA #REQUIRED
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:charCodeRange EMPTY>
+<!ATTLIST g:charCodeRange
+  minValue CDATA #REQUIRED
+  maxValue CDATA #REQUIRED
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:charRange EMPTY>
+<!ATTLIST g:charRange
+  minChar (0 | A | a) #REQUIRED
+  maxChar (0 | 9 | F | f | z | Z) #REQUIRED
+  if IDREFS #IMPLIED
+>
+
+<!-- Defines a character that must be complemented by another character of 
+     the same value, such as a quote. -->
+<!ELEMENT g:complement (g:charClass)>
+<!ATTLIST g:complement
+  if IDREFS #IMPLIED
+>
+
+<!-- Defines a string token. -->
+<!ELEMENT g:string (#PCDATA)>
+<!ATTLIST g:string
+  ignoreCase CDATA #IMPLIED
+  if IDREFS #IMPLIED
+>
+
+<!-- Talk to FS folks about what this is really supposed to mean.  -sb -->
+<!ELEMENT g:emph (#PCDATA)>
+<!ATTLIST g:emph
+  ignoreCase CDATA #IMPLIED
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:skip (g:choice | g:ref | g:xref | g:oneOrMore)>
+<!ATTLIST g:skip
+  recognize CDATA #IMPLIED
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:requiredSkip EMPTY>
+<!ATTLIST g:requiredSkip
+  recognize CDATA #IMPLIED
+  if IDREFS #IMPLIED
+  show (yes | no) #IMPLIED
+>
+
+<!--=================== Lexical State Transitions =================== -->
+
+<!ELEMENT g:state-list (g:state)+>
+<!ATTLIST g:state-list
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:state (g:description?, (g:transition)+)>
+<!ATTLIST g:state
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  show (yes | no) #IMPLIED
+>
+
+<!ELEMENT g:tref EMPTY>
+<!ATTLIST g:tref
+  name IDREF #REQUIRED
+  if IDREFS #IMPLIED
+  show (yes | no) #IMPLIED
+>
+
+<!ELEMENT g:description ANY>
+<!ATTLIST g:description
+  if IDREFS #IMPLIED
+>
+
+
+<!-- Define a transition table for lexical states.  Using this is more 
+     convenient and cleaner than defining transitions for each token. 
+     Attributes:
+         if -> space separated list of tokens for conditional processing.
+               (Not currently used by the stylesheet!)
+-->
+<!ELEMENT g:lexical-state-transitions (g:transition-default?, g:transition+)>
+<!ATTLIST g:lexical-state-transitions
+  if IDREFS #REQUIRED
+>
+
+<!-- Define the default transition for all tokens not defined by the 
+     transition element.
+     Attributes:
+         if -> space separated list of tokens for conditional processing.
+               (Not currently used by the stylesheet!)
+         recognize -> The state where the tokens will be recognized.
+         nextState -> The next state to transition to. Invalid if popState us 
+                      used for the action.
+         action -> State stack action.
+-->
+<!ELEMENT g:transition-default EMPTY>
+<!ATTLIST g:transition-default
+  if IDREFS #IMPLIED
+>
+
+<!-- Define a transition for a token or set of tokens.
+     Attributes:
+         refs -> IDREFS list of the tokens for which this transition applies. 
+         if -> space separated list of tokens for conditional processing.
+               (Not currently used by the stylesheet!)
+         recognize -> The state where the tokens will be recognized.
+         nextState -> The next state to transition to. Invalid if popState us 
+                      used for the action.
+         action -> State stack action.
+-->
+<!ELEMENT g:transition (g:description?, (g:tref | g:transition-default)+)>
+<!ATTLIST g:transition
+  if IDREFS #IMPLIED
+  next-state IDREF #IMPLIED
+  action CDATA #IMPLIED
+>
+
+<!--=================== Parser Production Specifications ===============-->
+<!-- A production that defines a "cascade" of productions that define 
+     operator precedence.
+         name -> the ID of the production. 
+         if -> space separated list of tokens for conditional processing.
+-->
+<!ELEMENT g:exprProduction (g:level+)>
+<!ATTLIST g:exprProduction
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  node-type CDATA #IMPLIED
+  condition CDATA #IMPLIED
+>
+
+<!ELEMENT g:level (g:postfix | g:binary | g:prefix | g:primary)+>
+<!ATTLIST g:level
+  if IDREFS #IMPLIED
+  node-type CDATA #IMPLIED
+  level-user-action CDATA #IMPLIED
+>
+
+<!-- Basic non-terminal production.  
+         name -> the ID of the production. 
+         if -> space separated list of tokens for conditional processing.
+         show -> Don't show in the BNF if this value is "no".
+-->
+<!ELEMENT g:production (g:optional | g:ref |g:xref | g:choice | g:zeroOrMore | g:oneOrMore)+>
+<!ATTLIST g:production
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  show (yes | no) #IMPLIED
+  sub-spec CDATA #IMPLIED
+  node-type CDATA #IMPLIED
+  is-binary (no | yes) #IMPLIED
+  whitespace-spec (not-significant | significant | explicit) #IMPLIED
+  comment-id CDATA #IMPLIED
+  condition CDATA #IMPLIED
+  prod-user-action CDATA #IMPLIED
+>
+
+<!ELEMENT g:exposition-production (g:optional | g:ref | g:xref | g:choice | g:sequence | g:zeroOrMore | g:oneOrMore)+>
+<!ATTLIST g:exposition-production
+  name CDATA #REQUIRED
+  if IDREFS #IMPLIED
+  show (yes | no) #IMPLIED
+  sub-spec CDATA #IMPLIED
+  node-type CDATA #IMPLIED
+  is-binary (no | yes) #IMPLIED
+  whitespace-spec (not-significant | significant | explicit) #IMPLIED
+  comment-id CDATA #IMPLIED
+>
+
+<!-- Defines a binary operator.  
+         name -> the ID of the production. 
+         if -> space separated list of tokens for conditional processing.
+       Example:
+       		<binary name="EqualityExpr">
+				<choice>
+					<ref name="Equals"/>
+					<ref name="NotEquals"/>
+				</choice>
+			</binary>
+-->
+<!ELEMENT g:binary (g:ref | g:xref | g:choice)>
+<!ATTLIST g:binary
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  prefix-seq-type CDATA #IMPLIED
+  condition CDATA #IMPLIED
+>
+
+<!ELEMENT g:optionalSkip EMPTY>
+<!ATTLIST g:optionalSkip
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:postfix (g:ref | g:xref | g:optional | g:sequence)+>
+<!ATTLIST g:postfix
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  prefix-seq-type CDATA #IMPLIED
+  condition CDATA #IMPLIED
+  node-type CDATA #IMPLIED
+>
+
+<!ELEMENT g:prefix (g:optional | g:ref | g:xref | g:choice | g:zeroOrMore | g:oneOrMore | g:sequence | g:next)+>
+<!ATTLIST g:prefix
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  prefix-seq-type CDATA "*"
+  condition CDATA #IMPLIED
+  node-type CDATA #IMPLIED
+>
+
+<!-- This element is used in exprProduction to control where the next production 
+     will be called from.  If it is not used, the next production will automatically be 
+     called.
+-->
+<!ELEMENT g:next EMPTY>
+<!ATTLIST g:next
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:primary (g:optional | g:ref | g:xref | g:choice | 
+                   g:zeroOrMore | g:oneOrMore | g:sequence)+>
+<!ATTLIST g:primary
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  condition CDATA #IMPLIED
+  node-type CDATA #IMPLIED
+>
+
+<!ELEMENT g:ref EMPTY>
+<!ATTLIST g:ref
+  name IDREF #REQUIRED
+  if IDREFS #IMPLIED
+  orig IDREF #IMPLIED
+  node-type CDATA #IMPLIED
+  sub-spec CDATA #IMPLIED
+  show (no | yes) #IMPLIED
+  notational-only (no | yes) #IMPLIED
+  needs-exposition-parens (no | yes) #IMPLIED
+  token-user-action CDATA #IMPLIED
+  nt-user-action-end CDATA #IMPLIED
+  nt-user-action-start CDATA #IMPLIED
+  subtract-reg-expr CDATA #IMPLIED
+>
+
+<!ELEMENT g:xref EMPTY>
+<!ATTLIST g:xref
+  name CDATA #REQUIRED
+  if IDREFS #IMPLIED
+  orig IDREF #IMPLIED
+  node-type CDATA #IMPLIED
+  sub-spec CDATA #IMPLIED
+  show (no | yes) #IMPLIED
+  notational-only (no | yes) #IMPLIED
+  needs-exposition-parens (no | yes) #IMPLIED
+>
+
+<!--================ General Constructs =================-->
+<!ELEMENT g:zeroOrMore (g:string | g:charClass | g:optional | g:ref | g:xref | 
+          g:choice | g:optional | g:zeroOrMore | g:oneOrMore | g:complement)+>
+<!ATTLIST g:zeroOrMore
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  subtract-reg-expr CDATA #IMPLIED
+>
+
+<!ELEMENT g:oneOrMore (g:string | g:charClass | g:optional | g:ref | g:xref |
+          g:choice | g:optional | g:zeroOrMore | g:oneOrMore | g:complement)+>
+<!ATTLIST g:oneOrMore
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+  subtract-reg-expr CDATA #IMPLIED
+>
+
+<!ELEMENT g:optional (g:string | g:charClass | g:optional | g:ref | g:xref |
+          g:choice | g:optional | g:requiredSkip | g:zeroOrMore | g:oneOrMore | g:sequence | g:complement)+>
+<!ATTLIST g:optional
+  name ID #REQUIRED
+  if IDREFS #IMPLIED
+>
+
+<!-- Maybe should be divided into a choice-token, and choice? -->
+<!ELEMENT g:choice (g:ref | g:xref | g:string | g:sequence | g:complement)+>
+<!ATTLIST g:choice
+  name ID #REQUIRED
+  break CDATA #IMPLIED
+  if IDREFS #IMPLIED
+>
+
+<!ELEMENT g:sequence (g:string | g:ref | g:xref | g:optional | 
+                    g:zeroOrMore | g:oneOrMore | g:choice |  
+                    g:next | g:char | g:optionalSkip | g:requiredSkip)+>
+<!ATTLIST g:sequence
+  name ID #IMPLIED
+  if IDREFS #IMPLIED
+>

Added: incubator/jackrabbit/trunk/src/grammar/xpath/javacc.xsl
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/javacc.xsl?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/javacc.xsl	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,1034 @@
+<?xml version="1.0"?>
+
+<!--
+ * Copyright (c) 2002 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+-->
+
+<!-- $Id: javacc.xsl,v 1.8 2004/06/02 13:46:25 sboag Exp $ -->
+	
+<!-- Use spec=xpath to generate an XQuery grammar rather
+     than an XQuery grammar. -->
+     
+ <!-- ==============  CHANGE LOG: ==============
+  $Log: javacc.xsl,v $
+  Revision 1.8  2004/06/02 13:46:25  sboag
+  Tweak to handle double quotes in strings.
+
+  Revision 1.7  2004/05/31 18:29:58  sboag
+  Latest grammar changes, part of last call comments response.  (Sorry for lack
+  of fine-grained detail, but CVS has been down for a week.)
+
+  Revision 1.6  2004/01/26 02:04:09  sboag
+  Removed some dead code.
+
+  Revision 1.5  2004/01/25 22:16:51  sboag
+  Updata language proposal integrated.  Note that the language conditional mechanism has changed a bit.
+
+  Revision 1.4  2003/09/10 17:38:45  sboag
+  Items from http://lists.w3.org/Archives/Member/w3c-query-editors/2003Sep/0028.html all addressed.  Some fixes for construction of AST.  Build target for test with formal XQuery test suite.
+
+  Revision 1.4  2003/09/02 03:55:21  sboag
+  Make isStep into a global, in order to make it possible for "dot" to be treated as a path expression (though it is now a primary expression).  Basic smoke test passes now, which is not to say I expect deeper testing to pass.
+
+  Revision 1.3  2003/09/01 19:55:55  sboag
+  Incremental checkin: basic PathExpressions seem to work (based only on test of foo/baz and foo()).
+
+  Revision 1.2  2003/08/26 15:12:26  sboag
+  On Lionel's advice, am removing the src directory and associated bat files.
+
+  Revision 1.3  2003/07/08 16:03:49  sboag
+  Add handling of exposition-only attribute.
+
+  Revision 1.2  2003/04/18 19:27:46  sboag
+  Fix problem with curly brace state transition for computed element and attribute constructors.
+
+  Revision 1.1  2003/04/07 22:18:01  sboag
+  Initial checkin of language build and parser build.
+
+  Revision 1.19  2003/03/20 12:48:04  sboag
+  no message
+
+  Revision 1.18  2003/03/05 15:33:00  sboag
+  Major changes for new SequenceType, etc.
+
+  Revision 1.17  2003/02/10 23:01:33  sboag
+  Implemented new alias-for attribute, which makes a token act as a sort of a
+  proxy for another definition.  In the JavaCC transformation, this token acts as
+  a true token for the sake of state transitioning.  In the BNF, the token is converted
+  to the token it is acting as an alias for.
+
+  Revision 1.16  2003/01/15 04:41:01  sboag
+  Major update to redo the structure of the lexical specification in xpath-grammar.xml
+  to make maintenence easier.  Also, fixed up the DTD so xpath-grammar.xml now
+  validates.
+
+  Revision 1.15  2002/11/29 17:20:57  sboag
+  Minor changes for pathx1 parser.
+
+  Revision 1.14  2002/11/06 07:42:25  sboag
+  1) I did some work on BNF production numbering.  At least it is consecutive
+  now in regards to the defined tokens.
+
+  2) (XQuery only) I added URL Literal to the main list of literals, and added a
+  short note that it is defined equivalently to string literal.  URL Literal has to
+  exist right now for relatively esoteric purposes for transitioning the lexical
+  state (to DEFAULT rather than OPERATOR as StringLiteral does).  It is
+  used in DefaultCollationDecl, NamespaceDecl, SubNamespaceDecl, and
+  DefaultNamespaceDecl.  To be clear, URL Literal was already in the August
+  draft, I just added it to the list of literals in the main doc.
+
+  Revision 1.13  2002/10/22 16:51:08  sboag
+  New Grammar Issues List.  New productions:
+  OrderBy, ComputedTextConstructor, PositionVar, Castable, As (TypeDecl).
+  Removed:
+  unordered, SortExpr
+  Fixed reserved word bugs with:
+  empty, stable
+  Other minor "fixes":
+  Change precedence of UnaryExpr to be looser binding than UnionExpr
+  Change RangeExpr to only allow one "to".
+
+  Revision 1.12  2002/07/28 19:54:13  sboag
+  Fixed problems with import, '*', '?', and ',', reported by Jonathan and Dana.
+
+  Revision 1.11  2002/07/18 01:17:39  sboag
+  Fixed some bugs.
+
+  Revision 1.10  2002/07/15 07:25:47  sboag
+  Bug fixes, added match patterns, and responses to
+  Don's email http://lists.w3.org/Archives/Member/w3c-xml-query-wg/2002Jul/0156.html.
+
+  Revision 1.9  2002/06/28 09:02:07  sboag
+  Merged Don's latest work with new grammar proposal.  Changes too numerous
+  to detail.
+
+  Revision 1.8  2002/03/17 21:31:08  sboag
+  Made new grammar element, <next/> for use in primary or prefix expressions,
+  to control when the next element is going to be called.  Somewhat experemental.
+
+  Changed javacc stylesheet and bnf stylesheets to handle g:next.
+
+  Fixed bugs with child::text(), by adding text, comment, etc., tokens to after forward
+  or reverse axis.  (note: have to do the same to names after @).  This is yet
+  another bad hack.
+
+  Fixed bug with @type, by adding At token to lexical stateswitch into QNAME state
+  for XQuery.
+
+  Revision 1.7  2002/03/13 15:45:05  sboag
+  Don changes (XPathXQuery.xml, introduction.xml, fragment.xml):
+  I have attempted to update these files with the latest terminology
+   (mainly changing "simple value" to "atomic value" and related changes.)
+
+  Grammar changes:
+  Moral equal of Philip Wadler's structural changes of 02/05/2002.
+    Make lookahead(2) so that ElementNameOrFunctionCall can be broken up
+    without using long tokens.
+  Integrated Robie's SequenceType productions.
+  Added Add Validate Production.
+  Reviewed and tweaked changes against Named Typing proposal.
+  Fixed Dana's bug about ContentElementConstructor and
+     ContentAttributeConstructor in ElementContent.
+  Allow multiple variable binding for some/every.
+  Lift restrictions of "." and "..".
+  add  XmlComment and XmlProcessingInstruction and also CdataSection to the
+  		  Constructor production.
+  Remove The Ref and Colon tokens.
+  Made multiply & star one token for XQuery, in spite of the fact that this causes
+  ambiguity.
+  Remove XQUERY_COMMENT state that is never entered.
+  Add QNAME lexical state for qnames following explicit axes, i.e. child::div.
+  BUG: child::text() will fail in XQuery.
+  BUG: Validate does not work so well for XPath.
+
+  Revision 1.6  2002/03/06 12:40:55  sboag
+  Tweak to make it possible to have prefix productions with optional suffixes.
+
+  Revision 1.5  2001/12/09 22:07:16  sboag
+  Fixed problem with comments from previous checkin.
+
+ 	-sb 10/29/01  Make parser productions extensible by an importing stylesheet.
+ ==============  END CHANGE LOG ============== -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:g="http://www.w3.org/2001/03/XPath/grammar">
+  
+  <xsl:param name="spec" select="'xquery'"/>
+  
+  <xsl:strip-space elements="*"/>
+  <!-- workaround for Xalan bug. -->
+  <xsl:preserve-space elements="g:char"/>
+  
+  <xsl:output method="text" encoding="iso-8859-1"/>
+  
+  <xsl:key name="ref" match="g:token|g:production" 
+    use="@name"/>
+
+  <xsl:template match="g:*" 
+    priority="-2000"/>
+
+  <xsl:template match="g:*[@exposition-only='yes']" 
+    priority="+2000"/>
+  
+  <xsl:template name="parser">
+    PARSER_BEGIN(XPath)
+    
+    public class XPath {
+    boolean isStep = false;
+    public static void main(String args[]) throws ParseException {
+    XPath parser = new XPath(System.in);
+    parser.Input();
+    }
+    }
+    
+    PARSER_END(XPath)
+  </xsl:template>
+
+<!-- Action templates for overrides from derived stylesheets -->
+
+<xsl:template name="action-production">
+</xsl:template>
+
+<xsl:template name="action-production-end">
+</xsl:template>
+
+<xsl:template name="action-exprProduction">
+</xsl:template>
+
+<xsl:template name="action-exprProduction-label">
+</xsl:template>
+
+<xsl:template name="action-exprProduction-end">
+</xsl:template>
+
+<xsl:template name="action-level">
+</xsl:template>
+
+<xsl:template name="action-level-jjtree-label"></xsl:template>
+<xsl:template name="binary-action-level-jjtree-label"></xsl:template>
+
+<xsl:template name="action-level-start">
+</xsl:template>
+
+<xsl:template name="action-level-end">
+</xsl:template>
+
+<xsl:template name="action-token-ref">
+</xsl:template>
+
+<!-- Begin LV -->
+<xsl:template name="user-action-ref-start">
+</xsl:template>
+
+<xsl:template name="user-action-ref-end">
+</xsl:template>
+<!-- End LV -->
+
+<xsl:template name="javacc-options">
+  STATIC = false;
+  LOOKAHEAD = 1;
+</xsl:template>
+
+<xsl:template name="input">
+	void Input() :
+	{}
+	{
+	  <xsl:value-of select="g:start/@name"/>()&lt;EOF&gt;
+	}
+</xsl:template>
+
+<xsl:template match="g:grammar">options {
+<xsl:call-template name="javacc-options"/>
+}
+
+<xsl:call-template name="parser"/>
+
+TOKEN_MGR_DECLS : {
+  private Stack stateStack = new Stack();
+  // private Vector persistentLexStates  = new Vector();
+  static final int PARENMARKER = 2000;
+  
+  /**
+   * Push the current state onto the state stack.
+   */
+  private void pushState()
+  {
+    // System.err.println("pushing: "+curLexState); printLinePos();
+    stateStack.addElement(new Integer(curLexState));
+  }
+  
+  /**
+   * Push the given state onto the state stack.
+   * @param state Must be a valid state.
+   */
+  private void pushState(int state)
+  {
+    stateStack.push(new Integer(state));
+  }
+  
+  /**
+   * Pop the state on the state stack, and switch to that state.
+   */
+  private void popState()
+  {
+    if (stateStack.size() == 0)
+    {
+      printLinePos();
+    }
+
+    int nextState = ((Integer) stateStack.pop()).intValue();
+    // System.err.println("pop "+nextState); printLinePos();
+    if(nextState == PARENMARKER)
+      printLinePos();
+    SwitchTo(nextState);
+  }
+  
+  /**
+   * Push the given state onto the state stack.
+   * @param state Must be a valid state.
+   */
+  private boolean isState(int state)
+  {
+	for (int i = 0; i &lt; stateStack.size(); i++) {
+        if(((Integer) stateStack.elementAt(i)).intValue() == state)
+        {
+        	return true;
+        }
+	}
+	return false;
+  }
+
+  /**
+   * Push a parenthesis state.  This pushes, in addition to the 
+   * lexical state value, a special marker that lets 
+   * resetParenStateOrSwitch(int state)
+   * know if it should pop and switch.  Used for the comma operator.
+   */
+  private void pushParenState(int commaState, int rparState)
+  {
+    stateStack.push(new Integer(rparState));
+    stateStack.push(new Integer(commaState));
+    stateStack.push(new Integer(PARENMARKER));
+    SwitchTo(commaState);
+  }
+
+
+  /**
+   * Print the current line position.
+   */
+  public void printLinePos()
+  {
+    System.err.println("Line: " + input_stream.getEndLine());
+  }
+}
+
+<xsl:call-template name="input"/>
+
+<xsl:apply-templates select="*"/>
+</xsl:template>
+
+<xsl:template match="g:state-list"/>
+
+<!--  END SB CHANGE: Make parser productions extensible by an importing stylesheet -->
+
+
+<xsl:template match="g:token|g:special">
+    
+  <xsl:variable name="tname" select="@name"/>
+  <xsl:variable name="otoken" select="."/>
+  <xsl:variable name="trefs"
+    select="/g:grammar/g:state-list//g:tref[@name=$tname]"/>
+  
+  <!-- At this time, flag an error if the token is not defined in the
+       transition tables! -->
+  <xsl:if test="not($trefs)">
+    <xsl:message terminate="yes">
+      <xsl:text>Transition not defined: </xsl:text>
+      <xsl:value-of select="@name"/>
+    </xsl:message>
+  </xsl:if>
+  
+  <xsl:variable name="token" select="key('ref', @alias-for)|self::*[not(@alias-for)]"/>
+  
+  <xsl:for-each select="$token">
+    <xsl:for-each select="$trefs">
+      <!-- Assert that this token occurs only once in this state! -->
+      <xsl:variable name="state" select="ancestor::g:state"/>
+      <xsl:if test="count($state//g:tref[@name=$tname]) > 1">
+        <xsl:message terminate="yes">
+          <xsl:text>Token multiply defined in same state: </xsl:text>
+          <xsl:value-of select="$tname"/>
+        </xsl:message>
+      </xsl:if>
+      <!-- JavaCC won't let us define a token per state, so test if this is 
+           the first tref, then process the rest of the trefs to make a 
+           comma delimited list per token. -->
+      <xsl:variable name="allTRefsOfName"
+        select="/g:grammar/g:state-list/g:state//g:tref[@name=$tname]"/>
+      <xsl:variable name="isFirstOccurance"
+        select="$allTRefsOfName[(position() = 1) 
+                and (ancestor::g:state/@name = $state/@name)]"/>
+      <xsl:if test="$isFirstOccurance">
+        <xsl:text>&#10;</xsl:text>
+        <xsl:if test="not($state/@name='ANY')">
+          <xsl:text>&lt;</xsl:text>
+          <xsl:for-each select="$allTRefsOfName">
+            <xsl:value-of select="ancestor::g:state/@name"/>
+            <xsl:if test="last()!=position()">
+              <xsl:text>, </xsl:text>
+            </xsl:if>
+          </xsl:for-each>
+          
+          <xsl:text>&gt;&#10;</xsl:text>
+        </xsl:if>
+        <xsl:choose>
+          <xsl:when test="($token/@more='yes') or $otoken/@more='yes'">
+            <xsl:text>MORE </xsl:text>
+          </xsl:when>
+          <xsl:when test="($token/@special='yes') or $otoken/@special='yes'">
+            <xsl:text>SPECIAL_TOKEN </xsl:text>
+          </xsl:when>
+          <xsl:when test="$token/@skip='yes' or $otoken/@skip='yes'">
+            <xsl:text>SKIP </xsl:text>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:text>TOKEN </xsl:text>
+          </xsl:otherwise>
+        </xsl:choose>
+        
+        <xsl:text>:&#10;{&#10; &lt; </xsl:text>
+        <xsl:if test="$state/@name='ANY'">#</xsl:if>
+        
+        <xsl:value-of select="$tname"/>
+        <xsl:text> : </xsl:text>
+        <xsl:for-each select="$token">
+          <xsl:call-template name="space"/>
+        </xsl:for-each>
+        <xsl:text> &gt;</xsl:text>
+        <xsl:variable name="action" select="$trefs/ancestor::g:transition/@action"/>
+        <!-- assert correctness -->
+        <xsl:if test="$action and count($action) &gt; 1">
+          <xsl:for-each select="$trefs[ancestor::g:transition/@action]">
+            <xsl:if test="ancestor::g:transition/@action != $action[1]">
+              <xsl:message terminate="yes">
+                <xsl:text>Error! Actions of transitions are not consistent! </xsl:text>
+                <xsl:value-of select="$tname"/>
+              </xsl:message>
+            </xsl:if>
+          </xsl:for-each>
+        </xsl:if>
+        <xsl:choose>
+          <xsl:when test="contains($action, '(')">
+            <xsl:text> { </xsl:text>
+            <xsl:value-of select="$action"/>
+            <xsl:text>; }</xsl:text>
+          </xsl:when>  
+          <xsl:when test="normalize-space($action) = 'input_stream.backup'">
+            <xsl:message>$action(2): <xsl:value-of select="$action"/></xsl:message>
+            <xsl:text> { </xsl:text>
+            <!-- xsl:text>System.out.println("lengthOfMatch: "+lengthOfMatch);</xsl:text -->
+            <xsl:value-of select="$action"/>
+            <xsl:text>(</xsl:text>
+            <xsl:text>lengthOfMatch</xsl:text>
+            <xsl:text>)</xsl:text>
+            <xsl:text>; }</xsl:text>
+          </xsl:when>  
+          <xsl:when test="$action">
+            <xsl:text> { </xsl:text>
+            <xsl:value-of select="$action"/>
+            <xsl:text>(); }</xsl:text>
+          </xsl:when>
+        </xsl:choose>
+        
+        <xsl:variable name="nextLexState" 
+          select="$trefs/ancestor::g:transition/@next-state"/>
+        
+        <!-- assert correctness -->
+        <xsl:if test="$nextLexState and count($nextLexState) &gt; 1">
+          <xsl:for-each select="$trefs[ancestor::g:transition/@next-state]">
+            <xsl:if test="ancestor::g:transition/@next-state != $nextLexState[1]">
+              <xsl:message terminate="yes">
+                <xsl:text>Error! Next-state of transitions are not consistent! </xsl:text>
+                <xsl:value-of select="$tname"/>
+              </xsl:message>
+            </xsl:if>
+          </xsl:for-each>
+        </xsl:if>
+        
+        <xsl:if test="$nextLexState">
+          <xsl:text> : </xsl:text>
+          <xsl:value-of select="$nextLexState"/>
+        </xsl:if>
+        <xsl:text>&#10;}&#10;</xsl:text>
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="g:skip">
+    <xsl:if test="@recognize">
+	    <xsl:text>&lt;</xsl:text>
+	    <xsl:call-template name="replace-char">
+	      <xsl:with-param name="string" select="@recognize"/>
+	      <xsl:with-param name="from" select="' '"/>
+	      <xsl:with-param name="to" select="', '"/>
+	    </xsl:call-template>
+	    <xsl:text>&gt;</xsl:text>
+    </xsl:if>
+SKIP:
+{
+  &lt;&lt;skip_&gt;&gt;
+}
+
+TOKEN :
+{
+  &lt; #skip_ : <xsl:call-template name="space"/> &gt;
+}
+
+</xsl:template>
+
+<xsl:template match="g:char|g:string">
+  <xsl:if test="@complement='yes'">
+    <xsl:text>~</xsl:text>
+  </xsl:if>
+  <xsl:text>"</xsl:text>
+  <xsl:call-template name="replace-char">
+    <xsl:with-param name="string" select="."/>
+    <xsl:with-param name="from" select="'&quot;'"/>
+    <xsl:with-param name="to" select="'\&quot;'"/>
+  </xsl:call-template>
+  <xsl:text>"</xsl:text>
+</xsl:template>
+
+<!-- For some reason, the JavaCC generated lexer produces a lexical error for a "]" if
+we use ]]> as a single token. -->
+<xsl:template match="g:string[.=']]&gt;']">
+ <xsl:text>("]" "]" ">")</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:string[@ignoreCase]">
+  <xsl:text>(</xsl:text>
+  <xsl:call-template name="ignore-case">
+    <xsl:with-param name="string" select="."/>
+  </xsl:call-template>
+  <xsl:text>)</xsl:text>
+</xsl:template>
+
+<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
+
+<xsl:template name="ignore-case">
+  <xsl:param name="string" select="''"/>
+  <xsl:if test="$string">
+    <xsl:variable name="c" select="substring($string,1,1)"/>
+    <xsl:variable name="uc" select="translate($c,$lower,$upper)"/>
+    <xsl:variable name="lc" select="translate($c,$upper,$lower)"/>
+    <xsl:choose>
+      <xsl:when test="$lc=$uc">
+        <xsl:text>"</xsl:text>
+        <xsl:value-of select="$c"/>
+        <xsl:text>"</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:text>["</xsl:text>
+	<xsl:value-of select="$uc"/>
+	<xsl:text>", "</xsl:text>
+	<xsl:value-of select="$lc"/>
+	<xsl:text>"]</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:if test="substring($string,2)">
+      <xsl:text xml:space="preserve"> </xsl:text>
+    </xsl:if>
+    <xsl:call-template name="ignore-case">
+      <xsl:with-param name="string" select="substring($string,2)"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template match="g:eof">&lt;EOF&gt;</xsl:template>
+
+<xsl:template match="g:charCode">
+  <xsl:text>"</xsl:text>
+  <xsl:choose>
+    <xsl:when test="@value='000A'">
+      <xsl:text>\n</xsl:text>
+    </xsl:when>
+    <xsl:when test="@value='000D'">
+      <xsl:text>\r</xsl:text>
+    </xsl:when>
+    <xsl:when test="@value='0009'">
+      <xsl:text>\t</xsl:text>
+    </xsl:when>
+    <xsl:when test="@value='0020'">
+      <xsl:text xml:space="preserve"> </xsl:text>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:text>\u</xsl:text>
+      <xsl:value-of select="@value"/>
+    </xsl:otherwise>
+  </xsl:choose>
+  <xsl:text>"</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:charClass">
+ <xsl:text>[</xsl:text>
+  <xsl:for-each select="*">
+    <xsl:if test="position()!=1">
+      <xsl:text>, </xsl:text>
+    </xsl:if>
+    <xsl:apply-templates select="."/>
+  </xsl:for-each>
+ <xsl:text>]</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:charRange">
+  <xsl:text>"</xsl:text>
+  <xsl:value-of select="@minChar"/>
+  <xsl:text>" - "</xsl:text>
+  <xsl:value-of select="@maxChar"/>
+  <xsl:text>"</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:charCodeRange">
+  <xsl:text>"\u</xsl:text>
+  <xsl:value-of select="@minValue"/>
+  <xsl:text>" - "\u</xsl:text>
+  <xsl:value-of select="@maxValue"/>
+  <xsl:text>"</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:complement">~<xsl:apply-templates/></xsl:template>
+
+<xsl:template match="g:production">
+  <xsl:text>void </xsl:text>
+  <xsl:value-of select="@name"/>
+  <xsl:text>() </xsl:text>
+  <xsl:choose>
+    <xsl:when test="@is-binary='yes'">
+      <xsl:call-template name="action-level-jjtree-label"/>
+    </xsl:when>
+    <xsl:when test="@node-type">
+      <xsl:call-template name="action-level-jjtree-label">
+        <xsl:with-param name="label" select="@node-type"/>
+        <xsl:with-param name="condition" select="@condition"/>
+      </xsl:call-template>
+    </xsl:when>
+    <!-- Begin LV -->
+    <xsl:when test="@condition">    
+      <xsl:call-template name="action-level-jjtree-label">
+	    <xsl:with-param name="label" select="@name"/>
+        <xsl:with-param name="condition" select="@condition"/>
+      </xsl:call-template>
+   	</xsl:when>
+     <!-- End LV -->
+    <xsl:otherwise>
+    </xsl:otherwise>
+  </xsl:choose>
+<xsl:text> :</xsl:text>
+{<xsl:call-template name="action-production"/>}
+{
+  <xsl:call-template name="space"/>
+  <xsl:call-template name="action-production-end"/>
+}
+
+</xsl:template>
+
+<xsl:template match="g:exprProduction">
+<xsl:variable name="name"
+              select="@name"/>void <xsl:value-of select="$name"/>() <xsl:call-template name="action-exprProduction-label"/> :
+{<xsl:call-template name="action-exprProduction"/>}
+{
+	<xsl:variable name="levels" select="g:level[*]"/>
+	<xsl:variable name="nextProd" select="concat($levels[1]/*/@name,'()')"/>
+	<xsl:value-of select="$nextProd"/>
+	<xsl:call-template name="action-exprProduction-end"/>
+}
+
+<xsl:for-each select="g:level[*]">
+  <!-- xsl:variable name="thisProd" select="concat($name,'_',position(),'()')"/>
+  <xsl:variable name="nextProd" select="concat($name,'_',position()+1,'()')"
+/ -->
+<xsl:variable name="thisProd" select="concat(*/@name,'()')"/>
+<xsl:variable name="levels" select="../g:level[*]"/>
+<xsl:variable name="position" select="position()"/>
+
+<xsl:variable name="nextProd" select="concat($levels[$position+1]/*/@name,'()')"
+/>void <xsl:value-of select="$thisProd"/>
+       <xsl:call-template name="action-level-jjtree-label">
+        <xsl:with-param name="label">
+          <xsl:choose>
+            <xsl:when test="@node-type">
+              <xsl:value-of select="@node-type"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:choose>
+                <!-- <xsl:when test="not(g:binary) and */g:sequence"> SMPG -->
+                <xsl:when test="g:binary or */g:sequence">
+                  <xsl:value-of select="*/@name"/>
+                  <!-- xsl:text>void</xsl:text -->
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:text>void</xsl:text>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:with-param>
+
+				<!-- Begin SMPG -->
+        <xsl:with-param name="condition">
+					<xsl:choose>
+						<xsl:when test="g:binary or */g:sequence or */g:choice">
+							<xsl:value-of select="*/@condition"/>
+						</xsl:when>
+						<xsl:otherwise/>
+					</xsl:choose>
+        </xsl:with-param>
+				<!-- End SMPG -->
+
+		   <xsl:with-param name="thisProd" select="$thisProd"/>
+		   <xsl:with-param name="nextProd" select="$nextProd"/>
+     </xsl:call-template> :
+{<xsl:call-template name="action-level">
+		   <xsl:with-param name="thisProd" select="$thisProd"/>
+		   <xsl:with-param name="nextProd" select="$nextProd"/>
+ </xsl:call-template>}
+{
+  <xsl:call-template name="action-level-start"/>
+ <xsl:choose>
+    <xsl:when test="g:binary and g:postfix">
+      <xsl:value-of select="$nextProd"/>
+      <xsl:text> ((</xsl:text>
+      
+      <xsl:call-template name="outputChoices">
+        <xsl:with-param name="choices"
+                        select="g:binary"/>
+        <xsl:with-param name="lookahead" select="ancestor-or-self::*/@lookahead"/>
+      </xsl:call-template>
+      <xsl:text xml:space="preserve"> </xsl:text>
+      <xsl:value-of select="$nextProd"/>
+      <!-- xsl:value-of select="concat($name,'_1')"/><xsl:text>()</xsl:text -->
+      
+      <xsl:call-template name="binary-action-level-jjtree-label">
+      		<xsl:with-param name="label" select="*/@name"/>
+          <xsl:with-param name="which" select="1"/>
+      </xsl:call-template>
+      
+      <xsl:text>) | </xsl:text>
+      
+      <xsl:call-template name="outputChoices">
+        <xsl:with-param name="choices"
+                        select="g:postfix"/>
+        <xsl:with-param name="lookahead" select="ancestor-or-self::*/@lookahead"/>
+      </xsl:call-template>
+      <xsl:text>)*</xsl:text>
+    </xsl:when>
+    
+    <xsl:when test="g:binary">
+      <xsl:value-of select="$nextProd"/>
+      <xsl:text> (</xsl:text>
+      <xsl:call-template name="outputChoices">
+         <xsl:with-param name="choices"
+                        select="g:binary"/>
+         <xsl:with-param name="lookahead" select="ancestor-or-self::*/@lookahead"/>
+      </xsl:call-template>
+            
+      <xsl:text xml:space="preserve"> </xsl:text>
+      
+      <xsl:value-of select="$nextProd"/>
+      <xsl:call-template name="binary-action-level-jjtree-label">
+      		<xsl:with-param name="label" select="*/@name"/>
+          <xsl:with-param name="which" select="2"/>
+      </xsl:call-template>
+      <!-- xsl:value-of select="concat($name,'_1')"/><xsl:text>()</xsl:text -->
+      
+      <!--
+      <xsl:variable name="thisName" select="g:binary/@name"/>
+      <xsl:text>(</xsl:text>
+      <xsl:for-each select="../g:level[*]">
+      		<xsl:variable name="theExprName" select="concat($name,'_',position(),'()')"/>
+      		<xsl:if test="not(*/@name = $thisName)">
+	      		<xsl:value-of select="$theExprName"/>
+	      		<xsl:if test="not(last()=position())"> | </xsl:if>
+      		</xsl:if>
+      </xsl:for-each>
+      <xsl:text>)</xsl:text>
+      -->
+      
+      <xsl:text>)</xsl:text>
+      <xsl:choose>
+        <xsl:when test="g:binary/@prefix-seq-type">
+          <xsl:value-of select="g:binary/@prefix-seq-type"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>*</xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+
+    </xsl:when>
+    <xsl:when test="g:postfix">
+      <xsl:if test="following-sibling::g:level">
+      	<xsl:value-of select="$nextProd"/>
+      </xsl:if> 
+      <xsl:text xml:space="preserve"> </xsl:text>
+      <xsl:call-template name="outputChoices">
+        <xsl:with-param name="choices"
+                        select="g:postfix"/>
+      </xsl:call-template>
+      <xsl:choose>
+        <xsl:when test="g:postfix/@prefix-seq-type">
+          <xsl:value-of select="g:postfix/@prefix-seq-type"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>*</xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+      
+    </xsl:when>
+    <xsl:when test="g:prefix">
+      <xsl:choose>
+        <xsl:when test="g:prefix/@suffix-optional='yes'">
+          <xsl:text>(</xsl:text>
+          <xsl:call-template name="outputChoices">
+            <xsl:with-param name="choices"
+              select="g:prefix"/>
+          </xsl:call-template>
+          <xsl:text>(</xsl:text>
+          <xsl:value-of select="$nextProd"/>
+          <xsl:text>)</xsl:text>
+          <xsl:text>? </xsl:text>
+          <xsl:value-of select="$nextProd"/>
+          <xsl:text>)</xsl:text>
+          
+          <xsl:text> | </xsl:text>
+          <xsl:if test="not(g:prefix//g:next)">
+            <xsl:value-of select="$nextProd"/>
+          </xsl:if>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="outputChoices">
+            <xsl:with-param name="choices"
+              select="g:prefix"/>
+          </xsl:call-template>
+          <xsl:choose>
+            <xsl:when test="g:prefix/@prefix-seq-type">
+              <xsl:value-of select="g:prefix/@prefix-seq-type"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:text>*</xsl:text>
+            </xsl:otherwise>
+          </xsl:choose>
+          <xsl:text> </xsl:text>
+          <xsl:if test="not(g:prefix//g:next)">
+            <xsl:value-of select="$nextProd"/>
+          </xsl:if>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:when>
+    <xsl:when test="g:primary">
+      <xsl:call-template name="outputChoices">
+        <xsl:with-param name="choices"
+                        select="g:primary"/>
+      </xsl:call-template>
+      <xsl:if test="g:primary/following-sibling::g:level | following-sibling::g:level">
+        <xsl:text> | </xsl:text>
+      	<xsl:value-of select="$nextProd"/>
+      </xsl:if> 
+    </xsl:when>
+    <xsl:otherwise>
+    </xsl:otherwise>
+  </xsl:choose>
+  <xsl:call-template name="action-level-end"/>
+}
+
+</xsl:for-each>
+</xsl:template>
+
+<xsl:template name="outputChoices">
+  <xsl:param name="choices" select="/.."/>
+  <xsl:param name="lookahead" select="ancestor-or-self::*/@lookahead"/>
+  
+  <xsl:if test="count($choices)>1">(</xsl:if>
+  <xsl:for-each select="$choices">
+    <xsl:if test="position()!=1"> | </xsl:if>
+    <xsl:if test="count(*)>1">(</xsl:if>
+    <xsl:for-each select="*">
+      <xsl:if test="position()!=1" xml:space="preserve">  </xsl:if>
+      <xsl:apply-templates select="."><xsl:with-param name="lookahead" select="$lookahead"/></xsl:apply-templates>
+    </xsl:for-each>
+    <xsl:if test="count(*)>1">)</xsl:if>
+  </xsl:for-each>
+  <xsl:if test="count($choices)>1">)</xsl:if>
+</xsl:template>
+
+<xsl:template match="g:optional">[<xsl:call-template name="lookahead"/>
+<xsl:call-template name="space"/>]</xsl:template>
+
+<xsl:template match="g:token//g:optional">(<xsl:call-template name="space"/>)?</xsl:template>
+<xsl:template match="g:zeroOrMore">(<xsl:call-template name="lookahead"/>
+<xsl:call-template name="space"/>)*</xsl:template>
+
+<xsl:template match="g:oneOrMore">(<xsl:call-template name="lookahead"/>
+<xsl:call-template name="space"/>)+ </xsl:template>
+
+<xsl:template match="g:sequence">(<xsl:call-template name="lookahead"/>
+<xsl:call-template name="space"/>)</xsl:template>
+
+<xsl:template match="g:ref[@notational-only='yes']">
+</xsl:template>
+
+<xsl:template match="g:ref">
+  <xsl:choose>
+    <xsl:when test="key('ref',@name)/self::g:token">
+      <xsl:text>&lt;</xsl:text>
+      <xsl:value-of select="@name"/>
+      <xsl:text>&gt;</xsl:text>
+      <!-- show when a token match is a success.  -sb -->
+	  <xsl:if test="ancestor::g:level | ancestor::g:production">
+	 	  	<xsl:call-template name="action-token-ref"/>
+	 	  	<xsl:if test="ancestor::g:binary">
+	 	  	      <!-- xsl:value-of select="$nextProd"/ -->
+	 	  	      
+	 	  	      <!-- Awww... it's not so bad... -sb -->
+	 	  	      <xsl:if test="false()">
+				<xsl:variable name="levels" select="ancestor::g:exprProduction/g:level[*]"/>
+				<xsl:variable name="position" select="count(ancestor::g:level/preceding-sibling::g:level[*])+1"/>
+				<xsl:variable name="nextProd" select="concat($levels[$position+1]/*/@name,'()')"/>
+	 	  	      
+	 	  	      <!-- xsl:variable name="nextProd" select="concat(ancestor::g:exprProduction/@name, 
+	 	  	                                                  '_',  count(ancestor::g:level/preceding-sibling::g:level[*])+2,'()')"/ -->
+
+			      <!-- xsl:value-of select="concat(ancestor::g:exprProduction/@name,'_1')"/ -->
+			      <!-- xsl:text>()</xsl:text -->
+			      <xsl:value-of select="$nextProd"/>
+			      
+			      <xsl:call-template name="binary-action-level-jjtree-label">
+              <xsl:with-param name="which" select="3"/>
+            </xsl:call-template>
+			      <xsl:text>
+</xsl:text>
+				</xsl:if>
+	 	  	</xsl:if>
+	  </xsl:if>
+    </xsl:when>
+    <xsl:otherwise>
+    	<!-- Begin LV -->
+      <xsl:call-template name="user-action-ref-start"/>
+      <!-- End LV -->
+    
+      <xsl:value-of select="@name"/>
+      <xsl:text>()</xsl:text>
+      
+      <!-- Begin LV -->
+      <xsl:call-template name="user-action-ref-end"/>
+      <!-- End LV -->
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match="g:next">
+  <!-- The assumption is this we're in a exprProduction, 
+       in a prefix, primary, etc., and want to call the next level. -->
+  <xsl:variable name="levels" select="ancestor::g:exprProduction[1]/g:level[*]"/>
+  <xsl:variable name="position">
+    <xsl:variable name="uniqueIdOfThisLevel" select="generate-id(ancestor::g:level[1])"/>
+    <xsl:for-each select="$levels">
+      <xsl:if test="generate-id(.) = $uniqueIdOfThisLevel">
+        <xsl:value-of select="position()"/>
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:variable>
+  <xsl:variable name="nextProd" select="concat($levels[$position+1]/*/@name,'()')"/>
+  <xsl:value-of select="$nextProd"/>
+  <!-- xsl:text>()</xsl:text -->
+</xsl:template>
+
+<xsl:template match="g:choice">
+  <xsl:variable name="lookahead" select="ancestor-or-self::*/@lookahead"/>
+  <xsl:if test="$lookahead > 0">LOOKAHEAD(<xsl:value-of select="$lookahead"/>) </xsl:if>
+  <xsl:text>(</xsl:text>
+  <xsl:for-each select="*[not(@notational-only='yes')]">
+    <xsl:if test="position()!=1">
+      <xsl:text> | </xsl:text>
+    </xsl:if>
+    <xsl:apply-templates select=".">
+    	<xsl:with-param name="lookahead" select="$lookahead"/>
+    </xsl:apply-templates>
+    
+  </xsl:for-each>
+  <xsl:text>)</xsl:text>
+</xsl:template>
+
+<!-- xsl:template match="g:choice" mode="binary">
+  <xsl:param name="name"/>
+  <xsl:text>(</xsl:text>
+  <xsl:for-each select="*">
+    <xsl:if test="position()!=1">
+      <xsl:text> | </xsl:text>
+    </xsl:if>
+    <xsl:apply-templates select="."/>
+    <xsl:value-of select="$name"/><xsl:text>()</xsl:text>
+  </xsl:for-each>
+  <xsl:text>)</xsl:text>
+</xsl:template -->
+
+<xsl:template match="g:requiredSkip">
+  <xsl:text>(&lt;skip_&gt;)+</xsl:text>
+</xsl:template>
+
+<xsl:template match="g:optionalSkip">
+  <xsl:text>(&lt;skip_&gt;)*</xsl:text>
+</xsl:template>
+
+<xsl:template name="lookahead" match="lookahead">
+  <xsl:if test="@lookahead">
+    <xsl:text>LOOKAHEAD(</xsl:text>
+    <xsl:value-of select="@lookahead"/>
+    <xsl:text>) </xsl:text>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template name="space">
+  <xsl:for-each select="*">
+    <xsl:if test="position()!=1">
+      <xsl:text> </xsl:text>
+    </xsl:if>
+    <xsl:apply-templates select="."/>
+  </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="replace-char">
+  <xsl:param name="from" select="''"/>
+  <xsl:param name="to" select="''"/>
+  <xsl:param name="string" select="''"/>
+  <xsl:if test="$string">
+    <xsl:choose>
+        <xsl:when test="substring($string,1,1)=$from">
+          <!-- Added this to avoid empty commas in sequences of
+               spaces. -sb -->
+          <xsl:if test="not(substring($string,2,1)=$from and $from=' ')">
+            <xsl:value-of select="$to"/>
+          </xsl:if>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="substring($string,1,1)"/>
+        </xsl:otherwise>
+    </xsl:choose>
+    <xsl:call-template name="replace-char">
+      <xsl:with-param name="string" select="substring($string, 2)"/>
+      <xsl:with-param name="to" select="$to"/>
+      <xsl:with-param name="from" select="$from"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file

Added: incubator/jackrabbit/trunk/src/grammar/xpath/jjtree-jackrabbit.xsl
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/jjtree-jackrabbit.xsl?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/jjtree-jackrabbit.xsl	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright 2004 The Apache Software Foundation
+
+   Licensed 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.
+  -->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+	<xsl:import href="jjtree.xsl" />
+
+	<xsl:template name="set-parser-package">
+	package org.apache.jackrabbit.core.search.xpath;
+	</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file

Added: incubator/jackrabbit/trunk/src/grammar/xpath/jjtree.xsl
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/jjtree.xsl?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/jjtree.xsl	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,372 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Copyright (c) 2002 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
+                                                xmlns:g="http://www.w3.org/2001/03/XPath/grammar">
+	<xsl:import href="javacc.xsl"/>
+	
+	<xsl:template name="javacc-options">
+	  <!-- xsl:apply-imports/ -->
+          STATIC = false;
+	   MULTI=false;
+	   VISITOR=true ;     // invokes the JJTree Visitor support
+	   NODE_SCOPE_HOOK=false;
+	   NODE_USES_PARSER=true;
+	</xsl:template>
+	
+	<xsl:template name="input">
+		SimpleNode <xsl:choose>
+			<xsl:when test="$spec='xquery'">XPath2</xsl:when>
+			<xsl:when test="$spec='xpath'">XPath2</xsl:when>
+			<xsl:when test="$spec='pathx1'">XPath2</xsl:when>
+      <xsl:otherwise>XPath2</xsl:otherwise>
+		</xsl:choose>() :
+		{}
+		{
+		  <xsl:value-of select="g:start/@name"/>()&lt;EOF&gt;
+		  { return jjtThis ; }
+		}
+      <xsl:if test="$spec='xpath' or $spec='pathx1'">
+		SimpleNode <xsl:choose>
+			<xsl:when test="$spec='xpath'">MatchPattern</xsl:when>
+			<xsl:when test="$spec='pathx1'">MatchPattern</xsl:when>
+      <xsl:otherwise>MatchPattern</xsl:otherwise>
+		</xsl:choose>() :
+		{m_isMatchPattern = true;}
+		{
+		  <xsl:value-of select="g:start[contains(@if,'xslt-patterns')]/@name"/>()&lt;EOF&gt;
+		  { return jjtThis ; }
+		}
+    </xsl:if>
+	</xsl:template>
+
+  <xsl:template name="extra-parser-code"/>
+	
+	<xsl:template name="parser">
+    <xsl:variable name="parser-class">
+      <xsl:choose>
+			<xsl:when test="$spec='xpath'">XPath</xsl:when>
+			<xsl:when test="$spec='pathx1'">XPath</xsl:when>
+      <xsl:otherwise>XPath</xsl:otherwise>
+    </xsl:choose>
+    </xsl:variable>
+    PARSER_BEGIN(<xsl:value-of select="$parser-class"/>)
+
+<xsl:call-template name="set-parser-package"/>
+import java.io.*;		
+import java.util.Stack;
+import java.util.Vector;
+
+public class <xsl:value-of select="$parser-class"/> {
+      <xsl:call-template name="extra-parser-code"/>
+
+      boolean m_isMatchPattern = false;
+      boolean isStep = false;
+
+		  Stack binaryTokenStack = new Stack();
+		  
+		  public Node createNode(int id) {
+			  return null;
+		  }
+		  
+		  
+		  
+		  public static void main(String args[])
+		     throws Exception
+		  {
+         int numberArgsLeft = args.length;
+         int argsStart = 0;
+         boolean isMatchParser = false;
+         if(numberArgsLeft > 0)
+         {
+           if(args[argsStart].equals("-match"))
+           {
+             isMatchParser = true;
+             System.out.println("Match Pattern Parser");
+             argsStart++;
+             numberArgsLeft--;
+           }
+         }
+		     if(numberArgsLeft > 0)
+		    {
+			try
+			{
+        final boolean dumpTree = true;
+        if(args[0].endsWith(".xquery"))
+        {
+          System.out.println("Running test for: "+args[0]);
+          File file = new File(args[0]);
+          FileInputStream fis = new FileInputStream(file);
+          XPath parser = new XPath(fis);
+          SimpleNode tree = parser.XPath2();
+          if(dumpTree)
+            tree.dump("|") ;
+        }
+        else
+        {
+				for(int i = argsStart; i &lt; args.length; i++)
+				{
+					System.out.println();
+					System.out.println("Test["+i+"]: "+args[i]);
+					XPath parser = new XPath(new java.io.StringBufferInputStream(args[i]));
+          SimpleNode tree;
+          if(isMatchParser)
+          {
+					tree = parser.<xsl:choose>
+						<xsl:when test="$spec='xquery'">XPath2</xsl:when>
+						<xsl:when test="$spec='xpath'">MatchPattern</xsl:when>
+						<xsl:when test="$spec='pathx1'">MatchPattern</xsl:when>
+            <xsl:otherwise>XPath2</xsl:otherwise>
+					</xsl:choose>();
+          }
+          else
+          {
+					tree = parser.<xsl:choose>
+						<xsl:when test="$spec='xquery'">XPath2</xsl:when>
+						<xsl:when test="$spec='xpath'">XPath2</xsl:when>
+						<xsl:when test="$spec='pathx1'">XPath2</xsl:when>
+            <xsl:otherwise>XPath2</xsl:otherwise>
+					</xsl:choose>();
+          }
+					((SimpleNode)tree.jjtGetChild(0)).dump("|") ;
+				}
+				System.out.println("Success!!!!");
+        }
+			}
+			catch(ParseException pe)
+			{
+				System.err.println(pe.getMessage());
+			}
+			return;
+		   }
+		    java.io.DataInputStream dinput = new java.io.DataInputStream(System.in);
+		    while(true)
+		    {
+			  try
+			  {
+			      System.err.println("Type Expression: ");
+			      String input =  dinput.readLine(); 
+			      if(null == input || input.trim().length() == 0)
+			        break;  
+			      XPath parser = new XPath(new java.io.StringBufferInputStream(input));
+          SimpleNode tree;
+          if(isMatchParser)
+          {
+					tree = parser.<xsl:choose>
+						<xsl:when test="$spec='xquery'">XPath2</xsl:when>
+						<xsl:when test="$spec='xpath'">MatchPattern</xsl:when>
+						<xsl:when test="$spec='pathx1'">MatchPattern</xsl:when>
+            <xsl:otherwise>XPath2</xsl:otherwise>
+					</xsl:choose>();
+          }
+          else
+          {
+					tree = parser.<xsl:choose>
+						<xsl:when test="$spec='xquery'">XPath2</xsl:when>
+						<xsl:when test="$spec='xpath'">XPath2</xsl:when>
+						<xsl:when test="$spec='pathx1'">XPath2</xsl:when>
+            <xsl:otherwise>XPath2</xsl:otherwise>
+					</xsl:choose>();
+          }
+			      ((SimpleNode)tree.jjtGetChild(0)).dump("|") ;
+			  }
+			  catch(ParseException pe)
+			  {
+			  	System.err.println(pe.getMessage());
+			  }
+			  catch(Exception e)
+			  {
+			  	System.err.println(e.getMessage());
+			  }
+		    }		    
+		  }
+		}
+
+    PARSER_END(<xsl:value-of select="$parser-class"/>)
+
+	</xsl:template>
+	
+	<xsl:template name="action-production">
+		<!-- Begin LV -->
+		<xsl:if test="@prod-user-action">
+				<xsl:value-of select="@prod-user-action"/>
+		</xsl:if>
+		<!-- End LV -->
+	</xsl:template>
+	
+	<xsl:template name="action-production-end">
+	</xsl:template>
+
+	<xsl:template name="action-exprProduction-label">
+    <xsl:if test="@node-type='void'">
+      <xsl:text> #void </xsl:text>
+    </xsl:if>
+	</xsl:template>
+	
+	
+	<xsl:template name="action-exprProduction">
+	</xsl:template>
+	
+	<xsl:template name="action-exprProduction-end">
+	</xsl:template>
+	
+	<xsl:template name="action-level">
+		<xsl:param name="thisProd"/>
+		<xsl:param name="nextProd"/>
+		 
+		<xsl:if test="@level-user-action">
+				<xsl:value-of select="@level-user-action"/>
+		</xsl:if>
+		<!-- xsl:text>
+printIndent(); System.err.println("</xsl:text>
+	   <xsl:value-of select="$thisProd"/>
+	   <xsl:text>");
+</xsl:text -->
+	</xsl:template>
+	
+	<xsl:template name="action-level-jjtree-label">
+    <xsl:param name="label">
+      <xsl:text>void</xsl:text>
+    </xsl:param>
+		<!-- Begin SMPG -->
+    <xsl:param name="condition"></xsl:param>
+		<!-- End SMPG -->
+
+    <xsl:text> #</xsl:text>
+    <xsl:value-of select="$label"/>
+
+		<!-- Begin SMPG -->
+		<xsl:if test="$condition != ''">
+			<xsl:text>(</xsl:text>
+			<xsl:value-of select="$condition"/>
+			<xsl:text>)</xsl:text>
+		</xsl:if>
+		<!-- End SMPG -->
+  </xsl:template>
+	
+	<xsl:template name="binary-action-level-jjtree-label">
+    <xsl:param name="label"/>
+    <xsl:param name="which" select="'unknown'"/>
+    <!-- xsl:message>
+      <xsl:text>In binary-action-level-jjtree-label: </xsl:text>
+      <xsl:value-of select="name(.)"/>
+      <xsl:text>  (</xsl:text>
+      <xsl:value-of select="$which"/>
+      <xsl:text>)</xsl:text>
+    </xsl:message -->
+    <xsl:if test="ancestor-or-self::g:binary or self::g:level/g:binary">
+		<xsl:text>
+		{
+         try
+         {
+		       jjtThis.processToken((Token)binaryTokenStack.pop());
+         }
+         catch(java.util.EmptyStackException e)
+         {
+           token_source.printLinePos();
+           e.printStackTrace();
+           throw e;
+         }
+		}
+		</xsl:text>
+		<xsl:text> #</xsl:text><xsl:value-of select="$label"/><xsl:text>(2)</xsl:text>
+    </xsl:if>
+	</xsl:template>
+
+	<xsl:template name="set-parser-package">
+	</xsl:template>
+	
+	<xsl:template name="action-level-start">
+	</xsl:template>
+	
+	<xsl:template name="action-level-end">
+	</xsl:template>
+	
+	<xsl:template name="action-token-ref">
+		<!-- xsl:if test="ancestor::g:binary">
+		<xsl:text> #</xsl:text><xsl:value-of select="@name"/>
+		</xsl:if -->
+		<xsl:choose>
+      <xsl:when test="not(ancestor::g:binary or ancestor-or-self::g:*/@is-binary='yes')">
+        <xsl:choose>
+          <xsl:when test="key('ref',@name)/self::g:token/@node-type='void'">
+            <!-- Don't produce a node.  #void doesn't seem to work here, for some reason. -->
+          </xsl:when>
+          <xsl:when test="@node-type='void'">
+            <!-- Don't produce a node.  #void doesn't seem to work here, for some reason. -->
+          </xsl:when>
+          <xsl:when test="key('ref',@name)/self::g:token/@node-type">
+            <xsl:text>{</xsl:text>
+						<xsl:if test="@token-user-action">
+							<xsl:value-of select="@token-user-action"/>
+						</xsl:if>
+						<xsl:text>jjtThis.processToken(token);}</xsl:text>
+            <xsl:text> #</xsl:text>
+            <xsl:value-of select="key('ref',@name)/self::g:token/@node-type"/>
+            <!-- See JTree doc for why I do the following... -->
+            <xsl:if test="true() or following-sibling::*[1][self::g:zeroOrMore or self::g:oneOrMore]">
+              <xsl:text>(true)</xsl:text>
+            </xsl:if>
+          </xsl:when>
+          <xsl:when test="@node-type">
+            <xsl:text>{</xsl:text>
+						<xsl:if test="@token-user-action">
+							<xsl:value-of select="@token-user-action"/>
+						</xsl:if>
+						<xsl:text>jjtThis.processToken(token);}</xsl:text>
+            <xsl:text> #</xsl:text>
+            <xsl:value-of select="@node-type"/>
+            <!-- See JTree doc for why I do the following... -->
+            <xsl:if test="true() or following-sibling::*[1][self::g:zeroOrMore or self::g:oneOrMore]">
+              <xsl:text>(true)</xsl:text>
+            </xsl:if>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:text>{</xsl:text>
+						<xsl:if test="@token-user-action">
+							<xsl:value-of select="@token-user-action"/>
+						</xsl:if>
+						<xsl:text>jjtThis.processToken(token);}</xsl:text>
+            <xsl:text> #</xsl:text>
+            <xsl:value-of select="@name"/>
+            <!-- See JTree doc for why I do the following... -->
+            <xsl:if test="true() or following-sibling::*[1][self::g:zeroOrMore or self::g:oneOrMore]">
+              <xsl:text>(true)</xsl:text>
+            </xsl:if>
+          </xsl:otherwise>
+        </xsl:choose>
+				
+
+			</xsl:when>
+			<xsl:otherwise>
+        <!-- xsl:message>
+          <xsl:text>In binary-action-level-jjtree-label: </xsl:text>
+          <xsl:value-of select="name(.)"/>
+        </xsl:message -->
+         {binaryTokenStack.push(token);}
+			</xsl:otherwise>
+		</xsl:choose>		
+	</xsl:template>
+	
+	<!-- Begin LV -->
+<xsl:template name="user-action-ref-start">
+<xsl:if test="@nt-user-action-start">{<xsl:value-of select="@nt-user-action-start"/>}</xsl:if>
+</xsl:template>
+
+<xsl:template name="user-action-ref-end">
+<xsl:if test="@nt-user-action-end">{<xsl:value-of select="@nt-user-action-end"/>}</xsl:if>
+</xsl:template>
+<!-- End LV -->
+	
+</xsl:stylesheet>

Added: incubator/jackrabbit/trunk/src/grammar/xpath/strip.xsl
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/strip.xsl?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/strip.xsl	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (c) 2002 World Wide Web Consortium,
+ * (Massachusetts Institute of Technology, Institut National de
+ * Recherche en Informatique et en Automatique, Keio University). All
+ * Rights Reserved. This program is distributed under the W3C's Software
+ * Intellectual Property License. This program is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  version="1.0" xmlns:g="http://www.w3.org/2001/03/XPath/grammar">
+  <xsl:param name="spec1" select="'xpath'"/>
+  <xsl:param name="spec2" select="'dummy'"/>
+  <xsl:param name="spec3" select="'dummy'"/>
+
+  <xsl:template match="@*|node()[@exposition-only='yes']">
+      <!-- empty -->
+  </xsl:template>
+  
+  <xsl:template match="@*|node()[not(@exposition-only='yes')]">
+      
+        <xsl:if test="self::node()[not(@if) 
+                      or contains(@if, $spec1) 
+                      or contains(@if, $spec2) 
+                      or contains(@if, $spec3)]">
+          <xsl:copy>
+            <xsl:apply-templates select="@*|node()"/>
+          </xsl:copy>        
+        </xsl:if>
+    
+  </xsl:template>
+
+</xsl:stylesheet>

Added: incubator/jackrabbit/trunk/src/grammar/xpath/xpath-grammar.xml
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/xpath/xpath-grammar.xml?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/grammar/xpath/xpath-grammar.xml	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,4147 @@
+<?xml version="1.0"?>
+<!-- edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by Scott Boag (XSL WG) -->
+<!DOCTYPE g:grammar SYSTEM "grammar.dtd">
+<!--
+Copyright (c) 2002 W3C(r) (http://www.w3.org/) (MIT (http://www.lcs.mit.edu/), 
+INRIA (http://www.inria.fr/), Keio (http://www.keio.ac.jp/)), 
+All Rights Reserved.
+See http://www.w3.org/Consortium/Legal/ipr-notice-20000612#Copyright.
+W3C liability 
+(http://www.w3.org/Consortium/Legal/ipr-notice-20000612#Legal_Disclaimer), 
+trademark 
+(http://www.w3.org/Consortium/Legal/ipr-notice-20000612#W3C_Trademarks), 
+document use 
+(http://www.w3.org/Consortium/Legal/copyright-documents-19990405), 
+and software licensing rules 
+(http://www.w3.org/Consortium/Legal/copyright-software-19980720) 
+apply.
+-->
+<g:grammar xmlns:g="http://www.w3.org/2001/03/XPath/grammar" >
+	<!-- ====================== Meta Information ==================== -->
+	<g:language id="xpath" display-name="XPath 2.0" if="xpath"/>
+	<g:language id="pathx1" display-name="XPath 1.0" if="pathx1"/>
+	<g:language id="xquery" display-name="XQuery 1.0" if="xquery"/>
+	<g:language id="core" display-name="XML Processing Formal Semantics Core Language 1.0" if="core"/>
+	<g:language id="xslt1-patterns" display-name="XSLT 1.0 Match Patterns" if="pathx1"/>
+	<g:language id="xslt-patterns" display-name="XSLT 2.0 Match Patterns" if="xslt-patterns"/>
+	<g:language id="update" display-name="XQuery Update Proposal" if="xquery"/>
+	<!-- ====================== Entry Point Information ==================== -->
+	<g:start name="ExprSingle" state="DEFAULT" if="pathx1"/>
+	<g:start name="XPath" state="DEFAULT" if="xpath"/>
+	<g:start name="QueryList" state="DEFAULT" if="core"/>
+	<g:start name="QueryList" state="DEFAULT" if="xquery"/>
+	<g:start name="Pattern" state="DEFAULT" if="xslt-patterns"/>
+	<!-- ====================== Lexical Specifications ==================== -->
+	<g:token name="IntegerLiteral" inline="false" value-type="number" type="literal">
+		<g:ref name="Digits"/>
+	</g:token>
+	<g:token name="DecimalLiteral" inline="false" value-type="number" type="literal" whitespace-spec="explicit">
+		<g:choice name="DecimalString">
+			<g:sequence>
+				<g:string>.</g:string>
+				<g:ref name="Digits"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="Digits"/>
+				<g:string>.</g:string>
+				<g:zeroOrMore name="DecimalFractionPart">
+					<g:charClass>
+						<g:charRange minChar="0" maxChar="9"/>
+					</g:charClass>
+				</g:zeroOrMore>
+			</g:sequence>
+		</g:choice>
+	</g:token>
+	<g:token name="DoubleLiteral" inline="false" value-type="number" type="literal" whitespace-spec="explicit">
+		<g:choice name="DoubleString">
+			<g:sequence>
+				<g:string>.</g:string>
+				<g:ref name="Digits"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="Digits"/>
+				<g:optional name="DoubleOptionFractionPart">
+					<g:string>.</g:string>
+					<g:zeroOrMore name="DoubleFractionPart">
+						<g:charClass>
+							<g:charRange minChar="0" maxChar="9"/>
+						</g:charClass>
+					</g:zeroOrMore>
+				</g:optional>
+			</g:sequence>
+		</g:choice>
+		<g:charClass>
+			<g:char>e</g:char>
+			<g:char>E</g:char>
+		</g:charClass>
+		<g:optional name="DoubleNegOrPos">
+			<g:charClass>
+				<g:char>+</g:char>
+				<g:char>-</g:char>
+			</g:charClass>
+		</g:optional>
+		<g:ref name="Digits"/>
+	</g:token>
+	<g:token name="StringLiteral" inline="false" value-type="string" type="literal" whitespace-spec="explicit">
+		<g:choice name="StringDilimitType">
+			<g:sequence>
+				<g:string>&quot;</g:string>
+				<g:zeroOrMore name="CharsInQuote">
+					<g:choice name="QuoteTypeChar">
+						<g:ref name="PredefinedEntityRef" if="xquery"/>
+						<g:ref name="CharRef" if="xquery"/>
+						<g:sequence>
+							<g:char>&quot;</g:char>
+							<g:char>&quot;</g:char>
+						</g:sequence>
+						<g:complement>
+							<g:charClass>
+								<g:char>&quot;</g:char>
+								<g:char if="xquery">&amp;</g:char>
+							</g:charClass>
+						</g:complement>
+					</g:choice>
+				</g:zeroOrMore>
+				<g:string>&quot;</g:string>
+			</g:sequence>
+			<g:sequence>
+				<g:string>&apos;</g:string>
+				<g:zeroOrMore name="CharsInApos">
+					<g:choice name="AposTypeChar">
+						<g:ref name="PredefinedEntityRef" if="xquery"/>
+						<g:ref name="CharRef" if="xquery"/>
+						<g:sequence>
+							<g:char>&apos;</g:char>
+							<g:char>&apos;</g:char>
+						</g:sequence>
+						<g:complement>
+							<g:charClass>
+								<g:char>&apos;</g:char>
+								<g:char if="xquery">&amp;</g:char>
+							</g:charClass>
+						</g:complement>
+					</g:choice>
+				</g:zeroOrMore>
+				<g:string>&apos;</g:string>
+			</g:sequence>
+		</g:choice>
+	</g:token>
+	<g:token name="StringLiteralForKindTest" alias-for="StringLiteral"/>
+	<g:token name="XQueryVersion" if="xquery core">
+		<g:string>xquery</g:string>
+		<g:optionalSkip/>
+		<g:string>version</g:string>
+	</g:token>
+  <g:token name="StringLiteralForVersion" alias-for="StringLiteral" if="xquery core"/>
+	<g:token name="XQueryEncoding" if="xquery core">
+		<g:string>encoding</g:string>
+	</g:token>
+	<g:token name="AtStringLiteral" if="xquery core">
+		<g:string>at</g:string>
+		<g:optionalSkip/>
+		<g:ref name="URLLiteral"/>
+	</g:token>
+	<g:token name="URLLiteral" alias-for="StringLiteral" if="xquery core"/>
+	<g:token name="ModuleNamespace" if="xquery core">
+		<g:string>module</g:string>
+		<g:optionalSkip/>
+		<g:string>namespace</g:string>
+	</g:token>
+	<g:skip recognize="DEFAULT OPERATOR KINDTEST NAMESPACEDECL XMLSPACE_DECL SINGLETYPE ITEMTYPE NAMESPACEKEYWORD VARNAME OCCURRENCEINDICATOR CLOSEKINDTEST XQUERYVERSION" 
+	    if="xquery core">
+	    <g:choice name="WhiteSpacePatterns">
+	        <g:sequence>
+                <g:oneOrMore name="SkippedWhitespaceString">
+                    <g:ref name="WhitespaceChar"/>
+                </g:oneOrMore>
+            </g:sequence>
+            <!-- g:ref name="Comment"/ -->
+	        <!-- g:sequence>
+                <g:ref name="CommentStart"/>
+                <g:zeroOrMore name="WhitespaceCommentContentBody">
+                    <g:choice name="WhitespaceCharOrComment">
+                        <g:ref name="CommentContent"/>
+                    </g:choice>
+                </g:zeroOrMore>
+                <g:ref name="CommentEnd"/>     	
+	        </g:sequence -->
+	    </g:choice>
+	</g:skip>
+
+	<g:skip recognize="DEFAULT OPERATOR SINGLETYPE ITEMTYPE KINDTEST CLOSEKINDTEST OCCURRENCEINDICATOR VARNAME" 
+	    if="xpath">
+		<g:oneOrMore name="SkippedWhitespaceStringForXPath">
+			<g:ref name="WhitespaceChar"/>
+		</g:oneOrMore>
+	</g:skip>
+	
+	<g:token name="NotOccurrenceIndicator" skip="yes">
+		<g:complement>
+			<g:charClass>
+				<g:char>*</g:char>
+				<g:char>?</g:char>
+				<g:char>+</g:char>
+			</g:charClass>
+		</g:complement>
+	</g:token>
+	<g:skip recognize="DEFAULT OPERATOR QNAME" if="pathx1">
+		<g:oneOrMore name="SkippedWhitespaceStringPathx1">
+			<g:ref name="WhitespaceChar"/>
+		</g:oneOrMore>
+	</g:skip>
+	<g:token name="ProcessingInstructionStart" if="xquery core">
+		<g:string>&lt;?</g:string>
+	</g:token>
+	<g:token name="ProcessingInstructionStartForElementContent" alias-for="ProcessingInstructionStart"  if="xquery core"/>
+	<g:token name="ProcessingInstructionEnd" if="xquery core">
+		<g:string>?></g:string>
+	</g:token>
+	<g:token name="AxisChild" value-type="string">
+		<g:string>child</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisDescendant" value-type="string">
+		<g:string>descendant</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisParent" value-type="string">
+		<g:string>parent</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisAttribute" value-type="string">
+		<g:string>attribute</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisSelf" value-type="string">
+		<g:string>self</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisDescendantOrSelf" value-type="string">
+		<g:string>descendant-or-self</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisAncestor" value-type="string" if="xquery xpath core">
+		<g:string>ancestor</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisFollowingSibling" value-type="string" if="xquery xpath core">
+		<g:string>following-sibling</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisPrecedingSibling" value-type="string" if="xquery xpath core">
+		<g:string>preceding-sibling</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisFollowing" value-type="string" if="xquery xpath core">
+		<g:string>following</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisPreceding" value-type="string" if="xquery xpath core">
+		<g:string>preceding</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisNamespace" value-type="string" if="xpath core">
+		<g:string>namespace</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="AxisAncestorOrSelf" value-type="string" if="xquery xpath core">
+		<g:string>ancestor-or-self</g:string>
+		<g:optionalSkip/>
+		<g:string>::</g:string>
+	</g:token>
+	<g:token name="DefineElement" if="core">
+		<g:string>define</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>element</g:string>
+	</g:token>
+	<g:token name="DefineAttribute" if="core">
+		<g:string>define</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>attribute</g:string>
+	</g:token>
+	<g:token name="DefineType" if="core">
+		<g:string>define</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>type</g:string>
+	</g:token>
+	<g:token name="DefineFunction" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>function</g:string>
+	</g:token>
+
+	<g:token name="DeclareOrdering" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>ordering</g:string>
+	</g:token>
+	<g:token name="Ordered" if="xquery core">
+		<g:string>ordered</g:string>
+	</g:token>
+	<g:token name="Unordered">
+		<g:string>unordered</g:string>
+	</g:token>
+
+	<g:token name="DeclareDefaultOrderingEmpty" if="xquery core">
+		<g:string>declare</g:string>
+    <g:requiredSkip show="no"/>
+		<g:string>default</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>order</g:string>
+	</g:token>
+
+	<g:token name="DeclareInheritNamespaces" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>inherit-namespaces</g:string>
+	</g:token>
+	<g:token name="Yes" if="xquery core">
+		<g:string>yes</g:string>
+	</g:token>
+	<g:token name="No">
+		<g:string>no</g:string>
+	</g:token>
+
+
+	<g:token name="External" if="xquery core">
+		<g:string>external</g:string>
+	</g:token>
+	<g:token name="Or">
+		<g:string>or</g:string>
+	</g:token>
+	<g:token name="And">
+		<g:string>and</g:string>
+	</g:token>
+	<g:token name="Div">
+		<g:string>div</g:string>
+	</g:token>
+	<g:token name="Idiv">
+		<g:string>idiv</g:string>
+	</g:token>
+	<g:token name="Mod">
+		<g:string>mod</g:string>
+	</g:token>
+	<g:token name="Multiply">
+		<g:string>*</g:string>
+	</g:token>
+	<g:token name="In" if="xpath xquery core">
+		<g:string>in</g:string>
+	</g:token>
+	<g:token name="PITarget" inline="false" if="xquery core" value-type="string" is-xml="yes" 
+    xhref="http://www.w3.org/TR/REC-xml#NT-PITarget" comment-id="xml-version">
+		<g:ref name="NCName"/>
+	</g:token>
+	<g:token name="Prefix" value-type="string" visible="false" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml-names/#NT-Prefix" comment-id="xml-version">
+		<g:ref name="NCName"/>
+	</g:token>
+	<g:token name="LocalPart" value-type="string" visible="false" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml-names/#NT-LocalPart" comment-id="xml-version">
+		<g:ref name="NCName"/>
+	</g:token>
+	<g:token name="VariableIndicator" inline="true" node-type="void">
+		<g:string>$</g:string>
+	</g:token>
+	<g:token name="VarName" inline="false" value-type="string">
+		<g:ref name="QName"/>
+	</g:token>
+	<g:token name="ValidationMode" if="xquery core" value-type="string" inline="false">
+		<g:choice name="VModeChoice">
+			<g:string>lax</g:string>
+			<g:string>strict</g:string>
+		</g:choice>
+	</g:token>
+	<g:token name="SchemaModeForDeclareConstruction" if="xquery core" value-type="string" inline="true">
+		<g:choice name="SMFDVModeChoice">
+			<g:string>preserve</g:string>
+			<g:string>strip</g:string>
+		</g:choice>
+	</g:token>
+	<g:token name="Nillable" value-type="id">
+		<g:string>?</g:string>
+	</g:token>
+	<g:token name="DeclareConstruction" if="xquery core" value-type="string">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>construction</g:string>
+	</g:token>
+	<!-- g:token name="SchemaGlobalContextSlash" if="xpath xquery core">
+		<g:ref name="SchemaGlobalContext"/>
+		<g:optionalSkip/>
+		<g:ref name="Slash"/>
+	</g:token -->
+	<!-- g:token name="SchemaGlobalTypeName" inline="false">
+		<g:string>type</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+		<g:optionalSkip/>
+		<!- - g:ref name="TypeName"/ - ->
+		<g:ref name="QName"/>
+		<g:optionalSkip/>
+		<g:string>)</g:string>
+	</g:token -->
+	<!-- g:token name="SchemaGlobalContext" inline="false" if="xpath xquery core">
+		<g:choice name="SGContext">
+			<!- - g:ref name="ElementName"/ - ->
+			<g:ref name="QName"/>
+			<g:ref name="SchemaGlobalTypeName"/>
+		</g:choice>
+	</g:token -->
+	<!-- g:token name="SchemaContextStepSlash" if="xpath xquery core">
+		<g:ref name="SchemaContextStep"/>
+		<g:optionalSkip/>
+		<g:ref name="Slash"/>
+	</g:token -->
+	<!-- g:token name="SchemaContextStep" inline="false" if="xpath xquery core">
+		<!- - g:ref name="ElementName"/ - ->
+		<g:ref name="QName"/>
+	</g:token -->
+	<!-- g:token name="InContextForKindTest" if="xquery core">
+		<g:string>context</g:string>
+	</g:token -->
+	<!-- g:token name="Global" if="xquery core">
+		<g:string>global</g:string>
+	</g:token -->
+	<g:token name="Satisfies" value-type="id">
+		<g:string>satisfies</g:string>
+	</g:token>
+	<g:token name="Return" node-type="void">
+		<g:string>return</g:string>
+	</g:token>
+	<g:token name="Then">
+		<g:string>then</g:string>
+	</g:token>
+	<g:token name="Else">
+		<g:string>else</g:string>
+	</g:token>
+	<g:token name="Default" if="xquery core">
+		<g:string>default</g:string>
+	</g:token>
+	<g:token name="DeclareXMLSpace" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>xmlspace</g:string>
+	</g:token>
+	<g:token name="DeclareBaseURI" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>base-uri</g:string>
+	</g:token>
+	<g:token name="XMLSpacePreserve" if="xquery core">
+		<g:string>preserve</g:string>
+	</g:token>
+	<g:token name="XMLSpaceStrip" if="xquery core">
+		<g:string>strip</g:string>
+	</g:token>
+	<g:token name="Namespace" if="xquery core">
+		<g:string>namespace</g:string>
+	</g:token>
+	<g:token name="DeclareNamespace" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>namespace</g:string>
+	</g:token>
+	<g:token name="To">
+		<g:string>to</g:string>
+	</g:token>
+	<g:token name="Where" if="xquery core">
+		<g:string>where</g:string>
+	</g:token>
+	<g:token name="Collation" if="xquery core">
+		<g:string>collation</g:string>
+	</g:token>
+	<g:token name="Intersect">
+		<g:string>intersect</g:string>
+	</g:token>
+	<g:token name="Union">
+		<g:string>union</g:string>
+	</g:token>
+	<g:token name="Except">
+		<g:string>except</g:string>
+	</g:token>
+	<g:token name="As" if="xquery core">
+		<g:string>as</g:string>
+	</g:token>
+	<g:token name="AtWord" if="xquery core">
+		<g:string>at</g:string>
+	</g:token>
+	<g:token name="Case" if="xquery core">
+		<g:string>case</g:string>
+	</g:token>
+	<g:token name="Instanceof">
+		<g:string>instance</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>of</g:string>
+	</g:token>
+	<g:token name="Castable">
+		<g:string>castable</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>as</g:string>
+	</g:token>
+	<g:token name="RparAs" if="xquery core">
+		<g:string>)</g:string>
+		<g:optionalSkip/>
+		<g:string>as</g:string>
+	</g:token>
+	<g:token name="Item" value-type="id">
+		<g:string>item</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+		<g:optionalSkip/>
+		<g:string>)</g:string>
+	</g:token>
+	<g:token name="ElementType" value-type="id">
+		<g:string>element</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="AttributeType" value-type="id">
+		<g:string>attribute</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="SchemaElementType" value-type="id">
+		<g:string>schema-element</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="SchemaAttributeType" value-type="id">
+		<g:string>schema-attribute</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="OrderedOpen" if="xquery core">
+		<g:string>ordered</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="UnorderedOpen" if="xquery core">
+		<g:string>unordered</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="ElementQNameLbrace" value-type="id" if="xquery core">
+		<g:string>element</g:string>
+		<g:requiredSkip show="no"/>
+		<g:ref name="QName"/>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="AttributeQNameLbrace" value-type="id" if="xquery core">
+		<g:string>attribute</g:string>
+		<g:requiredSkip show="no"/>
+		<g:ref name="QName"/>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<!-- g:token name="NamespaceNCNameLbrace" value-type="id" if="xquery core">
+			<g:string>namespace</g:string>
+			<g:optional name="PossibleNCName">
+				<g:requiredSkip show="no"/>
+				<g:ref name="NCName"/>
+			</g:optional>
+			<g:optionalSkip/>
+			<g:string>{</g:string>
+	</g:token -->
+	<g:token name="PINCNameLbrace" value-type="id" if="xquery core">
+		<g:string>processing-instruction</g:string>
+		<g:requiredSkip show="no"/>
+		<g:ref name="NCName"/>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="PILbrace" value-type="id" if="xquery core">
+		<g:string>processing-instruction</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="CommentLbrace" value-type="id" if="xquery core">
+		<g:string>comment</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="ElementLbrace" value-type="id" if="xquery core">
+		<g:string>element</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="AttributeLbrace" value-type="id" if="xquery core">
+		<g:string>attribute</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="TextLbrace" value-type="id" if="xquery core">
+		<g:string>text</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="DeclareCollation" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>default</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>collation</g:string>
+	</g:token>
+	<g:token name="DefaultElement" if="xquery core">
+		<g:string>default</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>element</g:string>
+	</g:token>
+	<g:token name="DeclareDefaultElement" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>default</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>element</g:string>
+	</g:token>
+	<g:token name="DeclareDefaultFunction" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>default</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>function</g:string>
+	</g:token>
+	<g:token name="Type" if="core" value-type="id">
+		<g:string>type</g:string>
+	</g:token>
+	<g:token name="EmptyTok" if="xquery core xpath" value-type="id">
+		<g:string>empty</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+		<g:optionalSkip/>
+		<g:string>)</g:string>
+	</g:token>
+	<g:token name="None" if="core">
+		<g:string>none</g:string>
+	</g:token>
+	<g:token name="ImportSchemaToken" if="xquery core">
+		<g:string>import</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>schema</g:string>
+	</g:token>
+	<g:token name="ImportModuleToken" if="xquery core">
+		<g:string>import</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>module</g:string>
+	</g:token>
+	<g:token name="Nmstart" inline="false" visible="false">
+		<g:choice name="NmstartChar">
+			<g:ref name="Letter"/>
+			<g:string>_</g:string>
+		</g:choice>
+	</g:token>
+	<g:token name="Nmchar" inline="false" visible="false">
+		<g:choice name="NmcharChoice">
+			<g:ref name="Letter"/>
+			<g:ref name="CombiningChar"/>
+			<g:ref name="Extender"/>
+			<g:ref name="Digit"/>
+			<g:string>.</g:string>
+			<g:string>-</g:string>
+			<g:string>_</g:string>
+		</g:choice>
+	</g:token>
+	<g:token name="Star" value-type="string">
+		<g:string>*</g:string>
+	</g:token>
+	<g:token name="AnyName" alias-for="Star"/>
+	<g:token name="NCNameColonStar" value-type="string">
+		<g:ref name="NCName"/>
+		<g:string>:</g:string>
+		<g:string>*</g:string>
+	</g:token>
+	<g:token name="StarColonNCName" value-type="string">
+		<g:string>*</g:string>
+		<g:string>:</g:string>
+		<g:ref name="NCName"/>
+	</g:token>
+	<g:token name="Root" value-type="id">
+		<g:string>&#47;</g:string>
+	</g:token>
+	<g:token name="RootDescendants" value-type="id">
+		<g:string>&#47;&#47;</g:string>
+	</g:token>
+	<g:token name="Slash">
+		<g:string>&#47;</g:string>
+	</g:token>
+	<g:token name="SlashSlash">
+		<g:string>&#47;&#47;</g:string>
+	</g:token>
+	<g:token name="Equals">
+		<g:string>=</g:string>
+	</g:token>
+	<g:token name="AssignEquals" if="xquery core">
+		<g:string>=</g:string>
+	</g:token>
+	<g:token name="Is">
+		<g:string>is</g:string>
+	</g:token>
+	<g:token name="NotEquals">
+		<g:string>!=</g:string>
+	</g:token>
+	<g:token name="LtEquals">
+		<g:string>&lt;=</g:string>
+	</g:token>
+	<g:token name="LtLt">
+		<g:string>&lt;&lt;</g:string>
+	</g:token>
+	<g:token name="GtEquals">
+		<g:string>&gt;=</g:string>
+	</g:token>
+	<g:token name="GtGt">
+		<g:string>&gt;&gt;</g:string>
+	</g:token>
+	<g:token name="FortranEq">
+		<g:string>eq</g:string>
+	</g:token>
+	<g:token name="FortranNe">
+		<g:string>ne</g:string>
+	</g:token>
+	<g:token name="FortranGt">
+		<g:string>gt</g:string>
+	</g:token>
+	<g:token name="FortranGe">
+		<g:string>ge</g:string>
+	</g:token>
+	<g:token name="FortranLt">
+		<g:string>lt</g:string>
+	</g:token>
+	<g:token name="FortranLe">
+		<g:string>le</g:string>
+	</g:token>
+	<g:token name="ColonEquals" if="xquery core">
+		<g:string>:=</g:string>
+	</g:token>
+	<g:token name="Lt">
+		<g:string>&lt;</g:string>
+	</g:token>
+	<g:token name="Gt">
+		<g:string>&gt;</g:string>
+	</g:token>
+	<g:token name="Minus" value-type="id">
+		<g:string>-</g:string>
+	</g:token>
+	<g:token name="Plus" value-type="id">
+		<g:string>+</g:string>
+	</g:token>
+	<g:token name="UnaryMinus" alias-for="Minus"/>
+	<g:token name="UnaryPlus" alias-for="Plus"/>
+	<g:token name="OccurrenceZeroOrOne">
+		<g:string>?</g:string>
+	</g:token>
+	<g:token name="OccurrenceZeroOrMore" alias-for="Star"/>
+	<g:token name="OccurrenceOneOrMore" alias-for="Plus"/>
+	<g:token name="Vbar">
+		<g:string>|</g:string>
+	</g:token>
+	<g:token name="Lpar" node-type="void">
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="At">
+		<g:string>@</g:string>
+	</g:token>
+	<g:token name="Lbrack">
+		<g:string>[</g:string>
+	</g:token>
+	<g:token name="Rbrack">
+		<g:string>]</g:string>
+	</g:token>
+	<g:token name="Rpar" node-type="void">
+		<g:string>)</g:string>
+	</g:token>
+	<g:token name="RparForKindTest" alias-for="Rpar" node-type="void"/>
+	<g:token name="Some" value-type="id">
+		<g:string>some</g:string>
+		<g:optionalSkip/>
+		<g:ref name="VariableIndicator"/>
+	</g:token>
+	<g:token name="Every" value-type="id">
+		<g:string>every</g:string>
+		<g:optionalSkip/>
+		<g:ref name="VariableIndicator"/>
+	</g:token>
+	<g:token name="ForVariable" override="yes" if="xpath xquery core" node-type="void">
+		<g:string>for</g:string>
+		<g:optionalSkip/>
+		<g:ref name="VariableIndicator"/>
+	</g:token>
+	<g:token name="LetVariable" if="xquery core">
+		<g:string>let</g:string>
+		<g:optionalSkip/>
+		<g:ref name="VariableIndicator"/>
+	</g:token>
+	<g:token name="CastAs">
+		<g:string>cast</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>as</g:string>
+	</g:token>
+	<g:token name="TreatAs">
+		<g:string>treat</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>as</g:string>
+	</g:token>
+	<!-- start update proposal tokens -->
+	<g:token name="UpdateTok" if="update">
+		<g:string>update</g:string>
+	</g:token>
+	<g:token name="UpdateListOpen" if="update">
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="UpdateListClose" if="update">
+		<g:string>}</g:string>
+	</g:token>
+	<g:token name="UpdateListSep" if="update">
+		<g:string>;</g:string>
+	</g:token>
+	<g:token name="InsertTok" if="update">
+		<g:string>insert</g:string>
+	</g:token>
+	<g:token name="DeleteTok" if="update">
+		<g:string>delete</g:string>
+	</g:token>
+	<g:token name="ReplaceTok" if="update">
+		<g:string>replace</g:string>
+	</g:token>
+	<g:token name="ValueOf" if="update">
+		<g:string>value</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>of</g:string>
+	</g:token>
+	<g:token name="With" if="update">
+		<g:string>with</g:string>
+	</g:token>
+	<g:token name="Do" if="update">
+		<g:string>do</g:string>
+	</g:token>
+	<g:token name="AsLast" if="update">
+		<g:string>as</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>last</g:string>
+	</g:token>
+	<g:token name="AsFirst" if="update">
+		<g:string>as</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>first</g:string>
+	</g:token>
+	<g:token name="Into" if="update">
+		<g:string>into</g:string>
+	</g:token>
+	<g:token name="After" if="update">
+		<g:string>after</g:string>
+	</g:token>
+	<g:token name="Before" if="update">
+		<g:string>before</g:string>
+	</g:token>
+	<g:token name="UpdateOpenUpdateList" if="update">
+		<g:string>update</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadFor" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>for</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadLet" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>let</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadIf" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>if</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadInsert" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>insert</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadReplace" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>replace</g:string>
+	</g:token>
+	<g:token name="UpdateLookaheadDelete" if="update">
+		<g:string>update</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>delete</g:string>
+	</g:token>
+	<!--===============================-->
+	<g:token name="Validate" if="xquery core" exposition-only="yes">
+		<g:string>validate</g:string>
+	</g:token>
+	<g:token name="ValidateLbrace" if="xquery core">
+		<g:string>validate</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<!-- g:token name="ValidateContext" if="xquery core">
+		<g:string>validate</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>context</g:string>
+	</g:token -->
+	<!-- g:token name="ValidateGlobal" if="xquery core">
+		<g:string>validate</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>global</g:string>
+	</g:token -->
+	<g:token name="ValidateSchemaMode" if="xquery core">
+		<g:string>validate</g:string>
+		<g:requiredSkip show="no"/>
+		<g:ref name="ValidationMode"/>
+	</g:token>
+	<g:token name="Digits" inline="false">
+		<g:oneOrMore name="DigitsString">
+			<g:charClass>
+				<g:charRange minChar="0" maxChar="9"/>
+			</g:charClass>
+		</g:oneOrMore>
+	</g:token>
+	<g:token name="DocumentLpar" override="yes" if="xquery core xpath" value-type="id">
+		<g:string>document-node</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="DocumentLparForKindTest" alias-for="DocumentLpar"/>
+	<g:token name="DocumentLbrace" override="yes" if="xquery core" value-type="id">
+		<g:string>document</g:string>
+		<g:optionalSkip/>
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="NodeLpar" if="xquery core xpath" node-type="void">
+		<g:string>node</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="CommentLpar" override="yes" if="xquery core xpath" node-type="void">
+		<g:string>comment</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="TextLpar" override="yes" if="xquery core xpath" node-type="void">
+		<g:string>text</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="ProcessingInstructionLpar" override="yes" if="xquery core xpath" node-type="void">
+		<g:string>processing-instruction</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="ElementTypeForKindTest" alias-for="ElementType"/>
+	<g:token name="ElementTypeForDocumentTest" alias-for="ElementType"/>
+	<g:token name="AttributeTypeForKindTest" alias-for="AttributeType"/>
+	<g:token name="SchemaElementTypeForKindTest" alias-for="SchemaElementType"/>
+	<g:token name="SchemaElementTypeForDocumentTest" alias-for="SchemaElementType"/>
+	<g:token name="SchemaAttributeTypeForKindTest" alias-for="SchemaAttributeType"/>
+	<g:token name="ProcessingInstructionLparForKindTest" alias-for="ProcessingInstructionLpar"/>
+	<g:token name="TextLparForKindTest" alias-for="TextLpar"/>
+	<g:token name="CommentLparForKindTest" alias-for="CommentLpar"/>
+	<g:token name="NodeLparForKindTest" alias-for="NodeLpar"/>
+	<g:token name="IfLpar" override="yes" if="xquery core xpath">
+		<g:string>if</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="TypeswitchLpar" override="yes" if="xquery core" node-type="void">
+		<g:string>typeswitch</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="Comma" node-type="void">
+		<g:string>,</g:string>
+	</g:token>
+	<g:token name="CommaForKindTest" alias-for="Comma"/>
+	<g:token name="SemiColon" if="xquery core" show="yes" node-type="void">
+		<g:string>;</g:string>
+	</g:token>
+	<g:token name="QuerySeparator" if="xquery core" show="no" node-type="void">
+		<g:string>%%%</g:string>
+	</g:token>
+
+	<!-- OpenQuot and CloseQuote need to be before StringLiteral in 
+	order for them to be matched by flex. -->
+	<g:token name="OpenQuot" if="xquery core">
+		<g:string>&quot;</g:string>
+	</g:token>
+	<g:token name="CloseQuot" if="xquery core">
+		<g:string>&quot;</g:string>
+	</g:token>
+	<g:token name="Dot" value-type="id">
+		<g:string>.</g:string>
+	</g:token>
+	<g:token name="DotDot" value-type="id">
+		<g:string>..</g:string>
+	</g:token>
+	<g:token name="OrderBy" if="xquery core">
+		<g:string>order</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>by</g:string>
+	</g:token>
+	<g:token name="OrderByStable" if="xquery core">
+		<g:string>stable</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>order</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>by</g:string>
+	</g:token>
+	<g:token name="Ascending" if="xquery core" value-type="id">
+		<g:string>ascending</g:string>
+	</g:token>
+	<g:token name="Descending" if="xquery core" value-type="id">
+		<g:string>descending</g:string>
+	</g:token>
+	<g:token name="EmptyGreatest" if="xquery core" value-type="id">
+		<g:string>empty</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>greatest</g:string>
+	</g:token>
+	<g:token name="EmptyLeast" if="xquery core" value-type="id">
+		<g:string>empty</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>least</g:string>
+	</g:token>
+
+	<g:token name="DefineVariable" value-type="string" if="xquery core">
+		<g:string>declare</g:string>
+		<g:requiredSkip show="no"/>
+		<g:string>variable</g:string>
+		<g:optionalSkip/>
+		<g:ref name="VariableIndicator"/>
+	</g:token>
+	<g:token name="QNameForSequenceType" alias-for="QName"/>
+	<g:token name="QNameForAtomicType" alias-for="QName"/>
+	<g:token name="QNameForItemType" alias-for="QName"/>
+	<g:token name="ExtensionQName" type="skip-token" inline="true" if="xquery" special="yes" alias-for="QName"/>
+	<g:token name="IDLpar" value-type="string" if="pathx1" sub-spec="xslt-patterns">
+		<g:string>id</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="KeyLpar" value-type="string" if="pathx1" sub-spec="xslt-patterns">
+		<g:string>key</g:string>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="QNameLpar" value-type="string">
+		<g:ref name="QName"/>
+		<g:optionalSkip/>
+		<g:string>(</g:string>
+	</g:token>
+	<g:token name="NCNameForPrefix" alias-for="NCName" if="xquery core"/>
+	<g:token name="NCNameForPI" alias-for="NCName"/>
+	<g:token name="CdataSectionStart" if="xquery core">
+		<g:string>&lt;![CDATA[</g:string>
+	</g:token>
+	<g:token name="CdataSectionStartForElementContent" alias-for="CdataSectionStart"  if="xquery core"/>
+	<!-- Recognizing it in content disallows ]]> in content same as XML. -->
+	<g:token name="CdataSectionEnd" if="xquery core">
+		<g:string>]]&gt;</g:string>
+	</g:token>
+	<!-- This effectively disallows in element content and attribute
+       values ampersands that are not part of entity or character
+       references. -->
+	<g:token name="Amp" override="yes" if="core">
+		<g:string>&amp;</g:string>
+	</g:token>
+	<g:token name="PredefinedEntityRef" if="xquery core" inline="false" whitespace-spec="explicit" force-delimiting="yes">
+		<g:string>&amp;</g:string>
+		<g:choice name="PredefinedEntityNames">
+			<g:string>lt</g:string>
+			<g:string>gt</g:string>
+			<g:string>amp</g:string>
+			<g:string>quot</g:string>
+			<g:string>apos</g:string>
+		</g:choice>
+		<g:string>;</g:string>
+	</g:token>
+	<g:token name="CharRef" if="xquery" inline="false" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-CharRef" comment-id="xml-version" force-delimiting="yes">
+		<g:string>&amp;#</g:string>
+		<g:choice name="CharRefChars">
+			<g:ref name="Digits"/>
+			<g:sequence>
+				<g:string>x</g:string>
+				<g:ref name="HexDigits"/>
+			</g:sequence>
+		</g:choice>
+		<g:string>;</g:string>
+	</g:token>
+	<g:token name="HexDigits" inline="false" if="xquery" show="no" visible="false">
+		<g:oneOrMore name="HexDigitsString">
+			<g:charClass>
+				<g:charRange minChar="0" maxChar="9"/>
+				<g:charRange minChar="a" maxChar="f"/>
+				<g:charRange minChar="A" maxChar="F"/>
+			</g:charClass>
+		</g:oneOrMore>
+	</g:token>
+	<g:token name="StartTagOpen" override="yes" if="xquery">
+		<g:string>&lt;</g:string>
+	</g:token>
+	<g:token name="StartTagOpenRoot" override="yes" if="xquery">
+		<g:string>&lt;</g:string>
+	</g:token>
+	<g:token name="StartTagClose" if="xquery">
+		<g:string>&gt;</g:string>
+	</g:token>
+	<g:token name="EmptyTagClose" if="xquery">
+		<g:string>/&gt;</g:string>
+	</g:token>
+	<g:token name="EndTagOpen" if="xquery">
+		<g:string>&lt;/</g:string>
+	</g:token>
+	<g:token name="EndTagClose" if="xquery">
+		<g:string>&gt;</g:string>
+	</g:token>
+	<g:token name="ValueIndicator" if="xquery">
+		<g:string>=</g:string>
+	</g:token>
+	<g:token name="TagQName" if="xquery">
+		<g:ref name="QName"/>
+	</g:token>
+	<!-- Recognize in OPERATOR state for function definitions. -->
+	<!-- These should be query only, once we get the validate issue fixed! -->
+	<g:token name="Lbrace" if="xquery core" override="yes">
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="LbraceExprEnclosure" if="xquery core" override="yes">
+		<g:string>{</g:string>
+	</g:token>
+	<g:token name="LCurlyBraceEscape" if="xquery core" override="yes">
+		<g:string>{{</g:string>
+	</g:token>
+	<g:token name="RCurlyBraceEscape" if="xquery core" override="yes">
+		<g:string>}}</g:string>
+	</g:token>
+
+	<!-- Should only be recognized in attribute content. -->
+	<g:token name="EscapeQuot" inline="false" override="yes" if="xquery" force-delimiting="yes">
+		<!-- g:sequence>
+			<g:char>&quot;</g:char>
+			<g:char>&quot;</g:char>
+		</g:sequence -->
+    <g:string>&quot;&quot;</g:string>
+	</g:token>
+
+	<g:token name="EscapeApos" inline="false" if="xquery" force-delimiting="yes">
+		<g:string>&apos;&apos;</g:string>
+	</g:token>
+
+	<g:token name="ElementContentChar" if="xquery core" inline="false" value-type="string" subtract-reg-expr="[{}&lt;&amp;]">
+		<g:ref name="Char"/>
+	</g:token>
+	<g:token name="QuotAttrContentChar" if="xquery core" inline="false" value-type="string" subtract-reg-expr="[&quot;{}&lt;&amp;]">
+		<g:ref name="Char"/>
+	</g:token>
+	<g:token name="AposAttrContentChar" if="xquery core" inline="false" value-type="string" subtract-reg-expr="[&apos;{}&lt;&amp;]">
+		<g:ref name="Char"/>
+	</g:token>
+
+	<g:token name="CommentContentChar" if="xquery core">
+    <g:ref name="Char" subtract-reg-expr="'-'"/>
+  </g:token>
+
+	<g:token name="CommentContentCharDash" if="xquery core">
+	    <g:char force-quote="single">-</g:char>
+      <g:ref name="Char" subtract-reg-expr="'-'"/>
+  </g:token>
+
+	<g:token name="PIContentChar" if="xquery core" alias-for="Char"/>
+	<g:token name="CDataSectionChar" if="xquery core" alias-for="Char"/>
+
+	<g:token name="OpenApos" if="xquery">
+		<g:string>&apos;</g:string>
+	</g:token>
+	<g:token name="CloseApos" override="yes" if="xquery">
+		<g:string>&apos;</g:string>
+	</g:token>
+
+
+	<g:token name="Pragma" if="xquery" special="yes" inline="false" type="skip-token" whitespace-spec="explicit" force-delimiting="yes">
+		<g:ref name="ExtensionStart"/>
+    <g:optional name="PragmaWhitespace1">
+      <g:ref name="SForExt"/>
+    </g:optional>
+		<g:ref name="PragmaKeyword"/>
+    <g:ref name="SForExt"/>
+		<g:ref name="ExtensionQName"/>
+    <g:optional name="PragmaOptContent">
+    <g:ref name="SForExt"/>
+    <g:ref name="ExtensionContents"/>
+		<!-- g:zeroOrMore name="PragmaContentsBody" subtract-reg-expr="(Char* '::)' Char*)">
+			<g:ref name="ExtensionContentChar"/>
+		</g:zeroOrMore -->
+    </g:optional>
+		<g:ref name="ExtensionEnd"/>
+	</g:token>
+	<g:token name="MUExtension" if="xquery" special="yes" inline="false" type="skip-token" whitespace-spec="explicit">
+		<g:ref name="ExtensionStart"/>
+    <g:optional name="MUESpace1">
+      <g:ref name="SForExt"/>
+    </g:optional>
+		<g:ref name="Extension"/>
+    <g:ref name="SForExt"/>
+		<g:ref name="ExtensionQName"/>
+    <g:optional name="MUEOptionalContent">
+    <g:ref name="SForExt"/>
+    <g:ref name="ExtensionContents"/>
+		<!-- g:zeroOrMore name="ExtensionContentsBody" subtract-reg-expr="(Char* '::)' Char*)">
+			<g:ref name="ExtensionContentChar"/>
+		</g:zeroOrMore -->
+    </g:optional>
+		<g:ref name="ExtensionEnd"/>
+	</g:token>
+  <g:token name="ExtensionContents" if="xquery" special="yes" inline="false">
+    <g:zeroOrMore name="PragmaContentsBody" subtract-reg-expr="(Char* '::)' Char*)">
+			<g:ref name="ExtensionContentChar"/>
+		</g:zeroOrMore>
+  </g:token>
+	<g:token name="ExtensionStart" if="xquery" special="yes" inline="true" type="skip-token">
+		<g:string>(::</g:string>
+	</g:token>
+	<g:token name="ExtensionContentChar" if="xquery" special="yes" inline="true" type="skip-token">
+	  <g:ref name="Char"/>
+	</g:token>
+	<g:token name="ExtensionEnd" if="xquery" special="yes" inline="true" type="skip-token">
+		<g:string>::)</g:string>
+	</g:token>
+	<g:token name="Comment" if="xquery core xpath" inline="false" 
+	    comment-id="comments"
+	    skip="yes" type="skip-token" whitespace-spec="explicit"
+      force-delimiting="yes"
+	    >
+		<g:ref name="CommentStart"/>
+    <g:zeroOrMore name="OptionalCommentContent">
+      <g:choice name="CharOrComment">
+        <g:ref name="CommentContents"/>
+        <g:ref name="Comment" notational-only="yes"/>
+      </g:choice>
+    </g:zeroOrMore>
+		<g:ref name="CommentEnd"/>
+	</g:token>
+	<g:token name="CommentContents" special="yes" inline="false">
+	  <g:oneOrMore name="CommentContentBody" 
+                 subtract-reg-expr="(Char* ':)' Char*)">
+			      <g:ref name="CommentContent"/>
+    </g:oneOrMore>
+	</g:token>
+	<g:token name="CommentStart" if="xquery core xpath" special="yes" inline="true" type="skip-token" comment-id="comments">
+		<g:string>(:</g:string>
+	</g:token>
+	<!-- For the moment removed special="yes" from CommentContent-->
+	<g:token name="CommentContent" if="xquery core xpath" special="yes"  inline="true" type="skip-token">
+	  <g:ref name="Char"/>
+	</g:token>
+
+	<g:token name="CommentEnd" if="xquery core xpath" special="yes" inline="true" type="skip-token">
+		<g:string>:)</g:string>
+	</g:token>
+	<g:token name="PragmaKeyword" inline="true" special="yes" if="xquery" type="skip-token">
+		<g:string>pragma</g:string>
+	</g:token>
+	<g:token name="Extension" inline="true" special="yes" if="xquery" type="skip-token">
+		<g:string>extension</g:string>
+	</g:token>
+	<g:token name="XmlCommentStart" if="xquery">
+		<g:string>&lt;!--</g:string>
+	</g:token>
+	<g:token name="XmlCommentStartForElementContent" alias-for="XmlCommentStart" if="xquery"/>
+	<g:token name="XmlCommentEnd" if="xquery">
+		<g:string>--></g:string>
+	</g:token>
+
+	<g:token name="QName" inline="false" value-type="string" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml-names/#NT-QName" comment-id="xml-version">
+		<g:optional name="QNamePrefixAndDelimiter">
+			<g:ref name="Prefix"/>
+			<g:string>:</g:string>
+		</g:optional>
+		<g:ref name="LocalPart"/>
+	</g:token>
+
+	<g:token name="NCName" inline="false" value-type="string" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml-names/#NT-NCName" comment-id="xml-version">
+		<g:ref name="Nmstart"/>
+		<g:zeroOrMore name="NCNameTail">
+			<g:ref name="Nmchar"/>
+		</g:zeroOrMore>
+	</g:token>
+
+	<g:token name="S" inline="false" if="xquery core" is-xml="yes" comment-id="xml-version" xhref="http://www.w3.org/TR/REC-xml#NT-S" force-delimiting="yes">
+		<g:oneOrMore name="SignificantWhitespace">
+			<g:ref name="WhitespaceChar"/>
+		</g:oneOrMore>
+	</g:token>
+	<g:token name="SForPI" alias-for="S" if="xquery core"/>
+  <g:token name="SForExt" alias-for="S" if="xquery core" special="yes"/>
+	<!-- This needs to come after the rules for special characters. -->
+	<g:token name="Char" if="xquery core xpath" is-macro="yes" inline="false" value-type="string" is-xml="yes" comment-id="xml-version" xhref="http://www.w3.org/TR/REC-xml#NT-Char">
+		<g:charClass>
+			<g:charCode value="0009"/>
+			<g:charCode value="000D"/>
+			<g:charCode value="000A"/>
+			<!-- This isn't quite right, but JavaCC doesn't understand surrogates. -->
+			<g:charCodeRange minValue="0020" maxValue="FFFD"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="Rbrace" if="xquery core" override="yes">
+		<g:string>}</g:string>
+	</g:token>
+	<!-- It would be nice to not take character content runs one character 
+       at a time.  However, it seems difficult to say, "all these characters 
+       but these three", at least in JavaCC. -->
+	<!-- token name="CharData" if="xquery" inline="true" value-type="string">
+    <g:oneOrMore>
+      <g:complement>
+      <g:charClass>
+        <g:char>&lt;</g:char>
+        <g:char>&amp;</g:char>
+        <g:char>{</g:char>
+      </g:charClass>
+      </g:complement>
+    </g:oneOrMore>
+  </g:token -->
+	<g:token name="WhitespaceChar" inline="false" visible="false">
+		<g:charClass>
+			<g:charCode value="0009"/>
+			<g:charCode value="000D"/>
+			<g:charCode value="000A"/>
+			<!-- char xml:space="preserve"> </g:char -->
+			<!-- SGML mode in EMacs doesn't like xml:space, so 
+                             we avoid it for now. -->
+			<g:charCode value="0020"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="Letter" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-Letter" comment-id="xml-version" visible="false">
+		<g:choice name="LetterChars">
+			<g:ref name="BaseChar"/>
+			<g:ref name="Ideographic"/>
+		</g:choice>
+	</g:token>
+	<g:token name="BaseChar" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-BaseChar" comment-id="xml-version" visible="false">
+		<g:charClass>
+			<g:charCodeRange minValue="0041" maxValue="005a"/>
+			<g:charCodeRange minValue="0061" maxValue="007a"/>
+			<g:charCodeRange minValue="00c0" maxValue="00d6"/>
+			<g:charCodeRange minValue="00d8" maxValue="00f6"/>
+			<g:charCodeRange minValue="00f8" maxValue="00ff"/>
+			<g:charCodeRange minValue="0100" maxValue="0131"/>
+			<g:charCodeRange minValue="0134" maxValue="013e"/>
+			<g:charCodeRange minValue="0141" maxValue="0148"/>
+			<g:charCodeRange minValue="014a" maxValue="017e"/>
+			<g:charCodeRange minValue="0180" maxValue="01c3"/>
+			<g:charCodeRange minValue="01cd" maxValue="01f0"/>
+			<g:charCodeRange minValue="01f4" maxValue="01f5"/>
+			<g:charCodeRange minValue="01fa" maxValue="0217"/>
+			<g:charCodeRange minValue="0250" maxValue="02a8"/>
+			<g:charCodeRange minValue="02bb" maxValue="02c1"/>
+			<g:charCode value="0386"/>
+			<g:charCodeRange minValue="0388" maxValue="038a"/>
+			<g:charCode value="038c"/>
+			<g:charCodeRange minValue="038e" maxValue="03a1"/>
+			<g:charCodeRange minValue="03a3" maxValue="03ce"/>
+			<g:charCodeRange minValue="03d0" maxValue="03d6"/>
+			<g:charCode value="03da"/>
+			<g:charCode value="03dc"/>
+			<g:charCode value="03de"/>
+			<g:charCode value="03e0"/>
+			<g:charCodeRange minValue="03e2" maxValue="03f3"/>
+			<g:charCodeRange minValue="0401" maxValue="040c"/>
+			<g:charCodeRange minValue="040e" maxValue="044f"/>
+			<g:charCodeRange minValue="0451" maxValue="045c"/>
+			<g:charCodeRange minValue="045e" maxValue="0481"/>
+			<g:charCodeRange minValue="0490" maxValue="04c4"/>
+			<g:charCodeRange minValue="04c7" maxValue="04c8"/>
+			<g:charCodeRange minValue="04cb" maxValue="04cc"/>
+			<g:charCodeRange minValue="04d0" maxValue="04eb"/>
+			<g:charCodeRange minValue="04ee" maxValue="04f5"/>
+			<g:charCodeRange minValue="04f8" maxValue="04f9"/>
+			<g:charCodeRange minValue="0531" maxValue="0556"/>
+			<g:charCode value="0559"/>
+			<g:charCodeRange minValue="0561" maxValue="0586"/>
+			<g:charCodeRange minValue="05d0" maxValue="05ea"/>
+			<g:charCodeRange minValue="05f0" maxValue="05f2"/>
+			<g:charCodeRange minValue="0621" maxValue="063a"/>
+			<g:charCodeRange minValue="0641" maxValue="064a"/>
+			<g:charCodeRange minValue="0671" maxValue="06b7"/>
+			<g:charCodeRange minValue="06ba" maxValue="06be"/>
+			<g:charCodeRange minValue="06c0" maxValue="06ce"/>
+			<g:charCodeRange minValue="06d0" maxValue="06d3"/>
+			<g:charCode value="06d5"/>
+			<g:charCodeRange minValue="06e5" maxValue="06e6"/>
+			<g:charCodeRange minValue="0905" maxValue="0939"/>
+			<g:charCode value="093d"/>
+			<g:charCodeRange minValue="0958" maxValue="0961"/>
+			<g:charCodeRange minValue="0985" maxValue="098c"/>
+			<g:charCodeRange minValue="098f" maxValue="0990"/>
+			<g:charCodeRange minValue="0993" maxValue="09a8"/>
+			<g:charCodeRange minValue="09aa" maxValue="09b0"/>
+			<g:charCode value="09b2"/>
+			<g:charCodeRange minValue="09b6" maxValue="09b9"/>
+			<g:charCodeRange minValue="09dc" maxValue="09dd"/>
+			<g:charCodeRange minValue="09df" maxValue="09e1"/>
+			<g:charCodeRange minValue="09f0" maxValue="09f1"/>
+			<g:charCodeRange minValue="0a05" maxValue="0a0a"/>
+			<g:charCodeRange minValue="0a0f" maxValue="0a10"/>
+			<g:charCodeRange minValue="0a13" maxValue="0a28"/>
+			<g:charCodeRange minValue="0a2a" maxValue="0a30"/>
+			<g:charCodeRange minValue="0a32" maxValue="0a33"/>
+			<g:charCodeRange minValue="0a35" maxValue="0a36"/>
+			<g:charCodeRange minValue="0a38" maxValue="0a39"/>
+			<g:charCodeRange minValue="0a59" maxValue="0a5c"/>
+			<g:charCode value="0a5e"/>
+			<g:charCodeRange minValue="0a72" maxValue="0a74"/>
+			<g:charCodeRange minValue="0a85" maxValue="0a8b"/>
+			<g:charCode value="0a8d"/>
+			<g:charCodeRange minValue="0a8f" maxValue="0a91"/>
+			<g:charCodeRange minValue="0a93" maxValue="0aa8"/>
+			<g:charCodeRange minValue="0aaa" maxValue="0ab0"/>
+			<g:charCodeRange minValue="0ab2" maxValue="0ab3"/>
+			<g:charCodeRange minValue="0ab5" maxValue="0ab9"/>
+			<g:charCode value="0abd"/>
+			<g:charCode value="0ae0"/>
+			<g:charCodeRange minValue="0b05" maxValue="0b0c"/>
+			<g:charCodeRange minValue="0b0f" maxValue="0b10"/>
+			<g:charCodeRange minValue="0b13" maxValue="0b28"/>
+			<g:charCodeRange minValue="0b2a" maxValue="0b30"/>
+			<g:charCodeRange minValue="0b32" maxValue="0b33"/>
+			<g:charCodeRange minValue="0b36" maxValue="0b39"/>
+			<g:charCode value="0b3d"/>
+			<g:charCodeRange minValue="0b5c" maxValue="0b5d"/>
+			<g:charCodeRange minValue="0b5f" maxValue="0b61"/>
+			<g:charCodeRange minValue="0b85" maxValue="0b8a"/>
+			<g:charCodeRange minValue="0b8e" maxValue="0b90"/>
+			<g:charCodeRange minValue="0b92" maxValue="0b95"/>
+			<g:charCodeRange minValue="0b99" maxValue="0b9a"/>
+			<g:charCode value="0b9c"/>
+			<g:charCodeRange minValue="0b9e" maxValue="0b9f"/>
+			<g:charCodeRange minValue="0ba3" maxValue="0ba4"/>
+			<g:charCodeRange minValue="0ba8" maxValue="0baa"/>
+			<g:charCodeRange minValue="0bae" maxValue="0bb5"/>
+			<g:charCodeRange minValue="0bb7" maxValue="0bb9"/>
+			<g:charCodeRange minValue="0c05" maxValue="0c0c"/>
+			<g:charCodeRange minValue="0c0e" maxValue="0c10"/>
+			<g:charCodeRange minValue="0c12" maxValue="0c28"/>
+			<g:charCodeRange minValue="0c2a" maxValue="0c33"/>
+			<g:charCodeRange minValue="0c35" maxValue="0c39"/>
+			<g:charCodeRange minValue="0c60" maxValue="0c61"/>
+			<g:charCodeRange minValue="0c85" maxValue="0c8c"/>
+			<g:charCodeRange minValue="0c8e" maxValue="0c90"/>
+			<g:charCodeRange minValue="0c92" maxValue="0ca8"/>
+			<g:charCodeRange minValue="0caa" maxValue="0cb3"/>
+			<g:charCodeRange minValue="0cb5" maxValue="0cb9"/>
+			<g:charCode value="0cde"/>
+			<g:charCodeRange minValue="0ce0" maxValue="0ce1"/>
+			<g:charCodeRange minValue="0d05" maxValue="0d0c"/>
+			<g:charCodeRange minValue="0d0e" maxValue="0d10"/>
+			<g:charCodeRange minValue="0d12" maxValue="0d28"/>
+			<g:charCodeRange minValue="0d2a" maxValue="0d39"/>
+			<g:charCodeRange minValue="0d60" maxValue="0d61"/>
+			<g:charCodeRange minValue="0e01" maxValue="0e2e"/>
+			<g:charCode value="0e30"/>
+			<g:charCodeRange minValue="0e32" maxValue="0e33"/>
+			<g:charCodeRange minValue="0e40" maxValue="0e45"/>
+			<g:charCodeRange minValue="0e81" maxValue="0e82"/>
+			<g:charCode value="0e84"/>
+			<g:charCodeRange minValue="0e87" maxValue="0e88"/>
+			<g:charCode value="0e8a"/>
+			<g:charCode value="0e8d"/>
+			<g:charCodeRange minValue="0e94" maxValue="0e97"/>
+			<g:charCodeRange minValue="0e99" maxValue="0e9f"/>
+			<g:charCodeRange minValue="0ea1" maxValue="0ea3"/>
+			<g:charCode value="0ea5"/>
+			<g:charCode value="0ea7"/>
+			<g:charCodeRange minValue="0eaa" maxValue="0eab"/>
+			<g:charCodeRange minValue="0ead" maxValue="0eae"/>
+			<g:charCode value="0eb0"/>
+			<g:charCodeRange minValue="0eb2" maxValue="0eb3"/>
+			<g:charCode value="0ebd"/>
+			<g:charCodeRange minValue="0ec0" maxValue="0ec4"/>
+			<g:charCodeRange minValue="0f40" maxValue="0f47"/>
+			<g:charCodeRange minValue="0f49" maxValue="0f69"/>
+			<g:charCodeRange minValue="10a0" maxValue="10c5"/>
+			<g:charCodeRange minValue="10d0" maxValue="10f6"/>
+			<g:charCode value="1100"/>
+			<g:charCodeRange minValue="1102" maxValue="1103"/>
+			<g:charCodeRange minValue="1105" maxValue="1107"/>
+			<g:charCode value="1109"/>
+			<g:charCodeRange minValue="110b" maxValue="110c"/>
+			<g:charCodeRange minValue="110e" maxValue="1112"/>
+			<g:charCode value="113c"/>
+			<g:charCode value="113e"/>
+			<g:charCode value="1140"/>
+			<g:charCode value="114c"/>
+			<g:charCode value="114e"/>
+			<g:charCode value="1150"/>
+			<g:charCodeRange minValue="1154" maxValue="1155"/>
+			<g:charCode value="1159"/>
+			<g:charCodeRange minValue="115f" maxValue="1161"/>
+			<g:charCode value="1163"/>
+			<g:charCode value="1165"/>
+			<g:charCode value="1167"/>
+			<g:charCode value="1169"/>
+			<g:charCodeRange minValue="116d" maxValue="116e"/>
+			<g:charCodeRange minValue="1172" maxValue="1173"/>
+			<g:charCode value="1175"/>
+			<g:charCode value="119e"/>
+			<g:charCode value="11a8"/>
+			<g:charCode value="11ab"/>
+			<g:charCodeRange minValue="11ae" maxValue="11af"/>
+			<g:charCodeRange minValue="11b7" maxValue="11b8"/>
+			<g:charCode value="11ba"/>
+			<g:charCodeRange minValue="11bc" maxValue="11c2"/>
+			<g:charCode value="11eb"/>
+			<g:charCode value="11f0"/>
+			<g:charCode value="11f9"/>
+			<g:charCodeRange minValue="1e00" maxValue="1e9b"/>
+			<g:charCodeRange minValue="1ea0" maxValue="1ef9"/>
+			<g:charCodeRange minValue="1f00" maxValue="1f15"/>
+			<g:charCodeRange minValue="1f18" maxValue="1f1d"/>
+			<g:charCodeRange minValue="1f20" maxValue="1f45"/>
+			<g:charCodeRange minValue="1f48" maxValue="1f4d"/>
+			<g:charCodeRange minValue="1f50" maxValue="1f57"/>
+			<g:charCode value="1f59"/>
+			<g:charCode value="1f5b"/>
+			<g:charCode value="1f5d"/>
+			<g:charCodeRange minValue="1f5f" maxValue="1f7d"/>
+			<g:charCodeRange minValue="1f80" maxValue="1fb4"/>
+			<g:charCodeRange minValue="1fb6" maxValue="1fbc"/>
+			<g:charCode value="1fbe"/>
+			<g:charCodeRange minValue="1fc2" maxValue="1fc4"/>
+			<g:charCodeRange minValue="1fc6" maxValue="1fcc"/>
+			<g:charCodeRange minValue="1fd0" maxValue="1fd3"/>
+			<g:charCodeRange minValue="1fd6" maxValue="1fdb"/>
+			<g:charCodeRange minValue="1fe0" maxValue="1fec"/>
+			<g:charCodeRange minValue="1ff2" maxValue="1ff4"/>
+			<g:charCodeRange minValue="1ff6" maxValue="1ffc"/>
+			<g:charCode value="2126"/>
+			<g:charCodeRange minValue="212a" maxValue="212b"/>
+			<g:charCode value="212e"/>
+			<g:charCodeRange minValue="2180" maxValue="2182"/>
+			<g:charCodeRange minValue="3041" maxValue="3094"/>
+			<g:charCodeRange minValue="30a1" maxValue="30fa"/>
+			<g:charCodeRange minValue="3105" maxValue="312c"/>
+			<g:charCodeRange minValue="ac00" maxValue="d7a3"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="Ideographic" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-Ideographic" comment-id="xml-version" visible="false">
+		<g:charClass>
+			<g:charCodeRange minValue="4e00" maxValue="9fa5"/>
+			<g:charCode value="3007"/>
+			<g:charCodeRange minValue="3021" maxValue="3029"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="CombiningChar" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-CombiningChar" comment-id="xml-version" visible="false">
+		<g:charClass>
+			<g:charCodeRange minValue="0300" maxValue="0345"/>
+			<g:charCodeRange minValue="0360" maxValue="0361"/>
+			<g:charCodeRange minValue="0483" maxValue="0486"/>
+			<g:charCodeRange minValue="0591" maxValue="05a1"/>
+			<g:charCodeRange minValue="05a3" maxValue="05b9"/>
+			<g:charCodeRange minValue="05bb" maxValue="05bd"/>
+			<g:charCode value="05bf"/>
+			<g:charCodeRange minValue="05c1" maxValue="05c2"/>
+			<g:charCode value="05c4"/>
+			<g:charCodeRange minValue="064b" maxValue="0652"/>
+			<g:charCode value="0670"/>
+			<g:charCodeRange minValue="06d6" maxValue="06dc"/>
+			<g:charCodeRange minValue="06dd" maxValue="06df"/>
+			<g:charCodeRange minValue="06e0" maxValue="06e4"/>
+			<g:charCodeRange minValue="06e7" maxValue="06e8"/>
+			<g:charCodeRange minValue="06ea" maxValue="06ed"/>
+			<g:charCodeRange minValue="0901" maxValue="0903"/>
+			<g:charCode value="093c"/>
+			<g:charCodeRange minValue="093e" maxValue="094c"/>
+			<g:charCode value="094d"/>
+			<g:charCodeRange minValue="0951" maxValue="0954"/>
+			<g:charCodeRange minValue="0962" maxValue="0963"/>
+			<g:charCodeRange minValue="0981" maxValue="0983"/>
+			<g:charCode value="09bc"/>
+			<g:charCode value="09be"/>
+			<g:charCode value="09bf"/>
+			<g:charCodeRange minValue="09c0" maxValue="09c4"/>
+			<g:charCodeRange minValue="09c7" maxValue="09c8"/>
+			<g:charCodeRange minValue="09cb" maxValue="09cd"/>
+			<g:charCode value="09d7"/>
+			<g:charCodeRange minValue="09e2" maxValue="09e3"/>
+			<g:charCode value="0a02"/>
+			<g:charCode value="0a3c"/>
+			<g:charCode value="0a3e"/>
+			<g:charCode value="0a3f"/>
+			<g:charCodeRange minValue="0a40" maxValue="0a42"/>
+			<g:charCodeRange minValue="0a47" maxValue="0a48"/>
+			<g:charCodeRange minValue="0a4b" maxValue="0a4d"/>
+			<g:charCodeRange minValue="0a70" maxValue="0a71"/>
+			<g:charCodeRange minValue="0a81" maxValue="0a83"/>
+			<g:charCode value="0abc"/>
+			<g:charCodeRange minValue="0abe" maxValue="0ac5"/>
+			<g:charCodeRange minValue="0ac7" maxValue="0ac9"/>
+			<g:charCodeRange minValue="0acb" maxValue="0acd"/>
+			<g:charCodeRange minValue="0b01" maxValue="0b03"/>
+			<g:charCode value="0b3c"/>
+			<g:charCodeRange minValue="0b3e" maxValue="0b43"/>
+			<g:charCodeRange minValue="0b47" maxValue="0b48"/>
+			<g:charCodeRange minValue="0b4b" maxValue="0b4d"/>
+			<g:charCodeRange minValue="0b56" maxValue="0b57"/>
+			<g:charCodeRange minValue="0b82" maxValue="0b83"/>
+			<g:charCodeRange minValue="0bbe" maxValue="0bc2"/>
+			<g:charCodeRange minValue="0bc6" maxValue="0bc8"/>
+			<g:charCodeRange minValue="0bca" maxValue="0bcd"/>
+			<g:charCode value="0bd7"/>
+			<g:charCodeRange minValue="0c01" maxValue="0c03"/>
+			<g:charCodeRange minValue="0c3e" maxValue="0c44"/>
+			<g:charCodeRange minValue="0c46" maxValue="0c48"/>
+			<g:charCodeRange minValue="0c4a" maxValue="0c4d"/>
+			<g:charCodeRange minValue="0c55" maxValue="0c56"/>
+			<g:charCodeRange minValue="0c82" maxValue="0c83"/>
+			<g:charCodeRange minValue="0cbe" maxValue="0cc4"/>
+			<g:charCodeRange minValue="0cc6" maxValue="0cc8"/>
+			<g:charCodeRange minValue="0cca" maxValue="0ccd"/>
+			<g:charCodeRange minValue="0cd5" maxValue="0cd6"/>
+			<g:charCodeRange minValue="0d02" maxValue="0d03"/>
+			<g:charCodeRange minValue="0d3e" maxValue="0d43"/>
+			<g:charCodeRange minValue="0d46" maxValue="0d48"/>
+			<g:charCodeRange minValue="0d4a" maxValue="0d4d"/>
+			<g:charCode value="0d57"/>
+			<g:charCode value="0e31"/>
+			<g:charCodeRange minValue="0e34" maxValue="0e3a"/>
+			<g:charCodeRange minValue="0e47" maxValue="0e4e"/>
+			<g:charCode value="0eb1"/>
+			<g:charCodeRange minValue="0eb4" maxValue="0eb9"/>
+			<g:charCodeRange minValue="0ebb" maxValue="0ebc"/>
+			<g:charCodeRange minValue="0ec8" maxValue="0ecd"/>
+			<g:charCodeRange minValue="0f18" maxValue="0f19"/>
+			<g:charCode value="0f35"/>
+			<g:charCode value="0f37"/>
+			<g:charCode value="0f39"/>
+			<g:charCode value="0f3e"/>
+			<g:charCode value="0f3f"/>
+			<g:charCodeRange minValue="0f71" maxValue="0f84"/>
+			<g:charCodeRange minValue="0f86" maxValue="0f8b"/>
+			<g:charCodeRange minValue="0f90" maxValue="0f95"/>
+			<g:charCode value="0f97"/>
+			<g:charCodeRange minValue="0f99" maxValue="0fad"/>
+			<g:charCodeRange minValue="0fb1" maxValue="0fb7"/>
+			<g:charCode value="0fb9"/>
+			<g:charCodeRange minValue="20d0" maxValue="20dc"/>
+			<g:charCode value="20e1"/>
+			<g:charCodeRange minValue="302a" maxValue="302f"/>
+			<g:charCode value="3099"/>
+			<g:charCode value="309a"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="Digit" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-Digit" visible="false">
+		<g:charClass>
+			<g:charCodeRange minValue="0030" maxValue="0039"/>
+			<g:charCodeRange minValue="0660" maxValue="0669"/>
+			<g:charCodeRange minValue="06f0" maxValue="06f9"/>
+			<g:charCodeRange minValue="0966" maxValue="096f"/>
+			<g:charCodeRange minValue="09e6" maxValue="09ef"/>
+			<g:charCodeRange minValue="0a66" maxValue="0a6f"/>
+			<g:charCodeRange minValue="0ae6" maxValue="0aef"/>
+			<g:charCodeRange minValue="0b66" maxValue="0b6f"/>
+			<g:charCodeRange minValue="0be7" maxValue="0bef"/>
+			<g:charCodeRange minValue="0c66" maxValue="0c6f"/>
+			<g:charCodeRange minValue="0ce6" maxValue="0cef"/>
+			<g:charCodeRange minValue="0d66" maxValue="0d6f"/>
+			<g:charCodeRange minValue="0e50" maxValue="0e59"/>
+			<g:charCodeRange minValue="0ed0" maxValue="0ed9"/>
+			<g:charCodeRange minValue="0f20" maxValue="0f29"/>
+		</g:charClass>
+	</g:token>
+	<g:token name="Extender" inline="false" is-macro="yes" is-xml="yes" xhref="http://www.w3.org/TR/REC-xml#NT-Extender" comment-id="xml-version" visible="false">
+		<g:charClass>
+			<g:charCode value="00b7"/>
+			<g:charCode value="02d0"/>
+			<g:charCode value="02d1"/>
+			<g:charCode value="0387"/>
+			<g:charCode value="0640"/>
+			<g:charCode value="0e46"/>
+			<g:charCode value="0ec6"/>
+			<g:charCode value="3005"/>
+			<g:charCodeRange minValue="3031" maxValue="3035"/>
+			<g:charCodeRange minValue="309d" maxValue="309e"/>
+			<g:charCodeRange minValue="30fc" maxValue="30fe"/>
+		</g:charClass>
+	</g:token>
+
+	<g:token name="NotOperatorKeyword" skip="yes" show="no">
+      <g:oneOrMore name="NotOperatorKeywordSequence">
+			  <g:charClass>
+				  <g:charRange minChar="0" maxChar="9"/>
+				  <g:charRange minChar="a" maxChar="z"/>
+				  <g:charRange minChar="A" maxChar="Z"/>
+			  </g:charClass>
+      </g:oneOrMore>
+	</g:token>
+
+	<g:token name="NotNumber" skip="yes" show="no">
+		<g:choice name="DoubleStringNotNumber">
+			<g:sequence>
+				<g:string>.</g:string>
+				<g:ref name="Digits"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="Digits"/>
+				<g:optional name="DoubleOptionFractionPartNotNumber">
+					<g:string>.</g:string>
+					<g:zeroOrMore name="DoubleFractionPartNotNumber">
+						<g:charClass>
+							<g:charRange minChar="0" maxChar="9"/>
+						</g:charClass>
+					</g:zeroOrMore>
+				</g:optional>
+			</g:sequence>
+		</g:choice>
+    <g:optional name="NotNumberOptionalFractionPart">
+		  <g:charClass>
+			  <g:char>e</g:char>
+			  <g:char>E</g:char>
+		  </g:charClass>
+		  <g:optional name="DoubleNegOrPosNotNumber">
+			  <g:charClass>
+				  <g:char>+</g:char>
+				  <g:char>-</g:char>
+			  </g:charClass>
+		  </g:optional>
+      <g:ref name="Digits"/>
+    </g:optional>
+	  <g:charClass>
+			<g:charRange minChar="a" maxChar="z"/>
+			<g:charRange minChar="A" maxChar="Z"/>
+		</g:charClass>
+    <g:zeroOrMore name="NotNumberTail">
+			  <g:charClass>
+				  <g:charRange minChar="0" maxChar="9"/>
+				  <g:charRange minChar="a" maxChar="z"/>
+				  <g:charRange minChar="A" maxChar="Z"/>
+			  </g:charClass>
+    </g:zeroOrMore>
+	</g:token>
+
+
+	<!-- ================================================
+       These states define the lex-time disambiguations of tokens.  The are 
+       probably non-normative. 
+  ================================================ -->
+	<g:state-list>
+		<g:state name="ANY" show="no">
+			<g:description>This state is for very general patterns that can be 
+                recognized in any state, but are not recognized as significant
+                patterns by themselves in the grammar. </g:description>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="WhitespaceChar"/>
+				<g:tref name="Nmstart"/>
+				<g:tref name="NCName"/>
+				<g:tref name="Char"/>
+				<g:tref name="Nmchar"/>
+				<g:tref name="Prefix"/>
+				<g:tref name="LocalPart"/>
+				<g:tref name="Digits"/>
+				<g:tref name="Letter"/>
+				<g:tref name="BaseChar"/>
+				<g:tref name="Ideographic"/>
+				<g:tref name="CombiningChar"/>
+				<g:tref name="Digit"/>
+				<g:tref name="Extender"/>
+				<g:tref name="HexDigits"/>
+				<g:tref name="ValidationMode" if="xquery core"/>
+				<g:tref name="Pragma"/>
+				<g:tref name="MUExtension"/>
+				<g:tref name="Comment"/>
+        <g:tref name="ExtensionContents"/>
+        <g:tref name="CommentContents"/>
+        <!-- g:tref name="SForExt"/ -->
+			</g:transition>
+		</g:state>
+		<!-- g:state name="DUMMY" show="no">
+			<g:description>XXX </g:description>
+			<g:transition next-state="OPERATOR">
+				<g:transition-default/>
+				<g:tref name="SchemaGlobalContext"/>
+				<g:tref name="SchemaContextStep"/>
+			</g:transition>
+		</g:state -->
+		<g:state name="DEFAULT">
+			<g:description>This state is for patterns that occur at the beginning 
+                of an expression or subexpression.</g:description>
+			<g:transition next-state="OPERATOR">
+				<g:transition-default/>
+				<g:tref name="DecimalLiteral"/>
+				<g:tref name="DotDot"/>
+				<g:tref name="Dot"/>
+				<g:tref name="DoubleLiteral"/>
+				<g:tref name="IntegerLiteral"/>
+        <g:tref name="NotNumber"/>
+				<g:tref name="NCNameColonStar"/>
+				<g:tref name="QName"/>
+				<g:tref name="Rpar"/>
+				<g:tref name="StarColonNCName"/>
+				<g:tref name="Star"/>
+				<g:tref name="StringLiteral"/>
+				<g:tref name="DeclareConstruction"/>
+        <g:tref name="DeclareOrdering"/>
+        <g:tref name="DeclareDefaultOrderingEmpty"/>
+        <g:tref name="DeclareInheritNamespaces"/>
+			</g:transition>
+			<g:transition next-state="NAMESPACEDECL">
+				<g:tref name="DeclareCollation"/>
+				<g:tref name="DeclareNamespace"/>
+				<g:tref name="DeclareBaseURI"/>
+				<g:tref name="ModuleNamespace"/>
+			</g:transition>
+			<g:transition next-state="NAMESPACEKEYWORD">
+				<g:tref name="DeclareDefaultElement"/>
+				<g:tref name="DeclareDefaultFunction"/>
+				<g:tref name="ImportSchemaToken"/>
+				<g:tref name="ImportModuleToken"/>
+			</g:transition>
+			<g:transition next-state="VARNAME">
+				<g:tref name="VariableIndicator"/>
+				<g:tref name="ForVariable"/>
+				<g:tref name="LetVariable"/>
+				<g:tref name="Some"/>
+				<g:tref name="Every"/>
+			</g:transition>
+			<g:transition next-state="VARNAME">
+				<g:tref name="DefineVariable"/>
+			</g:transition>
+			<g:transition next-state="ITEMTYPE">
+				<g:tref name="RparAs"/>
+			</g:transition>
+			<g:transition next-state="KINDTEST" action="pushState(OPERATOR)">
+				<g:tref name="ElementType"/>
+				<g:tref name="AttributeType"/>
+				<g:tref name="SchemaElementType"/>
+				<g:tref name="SchemaAttributeType"/>
+				<g:tref name="CommentLpar"/>
+				<g:tref name="TextLpar"/>
+				<g:tref name="NodeLpar"/>
+				<g:tref name="DocumentLpar"/>
+			</g:transition>
+			<g:transition next-state="KINDTESTFORPI" action="pushState(OPERATOR)">
+				<g:tref name="ProcessingInstructionLpar"/>
+			</g:transition>
+			<g:transition next-state="XML_COMMENT" action="pushState(OPERATOR)">
+				<g:tref name="XmlCommentStart"/>
+			</g:transition>
+			<g:transition next-state="PROCESSING_INSTRUCTION" action="pushState(OPERATOR)">
+				<g:tref name="ProcessingInstructionStart"/>
+			</g:transition>
+			<g:transition next-state="CDATA_SECTION" action="pushState(OPERATOR)">
+				<g:tref name="CdataSectionStart"/>
+			</g:transition>
+			<g:transition next-state="START_TAG" action="pushState(OPERATOR)">
+				<g:tref name="StartTagOpenRoot"/>
+			</g:transition>
+			<g:transition next-state="XMLSPACE_DECL">
+				<g:tref name="DeclareXMLSpace"/>
+			</g:transition>
+			<g:transition action="popState">
+				<g:tref name="Rbrace"/>
+			</g:transition>
+			<g:transition action="pushState(OPERATOR)" next-state="DEFAULT">
+				<g:tref name="ValidateLbrace"/>
+        <g:tref name="ValidateSchemaMode"/>
+			</g:transition>
+			<!-- g:transition next-state="DEFAULT">
+				<g:tref name="ValidateGlobal"/>
+			</g:transition -->
+			<g:transition next-state="DEFAULT">
+				<g:tref name="TypeswitchLpar"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(1); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateOpenUpdateList"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(3); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadFor"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(3); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadLet"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(2); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadIf"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(6); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadInsert"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(7); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadReplace"/>
+			</g:transition>
+			<g:transition next-state="UPDATE" action="input_stream.backup(6); pushState(UPDATE)" if="update">
+				<g:tref name="UpdateLookaheadDelete"/>
+			</g:transition>
+			<g:transition action="pushState(OPERATOR)" next-state="DEFAULT">
+				<g:tref name="ElementLbrace"/>
+				<g:tref name="AttributeLbrace"/>
+			</g:transition>
+			<g:transition action="pushState(OPERATOR)">
+				<g:tref name="AttributeQNameLbrace"/>
+				<!-- g:tref name="NamespaceNCNameLbrace"/ -->
+				<g:tref name="ElementQNameLbrace"/>
+				<g:tref name="DocumentLbrace"/>
+				<g:tref name="TextLbrace"/>
+				<g:tref name="PILbrace"/>
+				<g:tref name="PINCNameLbrace"/>
+				<g:tref name="CommentLbrace"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="DefineFunction"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+			<!-- g:transition action="if(isState(UPDATE)) SwitchTo(UPDATE); else SwitchTo(DEFAULT)"-->
+			<g:transition next-state="DEFAULT" action="pushState(OPERATOR)">
+				<g:tref name="LbraceExprEnclosure"/>
+        <g:tref name="OrderedOpen" if="xquery core"/>
+        <g:tref name="UnorderedOpen" if="xquery core"/>
+			</g:transition>
+      <g:transition next-state="XQUERYVERSION" if="xquery core">
+        <g:tref name="XQueryVersion" if="xquery core"/>
+      </g:transition>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="SemiColon"/>
+        <g:tref name="QuerySeparator" if="xquery core" show="no"/>
+        <g:tref name="Comma"/>
+        <g:tref name="AtStringLiteral"/>
+        <g:tref name="Lpar"/>
+        <g:tref name="QNameLpar"/>
+        <g:tref name="IfLpar"/>
+				<g:tref name="UnaryMinus"/>
+				<g:tref name="UnaryPlus"/>
+				<g:tref name="RootDescendants"/>
+				<g:tref name="Root"/>
+				<g:tref name="AxisAncestorOrSelf"/>
+				<g:tref name="AxisAncestor"/>
+				<g:tref name="AxisAttribute"/>
+				<g:tref name="AxisChild"/>
+				<g:tref name="AxisDescendantOrSelf"/>
+				<g:tref name="AxisDescendant"/>
+				<g:tref name="AxisFollowingSibling"/>
+				<g:tref name="AxisFollowing"/>
+				<g:tref name="AxisNamespace" if="xpath core"/>
+				<g:tref name="AxisParent"/>
+				<g:tref name="AxisPrecedingSibling"/>
+				<g:tref name="AxisPreceding"/>
+				<g:tref name="AxisSelf"/>
+        <g:tref name="At"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="IDLpar"/>
+				<g:tref name="KeyLpar"/>
+				<g:tref name="Type"/>
+				<!-- Do we need this??? -->
+				<g:tref name="ValueOf" if="update"/>
+			</g:transition>
+		</g:state>
+		<g:state name="OPERATOR">
+			<g:description>This state is for patterns that are defined for 
+                operators. </g:description>
+			<g:transition next-state="UPDATE" if="update">
+				<g:tref name="Do"/>
+			</g:transition>
+			<!-- g:transition action="if(isState(UPDATE)) SwitchTo(UPDATE); else SwitchTo(DEFAULT)" -->
+			<g:transition next-state="DEFAULT" action="pushState(OPERATOR)">
+				<!-- action correct?? -->
+				<g:tref name="LbraceExprEnclosure"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="SemiColon"/>
+				<g:tref name="Then"/>
+				<g:tref name="Else"/>
+				<g:tref name="External"/>
+				<g:tref name="And"/>
+				<!-- g:tref name="AtStringLiteral"/ *** -->
+				<g:tref name="AtWord"/>
+				<g:tref name="ColonEquals"/>
+				<g:tref name="Comma"/>
+				<g:tref name="Div"/>
+				<g:tref name="Equals"/>
+				<g:tref name="Except"/>
+				<g:tref name="FortranEq"/>
+				<g:tref name="FortranGe"/>
+				<g:tref name="FortranGt"/>
+				<g:tref name="FortranLe"/>
+				<g:tref name="FortranLt"/>
+				<g:tref name="FortranNe"/>
+				<g:tref name="GtEquals"/>
+				<g:tref name="GtGt"/>
+				<g:tref name="Gt"/>
+				<g:tref name="Idiv"/>
+				<g:tref name="Intersect"/>
+				<g:tref name="In"/>
+				<g:tref name="Is"/>
+				<g:tref name="Lbrack"/>
+				<g:tref name="LtEquals"/>
+				<g:tref name="LtLt"/>
+				<g:tref name="Lt"/>
+				<g:tref name="Minus"/>
+				<g:tref name="Mod"/>
+				<g:tref name="Multiply"/>
+				<g:tref name="NotEquals"/>
+				<g:tref name="OrderBy"/>
+				<g:tref name="OrderByStable"/>
+				<g:tref name="Or"/>
+				<g:tref name="Plus"/>
+				<g:tref name="Return"/>
+				<g:tref name="Satisfies"/>
+				<g:tref name="QuerySeparator" if="xquery core" show="no"/>
+				<g:tref name="SlashSlash"/>
+				<g:tref name="Slash"/>
+				<g:tref name="To"/>
+				<g:tref name="Type"/>
+				<g:tref name="Union"/>
+				<g:tref name="Vbar"/>
+				<g:tref name="Where"/>
+				<g:tref name="SchemaModeForDeclareConstruction"/>
+        <g:tref name="Ordered"/>
+        <g:tref name="Unordered"/>
+        <g:tref name="Yes"/>
+        <g:tref name="No"/>
+				<g:tref name="Into" if="update"/>
+				<g:tref name="After" if="update"/>
+				<g:tref name="Before" if="update"/>
+				<g:tref name="With" if="update"/>
+			</g:transition>
+			<g:transition next-state="SINGLETYPE">
+				<g:tref name="Castable"/>
+				<g:tref name="CastAs"/>
+			</g:transition>
+			<g:transition next-state="ITEMTYPE">
+				<g:tref name="Instanceof"/>
+				<g:tref name="TreatAs"/>
+				<g:tref name="Case"/>
+				<g:tref name="As"/>
+				<!-- tref name="DeclareResult"/ -->
+				<g:tref name="RparAs"/>
+			</g:transition>
+			<g:transition action="popState">
+				<g:tref name="Rbrace"/>
+			</g:transition>
+			<g:transition next-state="VARNAME">
+				<g:tref name="VariableIndicator"/>
+				<g:tref name="ForVariable"/>
+				<g:tref name="LetVariable"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+      <g:transition next-state="OPERATOR">
+        <g:tref name="Rpar"/>
+        <g:tref name="OccurrenceZeroOrOne"/>
+				<g:tref name="EmptyGreatest"/>
+				<g:tref name="EmptyLeast"/>
+				<g:tref name="Ascending"/>
+				<g:tref name="Descending"/>
+				<g:tref name="Collation"/>
+        <g:tref name="Default"/>
+        <g:tref name="Rbrack"/>
+      </g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:transition-default/>
+				<!-- anything else in the operator state -->
+				<g:tref name="StringLiteral"/>
+				<g:tref name="AsLast" if="update"/>
+				<g:tref name="AsFirst" if="update"/>
+        <g:tref name="NotOperatorKeyword"/>
+			</g:transition>
+		</g:state>
+		<!-- start update proposal states -->
+		<g:state name="UPDATE" if="update">
+			<g:description>[To Be Done]</g:description>
+			<g:transition next-state="VARNAME">
+				<g:tref name="ForVariable"/>
+				<g:tref name="LetVariable"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="InsertTok"/>
+				<g:tref name="ReplaceTok"/>
+				<g:tref name="DeleteTok"/>
+				<g:tref name="IfLpar"/>
+				<g:tref name="QuerySeparator" if="xquery core" show="no"/>
+			</g:transition>
+			<g:transition>
+				<g:tref name="UpdateTok"/>
+				<g:tref name="UpdateListOpen"/>
+				<g:tref name="UpdateListClose"/>
+				<g:tref name="UpdateListSep"/>
+			</g:transition>
+		</g:state>
+		<!-- end update proposal states -->
+		<g:state name="XQUERYVERSION" if="xquery core">
+       <g:description>This state is for recognition of XQuery version 
+                      specific keywords.</g:description>
+
+      <g:transition next-state="DEFAULT" if="xquery core">
+        <g:tref name="SemiColon"/>
+      </g:transition>
+
+			<g:transition next-state="XQUERYVERSION" if="xquery core">
+				<g:tref name="StringLiteralForVersion"/>
+        <g:tref name="XQueryEncoding"/>
+      </g:transition>
+		</g:state>
+		<g:state name="NAMESPACEDECL" if="xquery core">
+			<g:description>This state occurs inside of a namespace declaration, and 
+                is needed to recognize a NCName that is to be used as the prefix, 
+                as opposed to allowing a QName to occur. (Otherwise, the difference 
+                between NCName and QName are ambiguous.) </g:description>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="URLLiteral"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+			<g:transition next-state="NAMESPACEDECL">
+				<g:tref name="AssignEquals"/>
+				<g:tref name="NCNameForPrefix"/>
+			</g:transition>
+		</g:state>
+		<g:state name="NAMESPACEKEYWORD" if="xquery core">
+			<g:description>This state occurs at places where the keyword 
+                "namespace" is expected, which would otherwise be ambiguous 
+                compared to a QName. QNames can not occur in this state. 
+                </g:description>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="URLLiteral"/>
+			</g:transition>
+			<g:transition next-state="NAMESPACEDECL">
+				<g:tref name="Namespace"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+			<g:transition next-state="NAMESPACEKEYWORD">
+				<g:tref name="DefaultElement"/>
+			</g:transition>
+		</g:state>
+		<g:state name="XMLSPACE_DECL" if="xquery core">
+			<g:description>This state occurs at places where the keywords 
+                "preserve" and "strip" is expected to support "declare xmlspace". 
+                QNames can not occur in this state. </g:description>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="XMLSpacePreserve"/>
+				<g:tref name="XMLSpaceStrip"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+		</g:state>
+		<g:state name="SINGLETYPE">
+			<g:description>This state distinguishes tokens that can occur only 
+                inside the SingleType production. </g:description>
+			<g:transition next-state="OPERATOR">
+				<g:tref name="QNameForAtomicType"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+		</g:state>
+		<g:state name="ITEMTYPE">
+			<g:description>This state distinguishes tokens that can occur only 
+                inside the ItemType production. </g:description>
+			<!-- to support the case statement. -->
+			<g:transition next-state="VARNAME" if="xquery core">
+				<g:tref name="VariableIndicator"/>
+			</g:transition>
+			<g:transition next-state="OPERATOR">
+				<g:tref name="EmptyTok"/>
+        <g:tref name="QNameForAtomicType"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+			<g:transition next-state="KINDTEST" action="pushState(OCCURRENCEINDICATOR)">
+				<g:tref name="ElementTypeForKindTest"/>
+				<g:tref name="AttributeTypeForKindTest"/>
+				<g:tref name="SchemaElementTypeForKindTest"/>
+				<g:tref name="SchemaAttributeTypeForKindTest"/>
+				<g:tref name="CommentLparForKindTest"/>
+				<g:tref name="TextLparForKindTest"/>
+				<g:tref name="NodeLparForKindTest"/>
+				<g:tref name="DocumentLparForKindTest"/>
+			</g:transition>
+			<g:transition next-state="KINDTESTFORPI" action="pushState(OCCURRENCEINDICATOR)">
+				<g:tref name="ProcessingInstructionLparForKindTest"/>
+			</g:transition>
+			<g:transition next-state="OCCURRENCEINDICATOR">
+				<g:tref name="QNameForSequenceType"/>
+				<g:tref name="Item"/>
+			</g:transition>
+			<!-- g:transition action="if(isState(UPDATE)) SwitchTo(UPDATE); else SwitchTo(DEFAULT)" -->
+			<g:transition next-state="DEFAULT">
+				<g:tref name="SemiColon"/>
+				<g:tref name="Then"/>
+				<g:tref name="Else"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT">
+				<g:tref name="External"/>
+				<g:tref name="And"/>
+				<g:tref name="AtStringLiteral"/>
+				<g:tref name="AtWord"/>
+				<g:tref name="ColonEquals"/>
+				<g:tref name="Comma"/>
+				<g:tref name="Div"/>
+				<g:tref name="Equals"/>
+				<g:tref name="Except"/>
+				<g:tref name="FortranEq"/>
+				<g:tref name="FortranGe"/>
+				<g:tref name="FortranGt"/>
+				<g:tref name="FortranLe"/>
+				<g:tref name="FortranLt"/>
+				<g:tref name="FortranNe"/>
+				<g:tref name="GtEquals"/>
+				<g:tref name="GtGt"/>
+				<g:tref name="Gt"/>
+				<g:tref name="Idiv"/>
+				<g:tref name="Intersect"/>
+				<g:tref name="In"/>
+				<g:tref name="Is"/>
+				<g:tref name="Lbrack"/>
+				<g:tref name="Lpar"/>
+				<g:tref name="LtEquals"/>
+				<g:tref name="LtLt"/>
+				<g:tref name="Lt"/>
+				<g:tref name="Minus"/>
+				<g:tref name="Mod"/>
+				<g:tref name="NotEquals"/>
+				<g:tref name="OrderBy"/>
+				<g:tref name="OrderByStable"/>
+				<g:tref name="Or"/>
+				<g:tref name="Return"/>
+				<g:tref name="Satisfies"/>
+				<g:tref name="To"/>
+				<g:tref name="Type"/>
+				<g:tref name="Union"/>
+				<g:tref name="Vbar"/>
+				<g:tref name="Where"/>
+			</g:transition>
+			<g:transition next-state="SINGLETYPE">
+				<g:tref name="Castable"/>
+				<g:tref name="CastAs"/>
+			</g:transition>
+			<g:transition next-state="ITEMTYPE">
+				<g:tref name="Instanceof"/>
+				<g:tref name="TreatAs"/>
+				<g:tref name="Case"/>
+				<g:tref name="As"/>
+				<g:tref name="RparAs"/>
+			</g:transition>
+		</g:state>
+		<g:state name="KINDTEST">
+			<g:transition next-state="DEFAULT" action="pushState(OPERATOR)">
+				<g:tref name="LbraceExprEnclosure"/>
+			</g:transition>
+			<!-- g:transition next-state="SCHEMACONTEXTSTEP">
+				<g:tref name="SchemaGlobalContextSlash"/>
+				<!- - g:tref name="SchemaGlobalTypeName"/ - ->
+			</g:transition -->
+			<g:transition action="popState">
+				<g:tref name="RparForKindTest"/>
+			</g:transition>
+			<g:transition next-state="CLOSEKINDTEST">
+				<g:tref name="AnyName"/>
+				<g:tref name="QNameForItemType"/>
+			</g:transition>
+			<g:transition next-state="KINDTEST" action="pushState(KINDTEST)">
+				<g:tref name="ElementTypeForDocumentTest"/>
+				<g:tref name="SchemaElementTypeForDocumentTest"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+		</g:state>
+		<g:state name="KINDTESTFORPI">
+			<g:transition action="popState">
+				<g:tref name="RparForKindTest"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+      <g:transition next-state="KINDTESTFORPI">
+        <g:tref name="NCNameForPI"/>
+        <g:tref name="StringLiteralForKindTest"/>
+      </g:transition>
+		</g:state>
+		<g:state name="CLOSEKINDTEST">
+			<g:transition action="popState">
+				<g:tref name="RparForKindTest"/>
+			</g:transition>
+			<g:transition next-state="KINDTEST">
+				<g:tref name="CommaForKindTest"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT" action="pushState(OPERATOR)">
+				<g:tref name="LbraceExprEnclosure"/>
+			</g:transition>
+			<g:transition next-state="CLOSEKINDTEST">
+				<g:tref name="Nillable"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+		</g:state>
+		<g:state name="OCCURRENCEINDICATOR">
+      <g:description>This special state is needed to distinguish occurrence indicators that appear in the SequenceType production.  For instance, compare "foo instance of baz*" to  "baz*foo".  In the first case, the "*" is interpreted as an occurrence indicator, and in the second case, it must be interpreted as a multiplication operator.  But, when in the OCCURRENCEINDICATOR state, if anything else other than "?", "*", and "+", those symbols must be interpreted in the OPERATOR state.  For instance, this would occur with the expression "foo instance of baz and $x", with the operator "and".  This backing up of the lexical characters in order to reset the state, is symbolized by the notation "input_stream.backup(1)". NotOccurrenceIndicator is a special symbol for any character that is not an occurrence indicator.</g:description>
+			<g:transition next-state="OPERATOR" action="input_stream.backup(1)">
+				<g:tref name="NotOccurrenceIndicator"/>
+			</g:transition>
+			<g:transition next-state="OPERATOR">
+				<g:tref name="OccurrenceZeroOrOne"/>
+				<g:tref name="OccurrenceZeroOrMore"/>
+				<g:tref name="OccurrenceOneOrMore"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+		</g:state>
+		<!-- g:state name="SCHEMACONTEXTSTEP">
+			<g:description>This state distinguishes the SchemaContextStep from the 
+                SchemaGlobalContext. </g:description>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="SchemaContextStepSlash"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT" action="pushState(OPERATOR)">
+				<g:tref name="LbraceExprEnclosure"/>
+			</g:transition>
+			<g:transition next-state="CLOSEKINDTEST">
+				<g:tref name="QNameForItemType"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+		</g:state -->
+		<g:state name="VARNAME">
+			<g:description>This state differentiates variable names from qualified 
+                names. This allows only the pattern of a QName to be recognized 
+                when otherwise ambiguities could occur. </g:description>
+			<g:transition next-state="OPERATOR">
+				<g:tref name="VarName"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+		</g:state>
+		<g:state name="START_TAG" if="xquery core">
+			<g:description>This state allows attributes in the native XML syntax, 
+                and marks the beginning of an element construction. Element 
+                constructors also push the current state, popping it at the 
+                conclusion of an end tag. In the START_TAG state, the string ">" is 
+                recognized as a token which is associated with the transition to 
+                the original state. </g:description>
+			<g:transition action="popState">
+				<g:tref name="EmptyTagClose"/>
+			</g:transition>
+			<g:transition next-state="ELEMENT_CONTENT">
+				<g:tref name="StartTagClose"/>
+			</g:transition>
+			<g:transition next-state="QUOT_ATTRIBUTE_CONTENT">
+				<g:tref name="OpenQuot"/>
+			</g:transition>
+			<g:transition next-state="APOS_ATTRIBUTE_CONTENT">
+				<g:tref name="OpenApos"/>
+			</g:transition>
+			<g:transition next-state="START_TAG">
+				<g:tref name="ValueIndicator"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="S"/>
+				<g:tref name="TagQName"/>
+			</g:transition>
+		</g:state>
+		<g:state name="ELEMENT_CONTENT" if="xquery core">
+			<g:description>This state allows XML-like content, without these 
+                characters being misinterpreted as expressions. The character "{" 
+                marks a transition to the DEFAULT state, i.e. the start of an 
+                embedded expression, and the "}" character pops back to the 
+                ELEMENT_CONTENT state. To allow curly braces to be used as 
+                character content, a double left or right curly brace is 
+                interpreted as a single curly brace character. The string "&lt;/" 
+                is interpreted as the beginning of an end tag, which is associated 
+                with a transition to the END_TAG state.</g:description>
+			<g:transition next-state="END_TAG">
+				<g:tref name="EndTagOpen"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT" action="pushState">
+				<g:description>Transition to an Element Value 
+                    Template.</g:description>
+				<g:tref name="Lbrace"/>
+			</g:transition>
+			<g:transition next-state="XML_COMMENT" action="pushState">
+				<g:tref name="XmlCommentStartForElementContent"/>
+			</g:transition>
+			<g:transition next-state="PROCESSING_INSTRUCTION" action="pushState">
+				<g:tref name="ProcessingInstructionStartForElementContent"/>
+			</g:transition>
+			<g:transition next-state="CDATA_SECTION" action="pushState">
+				<g:tref name="CdataSectionStartForElementContent"/>
+			</g:transition>
+			<g:transition next-state="START_TAG" action="pushState">
+				<g:tref name="StartTagOpen"/>
+			</g:transition>
+			<g:transition next-state="ELEMENT_CONTENT">
+				<g:tref name="ElementContentChar"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="PredefinedEntityRef" if="xquery core"/>
+				<g:tref name="CharRef" if="xquery core"/>
+				<g:tref name="LCurlyBraceEscape" if="xquery core"/>
+				<g:tref name="RCurlyBraceEscape" if="xquery core"/>
+			</g:transition>
+		</g:state>
+		<g:state name="END_TAG" if="xquery core">
+			<g:description>When the end tag is terminated, the state is popped to 
+                the state that was pushed at the start of the corresponding start 
+                tag.</g:description>
+			<g:transition action="popState">
+				<g:tref name="EndTagClose"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="S"/>
+				<g:tref name="TagQName"/>
+			</g:transition>
+		</g:state>
+		<g:state name="XML_COMMENT" if="xquery core">
+			<g:description>The "&lt;--" token marks the beginning of an XML 
+                Comment, and the "-->" token marks the end. This allows no special 
+                interpretation of other characters in this state.</g:description>
+			<g:transition action="popState">
+				<g:tref name="XmlCommentEnd"/>
+			</g:transition>
+			<g:transition next-state="XML_COMMENT">
+				<g:tref name="CommentContentChar"/>
+        <g:tref name="CommentContentCharDash"/>
+			</g:transition>
+		</g:state>
+		<g:state name="EXPR_COMMENT">
+			<g:description>The "(:" token marks the beginning of an expression 
+                Comment, and the ":)" token marks the end. This allows no special 
+                interpretation of other characters in this state.</g:description>
+			<g:transition action="popState">
+				<g:tref name="CommentEnd"/>
+			</g:transition>
+			<g:transition next-state="EXPR_COMMENT" action="pushState">
+				<g:tref name="CommentStart"/>
+			</g:transition>
+			<g:transition next-state="EXT_KEY" action="pushState">
+				<g:tref name="ExtensionStart"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="CommentContent"/>
+			</g:transition>
+		</g:state>
+		<g:state name="EXT_CONTENT" if="xquery">
+			<g:description>This state occurs for the content of must-understand 
+                extension.</g:description>
+			<g:transition action="popState">
+				<g:tref name="ExtensionEnd"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="ExtensionContentChar"/>
+        <g:tref name="SForExt"/>
+			</g:transition>
+		</g:state>
+		<g:state name="EXT_KEY" if="xquery">
+			<g:description>The "(::" token marks the beginning of an expression 
+                extension, which must be followed by a keyword.</g:description>
+			<g:transition next-state="EXT_NAME">
+				<g:description>No state change.</g:description>
+				<g:tref name="PragmaKeyword"/>
+				<g:tref name="Extension"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="SForExt"/>
+			</g:transition>
+		</g:state>
+		<g:state name="EXT_NAME" if="xquery">
+			<g:description>This state recognizes extension names and transitions to 
+                the extension content state.</g:description>
+			<g:transition next-state="EXT_CONTENT">
+				<g:tref name="ExtensionQName"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="SForExt"/>
+			</g:transition>
+		</g:state>
+		<g:state name="PROCESSING_INSTRUCTION" if="xquery core">
+			<g:description>In this state, only patterns that are legal in a 
+                processing instruction name are recognized.</g:description>
+			<g:transition next-state="PROCESSING_INSTRUCTION_CONTENT">
+				<g:tref name="SForPI"/>
+			</g:transition>
+			<g:transition action="popState">
+				<g:tref name="ProcessingInstructionEnd"/>
+			</g:transition>
+			<g:transition next-state="PROCESSING_INSTRUCTION">
+				<g:tref name="PITarget"/>
+			</g:transition>
+		</g:state>
+		<g:state name="PROCESSING_INSTRUCTION_CONTENT" if="xquery core">
+			<g:description>In this state, only characters are that are legal in 
+                processing instruction content are recognized.</g:description>
+			<g:transition action="popState">
+				<g:tref name="ProcessingInstructionEnd"/>
+			</g:transition>
+			<g:transition next-state="PROCESSING_INSTRUCTION_CONTENT">
+				<g:tref name="PIContentChar"/>
+			</g:transition>
+		</g:state>
+		<g:state name="CDATA_SECTION" if="xquery core">
+			<g:description>In this state, only lexemes that are legal in a CDATA 
+                section are recognized.</g:description>
+			<g:transition action="popState">
+				<g:tref name="CdataSectionEnd"/>
+			</g:transition>
+			<g:transition next-state="CDATA_SECTION">
+				<g:tref name="CDataSectionChar"/>
+			</g:transition>
+		</g:state>
+		<g:state name="QUOT_ATTRIBUTE_CONTENT" if="xquery core">
+			<g:description>This state allows content legal for attributes. The 
+                character "{" marks a transition to the DEFAULT state, i.e. the 
+                start of an embedded expression, and the "}" character pops back to 
+                the original state. To allow curly braces to be used as character 
+                content, a double left or right curly brace is interpreted as a 
+                single curly brace character. This state is the same as 
+                APOS_ATTRIBUTE_CONTENT, except that apostrophes are allowed without 
+                escaping, and an unescaped quote marks the end of the 
+                state.</g:description>
+			<g:transition next-state="START_TAG">
+				<g:tref name="CloseQuot"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT" action="pushState">
+				<g:description>Transition to an Attribute Value 
+                    Template.</g:description>
+				<g:tref name="Lbrace"/>
+			</g:transition>
+		  <g:transition next-state="QUOT_ATTRIBUTE_CONTENT">
+        <g:tref name="EscapeQuot"/>
+        <g:tref name="QuotAttrContentChar"/>
+      </g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="PredefinedEntityRef" if="xquery core"/>
+				<g:tref name="CharRef" if="xquery core"/>
+				<g:tref name="LCurlyBraceEscape" if="xquery core"/>
+				<g:tref name="RCurlyBraceEscape" if="xquery core"/>
+			</g:transition>
+		</g:state>
+		<!-- ================== -->
+		<g:state name="APOS_ATTRIBUTE_CONTENT" if="xquery core">
+			<g:description>This state is the same as QUOT_ATTRIBUTE_CONTENT, except 
+                that quotes are allowed, and an unescaped apostrophe marks the end 
+                of the state.</g:description>
+			<g:transition next-state="START_TAG">
+				<g:tref name="CloseApos"/>
+			</g:transition>
+			<g:transition next-state="DEFAULT" action="pushState">
+				<g:description>Transition to an Attribute Value 
+                    Template.</g:description>
+				<g:tref name="Lbrace"/>
+			</g:transition>
+			<g:transition next-state="APOS_ATTRIBUTE_CONTENT">
+				<g:tref name="EscapeApos"/>
+        <g:tref name="AposAttrContentChar"/>
+			</g:transition>
+			<g:transition>
+				<g:description>No state change.</g:description>
+				<g:tref name="PredefinedEntityRef" if="xquery core"/>
+				<g:tref name="CharRef" if="xquery core"/>
+				<g:tref name="LCurlyBraceEscape" if="xquery core"/>
+				<g:tref name="RCurlyBraceEscape" if="xquery core"/>
+			</g:transition>
+		</g:state>
+	</g:state-list>
+	<!-- ====================== Grammar Productions ==================== -->
+	<!-- The QueryList production is  not in the official grammar, 
+       and is not shown in the bnf.  It is here only for the purpose 
+       of testing a series of queries. 
+    -->
+	<g:production name="QueryList" if="xquery core" show="no">
+		<g:ref name="Module"/>
+		<g:zeroOrMore name="QueryListTail">
+			<g:ref name="QuerySeparator"/>
+			<g:optional name="OptionalModule">
+				<g:ref name="Module"/>
+			</g:optional>
+		</g:zeroOrMore>
+	</g:production>
+	
+	<g:production name="XPath" if="xpath">
+		<!--<g:optional name="XPathOptionalExpr">-->
+			<g:ref name="Expr"/>
+		<!--</g:optional>-->
+	</g:production>
+	
+	<!-- START PROLOG -->
+
+	<!-- ### Use the name="" names instead of Expr_1() for generated .jj code -->
+	<g:production name="Module" if="xquery core">
+		<g:optional name="OptionalVersionDecl">
+			<g:ref name="VersionDecl"/>
+		</g:optional>
+		<g:choice name="MainOrLibraryModule">
+			<g:ref name="MainModule"/>
+			<g:ref name="LibraryModule"/>
+		</g:choice>
+	</g:production>
+	<g:production name="VersionDecl" if="xquery core">
+		<g:ref name="XQueryVersion"/>
+    <g:ref name="StringLiteralForVersion"/>
+    <g:optional name="OptionalEncodingSpec">
+      <g:ref name="XQueryEncoding"/>
+      <g:ref name="StringLiteralForVersion"/>
+    </g:optional>
+		<g:ref name="Separator"/>
+	</g:production>
+	<g:production name="MainModule" if="xquery core">
+		<g:ref name="Prolog"/>
+		<g:ref name="QueryBody"/>
+	</g:production>
+	<g:production name="LibraryModule" if="xquery core">
+		<g:ref name="ModuleDecl"/>
+		<g:ref name="Prolog"/>
+	</g:production>
+	<g:production name="ModuleDecl" if="xquery core">
+		<g:ref name="ModuleNamespace"/>
+		<g:ref name="NCNameForPrefix"/>
+		<g:ref name="AssignEquals"/>
+		<g:ref name="URLLiteral"/>
+		<g:ref name="Separator"/>
+	</g:production>
+	<g:production name="Prolog" if="xquery core">
+		<g:zeroOrMore name="SetterList">
+			<g:ref name="Setter"/>
+			<g:ref name="Separator"/>
+		</g:zeroOrMore>
+		<g:zeroOrMore name="DeclList">
+			<g:choice name="DeclChoice">
+				<g:ref name="Import"/>
+				<g:ref name="NamespaceDecl"/>
+        <g:ref name="DefaultNamespaceDecl"/>
+			</g:choice>
+			<g:ref name="Separator"/>
+		</g:zeroOrMore>
+		<g:zeroOrMore name="FunctionsAndVarsList">
+			<g:choice name="FunctionOrVar">
+				<g:ref name="VarDecl"/>
+				<g:ref name="FunctionDecl"/>
+			</g:choice>
+			<g:ref name="Separator"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="Setter" if="xquery core">
+		<g:choice name="SetterChoice">
+			<g:ref name="XMLSpaceDecl" if="xquery"/>
+			<g:ref name="DefaultCollationDecl"/>
+			<g:ref name="BaseURIDecl"/>
+			<g:ref name="ConstructionDecl"/>
+			<!-- g:ref name="DefaultNamespaceDecl"/ -->
+      <g:ref name="OrderingModeDecl"/>
+      <g:ref name="EmptyOrderingDecl"/>
+      <g:ref name="InheritNamespacesDecl"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Import" if="xquery core">
+		<g:choice name="Imports">
+			<g:ref name="SchemaImport"/>
+			<g:ref name="ModuleImport"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Separator" if="xquery core">
+		<g:ref name="SemiColon"/>
+	</g:production>
+	<g:production name="NamespaceDecl" if="xquery core">
+		<g:ref name="DeclareNamespace"/>
+		<g:ref name="NCNameForPrefix"/>
+		<g:ref name="AssignEquals"/>
+		<g:ref name="URLLiteral"/>
+	</g:production>
+	<g:production name="XMLSpaceDecl" if="xquery">
+		<g:ref name="DeclareXMLSpace"/>
+		<!-- g:ref name="XMLSpaceEquals"/ -->
+		<g:choice name="XMLSpacePreserveOrStrip">
+			<g:ref name="XMLSpacePreserve"/>
+			<g:ref name="XMLSpaceStrip"/>
+		</g:choice>
+	</g:production>
+	<g:production name="DefaultNamespaceDecl" if="xquery core">
+		<g:choice name="DeclareDefaultElementOrFunction">
+			<g:ref name="DeclareDefaultElement" needs-exposition-parens="yes"/>
+			<g:ref name="DeclareDefaultFunction" needs-exposition-parens="yes"/>
+		</g:choice>
+		<g:ref name="Namespace"/>
+		<!-- g:ref name="AssignEquals"/ -->
+		<g:ref name="URLLiteral"/>
+	</g:production>
+  <g:production name="OrderingModeDecl" if="xquery core">
+    <g:ref name="DeclareOrdering"/>
+    <g:choice name="DeclareOrderingArgument">
+      <g:ref name="Ordered"/>
+      <g:ref name="Unordered"/>
+    </g:choice>
+  </g:production>
+  <g:production name="EmptyOrderingDecl" if="xquery core">
+    <g:ref name="DeclareDefaultOrderingEmpty"/>
+    <g:choice name="DeclareEmptyOrderingArgument">
+      <g:ref name="EmptyGreatest"/>
+      <g:ref name="EmptyLeast"/>
+    </g:choice>
+  </g:production>
+
+  <g:production name="InheritNamespacesDecl" if="xquery core">
+    <g:ref name="DeclareInheritNamespaces"/>
+    <g:choice name="DeclareInheritNamespacesArgument">
+      <g:ref name="Yes"/>
+      <g:ref name="No"/>
+    </g:choice>
+  </g:production>
+
+	<g:production name="DefaultCollationDecl" if="xquery core">
+		<g:ref name="DeclareCollation"/>
+		<!-- ref name="StringLiteral"/ -->
+		<g:ref name="URLLiteral"/>
+	</g:production>
+	<g:production name="BaseURIDecl" if="xquery core">
+		<g:ref name="DeclareBaseURI"/>
+		<g:ref name="URLLiteral"/>
+	</g:production>
+	<g:production name="SchemaImport" if="xquery core">
+		<g:ref name="ImportSchemaToken"/>
+		<!-- See http://lists.w3.org/Archives/Member/w3c-xml-query-wg/2002Jan/0181.html -->
+		<g:optional name="OptionalSchemaImportPrefixDecl">
+			<g:ref name="SchemaPrefix"/>
+		</g:optional>
+		<g:ref name="URLLiteral"/>
+		<g:optional name="OptionalLocationHint">
+			<g:ref name="AtStringLiteral" needs-exposition-parens="yes"/>
+			<g:zeroOrMore name="AdditionalSchemaLocationHints">
+				<g:ref name="Comma"/>
+				<g:ref name="StringLiteral"/>
+			</g:zeroOrMore>
+		</g:optional>
+	</g:production>
+	<g:production name="SchemaPrefix" if="xquery core">
+		<g:choice name="SchemaPrefixNamespaceBinding">
+			<g:sequence>
+				<g:ref name="Namespace"/>
+				<g:ref name="NCNameForPrefix"/>
+				<g:ref name="AssignEquals"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="DefaultElement"/>
+				<g:ref name="Namespace"/>
+				<!-- g:ref name="AssignEquals"/ -->
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	<g:production name="ModuleImport" if="xquery core">
+		<g:ref name="ImportModuleToken"/>
+		<g:optional name="ImportPrefixDecl">
+			<g:ref name="Namespace"/>
+			<g:ref name="NCNameForPrefix"/>
+			<g:ref name="AssignEquals"/>
+		</g:optional>
+		<g:ref name="URLLiteral"/>
+		<g:optional name="LocationHint">
+			<g:ref name="AtStringLiteral" needs-exposition-parens="yes"/>
+			<g:zeroOrMore name="AdditionalModuleLocationHints">
+				<g:ref name="Comma"/>
+				<g:ref name="StringLiteral"/>
+			</g:zeroOrMore>
+		</g:optional>
+	</g:production>
+	<g:production name="VarDecl" if="xquery core">
+		<g:ref name="DefineVariable"/>
+		<g:ref name="VarName"/>
+		<g:optional name="VarDeclOptionalTypeDecl">
+			<g:ref name="TypeDeclaration" if="xquery core"/>
+		</g:optional>
+		<g:choice name="VarDeclAssignmentOrExtern">
+			<g:sequence>
+				<!-- ref name="ColonEquals"/ -->
+				<!-- g:ref name="LbraceExprEnclosure"/ -->
+        <g:ref name="ColonEquals"/>
+        <g:ref name="ExprSingle"/>
+				<!-- g:ref name="Expr"/ -->
+				<!-- g:ref name="Rbrace"/ -->
+			</g:sequence>
+			<g:ref name="External"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ConstructionDecl" if="xquery core">
+		<g:ref name="DeclareConstruction"/>
+		<g:ref name="SchemaModeForDeclareConstruction"/>
+	</g:production>
+	<g:production name="FunctionDecl" if="xquery core">
+		<g:ref name="DefineFunction"/>
+		<g:ref name="QNameLpar"/>
+		<!-- ref name="FuncPListOpen"/ -->
+		<g:optional name="OptionalParamList">
+			<g:ref name="ParamList"/>
+		</g:optional>
+		<g:choice name="FunctionDeclSigClose">
+			<g:ref name="Rpar"/>
+			<g:sequence if="xquery core">
+				<g:ref name="RparAs"/>
+				<!-- Was Datatype -->
+				<g:ref name="SequenceType"/>
+			</g:sequence>
+		</g:choice>
+		<g:choice name="FunctionDeclBody">
+			<g:ref name="EnclosedExpr"/>
+			<g:ref name="External"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ParamList" if="xquery core">
+		<g:ref name="Param"/>
+		<g:zeroOrMore name="ParamListTail">
+			<g:ref name="Comma"/>
+			<g:ref name="Param"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="Param" if="xquery core">
+		<g:ref name="VariableIndicator"/>
+		<g:ref name="VarName"/>
+		<g:optional name="OptionalTypeDeclarationForParam">
+			<g:ref name="TypeDeclaration"/>
+		</g:optional>
+	</g:production>
+	<g:production name="EnclosedExpr" if="xquery core">
+		<g:choice name="EnclosedExprOpening">
+			<g:ref name="Lbrace" show="no"/>
+			<g:ref name="LbraceExprEnclosure"/>
+		</g:choice>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	
+	<!-- END PROLOG -->
+
+	<g:production name="QueryBody" if="xquery core">
+		<g:choice name="QueryOrUpdate">
+			<g:ref name="Expr"/>
+			<g:ref name="UpdateBody" if="update"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Expr">
+		<g:ref name="ExprSingle"/>
+		<g:zeroOrMore name="CommaExpr">
+			<g:ref name="Comma"/>
+			<g:ref name="ExprSingle"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="ExprSingle" node-type="void">
+		<g:choice break="true" name="ExprSingleChoice">
+			<g:ref name="FLWORExpr" if="xquery core"/>
+			<g:ref name="ForExpr" if="xpath"/>
+			<g:ref name="QuantifiedExpr" if="xquery xpath"/>
+			<g:ref name="TypeswitchExpr" if="xquery core"/>
+			<g:ref name="IfExpr" if="xpath core xquery"/>
+			<g:ref name="OrExpr" if="xpath core xquery"/>
+		</g:choice>
+	</g:production>
+
+	<g:production name="FLWORExpr" if="xquery core">
+		<g:oneOrMore if="xquery" name="FLWORClauseList">
+			<g:choice name="ForOrLet">
+				<g:ref name="ForClause"/>
+				<g:ref name="LetClause"/>
+			</g:choice>
+		</g:oneOrMore>
+		<g:choice if="core" name="ForOrLetCore">
+			<g:ref name="ForClause"/>
+			<g:ref name="LetClause"/>
+		</g:choice>
+		<g:optional if="xquery" name="OptionalWhere">
+			<g:ref name="WhereClause"/>
+		</g:optional>
+		<g:optional if="xquery" name="OptionalOrderBy">
+			<g:ref name="OrderByClause" if="xquery core"/>
+		</g:optional>
+		<g:ref name="Return"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:production name="ForExpr" if="xpath">
+		<g:ref name="SimpleForClause"/>
+		<g:ref name="Return"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<!-- ForClause is slightly different now for XQuery vs. XPath.  -sb -->
+	<g:production name="ForClause" if="xquery core" node-type="void">
+		<g:ref name="ForVariable"/>
+		<!-- ref name="VariableIndicator" if="xquery core"/ -->
+		<g:ref name="VarName"/>
+		<g:optional if="xquery core" name="ForTypeDeclarationOption">
+			<g:ref name="TypeDeclaration" if="xquery core"/>
+		</g:optional>
+		<g:optional if="xquery core" name="PositionalVarOption">
+			<g:ref name="PositionalVar" if="xquery core"/>
+		</g:optional>
+		<g:ref name="In"/>
+		<g:ref name="ExprSingle"/>
+		<g:zeroOrMore if="xquery" name="ForClauseTail">
+			<g:ref name="Comma"/>
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+			<g:optional if="xquery core" name="ForTailTypeDeclarationOption">
+				<g:ref name="TypeDeclaration" if="xquery core"/>
+			</g:optional>
+			<g:optional if="xquery core" name="TailPositionalVarOption">
+				<g:ref name="PositionalVar" if="xquery core"/>
+			</g:optional>
+			<g:ref name="In"/>
+			<g:ref name="ExprSingle"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="PositionalVar" if="core xquery">
+		<g:ref name="AtWord"/>
+		<g:ref name="VariableIndicator"/>
+		<g:ref name="VarName"/>
+	</g:production>
+	<!-- SimpleForClause is slightly different now for XQuery vs. XPath.  -sb -->
+	<g:production name="SimpleForClause" if="xpath" node-type="void">
+		<g:ref name="ForVariable"/>
+		<g:ref name="VarName"/>
+		<g:ref name="In"/>
+		<g:ref name="ExprSingle"/>
+		<g:zeroOrMore name="SimpleForClauseTail">
+			<g:ref name="Comma"/>
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+			<g:ref name="In"/>
+			<g:ref name="ExprSingle"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="LetClause" if="xquery core">
+		<g:ref name="LetVariable"/>
+		<!-- ref name="VariableIndicator" if="xquery core"/ -->
+		<g:ref name="VarName"/>
+		<g:optional if="xquery core" name="LetTypeDeclarationOption">
+			<g:ref name="TypeDeclaration" if="xquery core"/>
+		</g:optional>
+		<g:ref name="ColonEquals"/>
+		<g:ref name="ExprSingle"/>
+		<g:zeroOrMore if="xquery" name="LetClauseTail">
+			<g:ref name="Comma"/>
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+			<g:optional if="xquery core" name="LetTailTypeDeclarationOption">
+				<g:ref name="TypeDeclaration" if="xquery core"/>
+			</g:optional>
+			<g:ref name="ColonEquals"/>
+			<g:ref name="ExprSingle"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="WhereClause" if="xquery">
+		<g:ref name="Where"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:production name="OrderByClause" if="xquery core">
+		<g:choice break="false" name="OrderByOrOrderByStable">
+			<g:ref name="OrderBy"/>
+			<g:ref name="OrderByStable"/>
+		</g:choice>
+		<g:ref name="OrderSpecList"/>
+	</g:production>
+	<g:production name="OrderSpecList" if="xquery core">
+		<g:ref name="OrderSpec"/>
+		<g:zeroOrMore name="OrderSpecListTail">
+			<g:ref name="Comma"/>
+			<g:ref name="OrderSpec"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="OrderSpec" if="xquery core">
+		<g:ref name="ExprSingle"/>
+		<g:ref name="OrderModifier"/>
+	</g:production>
+	<g:production name="OrderModifier" if="xquery core">
+		<g:optional name="SortDirectionOption">
+			<g:choice name="AscendingOrDescending">
+				<g:ref name="Ascending"/>
+				<g:ref name="Descending"/>
+			</g:choice>
+		</g:optional>
+		<g:optional name="EmptyPosOption">
+			<g:choice name="EmptyGreatestOrLeast">
+				<g:ref name="EmptyGreatest" needs-exposition-parens="yes"/>
+				<g:ref name="EmptyLeast" needs-exposition-parens="yes"/>
+			</g:choice>
+		</g:optional>
+		<g:optional name="CollationSpecOption">
+			<g:ref name="Collation"/>
+			<g:ref name="StringLiteral"/>
+		</g:optional>
+	</g:production>
+	<g:production name="QuantifiedExpr" if="xquery xpath core">
+		<g:choice name="SomeOrEvery">
+			<g:ref name="Some" needs-exposition-parens="yes"/>
+			<g:ref name="Every" needs-exposition-parens="yes"/>
+		</g:choice>
+		<!-- ref name="VariableIndicator" if="xquery core"/ -->
+		<g:ref name="VarName"/>
+		<g:optional if="xquery core" name="QuantifiedTypeDeclarationOption">
+			<g:ref name="TypeDeclaration" if="xquery core"/>
+		</g:optional>
+		<g:ref name="In"/>
+		<g:ref name="ExprSingle"/>
+		<g:zeroOrMore name="QuantifiedVarDeclListTail">
+			<g:ref name="Comma"/>
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+			<g:optional if="xquery core" name="QuantifiedTailTypeDeclarationOption">
+				<g:ref name="TypeDeclaration" if="xquery core"/>
+			</g:optional>
+			<g:ref name="In"/>
+			<g:ref name="ExprSingle"/>
+		</g:zeroOrMore>
+		<g:ref name="Satisfies"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:production name="TypeswitchExpr" if="xquery core">
+		<g:ref name="TypeswitchLpar"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rpar"/>
+		<g:oneOrMore name="CaseClauseList">
+			<g:ref name="CaseClause"/>
+		</g:oneOrMore>
+		<g:ref name="Default"/>
+		<g:optional name="DefaultClauseVarBindingOption">
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+		</g:optional>
+		<g:ref name="Return"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:production name="CaseClause" if="xquery core">
+		<g:ref name="Case"/>
+		<g:optional name="CaseClauseVarBindingOption">
+			<g:ref name="VariableIndicator"/>
+			<g:ref name="VarName"/>
+			<g:ref name="As"/>
+		</g:optional>
+		<g:ref name="SequenceType"/>
+		<g:ref name="Return"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:production name="IfExpr" if="xpath core xquery">
+		<g:ref name="IfLpar" node-type="void"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rpar" node-type="void"/>
+		<!-- XPath TF decision to remove, Oct 16, 2002 -->
+		<g:ref name="Then" node-type="void"/>
+		<g:ref name="ExprSingle"/>
+		<g:ref name="Else" node-type="void"/>
+		<g:ref name="ExprSingle"/>
+	</g:production>
+	<g:exprProduction name="OperatorExpr" node-type="void" if="xquery
+			core xpath">
+		<g:level>
+			<g:binary name="OrExpr" if="core xpath xquery" condition="> 1">
+				<g:ref name="Or"/>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="AndExpr" if="core xpath xquery" condition="> 1">
+				<g:ref name="And"/>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="ComparisonExpr" prefix-seq-type="?" if="xpath xquery" condition="> 1">
+				<g:choice break="true" name="ValueOrGeneralOrNodeComp">
+					<g:ref name="ValueComp"/>
+					<g:ref name="GeneralComp"/>
+					<g:ref name="NodeComp"/>
+				</g:choice>
+			</g:binary>
+			<g:binary name="ComparisonExprPathx1" if="pathx1" condition="> 1">
+				<g:ref name="GeneralComp" if="pathx1"/>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="RangeExpr" if="xquery xpath" prefix-seq-type="?" condition="> 1">
+				<g:ref name="To"/>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="AdditiveExpr" if="xquery xpath" condition="> 1">
+				<g:choice name="AdditiveOps">
+					<g:ref name="Plus"/>
+					<g:ref name="Minus"/>
+				</g:choice>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="MultiplicativeExpr" if="xquery xpath" condition="> 1">
+				<g:choice name="MultiplicativeOps">
+					<g:ref name="Multiply"/>
+					<g:ref name="Div"/>
+					<g:ref name="Idiv"/>
+					<g:ref name="Mod"/>
+				</g:choice>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="UnionExpr" if="xquery xpath" condition="> 1">
+				<g:choice name="UnionOps">
+					<g:ref name="Union" if="xquery xpath"/>
+					<g:ref name="Vbar"/>
+				</g:choice>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:binary name="IntersectExceptExpr" if="xquery xpath" condition="> 1">
+				<g:choice name="IntersectOps">
+					<g:ref name="Intersect"/>
+					<g:ref name="Except"/>
+				</g:choice>
+			</g:binary>
+		</g:level>
+		<g:level>
+			<g:postfix name="InstanceofExpr" if="xquery xpath" prefix-seq-type="?" condition="> 1">
+				<g:sequence name="InstanceOfExprOps">
+					<g:ref name="Instanceof" node-type="void"/>
+					<g:ref name="SequenceType"/>
+				</g:sequence>
+			</g:postfix>
+		</g:level>
+		<g:level>
+			<g:postfix name="TreatExpr" if="xquery xpath" prefix-seq-type="?" condition="> 1">
+				<g:sequence name="TreatExprOps">
+					<g:ref name="TreatAs" node-type="void"/>
+					<g:ref name="SequenceType"/>
+				</g:sequence>
+			</g:postfix>
+		</g:level>
+		<g:level>
+			<g:postfix name="CastableExpr" if="core xquery xpath" prefix-seq-type="?" condition="> 1">
+				<g:sequence name="CastableExprOps">
+					<g:ref name="Castable" node-type="void"/>
+					<g:ref name="SingleType"/>
+				</g:sequence>
+			</g:postfix>
+		</g:level>
+		<g:level>
+			<g:postfix name="CastExpr" if="core xquery xpath" prefix-seq-type="?" node-type="void" condition="> 1">
+				<g:sequence name="CastExprOps">
+					<g:ref name="CastAs"/>
+					<g:ref name="SingleType"/>
+				</g:sequence>
+			</g:postfix>
+		</g:level>
+		<g:level node-type="UnaryExpr" level-user-action="boolean keepUnary=false;">
+			<g:prefix name="UnaryExpr" if="xquery xpath" condition="keepUnary">
+				<g:choice name="UnaryExprOps">
+					<g:ref name="UnaryMinus" token-user-action="keepUnary=true;"/>
+					<g:ref name="UnaryPlus" if="xquery xpath core" token-user-action="keepUnary=true;"/>
+				</g:choice>
+			</g:prefix>
+		</g:level>
+		<g:level>
+			<g:primary name="ValueExpr">
+				<g:choice name="ValueExprChoices">
+					<g:ref name="ValidateExpr" if="xquery core"/>
+					<g:ref name="PathExpr" if="xquery xpath"/>
+					<g:ref name="StepExpr" if="core"/>
+				</g:choice>
+			</g:primary>
+		</g:level>
+	</g:exprProduction>
+	
+	<g:production name="GeneralComp" if="xpath xquery" is-binary="yes" comment-id="lt" node-type="void">
+		<g:choice break="false" name="GeneralCompOps">
+			<g:ref name="Equals"/>
+			<g:ref name="NotEquals"/>
+			<g:ref name="Lt"/>
+			<g:ref name="LtEquals"/>
+			<g:ref name="Gt"/>
+			<g:ref name="GtEquals"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ValueComp" if="xpath xquery" is-binary="yes" node-type="void">
+		<g:choice break="false" name="ValueCompOps">
+			<g:ref name="FortranEq"/>
+			<g:ref name="FortranNe"/>
+			<g:ref name="FortranLt"/>
+			<g:ref name="FortranLe"/>
+			<g:ref name="FortranGt"/>
+			<g:ref name="FortranGe"/>
+		</g:choice>
+	</g:production>
+	<g:production name="NodeComp" if="xpath xquery" is-binary="yes" node-type="void">
+		<g:choice break="false" name="NodeCompOps">
+			<g:ref name="Is"/>
+			<!-- g:ref name="IsNot"/ -->
+			<g:ref name="LtLt"/>
+			<g:ref name="GtGt"/>
+		</g:choice>
+	</g:production>
+
+	<g:exposition-production name="ValidateExpr" if="core xquery" comment-id="validate">
+		<g:ref name="Validate"/>
+		<g:optional name="VModeOption">
+			<g:ref name="ValidationMode"/>
+		</g:optional>
+		<g:ref name="LbraceExprEnclosure"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:exposition-production>
+
+	<g:production name="ValidateExpr" if="core xquery" comment-id="validate">
+		<g:choice name="ValidateExprSpecifiers">
+			<g:ref name="ValidateLbrace"/>
+			<g:sequence>
+				<g:ref name="ValidateSchemaMode"/>
+				<g:ref name="LbraceExprEnclosure"/>
+			</g:sequence>
+		</g:choice>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+
+	<!-- g:production name="ValidationContext" if="xquery core">
+		<g:choice name="InContextOrGlobal">
+			<g:sequence>
+				<g:ref name="InContextForKindTest"/>
+				<g:ref name="SchemaContextLoc"/>
+			</g:sequence>
+			<g:ref name="Global"/>
+		</g:choice>
+	</g:production -->
+	
+	<g:production name="PathExpr" comment-id="leading-lone-slash" if="xquery xpath" condition=">0">
+		<g:choice break="true" name="PathExprChoices">
+			<g:sequence>
+				<g:ref name="Root"/>
+				<g:optional name="OptionalRootExprTail">
+					<g:ref name="RelativePathExpr"/>
+				</g:optional>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="RootDescendants"/>
+				<g:ref name="RelativePathExpr"/>
+			</g:sequence>
+			<g:sequence if="pathx1">
+				<g:ref name="RHSPrimaryExpr" if="pathx1"/>
+				<g:optional if="pathx1" name="OptionalPathX1RelativeTail">
+					<g:choice if="pathx1" name="PathX1StepSep">
+						<g:ref name="Slash" if="pathx1"/>
+						<g:ref name="SlashSlash" if="pathx1"/>
+					</g:choice>
+					<g:ref name="RelativePathExpr" if="pathx1"/>
+				</g:optional>
+			</g:sequence>
+			<g:ref name="RelativePathExpr" if="xquery xpath"/>
+		</g:choice>
+	</g:production>
+	<g:production name="RelativePathExpr" node-type="void" if="xquery xpath">
+		<g:ref name="StepExpr"/>
+		<g:zeroOrMore name="RelativePathExprTail">
+			<g:choice name="RelativePathExprStepSep">
+				<g:ref name="Slash" node-type="void"/>
+				<g:ref name="SlashSlash"/>
+			</g:choice>
+			<g:ref name="StepExpr"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="StepExpr" node-type="StepExpr" if="core xquery xpath" condition=">1 || isStep" prod-user-action="boolean savedIsStep = isStep; isStep=false;">
+		<g:choice name="AxisOrFilterStep">
+			<g:ref name="AxisStep" nt-user-action-start="isStep=true;" nt-user-action-end="isStep = savedIsStep;"/>
+			<g:ref name="FilterExpr" if="xpath xquery" nt-user-action-end="isStep = savedIsStep;"/>
+                        <g:ref name="PrimaryExpr" if="core"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AxisStep" node-type="void">
+		<g:choice name="ForwardOrReverseStep">
+			<g:ref name="ForwardStep"/>
+			<g:ref name="ReverseStep"/>
+		</g:choice>
+		<g:ref name="PredicateList" if="xquery xpath"/>
+	</g:production>
+	<g:production name="ForwardStep" node-type="void">
+		<g:choice name="ForwardAxisOrAbbrev">
+			<g:sequence>
+				<g:ref name="ForwardAxis"/>
+				<g:ref name="NodeTest"/>
+			</g:sequence>
+			<g:ref name="AbbrevForwardStep" if="xpath xquery"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ForwardAxis" node-type="void">
+		<g:choice break="true" name="ForwardAxisNames">
+			<g:ref name="AxisChild" needs-exposition-parens="yes"/>
+			<g:ref name="AxisDescendant" needs-exposition-parens="yes"/>
+			<g:ref name="AxisAttribute" needs-exposition-parens="yes"/>
+			<g:ref name="AxisSelf" needs-exposition-parens="yes"/>
+			<g:ref name="AxisDescendantOrSelf" needs-exposition-parens="yes"/>
+			<g:ref name="AxisFollowingSibling" if="xquery xpath core" needs-exposition-parens="yes"/>
+			<g:ref name="AxisFollowing" if="xquery xpath core" needs-exposition-parens="yes"/>
+			<g:ref name="AxisNamespace" if="xpath core" needs-exposition-parens="yes"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AbbrevForwardStep" if="xquery xpath" node-type="void">
+		<!-- g:ref name="Dot"/ -->
+		<g:optional name="OptionalAtSugar">
+			<g:ref name="At"/>
+		</g:optional>
+		<g:ref name="NodeTest"/>
+		<!-- child axis -->
+	</g:production>
+	<g:production name="ReverseStep" node-type="void">
+		<g:choice name="ReverseAxisOrAbbrev">
+			<g:sequence>
+				<g:ref name="ReverseAxis"/>
+				<g:ref name="NodeTest"/>
+			</g:sequence>
+			<g:ref name="AbbrevReverseStep" if="xpath xquery"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ReverseAxis" node-type="void">
+		<g:choice break="true" name="ReverseAxisNames">
+			<g:ref name="AxisParent" needs-exposition-parens="yes"/>
+			<g:ref name="AxisAncestor" if="xquery xpath core" needs-exposition-parens="yes"/>
+			<g:ref name="AxisPrecedingSibling" if="xquery xpath core" needs-exposition-parens="yes"/>
+			<g:ref name="AxisPreceding" if="xquery xpath core" needs-exposition-parens="yes"/>
+			<g:ref name="AxisAncestorOrSelf" if="xquery xpath core" needs-exposition-parens="yes"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AbbrevReverseStep" if="xquery xpath" node-type="void">
+		<g:ref name="DotDot"/>
+	</g:production>
+	<g:production name="NodeTest">
+		<g:choice name="KindOrNameTest">
+			<g:ref name="KindTest"/>
+			<g:ref name="NameTest"/>
+		</g:choice>
+	</g:production>
+	<g:production name="NameTest">
+		<g:choice name="QNameOrWildcard">
+			<g:ref name="QName"/>
+			<g:ref name="Wildcard"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Wildcard" node-type="void" whitespace-spec="explicit">
+		<g:choice break="true" name="WildcardChoice">
+			<g:ref name="Star"/>
+			<g:ref name="NCNameColonStar" needs-exposition-parens="yes"/>
+			<g:ref name="StarColonNCName" if="xquery core xpath" needs-exposition-parens="yes"/>
+		</g:choice>
+	</g:production>
+	
+	<g:production name="FilterExpr" node-type="void" if="xquery xpath">
+		<g:ref name="PrimaryExpr" if="xpath xquery"/>
+		<g:ref name="PredicateList"/>
+	</g:production>
+	<g:production name="PredicateList" if="xquery xpath" condition="> 0">
+		<g:zeroOrMore name="PredicatesListX">
+			<g:ref name="Predicate"/>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="Predicate" if="xquery xpath" condition="> 0">
+		<g:ref name="Lbrack" node-type="void"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrack" node-type="void"/>
+	</g:production>
+	
+	<g:production name="PrimaryExpr" node-type="void">
+		<g:choice name="PrimaryExprChoices">
+			<g:ref name="Literal"/>
+			<g:ref name="VarRef"/>
+			<g:ref name="ParenthesizedExpr"/>
+			<g:ref name="ContextItemExpr" nt-user-action-start="isStep=true;" if="xquery xpath"/>
+			<g:ref name="FunctionCall"/>
+			<g:ref name="Constructor" if="xquery"/>
+      <g:ref name="OrderedExpr" if="xquery"/>
+      <g:ref name="UnorderedExpr" if="xquery"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Literal" node-type="void">
+		<g:choice name="NumericOrStringLit">
+			<g:ref name="NumericLiteral"/>
+			<g:ref name="StringLiteral"/>
+		</g:choice>
+	</g:production>
+	<g:production name="NumericLiteral" node-type="void">
+		<g:choice name="NumericLitChoice">
+			<g:ref name="IntegerLiteral"/>
+			<g:ref name="DecimalLiteral"/>
+			<g:ref name="DoubleLiteral"/>
+		</g:choice>
+	</g:production>
+	<g:production name="VarRef" node-type="void">
+		<g:ref name="VariableIndicator"/>
+		<g:ref name="VarName"/>
+	</g:production>
+	<g:production name="ParenthesizedExpr" node-type="void">
+		<g:ref name="Lpar"/>
+		<g:optional if="xquery core xpath" name="OptionalExpr">
+			<g:ref name="Expr"/>
+		</g:optional>
+		<g:ref name="Expr" if="pathx1"/>
+		<g:ref name="Rpar"/>
+	</g:production>
+	<g:production name="ContextItemExpr" if="xquery xpath" node-type="void">
+		<g:ref name="Dot"/>
+	</g:production>
+	<g:production name="OrderedExpr" node-type="void" if="xquery core">
+		<g:ref name="OrderedOpen"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="UnorderedExpr" node-type="void" if="xquery core">
+		<g:ref name="UnorderedOpen"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+
+  
+	<g:production name="FunctionCall" if="xpath xquery core"
+       comment-id="parens reserved-function-names">
+		<g:choice name="FunctionNameOpening">
+			<g:ref name="QNameLpar"/>
+			<g:ref name="IDLpar" sub-spec="xslt-patterns" if="pathx1"/>
+			<g:ref name="KeyLpar" sub-spec="xslt-patterns" if="pathx1"/>
+		</g:choice>
+		<g:optional name="ArgList">
+			<g:ref name="ExprSingle"/>
+			<g:zeroOrMore name="ArgListTail">
+				<g:ref name="Comma"/>
+				<g:ref name="ExprSingle"/>
+			</g:zeroOrMore>
+		</g:optional>
+		<g:ref name="Rpar"/>
+	</g:production>
+		
+	<g:production name="Constructor" if="xquery">
+		<g:choice break="true" name="ConstructorChoice">
+            <g:ref name="DirectConstructor"/>			
+			<g:ref name="ComputedConstructor"/>
+		</g:choice>
+	</g:production>
+	
+	<g:production name="DirectConstructor"  if="xquery">
+		<g:choice break="true" name="DirectConstructorChoice">
+            <g:ref name="DirElemConstructor"/>
+            <g:ref name="DirCommentConstructor"/>
+            <g:ref name="DirPIConstructor"/>
+		</g:choice>
+	</g:production>
+	<g:production name="DirElemConstructor" if="xquery" whitespace-spec="explicit" comment-id="lt">
+		<g:choice name="TagOpenStart">
+			<g:ref name="StartTagOpenRoot" show="no"/>
+			<g:ref name="StartTagOpen"/>
+		</g:choice>
+		<g:ref name="TagQName"/>
+		<g:ref name="DirAttributeList"/>
+		<g:choice name="TagClose">
+			<g:ref name="EmptyTagClose"/>
+			<g:sequence name="TagContent">
+				<g:ref name="StartTagClose"/>
+				<g:zeroOrMore name="ElementContentBody">
+					<g:ref name="DirElemContent"/>
+				</g:zeroOrMore>
+				<g:ref name="EndTagOpen"/>
+				<g:ref name="TagQName"/>
+				<g:optional name="OptionalWhitespaceBeforeEndTagClose">
+					<g:ref name="S"/>
+				</g:optional>
+				<g:ref name="EndTagClose"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	<g:production name="DirAttributeList" if="xquery" whitespace-spec="explicit">
+		<g:zeroOrMore name="OptionalAttributeList">
+			<g:ref name="S"/>
+			<g:optional name="OptionalAttribute">
+				<g:ref name="TagQName"/>
+				<g:optional name="OptionalWhitespaceBeforeValueIndicator">
+					<g:ref name="S"/>
+				</g:optional>
+				<g:ref name="ValueIndicator"/>
+				<g:optional name="OptionalWhitespaceBeforeAttributeValue">
+					<g:ref name="S"/>
+				</g:optional>
+				<g:ref name="DirAttributeValue"/>
+			</g:optional>
+		</g:zeroOrMore>
+	</g:production>
+	<g:production name="DirAttributeValue" if="xquery" whitespace-spec="explicit">
+		<g:choice break="true" name="AttributeValueComponent">
+			<g:sequence>
+				<g:ref name="OpenQuot"/>
+				<g:zeroOrMore name="QuotAttributeValueContents">
+					<g:choice name="QuotContentOrEscape">
+						<g:ref name="EscapeQuot"/>
+						<g:ref name="QuotAttrValueContent"/>
+					</g:choice>
+				</g:zeroOrMore>
+				<g:ref name="CloseQuot"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="OpenApos"/>
+				<g:zeroOrMore name="AposAttributeValueContents">
+					<g:choice name="AposContentOrEscape">
+						<g:ref name="EscapeApos"/>
+						<g:ref name="AposAttrValueContent"/>
+					</g:choice>
+				</g:zeroOrMore>
+				<g:ref name="CloseApos"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	<g:production name="QuotAttrValueContent" if="xquery">
+		<g:choice break="true" name="QuotAttrValueComponent">
+			<g:ref name="QuotAttrContentChar"/>
+			<g:ref name="CommonContent"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AposAttrValueContent" if="xquery">
+		<g:choice break="true" name="AposAttrValueComponent">
+			<g:ref name="AposAttrContentChar"/>
+			<g:ref name="CommonContent"/>
+		</g:choice>
+	</g:production>
+	<g:production name="DirElemContent" if="xquery">
+		<g:choice break="true" name="ElementContentComponents">
+		  <g:ref name="DirectConstructor"/>
+			<g:ref name="ElementContentChar"/>
+      <g:ref name="CDataSection"/>
+			<g:ref name="CommonContent"/>
+		</g:choice>
+	</g:production>
+	<g:production name="CommonContent" if="xquery">
+		<g:choice name="CommonContentChoice">
+			<g:ref name="PredefinedEntityRef"/>
+			<g:ref name="CharRef"/>
+			<g:ref name="LCurlyBraceEscape"/>
+			<g:ref name="RCurlyBraceEscape"/>
+			<g:ref name="EnclosedExpr"/>
+		</g:choice>
+	</g:production>
+
+	<g:production name="DirCommentConstructor" if="xquery" whitespace-spec="explicit">
+		<g:choice name="XmlCommentStartOpen">
+			<g:ref name="XmlCommentStartForElementContent" show="no"/>
+			<g:ref name="XmlCommentStart"/>
+		</g:choice>
+		<g:ref name="DirCommentContents"/>
+		<g:ref name="XmlCommentEnd"/>
+	</g:production>
+
+  <g:production name="DirCommentContents" if="xquery" whitespace-spec="explicit">
+    <g:zeroOrMore name="XmlCommentContents">
+      <g:choice name="XmlCommentContentsChar">
+			  <g:ref name="CommentContentChar"/>
+        <g:ref name="CommentContentCharDash" needs-exposition-parens="yes"/>
+      </g:choice>
+		</g:zeroOrMore>
+  </g:production>
+
+	<g:production name="DirPIConstructor" if="xquery" whitespace-spec="explicit">
+		<g:choice name="ProcessingInstructionStartOpen">
+			<g:ref name="ProcessingInstructionStartForElementContent" show="no"/>
+			<g:ref name="ProcessingInstructionStart"/>
+		</g:choice>
+		<g:ref name="PITarget"/>
+		<g:optional name="OptionalPIContent">
+			<g:ref name="SForPI"/>
+      <g:ref name="DirPIContents"/>
+		</g:optional>
+		<g:ref name="ProcessingInstructionEnd"/>
+	</g:production>
+
+	<g:production name="DirPIContents" if="xquery" whitespace-spec="explicit">
+    <g:zeroOrMore name="XmlPIContentBody" subtract-reg-expr="(Char* '?&gt;' Char*)">
+				<g:ref name="PIContentChar"/>
+			</g:zeroOrMore>
+  </g:production>
+
+
+	<g:production name="CDataSection" if="xquery" whitespace-spec="explicit">
+		<g:choice name="CdataSectionOpen">
+			<g:ref name="CdataSectionStartForElementContent" show="no"/>
+			<g:ref name="CdataSectionStart"/>
+		</g:choice>
+		<g:ref name="CDataSectionContents"/>
+		<g:ref name="CdataSectionEnd"/>
+	</g:production>
+
+	<g:production name="CDataSectionContents" if="xquery" whitespace-spec="explicit">
+    <g:zeroOrMore name="CdataSectionBody" subtract-reg-expr="(Char* ']]&gt;' Char*)">
+			<g:ref name="CDataSectionChar"/>
+		</g:zeroOrMore>
+  </g:production>
+	
+	<g:production name="ComputedConstructor" if="xquery core">
+		<g:choice break="true" name="ComputedConstructorChoice">
+			<g:ref name="CompDocConstructor" if="xquery core"/>
+			<g:ref name="CompElemConstructor" if="xquery core"/>
+			<g:ref name="CompAttrConstructor" if="xquery core"/>
+			<g:ref name="CompTextConstructor" if="xquery core"/>
+			<g:ref name="CompCommentConstructor" if="xquery core"/>
+			<g:ref name="CompPIConstructor" if="xquery core"/>
+		</g:choice>
+	</g:production>
+	<g:production name="CompDocConstructor" if="xquery core">
+		<g:ref name="DocumentLbrace"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="CompElemConstructor" if="xquery core">
+		<g:choice name="CompElemConstructorSpec">
+			<g:ref name="ElementQNameLbrace" needs-exposition-parens="yes"/>
+			<g:sequence>
+				<g:ref name="ElementLbrace"/>
+				<g:ref name="Expr"/>
+				<g:ref name="Rbrace"/>
+				<g:ref name="LbraceExprEnclosure"/>
+			</g:sequence>
+		</g:choice>
+		<g:optional name="OptionalContentExpr">
+			<g:ref name="ContentExpr"/>
+		</g:optional>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="ContentExpr" if="xquery core">
+		<!-- g:choice name="CompElemNamespaceOrExprSingle">
+			<g:ref name="LocalNamespaceDecl"/>
+			<g:ref name="ExprSingle"/>
+		</g:choice>
+		<g:zeroOrMore name="CompElemBodyTail">
+			<g:ref name="Comma"/>
+			<g:choice name="TailCompElemNamespaceOrExprSingle">
+				<g:ref name="LocalNamespaceDecl"/>
+				<g:ref name="ExprSingle"/>
+			</g:choice>
+		</g:zeroOrMore -->
+    <g:ref name="Expr"/>
+	</g:production>
+	<!-- g:production name="LocalNamespaceDecl" if="xquery core">
+		<g:ref name="NamespaceNCNameLbrace" needs-exposition-parens="no"/>
+		<g:ref name="StringLiteral"/>
+		<g:ref name="Rbrace"/>
+	</g:production -->
+	<g:production name="CompAttrConstructor" if="xquery core">
+		<g:choice name="CompAttrConstructorOpening">
+			<g:ref name="AttributeQNameLbrace" needs-exposition-parens="yes"/>
+			<g:sequence>
+				<g:ref name="AttributeLbrace"/>
+				<g:ref name="Expr"/>
+				<g:ref name="Rbrace"/>
+				<g:ref name="LbraceExprEnclosure"/>
+			</g:sequence>
+		</g:choice>
+		<g:optional name="OptionalCompAttrValExpr">
+			<g:ref name="Expr"/>
+		</g:optional>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="CompTextConstructor" if="xquery core">
+		<g:ref name="TextLbrace"/>
+			<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="CompCommentConstructor" if="xquery core">
+		<g:ref name="CommentLbrace"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rbrace"/>
+	</g:production>
+	<g:production name="CompPIConstructor" if="xquery core">
+		<g:choice name="CompXmlPIOpening">
+			<g:ref name="PINCNameLbrace" needs-exposition-parens="yes"/>
+			<g:sequence>
+				<g:ref name="PILbrace"/>
+				<g:ref name="Expr"/>
+				<g:ref name="Rbrace"/>
+				<g:ref name="LbraceExprEnclosure"/>
+			</g:sequence>
+		</g:choice>
+		<g:optional name="OptionalCompXmlPIExpr">
+			<g:ref name="Expr"/>
+		</g:optional>
+		<g:ref name="Rbrace"/>
+	</g:production>
+
+	<g:production name="SingleType" if="xquery core xpath">
+		<g:ref name="AtomicType"/>
+		<g:optional name="OptionalOccurrenceIndicator">
+			<g:ref name="OccurrenceZeroOrOne"/>
+		</g:optional>
+	</g:production>
+	<g:production name="TypeDeclaration" if="xquery core">
+		<g:ref name="As"/>
+		<g:ref name="SequenceType"/>
+	</g:production>
+	<g:production name="SequenceType" if="xquery core xpath">
+		<g:choice break="true" name="ItemTypeOrEmpty">
+			<g:sequence>
+				<g:ref name="ItemType"/>
+				<g:optional name="OptionalOccurrenceIndicatorForSequenceType">
+					<g:ref name="OccurrenceIndicator"/>
+				</g:optional>
+			</g:sequence>
+			<g:ref name="EmptyTok" needs-exposition-parens="yes"/>
+		</g:choice>
+	</g:production>
+	<g:production name="OccurrenceIndicator" if="xquery core xpath" node-type="void"
+      comment-id="occurrence-indicators">
+		<g:choice name="OccurrenceIndicatorOps">
+			<!-- ref name="Star" if="xpath xquery core" show="no"/>
+        <g:ref name="Multiply" if="xpath xquery core"/>
+        <g:ref name="Plus"/>
+        <g:ref name="QMark"/ -->
+			<g:ref name="OccurrenceZeroOrOne"/>
+			<g:ref name="OccurrenceZeroOrMore"/>
+			<g:ref name="OccurrenceOneOrMore"/>
+		</g:choice>
+	</g:production>
+	<g:production name="ItemType" if="xquery core xpath" node-type="void">
+		<g:choice break="false" name="ItemTypeChoice">
+			<g:ref name="AtomicType"/>
+			<g:ref name="KindTest"/>
+			<g:ref name="Item" needs-exposition-parens="yes"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AtomicType" if="xquery core xpath">
+		<g:choice name="QNameForAtomicOrSequenceType">
+			<g:ref name="QNameForAtomicType" show="no"/>
+			<g:ref name="QNameForSequenceType"/>
+		</g:choice>
+	</g:production>
+	<g:production name="KindTest" node-type="void">
+		<g:choice break="true" name="KindTestChoice">
+			<g:ref name="DocumentTest" if="xquery core xpath"/>
+			<g:ref name="ElementTest" if="xquery core xpath"/>
+			<g:ref name="AttributeTest" if="xquery core xpath"/>
+			<g:ref name="SchemaElementTest" if="xquery core xpath"/>
+			<g:ref name="SchemaAttributeTest" if="xquery core xpath"/>
+			<g:ref name="PITest"/>
+			<g:ref name="CommentTest"/>
+			<g:ref name="TextTest"/>
+			<g:ref name="AnyKindTest"/>
+		</g:choice>
+	</g:production>
+	<g:production name="AnyKindTest">
+		<g:choice name="AnyKindTestOpening">
+			<g:ref name="NodeLpar"/>
+			<g:ref name="NodeLparForKindTest" show="no"/>
+		</g:choice>
+		<g:ref name="RparForKindTest"/>
+	</g:production>	
+	<g:production name="DocumentTest" if="xquery core xpath">
+		<g:choice name="DocumentTestOpening">
+			<g:ref name="DocumentLpar"/>
+			<g:ref name="DocumentLparForKindTest" show="no"/>
+		</g:choice>
+		<g:optional name="OptionalDocumentTestBody">
+      <g:choice name="DocumentTestBodyChoice">
+			  <g:ref name="ElementTest"/>
+        <g:ref name="SchemaElementTest"/>
+      </g:choice>
+		</g:optional>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+	<g:production name="TextTest">
+		<g:choice name="TextTestOpen">
+			<g:ref name="TextLpar"/>
+			<g:ref name="TextLparForKindTest" show="no"/>
+		</g:choice>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+	<g:production name="CommentTest">
+		<g:choice name="CommentTestOpen">
+			<g:ref name="CommentLpar"/>
+			<g:ref name="CommentLparForKindTest" show="no"/>
+		</g:choice>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+	<g:production name="PITest">
+		<g:choice name="PITestOpening">
+			<g:ref name="ProcessingInstructionLpar"/>
+			<g:ref name="ProcessingInstructionLparForKindTest" show="no"/>
+		</g:choice>
+		<g:optional name="OptionalPITestBody">
+			<g:choice name="NCNameForPIOrStringLit">
+				<g:ref name="NCNameForPI"/>
+				<g:ref name="StringLiteralForKindTest"/>
+			</g:choice>
+		</g:optional>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+	<g:production name="AttributeTest" if="xquery core xpath">
+		<g:choice name="AttributeTestOpening">
+			<g:ref name="AttributeType"/>
+			<g:ref name="AttributeTypeForKindTest" show="no"/>
+		</g:choice>
+		<g:optional name="OptionalAttributeTestBody">
+				<g:sequence>
+					<!-- g:ref name="At"/ -->
+					<g:ref name="AttribNameOrWildcard"/>
+					<g:optional name="AttributeTestBodyOptionalParam">
+						<g:ref name="CommaForKindTest"/>
+						<g:ref name="TypeName"/>
+					</g:optional>
+				</g:sequence>
+		</g:optional>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+
+	<g:production name="AttribNameOrWildcard" if="xpath xquery core">
+		<g:choice name="AttrNameOrWildcardChoice">
+			<g:ref name="AttributeName"/>
+			<g:ref name="AnyName"/>
+		</g:choice>
+	</g:production>
+
+	<g:production name="SchemaAttributeTest" if="xquery core xpath">
+		<g:choice name="SchemaAttributeTypeOpen">
+			<g:ref name="SchemaAttributeType"/>
+			<g:ref name="SchemaAttributeTypeForKindTest" show="no"/>
+		</g:choice>
+    <g:ref name="AttributeDeclaration"/>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+
+  <g:production name="AttributeDeclaration">
+    <g:ref name="AttributeName"/>
+  </g:production>
+
+	<g:production name="ElementTest" if="xquery core xpath">
+		<g:choice name="ElementTypeOpen">
+			<g:ref name="ElementType"/>
+			<g:ref name="ElementTypeForKindTest" show="no"/>
+			<g:ref name="ElementTypeForDocumentTest" show="no"/>
+		</g:choice>
+		<g:optional name="OptionalElementTestBody">
+				<g:sequence>
+					<g:ref name="ElementNameOrWildcard"/>
+					<g:optional name="ElementTestBodyOptionalParam">
+						<g:ref name="CommaForKindTest"/>
+						<g:ref name="TypeName"/>
+						<g:optional name="NillableOption">
+							<g:ref name="Nillable"/>
+						</g:optional>
+					</g:optional>
+				</g:sequence>
+		</g:optional>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+
+	<g:production name="ElementNameOrWildcard" if="xpath xquery core">
+		<g:choice name="ElemNameOrWildcardChoice">
+			<g:ref name="ElementName"/>
+			<g:ref name="AnyName"/>
+		</g:choice>
+  </g:production>
+
+	<g:production name="SchemaElementTest" if="xquery core xpath">
+		<g:choice name="SchemaElementTypeOpen">
+			<g:ref name="SchemaElementType"/>
+			<g:ref name="SchemaElementTypeForKindTest" show="no"/>
+			<g:ref name="SchemaElementTypeForDocumentTest" show="no"/>
+		</g:choice>
+    <g:ref name="ElementDeclaration"/>
+		<g:ref name="RparForKindTest"/>
+	</g:production>
+
+  <g:production name="ElementDeclaration">
+    <g:ref name="ElementName"/>
+  </g:production>
+
+	<g:production name="AttributeName" if="xpath xquery core">
+		<g:ref name="QNameForItemType"/>
+	</g:production>
+	<g:production name="ElementName" if="xpath xquery core">
+		<g:ref name="QNameForItemType"/>
+	</g:production>
+	<g:production name="TypeName" if="xpath xquery core">
+		<g:ref name="QNameForItemType"/>
+	</g:production>
+
+	<!-- g:production name="SchemaContextLoc" if="xquery core">
+		<g:choice name="SchemaContextLocComponents">
+			<g:sequence>
+				<g:optional name="OptionalSchemaContextLocContextPath">
+					<g:ref name="SchemaContextPath"/>
+				</g:optional>
+				<g:ref name="QNameForItemType"/>
+			</g:sequence>
+			<g:ref name="SchemaGlobalTypeName"/>
+		</g:choice>
+	</g:production -->
+
+	<!-- g:production name="SchemaContextPath" if="xquery core xpath">
+		<g:ref name="SchemaGlobalContextSlash"/>
+		<g:zeroOrMore name="SchemaContextPathTail">
+			<g:ref name="SchemaContextStepSlash" needs-exposition-parens="yes"/>
+		</g:zeroOrMore>
+	</g:production -->
+	
+	<!-- ============================== -->
+	<!-- UPDATE SUPERSET PROPOSAL -->
+	<!-- ============================== -->	
+
+	<!-- start update proposal productions -->
+	<g:production name="UpdateBody" if="update">
+		<g:choice name="dummyUpdateChoice">
+			<g:ref name="UpdateLookaheadFor"/>
+			<g:ref name="UpdateLookaheadLet"/>
+			<g:ref name="UpdateLookaheadIf"/>
+			<g:ref name="UpdateLookaheadInsert"/>
+			<g:ref name="UpdateLookaheadReplace"/>
+			<g:ref name="UpdateLookaheadDelete"/>
+			<!-- g:ref name="UpdateLookaheadEmpty"/ -->
+			<g:ref name="UpdateOpenUpdateList"/>
+		</g:choice>
+		<!-- g:ref name="UpdateTok"/ -->
+		<g:ref name="UpdateAction"/>
+	</g:production>
+	<g:production name="UpdateAction" if="update">
+		<g:choice name="UpdateBodyChoice">
+			<g:ref name="Insert"/>
+			<g:ref name="Delete"/>
+			<g:ref name="Replace"/>
+			<g:ref name="FLWUpdate"/>
+			<g:ref name="ConditionalUpdate"/>
+			<g:ref name="CompositeUpdate"/>
+		</g:choice>
+	</g:production>
+	<g:production name="CompositeUpdate" if="update">
+		<g:ref name="UpdateListOpen"/>
+		<g:optional name="OptionalCompositeUpdateBody">
+			<g:ref name="UpdateAction"/>
+			<g:zeroOrMore name="UpdateListCar">
+				<g:choice name="UpdateListSepChoice">
+					<g:ref name="UpdateListSep"/>
+					<g:ref name="SemiColon" show="no"/>
+				</g:choice>
+				<g:ref name="UpdateAction"/>
+			</g:zeroOrMore>
+		</g:optional>
+		<g:choice name="RbraceChoice">
+			<g:ref name="UpdateListClose"/>
+			<g:ref name="Rbrace" show="no"/>
+		</g:choice>
+	</g:production>
+	<g:production name="Insert" if="update">
+		<g:ref name="InsertTok"/>
+		<g:ref name="Expr"/>
+		<g:ref name="InsertLocation"/>
+	</g:production>
+	<g:production name="InsertLocation" if="update">
+		<g:choice name="InsertLocationChoices">
+			<g:sequence name="InsertLocationInto">
+				<g:optional name="InsertLocationPositionOption">
+					<g:choice name="InsertLocationPositionChoice">
+						<g:ref name="AsLast"/>
+						<g:ref name="AsFirst"/>
+					</g:choice>
+				</g:optional>
+				<g:ref name="Into"/>
+				<g:ref name="Expr"/>
+			</g:sequence>
+			<g:sequence name="InsertLocationAfter">
+				<g:ref name="After"/>
+				<g:ref name="Expr"/>
+			</g:sequence>
+			<g:sequence name="InsertLocationBefore">
+				<g:ref name="Before"/>
+				<g:ref name="Expr"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	<g:production name="Delete" if="update">
+		<g:ref name="DeleteTok"/>
+		<g:ref name="Expr"/>
+	</g:production>
+	<g:production name="Replace" if="update">
+		<g:ref name="ReplaceTok"/>
+		<g:optional name="ValueOfOption2">
+			<g:ref name="ValueOf"/>
+		</g:optional>
+		<g:ref name="Expr"/>
+		<g:ref name="With"/>
+		<g:ref name="Expr"/>
+	</g:production>
+	<g:production name="FLWUpdate" if="update">
+		<g:oneOrMore name="FLWUpdateClauseList">
+			<g:choice name="FLWUpdateForOrLet">
+				<g:ref name="ForClause"/>
+				<g:ref name="LetClause"/>
+			</g:choice>
+		</g:oneOrMore>
+		<g:optional name="FLWUpdateOptionalWhere">
+			<g:ref name="WhereClause"/>
+		</g:optional>
+		<g:ref name="Do"/>
+		<g:ref name="UpdateAction"/>
+	</g:production>
+	<g:production name="ConditionalUpdate" if="update">
+		<g:ref name="IfLpar" node-type="void"/>
+		<g:ref name="Expr"/>
+		<g:ref name="Rpar" node-type="void"/>
+		<g:ref name="Then" node-type="void"/>
+		<g:ref name="UpdateAction"/>
+		<!-- g:optional name="OptionalElseClause" -->
+		<g:ref name="Else" node-type="void"/>
+		<g:ref name="UpdateAction"/>
+		<!-- /g:optional -->
+	</g:production>
+
+	
+	<!-- ============================== -->
+	<!-- XSLT PATTERNS -->
+	<!-- ============================== -->	
+	<g:production name="Pattern" if="xslt-patterns">
+		<g:ref name="PathPattern"/>
+		<g:optional name="PathPatternTail">
+			<g:choice name="UnionSpecifier">
+				<g:ref name="Union" if="xquery xpath" node-type="void"/>
+				<g:ref name="Vbar" node-type="void"/>
+			</g:choice>
+			<g:ref name="Pattern"/>
+		</g:optional>
+	</g:production>
+	<g:production name="PathPattern" if="xslt-patterns" comment-id="leading-lone-slash">
+		<g:choice break="true" name="PathPatternChoices">
+			<g:sequence>
+				<g:ref name="Root"/>
+				<g:optional name="OptionalRelativePathPattern">
+					<g:ref name="RelativePathPattern"/>
+				</g:optional>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="RootDescendants"/>
+				<g:ref name="RelativePathPattern"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="IdKeyPattern" if="pathx1"/>
+				<g:optional name="OptionalRelativePathPatternAfterIdKey">
+					<g:choice name="PatternStepSepAfterIdKey">
+						<g:ref name="Slash" node-type="void"/>
+						<g:ref name="SlashSlash"/>
+					</g:choice>
+					<g:ref name="RelativePathPattern"/>
+				</g:optional>
+			</g:sequence>
+			<g:ref name="RelativePathPattern"/>
+		</g:choice>
+	</g:production>
+	<g:production name="RelativePathPattern" if="xslt-patterns" node-type="void">
+		<g:ref name="PatternStep"/>
+		<g:optional name="RelativePathPatternTail">
+			<g:choice name="PatternStepSep">
+				<g:ref name="Slash" node-type="void"/>
+				<g:ref name="SlashSlash"/>
+			</g:choice>
+			<g:ref name="RelativePathPattern"/>
+		</g:optional>
+	</g:production>
+	<g:production name="PatternStep" if="xslt-patterns">
+		<g:optional name="OptionalPatternAxis">
+			<g:ref name="PatternAxis"/>
+		</g:optional>
+		<g:ref name="NodeTest"/>
+		<g:ref name="PredicateList"/>
+	</g:production>
+	<g:production name="PatternAxis" if="xslt-patterns" node-type="void">
+		<g:choice break="true" name="AxisChoice">
+			<g:ref name="AxisChild"/>
+			<g:ref name="AxisAttribute"/>
+			<g:ref name="At"/>
+		</g:choice>
+	</g:production>
+	<g:production name="IdKeyPattern" if="pathx1" sub-spec="xslt-patterns">
+		<g:choice name="KeyOrIDPattern">
+			<g:sequence>
+				<g:ref name="IDLpar"/>
+				<g:ref name="IdKeyValue"/>
+				<g:ref name="Rpar"/>
+			</g:sequence>
+			<g:sequence>
+				<g:ref name="KeyLpar"/>
+				<g:ref name="StringLiteral"/>
+				<g:ref name="Comma"/>
+				<g:ref name="IdKeyValue"/>
+				<g:ref name="Rpar"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	<g:production name="IdKeyValue" if="pathx1" node-type="void" sub-spec="xslt-patterns">
+		<g:choice name="VarOrKeyValue">
+			<g:ref name="StringLiteral"/>
+			<g:sequence>
+				<g:ref name="VariableIndicator"/>
+				<g:ref name="VarName"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>	
+	<g:production name="RHSPrimaryExpr" if="pathx1">
+		<g:choice break="true" name="RHSStepOrPrimary">
+			<g:ref name="StepExpr" if="pathx1"/>
+			<g:sequence>
+				<g:ref name="PrimaryExpr" if="pathx1"/>
+				<g:ref name="PredicateList"/>
+			</g:sequence>
+		</g:choice>
+	</g:production>
+	
+</g:grammar>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:nil
+sgml-namecase-general:nil
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:nil
+sgml-parent-document:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	Wed Dec 22 10:15:05 2004
@@ -37,6 +37,8 @@
 import org.apache.commons.collections.BeanMap;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.NamespaceException;
+import javax.jcr.NamespaceRegistry;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.Event;
 import java.io.IOException;
@@ -53,6 +55,15 @@
     /** Name of the file to persist search internal namespace mappings */
     private static final String NS_MAPPING_FILE = "ns_mappings.properties";
 
+    /** Namespace URI for xpath functions */
+    // @todo this is not final! What should we use?
+    private static final String NS_FN_PREFIX = "fn";
+    public static final String NS_FN_URI = "http://www.w3.org/2004/10/xpath-functions";
+
+    /** Namespace URI for XML schema */
+    private static final String NS_XS_PREFIX = "xs";
+    public static final String NS_XS_URI = "http://www.w3.org/2001/XMLSchema";
+
     /** The actual search index */
     private final SearchIndex index;
 
@@ -72,7 +83,7 @@
     private final NamespaceMappings nsMappings;
 
     public SearchManager(SessionImpl session, SearchConfig config)
-            throws IOException {
+            throws RepositoryException, IOException {
         this.session = session;
         this.stateProvider = session.getItemStateManager();
         this.hmgr = session.getHierarchyManager();
@@ -81,6 +92,21 @@
         FileSystemResource mapFile = new FileSystemResource(fs, NS_MAPPING_FILE);
         nsMappings = new NamespaceMappings(mapFile);
 
+        // register namespaces
+        NamespaceRegistry nsReg = session.getWorkspace().getNamespaceRegistry();
+        try {
+            nsReg.getPrefix(NS_XS_URI);
+        } catch (NamespaceException e) {
+            // not yet known
+            nsReg.registerNamespace(NS_XS_PREFIX, NS_XS_URI);
+        }
+        try {
+            nsReg.getPrefix(NS_FN_URI);
+        } catch (RepositoryException e) {
+            // not yet known
+            nsReg.registerNamespace(NS_FN_PREFIX, NS_FN_URI);
+        }
+
         // set properties
         BeanMap bm = new BeanMap(this);
         try {
@@ -145,13 +171,14 @@
         // FIXME according to spec this should be descending
         // by default. this contrasts to standard sql semantics
         // where default is ascending.
-        boolean ascending = true;
+        boolean[] orderSpecs = null;
         String[] orderProperties = null;
         if (orderNode != null) {
-            ascending = orderNode.isAscending();
             orderProperties = orderNode.getOrderByProperties();
+            orderSpecs = orderNode.getOrderBySpecs();
         } else {
             orderProperties = new String[0];
+            orderSpecs = new boolean[0];
         }
 
 
@@ -160,7 +187,7 @@
 
         // execute it
         try {
-            Hits result = index.executeQuery(query, orderProperties, ascending);
+            Hits result = index.executeQuery(query, orderProperties, orderSpecs);
             uuids = new ArrayList(result.length());
             for (int i = 0; i < result.length(); i++) {
                 String uuid = result.doc(i).get(FieldNames.UUID);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -46,6 +46,8 @@
     }
 
     /**
+     * This method can return <code>null</code> to indicate that this
+     * <code>AndQueryNode</code> does not contain any operands.
      * @see QueryNode#accept(org.apache.jackrabbit.core.search.QueryNodeVisitor, java.lang.Object)
      */
     public Object accept(QueryNodeVisitor visitor, Object data) {
@@ -81,12 +83,45 @@
 
     /**
      * Returns a string representation of this query node including its sub-nodes.
+     * The returned string is formatted in JCR SQL syntax.
+     *
+     * @return a string representation of this query node including its sub-nodes.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer();
+        boolean bracket = false;
+        if (getParent() instanceof NotQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String and = "";
+        for (Iterator it = operands.iterator(); it.hasNext();) {
+            sb.append(and);
+            sb.append(((QueryNode) it.next()).toJCRSQLString());
+            and = " AND ";
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns a string representation of this query node including its sub-nodes.
      * The returned string is formatted in XPath syntax.
      *
      * @return a string representation of this query node including its sub-nodes.
      */
     public String toXPathString() {
-        // @todo implement
-        return "";
+        StringBuffer sb = new StringBuffer();
+        String and = "";
+        for (Iterator it = operands.iterator(); it.hasNext();) {
+            sb.append(and);
+            sb.append(((QueryNode) it.next()).toXPathString());
+            and = " and ";
+        }
+        return sb.toString();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Constants.java	Wed Dec 22 10:15:05 2004
@@ -42,6 +42,11 @@
     public static int TYPE_DATE = 4;
 
     /**
+     * timestamp data type
+     */
+    public static int TYPE_TIMESTAMP = 5;
+
+    /**
      * equal operation: =
      */
     public static int OPERATION_EQ = 10;
@@ -72,8 +77,22 @@
     public static int OPERATION_LE = 15;
 
     /**
-     * like operation: LIKE
+     * like operation: identifier LIKE string_literal
      */
     public static int OPERATION_LIKE = 16;
 
+    /**
+     * between operation: identifier [ NOT ] BETWEEN literal AND literal
+     */
+    public static int OPERATION_BETWEEN = 17;
+
+    /**
+     * on operation: identifier [ NOT ] IN ( literal {, literal}* )
+     */
+    public static int OPERATION_IN = 18;
+
+    /**
+     * is null operation: identifier IS [ NOT ] NULL
+     */
+    public static int OPERATION_NULL = 19;
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -85,12 +85,21 @@
     }
 
     /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        return "\"" + property + "\"='" + value + "'";
+    }
+
+    /**
      * Returns an XPath representation for this query node.
      *
      * @return an XPath representation for this query node.
      */
     public String toXPathString() {
-        // todo implement
-        return "";
+        // todo use encoding for property name
+        return "@" + property + "='" + value.replaceAll("'", "''") + "'";
     }
 }

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search;
+
+import java.util.Iterator;
+
+/**
+ * Defines a location step for querying the path of a node.
+ * <p/>
+ * <code>
+ * /foo  -> descendants = false, nameTest = foo<br>
+ * //foo -> descendants = true, nameTest = foo<br>
+ * //*   -> descendants = true, nameTest = null<br>
+ * /*    -> descendants = false, nameTest = null
+ * </code>
+ */
+public class LocationStepQueryNode extends NAryQueryNode {
+
+    /** Empty <code>QueryNode</code> array for us as return value */
+    private static final QueryNode[] EMPTY = new QueryNode[0];
+
+    /**
+     * Name test for this location step. A <code>null</code> value indicates
+     * a '*' name test.
+     */
+    private String nameTest;
+
+    /**
+     * If set to <code>true</code> this location step uses the descendant-or-self
+     * axis.
+     */
+    private boolean includeDescendants;
+
+    /**
+     * If <code>index</code> is larger than 0 this location step contains
+     * a position index.
+     */
+    private int index = -1;
+
+    /**
+     * Creates a new <code>LocationStepQueryNode</code> with a reference to
+     * its <code>parent</code>.
+     * @param parent the parent of this <code>LocationStepQueryNode</code>.
+     * @param nameTest the name test or <code>null</code> if this step should
+     *   match all names.
+     * @param descendants if <code>true</code> this location step uses the
+     *   descendant-or-self axis; otherwise the child axis.
+     */
+    public LocationStepQueryNode(QueryNode parent, String nameTest, boolean descendants) {
+        super(parent);
+        this.nameTest = nameTest;
+        this.includeDescendants = descendants;
+    }
+
+    /**
+     * Returns the label of the node for this location step, or <code>null</code>
+     * if the name test is '*'.
+     * @return the label of the node for this location step.
+     */
+    public String getNameTest() {
+        return nameTest;
+    }
+
+    /**
+     * Sets a new name test.
+     * @param nameTest the name test or <code>null</code> to match all names.
+     */
+    public void setNameTest(String nameTest) {
+        this.nameTest = nameTest;
+    }
+
+    /**
+     * Returns <code>true</code> if this location step uses the
+     * descendant-or-self axis, <code>false</code> if this step uses the child
+     * axis.
+     * @return <code>true</code> if this step uses the descendant-or-self axis.
+     */
+    public boolean getIncludeDescendants() {
+        return includeDescendants;
+    }
+
+    /**
+     * Sets a new value for the includeDescendants property.
+     * @param include the new value.
+     * @see {@link #getIncludeDescendants()}
+     */
+    public void setIncludeDescendants(boolean include) {
+        this.includeDescendants = include;
+    }
+
+    /**
+     * Adds a predicate node to this location step.
+     * @param predicate the node to add.
+     */
+    public void addPredicate(QueryNode predicate) {
+        addOperand(predicate);
+    }
+
+    /**
+     * Returns the predicate nodes for this location step. This method will
+     * not return a position predicate. Use {@link #getIndex} to retrieve
+     * this information.
+     * @return the predicate nodes or an empty array if there are no predicates
+     *   for this location step.
+     */
+    public QueryNode[] getPredicates() {
+        if (operands == null) {
+            return EMPTY;
+        } else {
+            return (QueryNode[]) operands.toArray(new QueryNode[operands.size()]);
+        }
+    }
+
+    /**
+     * Sets the position index for this step.
+     * @param index the position index.
+     */
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    /**
+     * Returns the position index for this step.
+     * @return the position index for this step.
+     */
+    public int getIndex() {
+        return index;
+    }
+
+    /**
+     * @see QueryNode#accept(QueryNodeVisitor, Object)
+     */
+    public Object accept(QueryNodeVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+    /**
+     * Returns a JCRQL representation for this query node.
+     *
+     * @return a JCRQL representation for this query node.
+     */
+    public String toJCRQLString() {
+        StringBuffer sb = new StringBuffer();
+        if (nameTest == null) {
+            sb.append("*");
+        } else {
+            sb.append(nameTest);
+        }
+        if (index > -1) {
+            sb.append('[').append(index).append(']');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer();
+        if (nameTest == null) {
+            sb.append("*");
+        } else {
+            sb.append(nameTest);
+        }
+        if (index > -1) {
+            sb.append('[').append(index).append(']');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns an XPath representation for this query node.
+     *
+     * @return an XPath representation for this query node.
+     */
+    public String toXPathString() {
+        StringBuffer sb = new StringBuffer();
+        if (includeDescendants) {
+            sb.append('/');
+        }
+        if (nameTest == null) {
+            sb.append("*");
+        } else {
+            sb.append(nameTest);
+        }
+        if (index > -1) {
+            sb.append('[').append(index).append(']');
+        }
+        if (operands != null) {
+            for (Iterator it = operands.iterator(); it.hasNext();) {
+                QueryNode predicate = (QueryNode) it.next();
+                sb.append('[').append(predicate.toXPathString()).append(']');
+            }
+        }
+        return sb.toString();
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -25,9 +25,14 @@
 public abstract class NAryQueryNode extends QueryNode {
 
     /**
+     * Empty result.
+     */
+    private static final Object[] EMPTY = new Object[0];
+
+    /**
      * The list of operands / children
      */
-    protected List operands = new ArrayList();
+    protected List operands = null;
 
     /**
      * Creates a new <code>NAryQueryNode</code> with a reference to a parent
@@ -57,6 +62,9 @@
      * @param operand the child {@link QueryNode} to add.
      */
     public void addOperand(QueryNode operand) {
+        if (operands == null) {
+            operands = new ArrayList();
+        }
         operands.add(operand);
     }
 
@@ -69,10 +77,17 @@
      * @return the return values of the <code>visitor.visit()</code> calls.
      */
     public Object[] acceptOperands(QueryNodeVisitor visitor, Object data) {
-        Object[] result = new Object[operands.size()];
+        if (operands == null) {
+            return EMPTY;
+        }
+        
+        List result = new ArrayList(operands.size());
         for (int i = 0; i < operands.size(); i++) {
-            result[i] = ((QueryNode) operands.get(i)).accept(visitor, data);
+            Object r = ((QueryNode) operands.get(i)).accept(visitor, data);
+            if (r != null) {
+                result.add(r);
+            }
         }
-        return result;
+        return result.toArray();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -61,12 +61,26 @@
     }
 
     /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        if (operands.size() > 0) {
+            return "NOT " + ((QueryNode) operands.get(0)).toJCRSQLString();
+        }
+        return "";
+    }
+
+    /**
      * Returns an XPath representation for this query node.
      *
      * @return an XPath representation for this query node.
      */
     public String toXPathString() {
-        // todo implement
+        if (operands.size() > 0) {
+            return "fn:not(" + ((QueryNode) operands.get(0)).toXPathString() + ")";
+        }
         return "";
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -61,7 +61,9 @@
     public String toJCRQLString() {
         StringBuffer sb = new StringBuffer();
         boolean bracket = false;
-        if (getParent() instanceof AndQueryNode || getParent() instanceof NotQueryNode) {
+        if (getParent() instanceof LocationStepQueryNode
+                || getParent() instanceof AndQueryNode
+                || getParent() instanceof NotQueryNode) {
             bracket = true;
         }
         if (bracket) {
@@ -81,12 +83,57 @@
 
     /**
      * Returns a string representation of this query node including its sub-nodes.
+     * The returned string is formatted in JCR SQL syntax.
+     *
+     * @return a string representation of this query node including its sub-nodes.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer();
+        boolean bracket = false;
+        if (getParent() instanceof LocationStepQueryNode 
+                || getParent() instanceof AndQueryNode
+                || getParent() instanceof NotQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String or = "";
+        for (Iterator it = operands.iterator(); it.hasNext();) {
+            sb.append(or);
+            sb.append(((QueryNode) it.next()).toJCRSQLString());
+            or = " OR ";
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns a string representation of this query node including its sub-nodes.
      * The returned string is formatted in XPath syntax.
      *
      * @return a string representation of this query node including its sub-nodes.
      */
     public String toXPathString() {
-        // todo implement
-        return "";
+        StringBuffer sb = new StringBuffer();
+        boolean bracket = false;
+        if (getParent() instanceof AndQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String or = "";
+        for (Iterator it = operands.iterator(); it.hasNext();) {
+            sb.append(or);
+            sb.append(((QueryNode) it.next()).toXPathString());
+            or = " or ";
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb.toString();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -27,9 +27,9 @@
     private String[] properties;
 
     /**
-     * Flag indicating whether nodes are ordered ascending or descending
+     * Array of flag indicating whether a node is ordered ascending or descending
      */
-    private boolean ascending;
+    private boolean[] orderSpecs;
 
     /**
      * Creates a new <code>OrderQueryNode</code> with a reference to a parent
@@ -37,13 +37,14 @@
      *
      * @param parent     the parent node of this query node.
      * @param properties the names of the properties to sort the result nodes.
-     * @param asc        if <code>true</code> result nodes are orderd ascending;
+     * @param orderSpecs if <code>true</code> a result node is orderd ascending;
      *                   otherwise descending.
      */
-    public OrderQueryNode(QueryNode parent, String[] properties, boolean asc) {
+    public OrderQueryNode(QueryNode parent, String[] properties, boolean[] orderSpecs) {
         super(parent);
+        if (properties.length != orderSpecs.length)
         this.properties = properties;
-        this.ascending = asc;
+        this.orderSpecs = orderSpecs;
     }
 
 
@@ -55,13 +56,17 @@
     }
 
     /**
-     * Returns <code>true</code> if result nodes should be orderd ascending.
-     * If <code>false</code> result nodes are ordered descending.
+     * Returns <code>true</code> if the property <code>i</code> should be orderd
+     * ascending. If <code>false</code> the property is ordered descending.
+     * @param i index of the property
      *
-     * @return the value of the ascending property.
+     * @return the order spec for the property <code>i</code>.
+     *
+     * @exception ArrayIndexOutOfBoundsException if there is no property with
+     * index <code>i</code>.
      */
-    public boolean isAscending() {
-        return ascending;
+    public boolean isAscending(int i) {
+        return orderSpecs[i];
     }
 
     /**
@@ -75,6 +80,15 @@
     }
 
     /**
+     * Returns a boolean array that contains the sort order specification
+     * for each property returned by {@link #getOrderByProperties()}.
+     * @return the sort specification.
+     */
+    public boolean[] getOrderBySpecs() {
+        return orderSpecs;
+    }
+
+    /**
      * Returns a JCRQL representation for this query node.
      *
      * @return a JCRQL representation for this query node.
@@ -86,14 +100,37 @@
             for (int i = 0; i < properties.length; i++) {
                 sb.append(comma).append(" ");
                 sb.append(properties[i]);
+                if (isAscending(i)) {
+                    // FIXME really default to descending?
+                    sb.append(" ASCENDING");
+                }
                 comma = ",";
             }
         } else {
             sb.append(" SCORE");
         }
-        if (ascending) {
-            // FIXME really default to descending?
-            sb.append(" ASCENDING");
+        return sb.toString();
+    }
+
+    /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer("ORDER BY");
+        if (properties.length > 0) {
+            String comma = "";
+            for (int i = 0; i < properties.length; i++) {
+                sb.append(comma).append(" \"");
+                sb.append(properties[i]).append("\"");
+                if (!isAscending(i)) {
+                    sb.append(" DESC");
+                }
+                comma = ",";
+            }
+        } else {
+            sb.append(" SCORE");
         }
         return sb.toString();
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -18,80 +18,17 @@
 /**
  * Implements a query node that defines a path restriction.
  */
-public class PathQueryNode extends QueryNode {
+public class PathQueryNode extends NAryQueryNode {
 
     /**
-     * Match path exact
+     * Empty step node array.
      */
-    public static final int TYPE_EXACT = 1;
+    private static final LocationStepQueryNode[] EMPTY = new LocationStepQueryNode[0];
 
-    /**
-     * Match child nodes of path
-     */
-    public static final int TYPE_CHILDREN = 2;
-
-    /**
-     * Match descendant nodes or self of path
-     */
-    public static final int TYPE_DESCENDANT_SELF = 3;
-
-    /**
-     * The base path
-     */
-    private final String path;
-
-    /**
-     * Converted path without indexes. /bla[2] -> /bla
-     */
-    private final String indexlessPath;
-
-    /**
-     * The match type for this query node
-     */
-    private final int type;
-
-    /**
-     * Flag indicating if this path query contains indexed location steps
-     */
-    private final boolean indexedName;
-
-    /**
-     * Creates a new <code>PathQueryNode</code> instance.
-     *
-     * @param parent this parent node of this query node.
-     * @param path   the base path.
-     * @param type   one of {@link #TYPE_CHILDREN}, {@link #TYPE_DESCENDANT_SELF},
-     *               {@link #TYPE_EXACT}
-     */
-    public PathQueryNode(QueryNode parent, String path, int type) {
+    public PathQueryNode(QueryNode parent) {
         super(parent);
-        if (type < TYPE_EXACT || type > TYPE_DESCENDANT_SELF) {
-            throw new IllegalArgumentException(String.valueOf(type));
-        }
-        this.path = path;
-        this.type = type;
-        this.indexedName = (path.indexOf('[') > -1);
-        if (indexedName) {
-            // also create an indexless path
-            StringBuffer tmp = new StringBuffer(path);
-            int idx;
-            while ((idx = tmp.indexOf("[")) > -1) {
-                int end = tmp.indexOf("]", idx);
-                if (end > -1) {
-                    tmp.replace(idx, end, "");
-                } else {
-                    // should never happen
-                    // FIXME do some error logging?
-                    break;
-                }
-            }
-            this.indexlessPath = tmp.toString();
-        } else {
-            this.indexlessPath = path;
-        }
     }
 
-
     /**
      * @see QueryNode#accept(org.apache.jackrabbit.core.search.QueryNodeVisitor, java.lang.Object)
      */
@@ -100,60 +37,63 @@
     }
 
     /**
-     * Returns the unmodified path for this query node, as passed to the
-     * constructor.
-     *
-     * @return the unmodified path for this query node.
-     */
-    public String getPath() {
-        return path;
-    }
-
-    /**
-     * Returns a normalized path without indexes.
-     *
-     * @return a normalized path without indexes.
+     * Adds a path step to this <code>PathQueryNode</code>.
+     * @param step the step to add.
      */
-    public String getIndexlessPath() {
-        return indexlessPath;
+    public void addPathStep(LocationStepQueryNode step) {
+        addOperand(step);
     }
 
     /**
-     * Returns the type of this <code>PathQueryNode</code>.
-     *
-     * @return one of {@link #TYPE_CHILDREN}, {@link #TYPE_DESCENDANT_SELF},
-     *         {@link #TYPE_EXACT}
+     * Returns an array of all currently set location step nodes.
+     * @return an array of all currently set location step nodes.
      */
-    public int getType() {
-        return type;
+    public LocationStepQueryNode[] getPathSteps() {
+        if (operands == null) {
+            return EMPTY;
+        } else {
+            return (LocationStepQueryNode[]) operands.toArray(new LocationStepQueryNode[operands.size()]);
+        }
     }
 
     /**
-     * Returns <code>true</code> if the path contains an index. E.g. a location
-     * step in XPath has a position predicate. If the path does not contain any
-     * indexes <code>false</code> is returned.
+     * Returns a JCRQL representation for this query node.
      *
-     * @return <code>true</code> if the path contains an indexed location step.
+     * @return a JCRQL representation for this query node.
      */
-    public boolean hasIndexedName() {
-        return indexedName;
+    public String toJCRQLString() {
+        StringBuffer sb = new StringBuffer("LOCATION \"");
+        LocationStepQueryNode[] steps = getPathSteps();
+        for (int i = 0; i < steps.length; i++) {
+            if (steps[i].getNameTest() == null
+                    || steps[i].getNameTest().length() > 0) {
+                sb.append('/');
+            }
+            sb.append(steps[i].toJCRQLString());
+        }
+        sb.append('"');
+        return sb.toString();
     }
 
 
     /**
-     * Returns a JCRQL representation for this query node.
+     * Returns a JCR SQL representation for this query node.
      *
-     * @return a JCRQL representation for this query node.
+     * @return a JCR SQL representation for this query node.
      */
-    public String toJCRQLString() {
-        StringBuffer jcrql = new StringBuffer("LOCATION ");
-        jcrql.append(path);
-        if (type == TYPE_CHILDREN) {
-            jcrql.append("/*");
-        } else if (type == TYPE_DESCENDANT_SELF) {
-            jcrql.append("//");
+    public String toJCRSQLString() {
+        // FIXME implement namespace awareness
+        StringBuffer sb = new StringBuffer("\"jcr:path\"='");
+        LocationStepQueryNode[] steps = getPathSteps();
+        for (int i = 0; i < steps.length; i++) {
+            if (steps[i].getNameTest() == null
+                    || steps[i].getNameTest().length() > 0) {
+                sb.append('/');
+            }
+            sb.append(steps[i].toJCRSQLString());
         }
-        return jcrql.toString();
+        sb.append('\'');
+        return sb.toString();
     }
 
     /**
@@ -162,7 +102,15 @@
      * @return an XPath representation for this query node.
      */
     public String toXPathString() {
-        // todo implement correctly.
-        return "";
+        StringBuffer sb = new StringBuffer();
+        LocationStepQueryNode[] steps = getPathSteps();
+        for (int i = 0; i < steps.length; i++) {
+            if (steps[i].getNameTest() == null
+                    || steps[i].getNameTest().length() > 0) {
+                sb.append('/');
+            }
+            sb.append(steps[i].toXPathString());
+        }
+        return sb.toString();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java	Wed Dec 22 10:15:05 2004
@@ -19,8 +19,6 @@
  * Implements an abstract base class for nodes of a query tree that represents
  * a query. The query tree is independent from the query syntax which is used
  * to search the repository.
- * <p/>
- * todo: extend QueryNode with toString method for both XPath flavours
  */
 public abstract class QueryNode {
 
@@ -69,6 +67,14 @@
      * @return a string representation of this query node including its sub-nodes.
      */
     public abstract String toJCRQLString();
+
+    /**
+     * Returns a string representation of this query node including its sub-nodes.
+     * The returned string is formatted in JCRQL syntax.
+     *
+     * @return a string representation of this query node including its sub-nodes.
+     */
+    public abstract String toJCRSQLString();
 
     /**
      * Returns a string representation of this query node including its sub-nodes.

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNodeVisitor.java	Wed Dec 22 10:15:05 2004
@@ -38,6 +38,8 @@
 
     public Object visit(PathQueryNode node, Object data);
 
+    public Object visit(LocationStepQueryNode node, Object data);
+
     public Object visit(RelationQueryNode node, Object data);
 
     public Object visit(OrderQueryNode node, Object data);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java	Wed Dec 22 10:15:05 2004
@@ -16,6 +16,9 @@
 package org.apache.jackrabbit.core.search;
 
 import org.apache.jackrabbit.core.search.jcrql.JCRQLQueryBuilder;
+import org.apache.jackrabbit.core.search.xpath.XPathQueryBuilder;
+import org.apache.jackrabbit.core.search.sql.JCRSQLQueryBuilder;
+import org.apache.jackrabbit.core.NamespaceResolver;
 
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.query.Query;
@@ -36,9 +39,9 @@
      * Parses a query <code>statement</code> according to a query
      * <code>language</code> into a query tree.
      * <p/>
-     * <code>language</code> must be one of: {@link javax.query.Query#JCRQL},
-     * {@link javax.query.Query#XPATH_DOCUMENT_VIEW}, {@link
-     * javax.query.Query#XPATH_SYSTEM_VIEW}.
+     * <code>language</code> must be one of: {@link javax.jcr.query.Query#JCRQL},
+     * {@link javax.jcr.query.Query#XPATH_DOCUMENT_VIEW},
+     * {@link javax.jcr.query.Query#XPATH_SYSTEM_VIEW}.
      *
      * @param statement the query statement.
      * @param language  the language of the query statement.
@@ -46,11 +49,17 @@
      * @throws InvalidQueryException if an error occurs while parsing the
      *                               statement.
      */
-    public static QueryRootNode parse(String statement, String language)
+    public static QueryRootNode parse(String statement,
+                                      String language,
+                                      NamespaceResolver resolver)
             throws InvalidQueryException {
 
-        if (language == Query.JCRQL) {
+        if (Query.JCRQL.equals(language)) {
             return JCRQLQueryBuilder.createQuery(statement);
+        } else if (Query.XPATH_DOCUMENT_VIEW.equals(language)) {
+            return XPathQueryBuilder.createQuery(statement, resolver);
+        } else if ("sql".equals(language)) {
+            return JCRSQLQueryBuilder.createQuery(statement, resolver);
         } else {
             throw new InvalidQueryException("unknown language");
         }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java	Wed Dec 22 10:15:05 2004
@@ -31,6 +31,7 @@
 
     /**
      * The list of nodeType constraints. Might be null
+     * @todo not used anymore, node types can be specified in any predicate.
      */
     private List nodeTypes = new ArrayList();
 
@@ -40,16 +41,6 @@
     private List selectProperties = new ArrayList();
 
     /**
-     * Sub node that defines constraints. Might be null
-     */
-    private AndQueryNode constraintNode = new AndQueryNode(this);
-
-    /**
-     * The textsearch clause. Might be null
-     */
-    private TextsearchQueryNode textsearchNode;
-
-    /**
      * The list of property names to order the result nodes. Might be null
      */
     private OrderQueryNode orderNode;
@@ -100,33 +91,6 @@
     }
 
     /**
-     * Returns the constraint node.
-     *
-     * @return the constraint node.
-     */
-    public AndQueryNode getConstraintNode() {
-        return constraintNode;
-    }
-
-    /**
-     * Returns the textsearch node.
-     *
-     * @return the textsearch node.
-     */
-    public TextsearchQueryNode getTextsearchNode() {
-        return textsearchNode;
-    }
-
-    /**
-     * Sets a new textsearch node.
-     *
-     * @param textsearchNode the new textsearch node.
-     */
-    public void setTextsearchNode(TextsearchQueryNode textsearchNode) {
-        this.textsearchNode = textsearchNode;
-    }
-
-    /**
      * Returns the order node.
      *
      * @return the order node.
@@ -174,8 +138,56 @@
         if (locationNode != null) {
             sb.append(" ").append(locationNode.toJCRQLString());
         }
-        if (constraintNode != null) {
-            sb.append(" WHERE ").append(constraintNode.toJCRQLString());
+        LocationStepQueryNode[] steps = locationNode.getPathSteps();
+        QueryNode[] predicates = steps[steps.length - 1].getPredicates();
+        String and = "";
+        for (int i = 0; i < predicates.length; i++) {
+            if (i == 0) {
+                sb.append(" WHERE ");
+            }
+            sb.append(and).append(predicates[i].toJCRQLString());
+            and = " AND ";
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns a string representation of this query node including its sub-nodes.
+     * The returned string is formatted in JCR SQL syntax.
+     *
+     * @return a string representation of this query node including its sub-nodes.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer("SELECT *");
+        sb.append(" FROM");
+        String comma = "";
+        if (nodeTypes.size() > 0) {
+            for (Iterator it = nodeTypes.iterator(); it.hasNext();) {
+                NodeTypeQueryNode nodeType = (NodeTypeQueryNode) it.next();
+                sb.append(comma);
+                sb.append(" \"").append(nodeType.getValue()).append("\"");
+                comma = ",";
+            }
+        } else {
+            sb.append(" nt:base");
+        }
+        LocationStepQueryNode[] steps = locationNode.getPathSteps();
+        QueryNode[] predicates = steps[steps.length - 1].getPredicates();
+        String and = "";
+        for (int i = 0; i < predicates.length; i++) {
+            if (i == 0) {
+                sb.append(" WHERE ");
+            }
+            sb.append(and).append(predicates[i].toJCRSQLString());
+            and = " AND ";
+        }
+
+        if (steps.length == 2
+                && steps[1].getIncludeDescendants()
+                && steps[1].getNameTest() == null) {
+            // then this query selects all paths
+        } else {
+            sb.append(" AND ").append(locationNode.toJCRSQLString());
         }
         return sb.toString();
     }
@@ -187,6 +199,6 @@
      * @return a string representation of this query node including its sub-nodes.
      */
     public String toXPathString() {
-        return "";
+        return locationNode.toXPathString();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -176,6 +176,15 @@
     }
 
     /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        return "";
+    }
+
+    /**
      * Returns an XPath representation for this query node.
      *
      * @return an XPath representation for this query node.

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -68,6 +68,16 @@
     private int type;
 
     /**
+     * Creates a new <code>RelationQueryNode</code> without a type nor value
+     * assigned.
+     * @param parent the parent node for this query node.
+     */
+    public RelationQueryNode(QueryNode parent, int operation) {
+        super(parent);
+        this.operation = operation;
+    }
+
+    /**
      * Creates a new <code>RelationQueryNode</code> with a <code>long</code>
      * <code>value</code> and an <code>operation</code> type.
      *
@@ -161,6 +171,14 @@
     }
 
     /**
+     * Sets a new property name for this relation query node.
+     * @param name the new property name.
+     */
+    public void setProperty(String name) {
+        property = name;
+    }
+
+    /**
      * Returns the <code>long</code> value if this relation if of type
      * {@link #TYPE_LONG}.
      *
@@ -171,6 +189,15 @@
     }
 
     /**
+     * Sets a new value of type <code>long</code>.
+     * @param value the new value.
+     */
+    public void setLongValue(long value) {
+        valueLong = value;
+        type = TYPE_LONG;
+    }
+
+    /**
      * Returns the <code>double</code> value if this relation if of type
      * {@link #TYPE_DOUBLE}.
      *
@@ -181,6 +208,15 @@
     }
 
     /**
+     * Sets a new value of type <code>double</code>.
+     * @param value the new value.
+     */
+    public void setDoubleValue(double value) {
+        valueDouble = value;
+        type = TYPE_DOUBLE;
+    }
+
+    /**
      * Returns the <code>String</code> value if this relation if of type
      * {@link #TYPE_STRING}.
      *
@@ -191,6 +227,15 @@
     }
 
     /**
+     * Sets a new value of type <code>String</code>.
+     * @param value the new value.
+     */
+    public void setStringValue(String value) {
+        valueString = value;
+        type = TYPE_STRING;
+    }
+
+    /**
      * Returns the <code>Date</code> value if this relation if of type
      * {@link #TYPE_DATE}.
      *
@@ -201,6 +246,15 @@
     }
 
     /**
+     * Sets a new value of type <code>Date</code>.
+     * @param value the new value.
+     */
+    public void setDateValue(Date value) {
+        valueDate = value;
+        type = TYPE_DATE;
+    }
+
+    /**
      * Returns the operation type.
      *
      * @return the operation type.
@@ -223,19 +277,19 @@
         }
 
         if (operation == OPERATION_EQ) {
-            sb.append("=");
+            sb.append(" = ");
         } else if (operation == OPERATION_GE) {
-            sb.append(">=");
+            sb.append(" >= ");
         } else if (operation == OPERATION_GT) {
-            sb.append(">");
+            sb.append(" > ");
         } else if (operation == OPERATION_LE) {
-            sb.append("<=");
+            sb.append(" <= ");
         } else if (operation == OPERATION_LIKE) {
             sb.append(" LIKE ");
         } else if (operation == OPERATION_LT) {
-            sb.append("<");
+            sb.append(" < ");
         } else if (operation == OPERATION_NE) {
-            sb.append("<>");
+            sb.append(" <> ");
         } else {
             throw new RuntimeException("invalid operation: " + operation);
         }
@@ -247,7 +301,7 @@
             sb.append(valueDouble);
         } else if (type == TYPE_STRING) {
             sb.append("\"").append(valueString).append("\"");
-        } else if (type == TYPE_DATE) {
+        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
             Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
             cal.setTime(valueDate);
             sb.append(ISO8601.format(cal));
@@ -258,12 +312,93 @@
     }
 
     /**
+     * Returns a JCR SQL representation for this query node.
+     *
+     * @return a JCR SQL representation for this query node.
+     */
+    public String toJCRSQLString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("\"" + property + "\"");
+
+        if (operation == OPERATION_EQ) {
+            sb.append(" = ");
+        } else if (operation == OPERATION_GE) {
+            sb.append(" >= ");
+        } else if (operation == OPERATION_GT) {
+            sb.append(" > ");
+        } else if (operation == OPERATION_LE) {
+            sb.append(" <= ");
+        } else if (operation == OPERATION_LIKE) {
+            sb.append(" LIKE ");
+        } else if (operation == OPERATION_LT) {
+            sb.append(" < ");
+        } else if (operation == OPERATION_NE) {
+            sb.append(" <> ");
+        } else {
+            throw new RuntimeException("invalid operation: " + operation);
+        }
+
+
+        if (type == TYPE_LONG) {
+            sb.append(valueLong);
+        } else if (type == TYPE_DOUBLE) {
+            sb.append(valueDouble);
+        } else if (type == TYPE_STRING) {
+            sb.append("'").append(valueString.replaceAll("'", "''")).append("'");
+        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+            cal.setTime(valueDate);
+            sb.append("TIMESTAMP '").append(ISO8601.format(cal)).append("'");
+        } else {
+            throw new RuntimeException("Invalid type: " + type);
+        }
+        return sb.toString();
+    }
+
+    /**
      * Returns an XPath representation for this query node.
      *
      * @return an XPath representation for this query node.
      */
     public String toXPathString() {
-        // todo implement
-        return "";
+        StringBuffer sb = new StringBuffer();
+        // @todo use escaping for property name
+        sb.append("@" + property);
+
+        if (operation == OPERATION_EQ) {
+            sb.append(" = ");
+        } else if (operation == OPERATION_GE) {
+            sb.append(" >= ");
+        } else if (operation == OPERATION_GT) {
+            sb.append(" > ");
+        } else if (operation == OPERATION_LE) {
+            sb.append(" <= ");
+        } else if (operation == OPERATION_LIKE) {
+            // @todo make namespace aware
+            sb.insert(0, "jcrfn:like(").append(",");
+        } else if (operation == OPERATION_LT) {
+            sb.append(" < ");
+        } else if (operation == OPERATION_NE) {
+            sb.append(" != ");
+        } else {
+            throw new RuntimeException("invalid operation: " + operation);
+        }
+
+
+        if (type == TYPE_LONG) {
+            sb.append(valueLong);
+        } else if (type == TYPE_DOUBLE) {
+            sb.append(valueDouble);
+        } else if (type == TYPE_STRING) {
+            sb.append("'").append(valueString.replaceAll("'", "''")).append("'");
+        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+            cal.setTime(valueDate);
+            // @todo make namespace aware
+            sb.append("xs:dateTime('").append(ISO8601.format(cal)).append("')");
+        } else {
+            throw new RuntimeException("Invalid type: " + type);
+        }
+        return sb.toString();
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java	Wed Dec 22 10:15:05 2004
@@ -62,13 +62,16 @@
         return "TEXTSEARCH \"" + query + "\"";
     }
 
+    public String toJCRSQLString() {
+        return "CONTAINS('" + query + "')";
+    }
+
     /**
      * Returns an XPath representation for this query node.
      *
      * @return an XPath representation for this query node.
      */
     public String toXPathString() {
-        // todo implement
-        return "";
+        return "jcrfn:contains('" + query.replaceAll("'", "''") + "')";
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jj	Wed Dec 22 10:15:05 2004
@@ -16,7 +16,7 @@
   BUILD_PARSER = true;
   BUILD_TOKEN_MANAGER = true;
   SANITY_CHECK = true;
-  FORCE_LA_CHECK = true;                                                                                                       
+  FORCE_LA_CHECK = true;                                                                                                   
 }
 
 PARSER_BEGIN(JCRQLParser)
@@ -950,7 +950,7 @@
                            jjtree.closeNodeScope(jjtn000, true);
                            jjtc000 = false;
                          }
-/*@egen*/         { jjtn000.setType(Constants.TYPE_DATE);   jjtn000.setValue(t.image); }
+/*@egen*/         { jjtn000.setType(Constants.TYPE_TIMESTAMP);   jjtn000.setValue(t.image); }
 | t = <STRING_LITERAL>/*@bgen(jjtree)*/
                          {
                            jjtree.closeNodeScope(jjtn000, true);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQL.jjt	Wed Dec 22 10:15:05 2004
@@ -584,7 +584,7 @@
 | t = <FALSE>            { jjtThis.setType(Constants.TYPE_STRING); jjtThis.setValue(t.image); }
 | value = ItemPath()     { jjtThis.setType(Constants.TYPE_STRING); jjtThis.setValue(value); }
 | t = <UUID>             { jjtThis.setType(Constants.TYPE_STRING); jjtThis.setValue(t.image); }
-| t = <ISO_DATE>         { jjtThis.setType(Constants.TYPE_DATE);   jjtThis.setValue(t.image); }
+| t = <ISO_DATE>         { jjtThis.setType(Constants.TYPE_TIMESTAMP);   jjtThis.setValue(t.image); }
 | t = <STRING_LITERAL>   { jjtThis.setType(Constants.TYPE_STRING); jjtThis.setValue(t.image.substring(1, t.image.length()-1)); }
   )
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParser.java	Wed Dec 22 10:15:05 2004
@@ -1119,7 +1119,7 @@
                     t = jj_consume_token(ISO_DATE);
                     jjtree.closeNodeScope(jjtn000, true);
                     jjtc000 = false;
-                    jjtn000.setType(Constants.TYPE_DATE);
+                    jjtn000.setType(Constants.TYPE_TIMESTAMP);
                     jjtn000.setValue(t.image);
                     break;
                 case STRING_LITERAL:
@@ -1311,9 +1311,7 @@
         token = new Token();
         jj_ntk = -1;
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     public void ReInit(java.io.InputStream stream) {
@@ -1323,9 +1321,7 @@
         jj_ntk = -1;
         jjtree.reset();
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     public JCRQLParser(java.io.Reader stream) {
@@ -1334,9 +1330,7 @@
         token = new Token();
         jj_ntk = -1;
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     public void ReInit(java.io.Reader stream) {
@@ -1346,9 +1340,7 @@
         jj_ntk = -1;
         jjtree.reset();
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     public JCRQLParser(JCRQLParserTokenManager tm) {
@@ -1356,9 +1348,7 @@
         token = new Token();
         jj_ntk = -1;
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     public void ReInit(JCRQLParserTokenManager tm) {
@@ -1367,9 +1357,7 @@
         jj_ntk = -1;
         jjtree.reset();
         jj_gen = 0;
-        for (int i = 0; i < 28; i++) {
-            jj_la1[i] = -1;
-        }
+        for (int i = 0; i < 28; i++) jj_la1[i] = -1;
     }
 
     final private Token jj_consume_token(int kind) throws ParseException {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLParserTokenManager.java	Wed Dec 22 10:15:05 2004
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.core.search.jcrql;
 
-
 public class JCRQLParserTokenManager implements JCRQLParserConstants {
     public java.io.PrintStream debugStream = System.out;
 
@@ -1712,9 +1711,8 @@
     private final void ReInitRounds() {
         int i;
         jjround = 0x80000001;
-        for (i = 98; i-- > 0;) {
+        for (i = 98; i-- > 0;)
             jjrounds[i] = 0x80000000;
-        }
     }
 
     public void ReInit(SimpleCharStream stream, int lexState) {
@@ -1767,9 +1765,8 @@
 
             try {
                 input_stream.backup(0);
-                while (curChar <= 32 && (0x100002400L & (1L << curChar)) != 0L) {
+                while (curChar <= 32 && (0x100002400L & (1L << curChar)) != 0L)
                     curChar = input_stream.BeginToken();
-                }
             } catch (java.io.IOException e1) {
                 continue EOFLoop;
             }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/JCRQLQueryBuilder.java	Wed Dec 22 10:15:05 2004
@@ -16,20 +16,41 @@
 package org.apache.jackrabbit.core.search.jcrql;
 
 import org.apache.jackrabbit.core.search.*;
+import org.apache.log4j.Logger;
 
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.util.ISO8601;
 import java.util.Date;
+import java.util.Arrays;
 
 /**
  * Query builder that translates a JCRQL statement into query tree structure.
  */
 public class JCRQLQueryBuilder implements JCRQLParserVisitor {
 
+    private static final Logger log = Logger.getLogger(JCRQLQueryBuilder.class);
+
+    /**
+     * Match path exact
+     */
+    public static final int TYPE_EXACT = 1;
+
+    /**
+     * Match child nodes of path
+     */
+    public static final int TYPE_CHILDREN = 2;
+
+    /**
+     * Match descendant nodes or self of path
+     */
+    public static final int TYPE_DESCENDANT_SELF = 3;
+
     private final ASTStatement stmt;
 
     private QueryRootNode root;
 
+    private AndQueryNode constraintNode = new AndQueryNode(null);
+
     private JCRQLQueryBuilder(ASTStatement stmt) {
         this.stmt = stmt;
     }
@@ -60,9 +81,22 @@
 
     public Object visit(ASTStatement node, Object data) {
         QueryRootNode root = new QueryRootNode();
+        root.setLocationNode(new PathQueryNode(root));
 
-        node.childrenAccept(this, root);
         // pass to select, from, location, where, textsearch clause
+        node.childrenAccept(this, root);
+
+        // use //* if no path has been set
+        PathQueryNode pathNode = root.getLocationNode();
+        if (pathNode.getPathSteps().length == 0) {
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
+        }
+
+        // attach constraint to last path step
+        LocationStepQueryNode[] steps = pathNode.getPathSteps();
+        steps[steps.length - 1].addPredicate(constraintNode);
+
         return root;
     }
 
@@ -76,9 +110,7 @@
     }
 
     public Object visit(ASTFromClause node, Object data) {
-        QueryRootNode root = (QueryRootNode) data;
-        // add node type query to parent
-        node.childrenAccept(this, root.getConstraintNode());
+        node.childrenAccept(this, constraintNode);
 
         return data;
     }
@@ -91,15 +123,60 @@
 
     public Object visit(ASTLocationClause node, Object data) {
         QueryRootNode root = (QueryRootNode) data;
-        root.setLocationNode(new PathQueryNode(root, node.getStringLocation(),
-                node.getType()));
+        PathQueryNode pathNode = root.getLocationNode();
+
+        String path = node.getStringLocation();
+        String[] names = path.split("/");
+        for (int i = 0; i < names.length; i++) {
+            if (names[i].length() == 0) {
+                if (i == 0) {
+                    // root
+                    pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+                } else {
+                    log.error("Internal error: descendant-or-self axis not allowed here");
+                }
+            } else {
+                int idx = names[i].indexOf('[');
+                String name = null;
+                int index = 0;
+                if (idx > -1) {
+                    // contains index
+                    name = names[i].substring(0, idx);
+                    String suffix = names[i].substring(idx);
+                    try {
+                        index = Integer.parseInt(suffix.substring(1, suffix.length() - 1));
+                    } catch (NumberFormatException e) {
+                        log.warn("Unable to parse index for path element: " + names[i]);
+                    }
+                } else {
+                    // no index
+                    name = names[i];
+                }
+                if (name.equals("%") || name.equals("*")) {
+                    name = null;
+                }
+                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, name, false);
+                if (index > 0) {
+                    step.setIndex(index);
+                }
+                pathNode.addPathStep(step);
+            }
+        }
+
+        if (node.getType() == TYPE_CHILDREN) {
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, false));
+        } else if (node.getType() == TYPE_DESCENDANT_SELF) {
+            //LocationStepQueryNode[] steps = pathNode.getPathSteps();
+            //steps[steps.length - 1].setIncludeDescendants(true);
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
+        }
+
         return root;
     }
 
     public Object visit(ASTWhereClause node, Object data) {
-        QueryRootNode root = (QueryRootNode) data;
         // just pass it to the expression
-        return node.childrenAccept(this, root.getConstraintNode());
+        return node.childrenAccept(this, constraintNode);
     }
 
     public Object visit(ASTOrExpr node, Object data) {
@@ -138,7 +215,7 @@
         int type = value.getType();
         RelationQueryNode rel = null;
 
-        if (type == Constants.TYPE_DATE) {
+        if (type == Constants.TYPE_TIMESTAMP) {
             Date date = ISO8601.parse(value.getValue()).getTime();
             rel = new RelationQueryNode(parent,
                     node.getProperty(),
@@ -182,14 +259,16 @@
     }
 
     public Object visit(ASTTextsearchClause node, Object data) {
-        QueryRootNode root = (QueryRootNode) data;
-        root.setTextsearchNode(new TextsearchQueryNode(root, node.getQuery()));
-        return root;
+        constraintNode.addOperand(new TextsearchQueryNode(constraintNode, node.getQuery()));
+        return data;
     }
 
     public Object visit(ASTOrderClause node, Object data) {
         QueryRootNode root = (QueryRootNode) data;
-        root.setOrderNode(new OrderQueryNode(root, node.getProperties(), node.isAscending()));
+        String[] props = node.getProperties();
+        boolean[] orders = new boolean[props.length];
+        Arrays.fill(orders, node.isAscending());
+        root.setOrderNode(new OrderQueryNode(root, props, orders));
         return root;
     }
 }

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/ChildAxisQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/ChildAxisQuery.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/ChildAxisQuery.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.lucene;
+
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.HitCollector;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
+
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Implements a lucene <code>Query</code> which returns the child nodes of the
+ * nodes selected by another <code>Query</code>.
+ */
+class ChildAxisQuery extends Query {
+
+    /** The context query */
+    private final Query contextQuery;
+
+    /** The scorer of the context query */
+    private Scorer contextScorer;
+
+    /**
+     * Creates a new <code>ChildAxisQuery</code> based on a <code>context</code>
+     * query.
+     * @param context the context for this query.
+     */
+    ChildAxisQuery(Query context) {
+        this.contextQuery = context;
+    }
+
+    /**
+     * Creates a <code>Weight</code> instance for this query.
+     * @param searcher the <code>Searcher</code> instance to use.
+     * @return a <code>ChildAxisWeight</code>.
+     */
+    protected Weight createWeight(Searcher searcher) {
+        return new ChildAxisWeight(searcher);
+    }
+
+    /**
+     * Always returns 'ChildAxisQuery'.
+     * @param field the name of a field.
+     * @return 'ChildAxisQuery'.
+     */
+    public String toString(String field) {
+        return "ChildAxisQuery";
+    }
+
+    //-------------------< ChildAxisWeight >------------------------------------
+
+    /**
+     * The <code>Weight</code> implementation for this <code>ChildAxisQuery</code>.
+     */
+    private class ChildAxisWeight implements Weight {
+
+        /** The searcher in use */
+        private final Searcher searcher;
+
+        /**
+         * Creates a new <code>ChildAxisWeight</code> instance using
+         * <code>searcher</code>.
+         * @param searcher a <code>Searcher</code> instance.
+         */
+        private ChildAxisWeight(Searcher searcher) {
+            this.searcher = searcher;
+        }
+
+        /**
+         * Returns this <code>ChildAxisQuery</code>.
+         * @return this <code>ChildAxisQuery</code>.
+         */
+        public Query getQuery() {
+            return ChildAxisQuery.this;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#getValue()
+         */
+        public float getValue() {
+            // @todo implement properly
+            return 0;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#sumOfSquaredWeights()
+         */
+        public float sumOfSquaredWeights() throws IOException {
+            // @todo implement properly
+            return 0;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#normalize(float)
+         */
+        public void normalize(float norm) {
+            // @todo implement properly
+        }
+
+        /**
+         * Creates a scorer for this <code>ChildAxisQuery</code>.
+         * @param reader a reader for accessing the index.
+         * @return a <code>ChildAxisScorer</code>.
+         * @throws IOException if an error occurs while reading from the index.
+         */
+        public Scorer scorer(IndexReader reader) throws IOException {
+            contextScorer = contextQuery.weight(searcher).scorer(reader);
+            return new ChildAxisScorer(searcher.getSimilarity(), reader);
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int)
+         */
+        public Explanation explain(IndexReader reader, int doc) throws IOException {
+            return new Explanation();
+        }
+    }
+
+    //----------------------< ChildAxisScorer >---------------------------------
+
+    /**
+     * Implements a <code>Scorer</code> for this <code>ChildAxisQuery</code>.
+     */
+    private class ChildAxisScorer extends Scorer {
+
+        /** An <code>IndexReader</code> to access the index. */
+        private final IndexReader reader;
+
+        /** BitSet storing the id's of selected documents */
+        private final BitSet hits;
+
+        /** List of UUIDs of selected nodes */
+        private List uuids = null;
+
+        /** The next document id to return */
+        private int nextDoc = 0;
+
+        /**
+         * Creates a new <code>ChildAxisScorer</code>.
+         * @param similarity the <code>Similarity</code> instance to use.
+         * @param reader for index access.
+         */
+        protected ChildAxisScorer(Similarity similarity, IndexReader reader) {
+            super(similarity);
+            this.reader = reader;
+            this.hits = new BitSet(reader.maxDoc());
+        }
+
+        /**
+         * @see Scorer#score(org.apache.lucene.search.HitCollector, int)
+         */
+        public void score(HitCollector hc, int maxDoc) throws IOException {
+            if (uuids == null) {
+                uuids = new ArrayList();
+                contextScorer.score(new HitCollector() {
+                    public void collect(int doc, float score) {
+                        // @todo maintain cache of doc id hierarchy
+                        hits.set(doc);
+                    }
+                }, reader.maxDoc()); // find all
+                for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
+                    String uuid = reader.document(i).get(FieldNames.UUID);
+                    uuids.add(uuid);
+                }
+
+                hits.clear();
+                for (Iterator it = uuids.iterator(); it.hasNext();) {
+                    TermDocs children = reader.termDocs(new Term(FieldNames.PARENT, (String) it.next()));
+                    while (children.next()) {
+                        hits.set(children.doc());
+                    }
+                }
+                nextDoc = hits.nextSetBit(0);
+            }
+
+            while (nextDoc > -1 && nextDoc < maxDoc) {
+                hc.collect(nextDoc, 1.0f);
+                // move to next doc
+                nextDoc = hits.nextSetBit(nextDoc + 1);
+            }
+        }
+
+        /**
+         * @exception UnsupportedOperationException this implementation always
+         * throws an <code>UnsupportedOperationException</code>.
+         */
+        public Explanation explain(int doc) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/DescendantSelfAxisQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/DescendantSelfAxisQuery.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/DescendantSelfAxisQuery.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.lucene;
+
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.HitCollector;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.index.Term;
+
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * Implements a lucene <code>Query</code> which filters a sub query by checking
+ * whether the nodes selected by that sub query are descendants or self of
+ * nodes selected by a context query.
+ */
+class DescendantSelfAxisQuery extends Query {
+
+    /** The context query */
+    private final Query contextQuery;
+
+    /** The scorer of the context query */
+    private Scorer contextScorer;
+
+    /** The sub query to filter */
+    private final Query subQuery;
+
+    /** The scorer of the sub query to filter */
+    private Scorer subScorer;
+
+    /**
+     * Creates a new <code>DescendantSelfAxisQuery</code> based on a
+     * <code>context</code> query and filtering the <code>sub</code> query.
+     * @param context the context for this query.
+     * @param sub the sub query.
+     */
+    public DescendantSelfAxisQuery(Query context, Query sub) {
+        this.contextQuery = context;
+        this.subQuery = sub;
+    }
+
+    /**
+     * Creates a <code>Weight</code> instance for this query.
+     * @param searcher the <code>Searcher</code> instance to use.
+     * @return a <code>DescendantSelfAxisWeight</code>.
+     */
+    protected Weight createWeight(Searcher searcher) {
+        return new DescendantSelfAxisWeight(searcher);
+    }
+
+    /**
+     * Always returns 'DescendantSelfAxisQuery'.
+     * @param field the name of a field.
+     * @return 'DescendantSelfAxisQuery'.
+     */
+    public String toString(String field) {
+        return "DescendantSelfAxisQuery";
+    }
+
+    //------------------------< DescendantSelfAxisWeight >--------------------------
+
+    /**
+     * The <code>Weight</code> implementation for this
+     * <code>DescendantSelfAxisWeight</code>.
+     */
+    private class DescendantSelfAxisWeight implements Weight {
+
+        /** The searcher in use */
+        private final Searcher searcher;
+
+        /**
+         * Creates a new <code>DescendantSelfAxisWeight</code> instance using
+         * <code>searcher</code>.
+         * @param searcher a <code>Searcher</code> instance.
+         */
+        private DescendantSelfAxisWeight(Searcher searcher) {
+            this.searcher = searcher;
+        }
+
+        /**
+         * Returns this <code>DescendantSelfAxisQuery</code>.
+         * @return this <code>DescendantSelfAxisQuery</code>.
+         */
+        public Query getQuery() {
+            return DescendantSelfAxisQuery.this;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#getValue()
+         */
+        public float getValue() {
+            // @todo implement properly
+            return 0;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#sumOfSquaredWeights()
+         */
+        public float sumOfSquaredWeights() throws IOException {
+            // @todo implement properly
+            return 0;
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#normalize(float)
+         */
+        public void normalize(float norm) {
+            // @todo implement properly
+        }
+
+        /**
+         * Creates a scorer for this <code>DescendantSelfAxisScorer</code>.
+         * @param reader a reader for accessing the index.
+         * @return a <code>DescendantSelfAxisScorer</code>.
+         * @throws IOException if an error occurs while reading from the index.
+         */
+        public Scorer scorer(IndexReader reader) throws IOException {
+            contextScorer = contextQuery.weight(searcher).scorer(reader);
+            subScorer = subQuery.weight(searcher).scorer(reader);
+            return new DescendantSelfAxisScorer(searcher.getSimilarity(), reader);
+        }
+
+        /**
+         * @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int)
+         */
+        public Explanation explain(IndexReader reader, int doc) throws IOException {
+            return new Explanation();
+        }
+    }
+
+    //----------------------< DescendantSelfAxisScorer >---------------------------------
+
+    /**
+     * Implements a <code>Scorer</code> for this
+     * <code>DescendantSelfAxisQuery</code>.
+     */
+    private class DescendantSelfAxisScorer extends Scorer {
+
+        /** An <code>IndexReader</code> to access the index. */
+        private final IndexReader reader;
+
+        /** BitSet storing the id's of selected documents */
+        private final BitSet hits;
+
+        /** BitSet storing the id's of selected documents from the sub query */
+        private final BitSet subHits;
+
+        /** List of UUIDs of selected nodes by the context query */
+        private Set contextUUIDs = null;
+
+        /** The next document id to return */
+        private int nextDoc = 0;
+
+        /**
+         * Creates a new <code>DescendantSelfAxisScorer</code>.
+         * @param similarity the <code>Similarity</code> instance to use.
+         * @param reader for index access.
+         */
+        protected DescendantSelfAxisScorer(Similarity similarity, IndexReader reader) {
+            super(similarity);
+            this.reader = reader;
+            this.hits = new BitSet(reader.maxDoc());
+            this.subHits = new BitSet(reader.maxDoc());
+        }
+
+        /**
+         * @see Scorer#score(org.apache.lucene.search.HitCollector, int)
+         */
+        public void score(HitCollector hc, int maxDoc) throws IOException {
+            if (contextUUIDs == null) {
+                contextUUIDs = new HashSet();
+                contextScorer.score(new HitCollector() {
+                    public void collect(int doc, float score) {
+                        // @todo maintain cache of doc id hierarchy
+                        hits.set(doc);
+                    }
+                }, reader.maxDoc()); // find all
+                for (int i = hits.nextSetBit(0); i >= 0; i = hits.nextSetBit(i + 1)) {
+                    contextUUIDs.add(reader.document(i).get(FieldNames.UUID));
+                }
+
+                // reuse for final hits
+                hits.clear();
+
+                subScorer.score(new HitCollector() {
+                    public void collect(int doc, float score) {
+                        subHits.set(doc);
+                    }
+                }, reader.maxDoc());
+
+                nextDoc = subHits.nextSetBit(0);
+            }
+
+            while (nextDoc > -1 && nextDoc < maxDoc) {
+                // check if nextDoc is really valid
+                String parentUUID = reader.document(nextDoc).get(FieldNames.PARENT);
+                while (parentUUID != null && !contextUUIDs.contains(parentUUID)) {
+                    // traverse
+                    TermDocs ancestor = reader.termDocs(new Term(FieldNames.UUID, parentUUID));
+                    if (ancestor.next()) {
+                        parentUUID = reader.document(ancestor.doc()).get(FieldNames.PARENT);
+                        if (parentUUID.length() == 0) {
+                            parentUUID = null;
+                        }
+                    } else {
+                        parentUUID = null;
+                    }
+                }
+                if (parentUUID != null) {
+                    // match
+                    hc.collect(nextDoc, 1.0f);
+                }
+                // move to next doc
+                nextDoc = subHits.nextSetBit(nextDoc + 1);
+
+            }
+        }
+
+        /**
+         * @exception UnsupportedOperationException this implementation always
+         * throws an <code>UnsupportedOperationException</code>.
+         */
+        public Explanation explain(int doc) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java	Wed Dec 22 10:15:05 2004
@@ -16,20 +16,32 @@
 package org.apache.jackrabbit.core.search.lucene;
 
 /**
- * Defines field names that are used internally to store UUID, Path, etc in the
+ * Defines field names that are used internally to store UUID, etc in the
  * search index.
  */
 public class FieldNames {
 
+    /**
+     * Name of the field that contains the UUID of the node. Terms are stored
+     * but not tokenized.
+     */
     public static final String UUID = "_:UUID";
 
-    public static final String PATH = "_:Path";
-
+    /**
+     * Name of the field that contains the fulltext index including terms
+     * from all properties of a node. Terms are tokenized.
+     */
     public static final String FULLTEXT = "_:FULLTEXT";
 
-    public static final String ANCESTORS = "_:ANCESTORS";
-
+    /**
+     * Name of the field that contains the UUID of the parent node. Terms are
+     * stored and but not tokenized.
+     */
+    public static final String PARENT = "_:PARENT";
+
+    /**
+     * Name of the field that contains the label of the node. Terms are not
+     * tokenized.
+     */
     public static final String LABEL = "_:LABEL";
-
-    public static final String LEVEL = "_:LEVEL";
 }

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredScorer.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredScorer.java?view=auto&rev=123134
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LocationStepQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LocationStepQuery.java?view=auto&rev=123134
==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java	Wed Dec 22 10:15:05 2004
@@ -15,11 +15,12 @@
  */
 package org.apache.jackrabbit.core.search.lucene;
 
-import org.apache.jackrabbit.core.MalformedPathException;
-import org.apache.jackrabbit.core.Path;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.IllegalNameException;
 import org.apache.jackrabbit.core.UnknownPrefixException;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.search.*;
 import org.apache.log4j.Logger;
@@ -46,6 +47,8 @@
 
     private static final Logger log = Logger.getLogger(LuceneQueryBuilder.class);
 
+    private static QName primaryType = new QName(NamespaceRegistryImpl.NS_JCR_URI, "primaryType");
+
     private QueryRootNode root;
 
     private SessionImpl session;
@@ -92,10 +95,6 @@
 
     public Object visit(QueryRootNode node, Object data) {
         BooleanQuery root = new BooleanQuery();
-        Query constraintQuery = (Query) node.getConstraintNode().accept(this, null);
-        if (constraintQuery != null) {
-            root.add(constraintQuery, true, false);
-        }
 
         String[] props = node.getSelectProperties();
         for (int i = 0; i < props.length; i++) {
@@ -110,14 +109,6 @@
             root.add(new MatchAllQuery(prop), true, false);
         }
 
-        TextsearchQueryNode textsearchNode = node.getTextsearchNode();
-        if (textsearchNode != null) {
-            Query textsearch = (Query) textsearchNode.accept(this, null);
-            if (textsearch != null) {
-                root.add(textsearch, true, false);
-            }
-        }
-
         Query wrapped = root;
         if (node.getLocationNode() != null) {
             wrapped = (Query) node.getLocationNode().accept(this, root);
@@ -151,9 +142,17 @@
 
     public Object visit(NotQueryNode node, Object data) {
         BooleanQuery notQuery = new BooleanQuery();
+        try {
+            // first select any node
+            notQuery.add(new MatchAllQuery(primaryType.toJCRName(nsMappings)),
+                    false, false);
+        } catch (NoPrefixDeclaredException e) {
+            // will never happen, prefixes are created when unknown
+        }
         Object[] result = node.acceptOperands(this, null);
         for (int i = 0; i < result.length; i++) {
             Query operand = (Query) result[i];
+            // then prohibit the nodes from the not clause
             notQuery.add(operand, false, true);
         }
         return notQuery;
@@ -258,23 +257,82 @@
     }
 
     public Object visit(PathQueryNode node, Object data) {
-        PathQuery pathQuery = null;
-        try {
-            // FIXME what about relative path?
-            Path p = Path.create(node.getPath(),
-                    session.getNamespaceResolver(), false);
-            pathQuery = new PathQuery(p, nsMappings, node.getType());
-        } catch (MalformedPathException e) {
-            exceptions.add(e);
+        Query context = null;
+        // loop over steps
+        QueryNode[] steps = node.getPathSteps();
+        for (int i = 0; i < steps.length; i++) {
+            context = (Query) steps[i].accept(this, context);
+        }
+        if (data instanceof BooleanQuery) {
+            BooleanQuery constraint = (BooleanQuery) data;
+            if (constraint.getClauses().length > 0) {
+                constraint.add(context, true, false);
+                context = constraint;
+            }
+        }
+        return context;
+    }
+
+    public Object visit(LocationStepQueryNode node, Object data) {
+        if (node.getNameTest() != null && node.getNameTest().length() == 0) {
+            // select root node
+            return new TermQuery(new Term(FieldNames.PARENT, ""));
+        }
+
+        Query context = (Query) data;
+
+        BooleanQuery andQuery = new BooleanQuery();
+        if (context == null) {
+            exceptions.add(new IllegalArgumentException("Unsupported query"));
+        }
+
+        // predicate on step?
+        Object[] predicates = node.acceptOperands(this, data);
+        for (int i = 0; i < predicates.length; i++) {
+            andQuery.add((Query) predicates[i], true, false);
         }
-        if (pathQuery != null && pathQuery.getClauses().length > 0) {
-            BooleanQuery combined = new BooleanQuery();
-            combined.add(pathQuery, true, false);
-            combined.add((Query) data, true, false);
-            return combined;
+
+        TermQuery nameTest = null;
+        if (node.getNameTest() != null) {
+            try {
+                String internalName = nsMappings.translatePropertyName(node.getNameTest(),
+                        session.getNamespaceResolver());
+                nameTest = new TermQuery(new Term(FieldNames.LABEL, internalName));
+            } catch (IllegalNameException e) {
+                exceptions.add(e);
+            } catch (UnknownPrefixException e) {
+                exceptions.add(e);
+            }
+        }
+
+        if (node.getIncludeDescendants()) {
+            if (nameTest != null) {
+                andQuery.add(new DescendantSelfAxisQuery(context, nameTest), true, false);
+            } else {
+                // descendant-or-self with nametest=*
+                if (predicates.length > 0) {
+                    // if we have a predicate attached, the condition acts as
+                    // the sub query.
+                    Query subQuery = new DescendantSelfAxisQuery(context, andQuery);
+                    andQuery = new BooleanQuery();
+                    andQuery.add(subQuery, true, false);
+                } else {
+                    // @todo this will traverse the whole index, optimize!
+                    Query subQuery = new MatchAllQuery(FieldNames.UUID);
+                    andQuery.add(new DescendantSelfAxisQuery(context, subQuery), true, false);
+                }
+            }
         } else {
-            return data;
+            // select child nodes
+            andQuery.add(new ChildAxisQuery(context), true, false);
+
+            // name test
+            if (nameTest != null) {
+                andQuery.add(nameTest, true, false);
+            }
         }
+
+        return andQuery;
     }
 
     public Object visit(RelationQueryNode node, Object data) {
@@ -322,6 +380,7 @@
                 query = new RangeQuery(null, new Term(field, stringValue), true);
                 break;
             case Constants.OPERATION_LIKE:	// LIKE
+                // @todo use MatchAllQuery if stringValue is "*" (or "%" ?)
                 query = new WildcardQuery(new Term(field, stringValue));
                 break;
             case Constants.OPERATION_LT:	// <
@@ -341,9 +400,6 @@
     }
 
     public Object visit(OrderQueryNode node, Object data) {
-        return null;
+        return data;
     }
-
-    //---------------------------< internal >-----------------------------------
-
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	Wed Dec 22 10:15:05 2004
@@ -64,31 +64,18 @@
         // UUID
         doc.add(new Field(FieldNames.UUID, node.getUUID(), true, true, false));
         try {
-            // Path
-            doc.add(new Field(FieldNames.PATH, path.toJCRPath(mappings), true, true, false));
-            Path p = null;
+            // parent UUID
             if (path.denotesRoot()) {
-                p = path;
+                doc.add(new Field(FieldNames.PARENT, "", true, true, false));
             } else {
-                p = path.getAncestor(1);
-            }
-            // Ancestors
-            while (!p.denotesRoot()) {
-                doc.add(new Field(FieldNames.ANCESTORS, p.toJCRPath(mappings),
-                        false, true, false));
-                p = p.getAncestor(1);
+                doc.add(new Field(FieldNames.PARENT, node.getParentUUID(), true, true, false));
             }
             // Label
             doc.add(new Field(FieldNames.LABEL, path.getNameElement().toJCRName(mappings),
                     false, true, false));
-            // hierarchy level
-            doc.add(new Field(FieldNames.LEVEL, String.valueOf(path.getAncestorCount()),
-                    false, true, false));
         } catch (NoPrefixDeclaredException e) {
             // will never happen, because this.mappings will dynamically add
             // unknown uri<->prefix mappings
-        } catch (PathNotFoundException e) {
-            // will never happen because we check for root
         }
 
         List props = node.getPropertyEntries();

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PackageFilter.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PackageFilter.java?view=auto&rev=123134
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilter.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilter.java?view=auto&rev=123134
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilterQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathFilterQuery.java?view=auto&rev=123134
==============================================================================

Deleted: /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PathQuery.java?view=auto&rev=123134
==============================================================================

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java	Wed Dec 22 10:15:05 2004
@@ -71,7 +71,7 @@
 
         // parse query according to language
         // build query tree
-        this.root = QueryParser.parse(statement, language);
+        this.root = QueryParser.parse(statement, language, session.getNamespaceResolver());
     }
 
     public QueryImpl(SessionImpl session,
@@ -106,7 +106,7 @@
 
             // parse query according to language
             // build query tree and pass to QueryImpl
-            QueryRootNode root = QueryParser.parse(statement, language);
+            QueryRootNode root = QueryParser.parse(statement, language, session.getNamespaceResolver());
             this.root = root;
         } catch (NoPrefixDeclaredException e) {
             throw new InvalidQueryException(e.getMessage(), e);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java	Wed Dec 22 10:15:05 2004
@@ -118,7 +118,7 @@
 
     public Hits executeQuery(Query query,
                              String[] orderProps,
-                             boolean ascending) throws IOException {
+                             boolean[] orderSpecs) throws IOException {
         try {
             readWriteLock.readLock().acquire();
         } catch (InterruptedException e) {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java&r1=123134&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java	Wed Dec 22 10:15:05 2004
@@ -74,7 +74,7 @@
                     escaped = true;
                 }
             } else {
-                if (Character.isLetter(likePattern.charAt(i))) {
+                if (Character.isLetterOrDigit(likePattern.charAt(i))) {
                     if (escaped) {
                         regexp.append("\\\\").append(likePattern.charAt(i));
                         escaped = false;

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+public class ASTContainsExpression extends SimpleNode {
+    private String query;
+
+    public ASTContainsExpression(int id) {
+        super(id);
+    }
+
+    public ASTContainsExpression(JCRSQLParser p, int id) {
+        super(p, id);
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+
+    /**
+     * Accept the visitor. *
+     */
+    public Object jjtAccept(JCRSQLParserVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+public class ASTIdentifier extends SimpleNode {
+
+    private String name;
+
+    public ASTIdentifier(int id) {
+    super(id);
+  }
+
+  public ASTIdentifier(JCRSQLParser p, int id) {
+    super(p, id);
+  }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JCRSQLParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+
+    public String toString() {
+        return super.toString() + ": " + name;
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTLiteral.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTLiteral.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTLiteral.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+public class ASTLiteral extends SimpleNode {
+
+    private String value;
+
+    private int type;
+
+
+    public ASTLiteral(int id) {
+        super(id);
+    }
+
+    public ASTLiteral(JCRSQLParser p, int id) {
+        super(p, id);
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+
+    /**
+     * Accept the visitor. *
+     */
+    public Object jjtAccept(JCRSQLParserVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+    public String toString() {
+        return super.toString() + ": " + value + " type:" + type;
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+public class ASTPredicate extends SimpleNode {
+
+    private int operationType;
+
+    private boolean negate = false;
+
+    private String identifier;
+
+    private String identifierOperand;
+
+  public ASTPredicate(int id) {
+    super(id);
+  }
+
+  public ASTPredicate(JCRSQLParser p, int id) {
+    super(p, id);
+  }
+
+    public void setOperationType(int type) {
+        this.operationType = type;
+    }
+
+    public int getOperationType() {
+        return operationType;
+    }
+
+    public void setNegate(boolean b) {
+        this.negate = b;
+    }
+
+    public boolean isNegate() {
+        return this.negate;
+    }
+
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    public void setIdentifierOperand(String identifier) {
+        this.identifierOperand = identifier;
+    }
+
+    public String getIdentifierOperand() {
+        return identifierOperand;
+    }
+
+  /** Accept the visitor. **/
+  public Object jjtAccept(JCRSQLParserVisitor visitor, Object data) {
+    return visitor.visit(this, data);
+  }
+
+    public String toString() {
+        return super.toString() + " type: " + operationType + " negate: " + negate;
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/DefaultParserVisitor.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/DefaultParserVisitor.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/DefaultParserVisitor.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+/**
+ * Implements a {@link JCRSQLParserVisitor} with default method implementations.
+ * All visit method simply return the <code>data</code> parameter.
+ */
+class DefaultParserVisitor implements JCRSQLParserVisitor {
+
+    public Object visit(SimpleNode node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTQuery node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTSelectList node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTFromClause node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTWhereClause node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTPredicate node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTOrExpression node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTAndExpression node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTNotExpression node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTBracketExpression node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTLiteral node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTIdentifier node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTOrderByClause node, Object data) {
+        return data;
+    }
+
+    public Object visit(ASTContainsExpression node, Object data) {
+        return data;
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.sql;
+
+import org.apache.jackrabbit.core.search.QueryRootNode;
+import org.apache.jackrabbit.core.search.AndQueryNode;
+import org.apache.jackrabbit.core.search.NodeTypeQueryNode;
+import org.apache.jackrabbit.core.search.NAryQueryNode;
+import org.apache.jackrabbit.core.search.OrQueryNode;
+import org.apache.jackrabbit.core.search.NotQueryNode;
+import org.apache.jackrabbit.core.search.OrderQueryNode;
+import org.apache.jackrabbit.core.search.RelationQueryNode;
+import org.apache.jackrabbit.core.search.Constants;
+import org.apache.jackrabbit.core.search.QueryNode;
+import org.apache.jackrabbit.core.search.TextsearchQueryNode;
+import org.apache.jackrabbit.core.search.PathQueryNode;
+import org.apache.jackrabbit.core.search.LocationStepQueryNode;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.log4j.Logger;
+
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.util.ISO8601;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Calendar;
+import java.text.SimpleDateFormat;
+
+/**
+ * Implements the query builder for the JCR SQL syntax.
+ */
+public class JCRSQLQueryBuilder implements JCRSQLParserVisitor {
+
+    /** logger instance for this class */
+    private static final Logger log = Logger.getLogger(JCRSQLQueryBuilder.class);
+
+    /**
+     * DateFormat pattern for type
+     * {@link org.apache.jackrabbit.core.search.Constants.TYPE_DATE}.
+     */
+    private static final String DATE_PATTERN = "yyyy-MM-dd";
+
+    /**
+     * QName for jcr:path
+     */
+    private static final QName JCR_PATH = new QName(NamespaceRegistryImpl.NS_JCR_URI, "path");
+
+    /** The root node of the sql query syntax tree */
+    private final ASTQuery stmt;
+
+    /** The root query node */
+    private QueryRootNode root;
+
+    /** Query node to gather the constraints defined in the WHERE clause */
+    private final AndQueryNode constraintNode = new AndQueryNode(null);
+
+    /**
+     * The resolved jcr:path QName using the NamespaceResolver passed in the
+     * constructor.
+     */
+    private final String jcrPathResolved;
+
+    /**
+     * Creates a new <code>JCRSQLQueryBuilder</code>.
+     * @param statement the root node of the SQL syntax tree.
+     * @param resolver a namespace resolver to use for names in the
+     *   <code>statement</code>.
+     * @throws NoPrefixDeclaredException if a prefix in the statement cannot
+     *   be resolved.
+     */
+    private JCRSQLQueryBuilder(ASTQuery statement, NamespaceResolver resolver)
+            throws NoPrefixDeclaredException {
+        this.stmt = statement;
+        jcrPathResolved = JCR_PATH.toJCRName(resolver);
+    }
+
+    /**
+     * Creates a <code>QueryNode</code> tree from a SQL <code>statement</code>.
+     * @param statement the SQL statement.
+     * @param resolver the namespace resolver to use.
+     * @return the <code>QueryNode</code> tree.
+     * @throws InvalidQueryException if <code>statement</code> is malformed.
+     */
+    public static QueryRootNode createQuery(String statement, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        try {
+            JCRSQLQueryBuilder builder = new JCRSQLQueryBuilder(JCRSQLParser.parse(statement), resolver);
+            return builder.getRootNode();
+        } catch (ParseException e) {
+            throw new InvalidQueryException(e.getMessage());
+        } catch (NoPrefixDeclaredException e) {
+            throw new InvalidQueryException(e.getMessage());
+        }
+    }
+
+    /**
+     * Parses the statement and returns the root node of the <code>QueryNode</code>
+     * tree.
+     * @return the root node of the <code>QueryNode</code> tree.
+     */
+    private QueryRootNode getRootNode() {
+        if (root == null) {
+            stmt.jjtAccept(this, null);
+        }
+        return root;
+    }
+
+    //----------------< JCRSQLParserVisitor >------------------------------------
+
+    public Object visit(SimpleNode node, Object data) {
+        // do nothing, should never be called actually
+        return data;
+    }
+
+    public Object visit(ASTQuery node, Object data) {
+        root = new QueryRootNode();
+        root.setLocationNode(new PathQueryNode(root));
+
+        // pass to select, from, where, ...
+        node.childrenAccept(this, root);
+
+        // use //* if no path has been set
+        PathQueryNode pathNode = root.getLocationNode();
+        if (pathNode.getPathSteps().length == 0) {
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
+        }
+
+        // attach constraint to last path step
+        LocationStepQueryNode[] steps = pathNode.getPathSteps();
+        steps[steps.length - 1].addPredicate(constraintNode);
+
+        return root;
+    }
+
+    public Object visit(ASTSelectList node, Object data) {
+        final QueryRootNode root = (QueryRootNode) data;
+
+        node.childrenAccept(new DefaultParserVisitor() {
+            public Object visit(ASTIdentifier node, Object data) {
+                root.addSelectProperty(node.getName());
+                return data;
+            }
+        }, root);
+
+        return data;
+    }
+
+    public Object visit(ASTFromClause node, Object data) {
+        QueryRootNode root = (QueryRootNode) data;
+
+        return node.childrenAccept(new DefaultParserVisitor() {
+            public Object visit(ASTIdentifier node, Object data) {
+                // node is either primary or mixin node type
+                NodeTypeQueryNode nodeType
+                        = new NodeTypeQueryNode(constraintNode, node.getName());
+                constraintNode.addOperand(nodeType);
+                return data;
+            }
+        }, root);
+    }
+
+    public Object visit(ASTWhereClause node, Object data) {
+        return node.childrenAccept(this, constraintNode);
+    }
+
+    public Object visit(ASTPredicate node, Object data) {
+        NAryQueryNode parent = (NAryQueryNode) data;
+
+        if (node.isNegate()) {
+            parent = new NotQueryNode(parent);
+        }
+
+        int type = node.getOperationType();
+        QueryNode predicateNode = null;
+
+        String identifier = ((ASTIdentifier) node.children[0]).getName();
+        if (identifier.equals(jcrPathResolved)) {
+            if (node.children[1] instanceof ASTIdentifier) {
+                // simply ignore, this is a join of a mixin node type
+            } else {
+                createPathQuery(((ASTLiteral) node.children[1]).getValue());
+            }
+            // done
+            return data;
+        }
+
+        try {
+            if (type == Constants.OPERATION_BETWEEN) {
+                AndQueryNode between = new AndQueryNode(parent);
+                RelationQueryNode rel = createRelationQueryNode(between,
+                        identifier, Constants.OPERATION_GE, (ASTLiteral) node.children[1]);
+                between.addOperand(rel);
+                rel = createRelationQueryNode(between,
+                        identifier, Constants.OPERATION_LE, (ASTLiteral) node.children[2]);
+                between.addOperand(rel);
+                predicateNode = between;
+            } else if (type == Constants.OPERATION_EQ) {
+                if (node.children[1] instanceof ASTIdentifier) {
+                    // simply ignore, this is a join of a mixin node type
+                } else {
+                    predicateNode = createRelationQueryNode(parent,
+                            identifier, type, (ASTLiteral) node.children[1]);
+                }
+            } else if (type == Constants.OPERATION_GE
+                    || type == Constants.OPERATION_GT
+                    || type == Constants.OPERATION_LE
+                    || type == Constants.OPERATION_LIKE
+                    || type == Constants.OPERATION_LT
+                    || type == Constants.OPERATION_NE) {
+                predicateNode = createRelationQueryNode(parent,
+                        identifier, type, (ASTLiteral) node.children[1]);
+            } else if (type == Constants.OPERATION_IN) {
+                OrQueryNode in = new OrQueryNode(parent);
+                for (int i = 1; i < node.children.length; i++) {
+                    RelationQueryNode rel = createRelationQueryNode(in,
+                            identifier, Constants.OPERATION_EQ, (ASTLiteral) node.children[i]);
+                    in.addOperand(rel);
+                }
+                predicateNode = in;
+            } else if (type == Constants.OPERATION_NULL) {
+                ASTLiteral star = new ASTLiteral(JCRSQLParserTreeConstants.JJTLITERAL);
+                star.setType(Constants.TYPE_STRING);
+                star.setValue("*");
+                predicateNode = createRelationQueryNode(parent,
+                        identifier, Constants.OPERATION_LIKE, star);
+            }
+        } catch (IllegalArgumentException e) {
+            log.error(e.toString());
+        } catch (ArrayIndexOutOfBoundsException e) {
+            log.error("Too few arguments");
+        }
+
+        if (predicateNode != null) {
+            parent.addOperand(predicateNode);
+        }
+
+        return data;
+    }
+
+    public Object visit(ASTOrExpression node, Object data) {
+        NAryQueryNode parent = (NAryQueryNode) data;
+        OrQueryNode orQuery = new OrQueryNode(parent);
+        // pass to operands
+        node.childrenAccept(this, orQuery);
+
+        parent.addOperand(orQuery);
+        return parent;
+    }
+
+    public Object visit(ASTAndExpression node, Object data) {
+        NAryQueryNode parent = (NAryQueryNode) data;
+        AndQueryNode andQuery = new AndQueryNode(parent);
+        // pass to operands
+        node.childrenAccept(this, andQuery);
+
+        parent.addOperand(andQuery);
+        return parent;
+    }
+
+    public Object visit(ASTNotExpression node, Object data) {
+        NAryQueryNode parent = (NAryQueryNode) data;
+        NotQueryNode notQuery = new NotQueryNode(parent);
+        // pass to operand
+        node.childrenAccept(this, notQuery);
+
+        parent.addOperand(notQuery);
+        return parent;
+    }
+
+    public Object visit(ASTBracketExpression node, Object data) {
+        // bracket expression only has influence on how the syntax tree
+        // is created.
+        // simply pass on to children
+        return node.childrenAccept(this, data);
+    }
+
+    public Object visit(ASTLiteral node, Object data) {
+        // do nothing, should never be called actually
+        return data;
+    }
+
+    public Object visit(ASTIdentifier node, Object data) {
+        // do nothing, should never be called actually
+        return data;
+    }
+
+    public Object visit(ASTOrderByClause node, Object data) {
+        QueryRootNode root = (QueryRootNode) data;
+
+        final List identifiers = new ArrayList();
+        // collect identifiers
+        node.childrenAccept(new DefaultParserVisitor() {
+            public Object visit(ASTIdentifier node, Object data) {
+                identifiers.add(node.getName());
+                return data;
+            }
+        }, root);
+
+        String[] props = (String[]) identifiers.toArray(new String[identifiers.size()]);
+        boolean[] orders = new boolean[props.length];
+        root.setOrderNode(new OrderQueryNode(root, props, orders));
+        return root;
+    }
+
+    public Object visit(ASTContainsExpression node, Object data) {
+        NAryQueryNode parent = (NAryQueryNode) data;
+        parent.addOperand(new TextsearchQueryNode(parent, node.getQuery()));
+        return parent;
+    }
+
+    //------------------------< internal >--------------------------------------
+
+    /**
+     * Creates a new {@link org.apache.jackrabbit.core.search.RelationQueryNode}.
+     * @param parent the parent node for the created <code>RelationQueryNode</code>.
+     * @param propertyName the property name for the relation.
+     * @param operationType the operation type.
+     * @param literal the literal value for the relation.
+     * @return a <code>RelationQueryNode</code>.
+     * @throws IllegalArgumentException if the literal value does not conform
+     * to its type. E.g. a malformed String representation of a date.
+     */
+    private RelationQueryNode createRelationQueryNode(QueryNode parent,
+                                                      String propertyName,
+                                                      int operationType,
+                                                      ASTLiteral literal)
+            throws IllegalArgumentException {
+
+        String stringValue = literal.getValue();
+        RelationQueryNode node = null;
+
+        try {
+            if (literal.getType() == Constants.TYPE_DATE) {
+                SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
+                Date date = format.parse(stringValue);
+                node = new RelationQueryNode(parent, propertyName, date, operationType);
+            } else if (literal.getType() == Constants.TYPE_DOUBLE) {
+                double d = Double.parseDouble(stringValue);
+                node = new RelationQueryNode(parent, propertyName, d, operationType);
+            } else if (literal.getType() == Constants.TYPE_LONG) {
+                long l = Long.parseLong(stringValue);
+                node = new RelationQueryNode(parent, propertyName, l, operationType);
+            } else if (literal.getType() == Constants.TYPE_STRING) {
+                // @todo convert % and _ into * and ? if opType is LIKE
+                // @todo take care of escaping!
+                node = new RelationQueryNode(parent, propertyName, stringValue, operationType);
+            } else if (literal.getType() == Constants.TYPE_TIMESTAMP) {
+                Calendar c = ISO8601.parse(stringValue);
+                node = new RelationQueryNode(parent, propertyName, c.getTime(), operationType);
+            }
+        } catch (java.text.ParseException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+
+        if (node == null) {
+            throw new IllegalArgumentException("Unknown type for literal: " + literal.getType());
+        }
+        return node;
+    }
+
+    /**
+     * Creates <code>LocationStepQueryNode</code>s from a <code>path</code>.
+     */
+    private void createPathQuery(String path) {
+        PathQueryNode pathNode = root.getLocationNode();
+
+        String[] names = path.split("/");
+
+        for (int i = 0; i < names.length; i++) {
+            if (names[i].length() == 0) {
+                if (i == 0) {
+                    // root
+                    pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+                } else {
+                    // descendant '//'
+                    // FIXME this is not possible
+                }
+            } else {
+                int idx = names[i].indexOf('[');
+                String name = null;
+                int index = 0;
+                if (idx > -1) {
+                    // contains index
+                    name = names[i].substring(0, idx);
+                    String suffix = names[i].substring(idx);
+                    try {
+                        index = Integer.parseInt(suffix.substring(1, suffix.length() - 1));
+                    } catch (NumberFormatException e) {
+                        log.warn("Unable to parse index for path element: " + names[i]);
+                    }
+                } else {
+                    // no index
+                    name = names[i];
+                }
+                if (name.equals("%")) {
+                    name = null;
+                }
+                // @todo how to specify descendant-or-self?
+                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, name, false);
+                if (index > 0) {
+                    step.setIndex(index);
+                }
+                pathNode.addPathStep(step);
+            }
+        }
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/SimpleNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/SimpleNode.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/SimpleNode.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.xpath;
+
+/**
+ * Implements a JavaCC Node interface.
+ * This Class was initially created by JavaCC and then adapted for our needs.
+ */
+public class SimpleNode implements Node {
+    protected Node parent;
+    protected Node[] children;
+    protected int id;
+    protected XPath parser;
+
+    public SimpleNode(int i) {
+        id = i;
+    }
+
+    public SimpleNode(XPath p, int i) {
+        this(i);
+        parser = p;
+    }
+
+    // Factory method
+    public static Node jjtCreate(XPath p, int id) {
+        return new SimpleNode(p, id);
+    }
+
+    public void jjtOpen() {
+    }
+
+    public void jjtClose() {
+    }
+
+    public void jjtSetParent(Node n) {
+        parent = n;
+    }
+
+    public Node jjtGetParent() {
+        return parent;
+    }
+
+    public void jjtAddChild(Node n, int i) {
+        if (children == null) {
+            children = new Node[i + 1];
+        } else if (i >= children.length) {
+            Node c[] = new Node[i + 1];
+            System.arraycopy(children, 0, c, 0, children.length);
+            children = c;
+        }
+        children[i] = n;
+    }
+
+    public Node jjtGetChild(int i) {
+        return children[i];
+    }
+
+    public int jjtGetNumChildren() {
+        return (children == null) ? 0 : children.length;
+    }
+
+    /**
+     * Accept the visitor. *
+     */
+    public Object jjtAccept(XPathVisitor visitor, Object data) {
+        return visitor.visit(this, data);
+    }
+
+    /**
+     * Accept the visitor. *
+     */
+    public Object childrenAccept(XPathVisitor visitor, Object data) {
+        if (children != null) {
+            for (int i = 0; i < children.length; ++i) {
+                children[i].jjtAccept(visitor, data);
+            }
+        }
+        return data;
+    }
+
+    /* You can override these two methods in subclasses of SimpleNode to
+       customize the way the node appears when the tree is dumped.  If
+       your output uses more than one line you should override
+       toString(String), otherwise overriding toString() is probably all
+       you need to do. */
+
+    public String toString() {
+        return XPathTreeConstants.jjtNodeName[id];
+    }
+
+    public String toString(String prefix) {
+        return prefix + toString();
+    }
+
+    public void dump(String prefix) {
+        dump(prefix, System.out);
+    }
+
+    public void dump(String prefix, java.io.PrintStream ps) {
+        ps.print(toString(prefix));
+        printValue(ps);
+        ps.println();
+        if (children != null) {
+            for (int i = 0; i < children.length; ++i) {
+                SimpleNode n = (SimpleNode) children[i];
+                if (n != null) {
+                    n.dump(prefix + "   ", ps);
+                }
+            }
+        }
+    }
+
+
+    // Manually inserted code begins here
+
+    protected String m_value;
+
+    public void processToken(Token t) {
+        m_value = t.image;
+    }
+
+    public void printValue(java.io.PrintStream ps) {
+        if (null != m_value) {
+            ps.print(" " + m_value);
+        }
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public String getValue() {
+        return m_value;
+    }
+
+}
+

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.core.search.xpath;
+
+import org.apache.jackrabbit.core.search.QueryRootNode;
+import org.apache.jackrabbit.core.search.PathQueryNode;
+import org.apache.jackrabbit.core.search.LocationStepQueryNode;
+import org.apache.jackrabbit.core.search.QueryNode;
+import org.apache.jackrabbit.core.search.AndQueryNode;
+import org.apache.jackrabbit.core.search.NAryQueryNode;
+import org.apache.jackrabbit.core.search.OrQueryNode;
+import org.apache.jackrabbit.core.search.RelationQueryNode;
+import org.apache.jackrabbit.core.search.NotQueryNode;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.SearchManager;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.util.ISO8601;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Calendar;
+
+/**
+ * Query builder that translates a XPath statement into a query tree structure.
+ */
+public class XPathQueryBuilder implements XPathVisitor {
+
+    /** QName for 'fn:not' */
+    private static final QName FN_NOT = new QName(SearchManager.NS_FN_URI, "not");
+
+    /** QName for 'not' as defined in XPath 1.0 (no prefix) */
+    private static final QName FN_NOT_10 = new QName("", "not");
+
+    /** QName for xs:dateTime */
+    private static final QName XS_DATETIME = new QName(SearchManager.NS_XS_URI, "dateTime");
+
+    /** String constant for operator 'eq' */
+    private static final String OP_EQ = "eq";
+
+    /** String constant for operator 'ne' */
+    private static final String OP_NE = "ne";
+
+    /** String constant for operator 'gt' */
+    private static final String OP_GT = "gt";
+
+    /** String constant for operator 'ge' */
+    private static final String OP_GE = "ge";
+
+    /** String constant for operator 'lt' */
+    private static final String OP_LT = "lt";
+
+    /** String constant for operator 'le' */
+    private static final String OP_LE = "le";
+
+    /** String constant for operator '=' */
+    private static final String OP_SIGN_EQ = "=";
+
+    /** String constant for operator '!=' */
+    private static final String OP_SIGN_NE = "!=";
+
+    /** String constant for operator '>' */
+    private static final String OP_SIGN_GT = ">";
+
+    /** String constant for operator '>=' */
+    private static final String OP_SIGN_GE = ">=";
+
+    /** String constant for operator '<' */
+    private static final String OP_SIGN_LT = "<";
+
+    /** String constant for operator '<=' */
+    private static final String OP_SIGN_LE = "<=";
+
+    /** The root <code>QueryNode</code> */
+    private final QueryRootNode root = new QueryRootNode();
+
+    /** The {@link org.apache.jackrabbit.core.NamespaceResolver} in use */
+    private final NamespaceResolver resolver;
+
+    /** List of exceptions that are created while building the query tree */
+    private final List exceptions = new ArrayList();
+
+    /**
+     * Creates a new <code>XPathQueryBuilder</code> instance.
+     * @param statement the XPath statement.
+     * @param resolver the namespace resolver to use.
+     * @throws InvalidQueryException if the XPath statement is malformed.
+     */
+    private XPathQueryBuilder(String statement, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        this.resolver = resolver;
+        try {
+            XPath query = new XPath(new StringReader(statement));
+            query.XPath2().jjtAccept(this, root);
+        } catch (ParseException e) {
+            throw new InvalidQueryException(e.getMessage(), e);
+        } catch (Exception e) {
+            // also catch any other exception
+            throw new InvalidQueryException(e.getMessage(), e);
+        }
+        if (exceptions.size() > 0) {
+            // simply report the first one
+            Exception e = (Exception) exceptions.get(0);
+            if (e instanceof InvalidQueryException) {
+                // just re-throw
+                throw (InvalidQueryException) e;
+            } else {
+                // otherwise package
+                throw new InvalidQueryException(e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * Creates a <code>QueryNode</code> tree from a XPath statement.
+     * @param statement the XPath statement.
+     * @param resolver the namespace resolver to use.
+     * @return the <code>QueryNode</code> tree for the XPath statement.
+     * @throws InvalidQueryException if the XPath statement is malformed.
+     */
+    public static QueryRootNode createQuery(String statement,
+                                            NamespaceResolver resolver)
+            throws InvalidQueryException {
+        QueryRootNode root = new XPathQueryBuilder(statement, resolver).getRootNode();
+        LocationStepQueryNode[] steps = root.getLocationNode().getPathSteps();
+        if (steps.length > 0) {
+            String nameTest = steps[0].getNameTest();
+            if (nameTest == null || nameTest.length() > 0) {
+                throw new InvalidQueryException("Path must be absolute: " + statement);
+            }
+        }
+        return root;
+    }
+
+    /**
+     * Returns the root node of the <code>QueryNode</code> tree.
+     * @return the root node of the <code>QueryNode</code> tree.
+     */
+    QueryRootNode getRootNode() {
+        return root;
+    }
+
+    //---------------------< XPathVisitor >-------------------------------------
+
+    /**
+     * Implements the generic visit method for this <code>XPathVisitor</code>.
+     * @param node the current node as created by the XPath parser.
+     * @param data the current <code>QueryNode</code> created by this
+     *  <code>XPathVisitor</code>.
+     * @return the current <code>QueryNode</code>. Can be different from
+     *  <code>data</code>.
+     */
+    public Object visit(SimpleNode node, Object data) {
+        switch (node.getId()) {
+            case XPathTreeConstants.JJTXPATH:
+                data = createPathQueryNode(node);
+                break;
+            case XPathTreeConstants.JJTROOT:
+                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, "", false));
+                break;
+            case XPathTreeConstants.JJTROOTDESCENDANTS:
+                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, "", false));
+                break;
+            case XPathTreeConstants.JJTSTEPEXPR:
+                if (isAttributeAxis(node)) {
+                    // @todo do what?
+                    // traverse
+                    node.childrenAccept(this, data);
+                } else {
+                    if (data instanceof PathQueryNode) {
+                        data = createLocationStep(node, (PathQueryNode) data);
+                    } else {
+                        exceptions.add(new InvalidQueryException("Only attribute axis is allowed in predicate"));
+                    }
+                }
+                break;
+            case XPathTreeConstants.JJTNAMETEST:
+                if (data instanceof LocationStepQueryNode
+                        || data instanceof RelationQueryNode) {
+                    createNameTest(node, (QueryNode) data);
+                } else {
+                    // traverse
+                    node.childrenAccept(this, data);
+                }
+                break;
+            case XPathTreeConstants.JJTOREXPR:
+                NAryQueryNode parent = (NAryQueryNode) data;
+                data = new OrQueryNode(parent);
+                parent.addOperand((QueryNode) data);
+                // traverse
+                node.childrenAccept(this, data);
+                break;
+            case XPathTreeConstants.JJTANDEXPR:
+                parent = (NAryQueryNode) data;
+                data = new AndQueryNode(parent);
+                parent.addOperand((QueryNode) data);
+                // traverse
+                node.childrenAccept(this, data);
+                break;
+            case XPathTreeConstants.JJTCOMPARISONEXPR:
+                createExpression(node, (NAryQueryNode) data);
+                break;
+            case XPathTreeConstants.JJTSTRINGLITERAL:
+            case XPathTreeConstants.JJTDECIMALLITERAL:
+            case XPathTreeConstants.JJTDOUBLELITERAL:
+            case XPathTreeConstants.JJTINTEGERLITERAL:
+                if (data instanceof RelationQueryNode) {
+                    assignValue(node, (RelationQueryNode) data);
+                } else {
+                    exceptions.add(new InvalidQueryException("Internal error: data is not a RelationQueryNode"));
+                }
+                break;
+            case XPathTreeConstants.JJTFUNCTIONCALL:
+                data = createFunction(node, (QueryNode) data);
+                break;
+            default:
+                // per default traverse
+                node.childrenAccept(this, data);
+        }
+        return data;
+    }
+
+    //----------------------< internal >----------------------------------------
+
+    /**
+     * Creates a <code>LocationStepQueryNode</code> at the current position
+     * in parent.
+     * @param node the current node in the xpath syntax tree.
+     * @param parent the parent <code>PathQueryNode</code>.
+     * @return the created <code>LocationStepQueryNode</code>.
+     */
+    private LocationStepQueryNode createLocationStep(SimpleNode node, PathQueryNode parent) {
+        LocationStepQueryNode queryNode = null;
+        boolean descenant = false;
+        Node p = node.jjtGetParent();
+        for (int i = 0; i < p.jjtGetNumChildren(); i++) {
+            SimpleNode c = (SimpleNode) p.jjtGetChild(i);
+            if (c == node) {
+                queryNode = new LocationStepQueryNode(parent, null, descenant);
+                parent.addPathStep(queryNode);
+                break;
+            }
+            descenant = (c.getId() == XPathTreeConstants.JJTSLASHSLASH
+                    || c.getId() == XPathTreeConstants.JJTROOTDESCENDANTS);
+        }
+
+        node.childrenAccept(this, queryNode);
+
+        return queryNode;
+    }
+
+    /**
+     * Creates a name test either for a <code>LocationStepQueryNode</code> or
+     * for a <code>RelationQueryNode</code>.
+     * @param node the current node in the xpath syntax tree.
+     * @param queryNode either a <code>LocationStepQueryNode</code> or a
+     *   <code>RelationQueryNode</code>.
+     */
+    private void createNameTest(SimpleNode node, QueryNode queryNode) {
+        if (node.jjtGetNumChildren() > 0) {
+            SimpleNode child = (SimpleNode) node.jjtGetChild(0);
+            if (child.getId() == XPathTreeConstants.JJTQNAME) {
+                if (queryNode instanceof LocationStepQueryNode) {
+                    ((LocationStepQueryNode) queryNode).setNameTest(child.getValue());
+                } else if (queryNode instanceof RelationQueryNode) {
+                    ((RelationQueryNode) queryNode).setProperty(child.getValue());
+                }
+            } else if (child.getId() == XPathTreeConstants.JJTSTAR) {
+                if (queryNode instanceof LocationStepQueryNode) {
+                    ((LocationStepQueryNode) queryNode).setNameTest(null);
+                }
+            } else {
+                exceptions.add(new InvalidQueryException("Unsupported location for name test: " + child));
+            }
+        }
+    }
+
+    /**
+     * Creates a new {@link org.apache.jackrabbit.core.search.RelationQueryNode}
+     * with <code>queryNode</code> as its parent node.
+     * @param node a comparison expression node.
+     * @param queryNode the current <code>QueryNode</code>.
+     */
+    private void createExpression(SimpleNode node, NAryQueryNode queryNode) {
+        if (node.getId() != XPathTreeConstants.JJTCOMPARISONEXPR) {
+            throw new IllegalArgumentException("node must be of type ComparisonExpr");
+        }
+        // get operation type
+        String opType = node.getValue();
+        int type = 0;
+        if (opType.equals(OP_EQ) || opType.equals(OP_SIGN_EQ)) {
+            type = RelationQueryNode.OPERATION_EQ;
+        } else if (opType.equals(OP_GE) || opType.equals(OP_SIGN_GE)) {
+            type = RelationQueryNode.OPERATION_GE;
+        } else if (opType.equals(OP_GT) || opType.equals(OP_SIGN_GT)) {
+            type = RelationQueryNode.OPERATION_GT;
+        } else if (opType.equals(OP_LE) || opType.equals(OP_SIGN_LE)) {
+            type = RelationQueryNode.OPERATION_LE;
+        } else if (opType.equals(OP_LT) || opType.equals(OP_SIGN_LT)) {
+            type = RelationQueryNode.OPERATION_LT;
+        } else if (opType.equals(OP_NE) || opType.equals(OP_SIGN_NE)) {
+            type = RelationQueryNode.OPERATION_NE;
+        } else {
+            exceptions.add(new InvalidQueryException("Unsupported ComparisonExpr type:" + node.getValue()));
+        }
+
+        RelationQueryNode rqn = new RelationQueryNode(queryNode, type);
+
+        // traverse
+        node.childrenAccept(this, rqn);
+        queryNode.addOperand(rqn);
+    }
+
+    /**
+     * Creates the primary path query node.
+     * @param node xpath node representing the root of the parsed tree.
+     * @return
+     */
+    private PathQueryNode createPathQueryNode(SimpleNode node) {
+        root.setLocationNode(new PathQueryNode(root));
+        node.childrenAccept(this, root.getLocationNode());
+        return root.getLocationNode();
+    }
+
+    /**
+     * Assigns a value to the <code>queryNode</code>.
+     * @param node must be of type string, decimal, double or integer; otherwise
+     *   an InvalidQueryException is added to {@link #exceptions}.
+     * @param queryNode current node in the query tree.
+     */
+    private void assignValue(SimpleNode node, RelationQueryNode queryNode) {
+        if (node.getId() == XPathTreeConstants.JJTSTRINGLITERAL) {
+            String value = node.getValue().substring(1, node.getValue().length() - 1);
+            if (node.getValue().charAt(0) == '"') {
+                value = value.replaceAll("\"\"", "\"");
+            } else {
+                value = value.replaceAll("''", "'");
+            }
+            queryNode.setStringValue(value);
+        } else if (node.getId() == XPathTreeConstants.JJTDECIMALLITERAL) {
+            queryNode.setDoubleValue(Double.parseDouble(node.getValue()));
+        } else if (node.getId() == XPathTreeConstants.JJTDOUBLELITERAL) {
+            queryNode.setDoubleValue(Double.parseDouble(node.getValue()));
+        } else if (node.getId() == XPathTreeConstants.JJTINTEGERLITERAL) {
+            queryNode.setLongValue(Long.parseLong(node.getValue()));
+        } else {
+            exceptions.add(new InvalidQueryException("Unsupported literal type:" + node.toString()));
+        }
+    }
+
+    /**
+     * Creates a function based on <code>node</code>.
+     * @param node the function node from the xpath tree.
+     * @param queryNode the current query node.
+     * @return
+     */
+    private QueryNode createFunction(SimpleNode node, QueryNode queryNode) {
+        // find out function name
+        String fName = ((SimpleNode) node.jjtGetChild(0)).getValue();
+        fName = fName.substring(0, fName.length() - 1);
+        try {
+            if (FN_NOT.toJCRName(resolver).equals(fName)
+                    || FN_NOT_10.toJCRName(resolver).equals(fName)) {
+                if (queryNode instanceof NAryQueryNode) {
+                    QueryNode not = new NotQueryNode(queryNode);
+                    ((NAryQueryNode) queryNode).addOperand(not);
+                    queryNode = not;
+                    // traverse
+                    if (node.jjtGetNumChildren() == 2) {
+                        node.jjtGetChild(1).jjtAccept(this, queryNode);
+                    } else {
+                        exceptions.add(new InvalidQueryException("fn:not only supports one expression argument"));
+                    }
+                } else {
+                    exceptions.add(new InvalidQueryException("Unsupported location for function fn:not"));
+                }
+            } else if (XS_DATETIME.toJCRName(resolver).equals(fName)) {
+                // check arguments
+                if (node.jjtGetNumChildren() == 2) {
+                    if (queryNode instanceof RelationQueryNode) {
+                        RelationQueryNode rel = (RelationQueryNode) queryNode;
+                        SimpleNode literal = (SimpleNode) node.jjtGetChild(1).jjtGetChild(0);
+                        if (literal.getId() == XPathTreeConstants.JJTSTRINGLITERAL) {
+                            String value = literal.getValue();
+                            // strip quotes
+                            value = value.substring(1, value.length() - 1);
+                            Calendar c = ISO8601.parse(value);
+                            if (c == null) {
+                                exceptions.add(new InvalidQueryException("Unable to parse string literal for xs:dateTime: " + value));
+                            } else {
+                                rel.setDateValue(c.getTime());
+                            }
+                        } else {
+                            exceptions.add(new InvalidQueryException("Wrong argument type for xs:dateTime"));
+                        }
+                    } else {
+                        exceptions.add(new InvalidQueryException("Unsupported location for function xs:dateTime"));
+                    }
+                } else {
+                    // wrong number of arguments
+                    exceptions.add(new InvalidQueryException("Wrong number of arguments for xs:dateTime"));
+                }
+            } else {
+                exceptions.add(new InvalidQueryException("Unsupported function: " + fName));
+            }
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        return queryNode;
+    }
+
+    /**
+     * Returns true if <code>node</code> has a child node which is the attribute
+     * axis.
+     * @param node a node with type {@link org.apache.jackrabbit.core.search.xpath.XPathTreeConstants.JJTSTEPEXPR}.
+     * @return <code>true</code> if this step expression uses the attribute axis.
+     */
+    private boolean isAttributeAxis(SimpleNode node) {
+        for (int i = 0; i < node.jjtGetNumChildren(); i++) {
+            if (((SimpleNode) node.jjtGetChild(i)).getId() == XPathTreeConstants.JJTAT) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java&r1=123134&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/AbstractQueryTest.java	Wed Dec 22 10:15:05 2004
@@ -26,6 +26,19 @@
 public class AbstractQueryTest extends AbstractJCRTest {
 
     /**
+     * Overwrites the <code>setUp</code> method from 
+     * {@link org.apache.jackrabbit.test.AbstractJCRTest} and adds additional
+     * setup code.
+     * @throws Exception if an error occurs during setup.
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        // make sure root node is indexed
+        superuser.getRootNode().setProperty("dummy", new String[]{"dummy"});
+        superuser.getRootNode().save();
+    }
+
+    /**
      * Checks if the <code>result</code> contains a number of <code>hits</code>.
      *
      * @param result the <code>QueryResult</code>.

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java&r1=123134&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java	Wed Dec 22 10:15:05 2004
@@ -36,6 +36,34 @@
         checkResult(result, 1);
     }
 
+    public void testFulltextSimpleSQL1() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('fox')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
+    public void testFulltextSimpleSQL2() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" = '" + testRoot + "/foo"
+                + "' AND CONTAINS('fox')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
     public void testFulltextMultiWord() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -53,6 +81,25 @@
         checkResult(result, 1);
     }
 
+    public void testFulltextMultiWordSQL() throws Exception {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"test text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"other text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('fox test')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
     public void testFulltextPhrase() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -70,6 +117,25 @@
         checkResult(result, 1);
     }
 
+    public void testFulltextPhraseSQL() throws Exception {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"test text"});
+        n.setProperty("mytext", new String[]{"the quick brown jumps fox over the lazy dog."});
+
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"other text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('text ''fox jumps''')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
     public void testFulltextExclude() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -87,6 +153,25 @@
         checkResult(result, 1);
     }
 
+    public void testFulltextExcludeSQL() throws Exception {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"test text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"other text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        superuser.getRootNode().save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('text ''fox jumps'' -other')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
     public void testFulltextOr() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -104,6 +189,25 @@
         checkResult(result, 2);
     }
 
+    public void testFulltextOrSQL() throws Exception {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"test text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"other text"});
+        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('''fox jumps'' test OR other')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 2);
+    }
+
     public void testFulltextIntercap() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"tEst text"});
@@ -117,6 +221,25 @@
 
         String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"'fox juMps' Test OR otheR\"";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        QueryResult result = q.execute();
+        checkResult(result, 2);
+    }
+
+    public void testFulltextIntercapSQL() throws Exception {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"tEst text"});
+        n.setProperty("mytext", new String[]{"The quick brown Fox jumps over the lazy dog."});
+
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("title", new String[]{"Other text"});
+        n.setProperty("mytext", new String[]{"the quick brown FOX jumPs over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_UNSTRUCTURED
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
+                + "' AND CONTAINS('''fox juMps'' Test OR otheR')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2);
     }

Added: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SQLTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SQLTest.java?view=auto&rev=123135
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SQLTest.java	Wed Dec 22 10:15:05 2004
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.apache.jackrabbit.test.search;
+
+import javax.jcr.Node;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+
+/**
+ */
+public class SQLTest extends AbstractQueryTest {
+
+
+    public void testSimpleQuery1() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("bla", new String[]{"bla"});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"nt:unstructured\" WHERE bla='bla'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
+    public void testFulltextSimple() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"nt:unstructured\" WHERE contains('fox')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
+    public void testFulltextComplex() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"nt:unstructured\" WHERE contains('fox') AND NOT contains('bla')";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
+
+}

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java&r1=123134&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java	Wed Dec 22 10:15:05 2004
@@ -49,7 +49,35 @@
         q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
         result = q.execute();
         checkResult(result, 2);
+    }
+
+    public void testSelectSQL() throws RepositoryException {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"foo"});
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"bar"});
+        n = testRootNode.addNode("node3", NT_UNSTRUCTURED);
+        n.setProperty("yourvalue", new String[]{"foo"});
+
+        testRootNode.save();
+
+        String sql = "SELECT myvalue FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 2);
+
+        sql = "SELECT myvalue FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+                + " AND yourvalue = 'foo'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 0);
 
+        sql = "SELECT myvalue FROM \"" + NT_BASE + "\"";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 2);
     }
 
     public void testPropertyCount() throws RepositoryException {
@@ -83,6 +111,42 @@
         checkResult(result, 2, 4);
     }
 
+    public void testPropertyCountSQL() throws RepositoryException {
+        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"foo"});
+        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"bar"});
+        n = testRootNode.addNode("node3", NT_UNSTRUCTURED);
+        n.setProperty("yourvalue", new String[]{"foo"});
+
+        testRootNode.save();
+
+        String sql = "SELECT myvalue FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 2, 2);
+
+        sql = "SELECT myvalue FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+                + " AND yourvalue = 'foo'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 0, 0);
+
+        sql = "SELECT myvalue FROM \"" + NT_BASE + "\"";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 2, 2);
+
+        sql = "SELECT * FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+                + " AND myvalue LIKE '%'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 2, 4);
+    }
+
     public void testSameNameSibling() throws RepositoryException {
         Node n = testRootNode.addNode("node", NT_UNSTRUCTURED);
         n.setProperty("myvalue", new String[]{"foo"});
@@ -95,6 +159,24 @@
 
         String jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "/node";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        QueryResult result = q.execute();
+        checkResult(result, 2, 2);
+
+    }
+
+    public void testSameNameSiblingSQL() throws RepositoryException {
+        Node n = testRootNode.addNode("node", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"foo"});
+        n = testRootNode.addNode("node", NT_UNSTRUCTURED);
+        n.setProperty("myvalue", new String[]{"bar"});
+        n = testRootNode.addNode("node", NT_UNSTRUCTURED);
+        n.setProperty("yourvalue", new String[]{"foo"});
+
+        testRootNode.save();
+
+        String sql = "SELECT myvalue FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/node'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2, 2);
 

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java&r1=123134&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java	Wed Dec 22 10:15:05 2004
@@ -38,13 +38,27 @@
         checkResult(result, 1);
     }
 
+    public void testSimpleQuerySQL1() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("bla", new String[]{"bla"});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"" + NT_BASE
+                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/foo'"
+                + " AND bla = 'bla'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 1);
+    }
+
     public void testSimpleQuery2() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
-        Node bla = superuser.getRootNode().addNode("bla", NT_UNSTRUCTURED);
+        Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
         bla.setProperty("bla", new String[]{"bla"});
 
-        superuser.getRootNode().save();
+        testRootNode.save();
 
         String jcrql = "SELECT * FROM nt:file LOCATION " + testRoot + "// WHERE bla=\"bla\"";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
@@ -52,6 +66,22 @@
         checkResult(result, 0);
     }
 
+    public void testSimpleQuerySQL2() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("bla", new String[]{"bla"});
+        Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
+        bla.setProperty("bla", new String[]{"bla"});
+
+        superuser.getRootNode().save();
+
+        String sql = "SELECT * FROM \"nt:file\"" +
+                " WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+                + " AND bla = 'bla'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        QueryResult result = q.execute();
+        checkResult(result, 0);
+    }
+
     public void testSimpleQuery3() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
@@ -62,6 +92,22 @@
 
         String jcrql = "SELECT * FROM nt:unstructured LOCATION " + testRoot + "// WHERE bla=\"bla\"";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        QueryResult result = q.execute();
+        checkResult(result, 2);
+    }
+
+    public void testSimpleQuerySQL3() throws Exception {
+        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
+        foo.setProperty("bla", new String[]{"bla"});
+        Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
+        bla.setProperty("bla", new String[]{"bla"});
+
+        testRootNode.save();
+
+        String sql = "SELECT * FROM \"nt:unstructured\"" +
+                " WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+                + " AND bla = 'bla'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2);
     }

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java?view=diff&rev=123135&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java&r1=123134&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java&r2=123135
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/TestAll.java	Wed Dec 22 10:15:05 2004
@@ -37,6 +37,7 @@
         suite.addTestSuite(SimpleQueryTest.class);
         suite.addTestSuite(FulltextQueryTest.class);
         suite.addTestSuite(SelectClauseTest.class);
+        suite.addTestSuite(SQLTest.class);
 
         return suite;
     }