Hi,

I wonder which is the best way to have "almost duplicate" but
different parser/tokenizer pair for XSLT "Pattern" apart from
XPath (I'm going to fix a bug that allows improper XPath for
XSLT pattern e.g. namespace::*).

With my way to do, they could be generated by attached patches:

  $ patch -i pattern-parser.diff System.Xml.XPath/Parser.jay -o
    System.Xml.XPath/PatternParser.jay
  $ patch -i pattern-parser.diff System.Xml.XPath/Tokenizer.cs -o
    System.Xml.XPath/PatternTokenizer.cs
  $ patch -i use-pattern-parser.diff

... but I wonder if there are better ways to do handle those
parser/tokenizer stuff, because parser/tokenizer patches are easy
to become broken when we fix XPath parser and/or tokenizer sources.

Would it be better if I just put another parser/tokenizer pair?

Atsushi Eno
--- System.Xml.XPath/Parser.jay 2005-03-17 06:18:09.720068800 +0900
+++ System.Xml.XPath/PatternParser.jay  2005-03-17 06:15:04.253380800 +0900
@@ -1,7 +1,9 @@
 %{
-// XPath parser
+// XSLT Pattern parser
 //
-// Author - Piers Haken <[EMAIL PROTECTED]>
+// Author: Atsushi Enomoto  <[EMAIL PROTECTED]>
+//
+// mostly copied from XPath Parser.jay by Piers Haken <[EMAIL PROTECTED]>
 //
 
 using System;
@@ -9,15 +11,15 @@
 using System.Xml;
 using System.Xml.XPath;
 
-namespace Mono.Xml.XPath
+namespace System.Xml.Xsl
 {
-       internal class XPathParser
+       internal class XsltPatternParser
        {
        
                internal System.Xml.Xsl.IStaticXsltContext Context;
                
-               public XPathParser () : this (null) {}
-               internal XPathParser (System.Xml.Xsl.IStaticXsltContext context)
+               public XsltPatternParser () : this (null) {}
+               internal XsltPatternParser (System.Xml.Xsl.IStaticXsltContext 
context)
                {
                        Context = context;
                        ErrorOutput = System.IO.TextWriter.Null;
@@ -27,12 +29,12 @@
                internal Expression Compile (string xpath)
                {
                        try {
-                               Tokenizer tokenizer = new Tokenizer (xpath);
+                               PatternTokenizer tokenizer = new 
PatternTokenizer (xpath);
                                return (Expression) yyparse (tokenizer);
                        } catch (XPathException e) {
                                throw;
-                       } catch (Exception e) {
-                               throw new XPathException ("Error during parse 
of " + xpath, e);
+//                     } catch (Exception e) {
+//                             throw new XPathException ("Error during parse 
of " + xpath, e);
                        }
                }
                static int yacc_verbose_flag;
@@ -125,7 +127,7 @@
 %token QName
 
 
-%start Expr
+%start Pattern
 
 
 %left AND
@@ -144,6 +146,115 @@
 
 %%
 
+/* XSLT Pattern */
+
+Pattern
+       : LocationPathPattern
+       | Pattern BAR LocationPathPattern
+       {
+               $$ = new ExprUNION ((NodeSet) $1, (NodeSet) $3);
+       }
+       ;
+
+LocationPathPattern
+       : SLASH
+       {
+               $$ = new ExprRoot ();
+       }
+       | SLASH RelativePathPattern
+       {
+               $$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2);
+       }
+       | IdKeyPattern
+       | IdKeyPattern SLASH RelativePathPattern
+       {
+               $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
+       }
+       | IdKeyPattern SLASH2 RelativePathPattern
+       {
+               $$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
+       }
+       | SLASH2 RelativePathPattern
+       {
+               $$ = new ExprSLASH2 (new ExprRoot (), (NodeSet) $2);
+       }
+       | RelativePathPattern
+       ;
+
+// to avoid context-sensitive tokenizer, I just reuse FUNCTION_NAME
+IdKeyPattern
+       : FUNCTION_NAME PAREN_OPEN LITERAL PAREN_CLOSE
+       {
+               XmlQualifiedName name = (XmlQualifiedName) $1;
+               if (name.Name != "id" || name.Namespace != String.Empty)
+                       throw new XPathException (String.Format ("Expected 'id' 
but got '{0}'", name));
+               $$ = ExprFunctionCall.Factory (name,
+                       new FunctionArguments (
+                               new ExprLiteral ((string) $3),
+                               null),
+                       Context);
+       }
+       | FUNCTION_NAME PAREN_OPEN LITERAL COMMA LITERAL PAREN_CLOSE
+       {
+               XmlQualifiedName name = (XmlQualifiedName) $1;
+               if (name.Name != "key" || name.Namespace != String.Empty)
+                       throw new XPathException (String.Format ("Expected 
'key' but got '{0}'", name));
+               $$ = Context.TryGetFunction (name,
+                       new FunctionArguments (
+                               new ExprLiteral ((string) $3),
+                               new FunctionArguments (
+                                       new ExprLiteral ((string) $5),
+                                       null)));
+       }
+       ;
+
+RelativePathPattern
+       : StepPattern
+       | RelativePathPattern SLASH StepPattern
+       {
+               $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
+       }
+       | RelativePathPattern SLASH2 StepPattern
+       {
+               $$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
+       }
+       ;
+
+StepPattern
+       : ChildOrAttributeAxisSpecifier NodeTest Predicates
+       {
+               $$ = CreateNodeTest ((Axes) $1, $2, (ArrayList) $3);
+       }
+       ;
+
+ChildOrAttributeAxisSpecifier
+       : AbbreviatedAxisSpecifier
+       | CHILD COLON2
+       {
+               $$ = Axes.Child;
+       }
+       | ATTRIBUTE COLON2
+       {
+               $$ = Axes.Attribute;
+       }
+       ;
+
+Predicates
+       : // empty
+       {
+               $$ = null;
+       }
+       | Predicates Predicate
+       {
+               ArrayList al = (ArrayList) $1;
+               if (al == null)
+                       al = new ArrayList ();
+               al.Add ((Expression) $2);
+               $$ = al;
+       }
+       ;
+
+/* ---- end of XSLT Pattern ---- */
 
 
 Expr
--- System.Xml.XPath/Tokenizer.cs       2005-03-17 05:06:04.510723200 +0900
+++ System.Xml.XPath/PatternTokenizer.cs        2005-03-17 05:40:17.192334400 
+0900
@@ -32,12 +32,12 @@
 using System.IO;
 using System.Text;
 using System.Collections;
+using System.Xml.XPath;
 using Mono.Xml.XPath;
-using Mono.Xml.XPath.yyParser;
 
-namespace System.Xml.XPath
+namespace System.Xml.Xsl
 {
-       internal class Tokenizer : Mono.Xml.XPath.yyParser.yyInput
+       internal class PatternTokenizer : yyParser.yyInput
        {
                private string m_rgchInput;
                private int m_ich;
@@ -74,13 +74,13 @@
                };
                private const char EOL = '\0';
 
-               static Tokenizer ()
+               static PatternTokenizer ()
                {
                        for (int i = 0; i < s_rgTokenMap.Length; i += 2)
                                s_mapTokens.Add (s_rgTokenMap [i + 1], 
s_rgTokenMap [i]);
                }
 
-               public Tokenizer (string strInput)
+               public PatternTokenizer (string strInput)
                {
                        //Console.WriteLine ("Tokenizing: " + strInput);
                        m_rgchInput = strInput;
Index: Makefile
===================================================================
--- Makefile    (revision 41902)
+++ Makefile    (working copy)
@@ -40,6 +40,7 @@
        $(wildcard System.Xml.Serialization/standalone_tests/*.cs) \
        $(wildcard System.Xml.Serialization/standalone_tests/*.output) \
        System.Xml.XPath/Parser.jay     \
+       System.Xml.XPath/PatternParser.jay      \
        System.Xml.Query/XQueryParser.jay       \
        System.Xml.Query/skeleton-2.0.cs        \
        Test/Microsoft.Test.csproj      \
@@ -54,10 +55,15 @@
 System.Xml.XPath/Parser.cs: System.Xml.XPath/Parser.jay 
$(topdir)/jay/skeleton.cs
        $(topdir)/jay/jay -ct < $(topdir)/jay/skeleton.cs $< >$@
 
+System.Xml.XPath/PatternParser.cs: System.Xml.XPath/PatternParser.jay 
$(topdir)/jay/skeleton.cs
+       $(topdir)/jay/jay -ct < $(topdir)/jay/skeleton.cs $< >$@
+
 System.Xml.Query/XQueryParser.cs: System.Xml.Query/XQueryParser.jay 
System.Xml.Query/skeleton-2.0.cs
        $(topdir)/jay/jay -ct < System.Xml.Query/skeleton-2.0.cs $< >$@
 
-BUILT_SOURCES = System.Xml.XPath/Parser.cs #System.Xml.Query/XQueryParser.cs
+BUILT_SOURCES = System.Xml.XPath/Parser.cs \
+       System.Xml.XPath/PatternParser.cs
+       #System.Xml.Query/XQueryParser.cs
 CLEAN_FILES = Test/XmlFiles/xsl/result.xml System.Xml.Query/XQueryParser.cs
 
 include ../../build/library.make
Index: Mono.Xml.XPath/Pattern.cs
===================================================================
--- Mono.Xml.XPath/Pattern.cs   (revision 41902)
+++ Mono.Xml.XPath/Pattern.cs   (working copy)
@@ -43,7 +43,7 @@
        {
                internal static Pattern Compile (string s, Compiler comp)
                {               
-                       return Compile (comp.parser.Compile (s));
+                       return Compile (comp.patternParser.Compile (s));
                }
                
                internal static Pattern Compile (Expression e)
Index: Mono.Xml.Xsl/Compiler.cs
===================================================================
--- Mono.Xml.Xsl/Compiler.cs    (revision 41902)
+++ Mono.Xml.Xsl/Compiler.cs    (working copy)
@@ -127,7 +127,8 @@
        
                public CompiledStylesheet Compile (XPathNavigator nav, 
XmlResolver res, Evidence evidence)
                {
-                       this.parser = new XPathParser (this);
+                       this.xpathParser = new XPathParser (this);
+                       this.patternParser = new XsltPatternParser (this);
                        this.res = res;
                        if (res == null)
                                this.res = new XmlUrlResolver ();
@@ -350,7 +351,8 @@
                        return p;
                }
 
-               internal XPathParser parser;
+               internal XPathParser xpathParser;
+               internal XsltPatternParser patternParser;
                internal CompiledExpression CompileExpression (string 
expression)
                {
                        return CompileExpression (expression, false);
@@ -360,7 +362,7 @@
                {
                        if (expression == null || expression == "") return null;
 
-                       Expression expr = parser.Compile (expression);
+                       Expression expr = xpathParser.Compile (expression);
                        if (isKey)
                                expr = new ExprKeyContainer (expr);
                        CompiledExpression e = new CompiledExpression 
(expression, expr);

Reply via email to