%{ // // XQueryParser.jay // // Author: // Atsushi Enomoto // // Copyright (C) 2004 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // // FIXME: // attribute value template // handle double literal // #if NET_2_0 using System; using System.Collections; using System.IO; using System.Xml; using System.Xml.Query; using System.Xml.Schema; using System.Xml.XPath; using System.Security.Policy; using Mono.Xml.XPath2; using Mono.Xml.XQuery; namespace Mono.Xml.XQuery.Parser { internal class XQueryParser { // FIXME: Wait for recommendation public const string XdtNamespace = "http://www.w3.org/2003/11/xpath-datatypes"; // See also FunctionCall production rule. static Hashtable reservedFunctionNames; static XQueryParser () { reservedFunctionNames = new Hashtable (); reservedFunctionNames.Add ("attribute", "attribute"); reservedFunctionNames.Add ("comment", "comment"); reservedFunctionNames.Add ("document", "document"); reservedFunctionNames.Add ("element", "element"); reservedFunctionNames.Add ("empty", "empty"); reservedFunctionNames.Add ("if", "if"); reservedFunctionNames.Add ("item", "item"); reservedFunctionNames.Add ("node", "node"); reservedFunctionNames.Add ("processing-instruction", "processing-instruction"); reservedFunctionNames.Add ("text", "text"); reservedFunctionNames.Add ("type", "type"); reservedFunctionNames.Add ("typeswitch", "typeswitch"); } public static XQueryModule Parse (TextReader reader) { return new XQueryParser ().RunParse (reader); } private XQueryTokenizer tokenizer; private XQueryParser () { } // FIXME: we don't need Evidence here at all. It is used only // to generate runnable IL (on loading resulting Assembly). public XQueryModule RunParse (TextReader source) { tokenizer = null; try { // debug = new yydebug.yyDebugSimple (); tokenizer = new XQueryTokenizer (source); XQueryModule mod = (XQueryModule) yyparse (tokenizer); mod.NSResolver = tokenizer.NSResolver; return mod; } catch (yyParser.yyException ex) { throw new XmlQueryCompileException (String.Format ("Tokenizer error at line {0}, column {1}: {2}", tokenizer.LineNumber, tokenizer.LinePosition, ex.Message), ex); } } public XmlTypeCode GetAtomicTypeCode (XmlQualifiedName name) { if (name.Namespace == XdtNamespace) { switch (name.Name) { case "anyAtomicType": return XmlTypeCode.AnyAtomicType; case "dayTimeDuration": return XmlTypeCode.DayTimeDuration; case "item": return XmlTypeCode.Item; case "untypedAtomic": return XmlTypeCode.UntypedAtomic; case "yearMonthDuration": return XmlTypeCode.YearMonthDuration; } } else if (name.Namespace == XmlSchema.Namespace) { switch (name.Name) { case "boolean": return XmlTypeCode.Boolean; case "byte": return XmlTypeCode.Byte; case "date": return XmlTypeCode.Date; case "dateTime": return XmlTypeCode.DateTime; case "decimal": return XmlTypeCode.Decimal; case "double": return XmlTypeCode.Double; case "duration": return XmlTypeCode.Duration; case "entity": return XmlTypeCode.Entity; case "float": return XmlTypeCode.Float; case "gDay": return XmlTypeCode.GDay; case "gMonth": return XmlTypeCode.GMonth; case "gMonthDay": return XmlTypeCode.GMonthDay; case "gYear": return XmlTypeCode.GYear; case "gYearMonth": return XmlTypeCode.GYearMonth; case "hexBinary": return XmlTypeCode.HexBinary; case "id": return XmlTypeCode.Id; case "idref": return XmlTypeCode.Idref; case "int": return XmlTypeCode.Int; case "integer": return XmlTypeCode.Integer; case "language": return XmlTypeCode.Language; case "long": return XmlTypeCode.Long; case "Name": return XmlTypeCode.Name; case "NCName": return XmlTypeCode.NCName; case "negativeInteger": return XmlTypeCode.NegativeInteger; case "NMTOKEN": return XmlTypeCode.NmToken; case "nonNegativeInteger": return XmlTypeCode.NonNegativeInteger; case "nonPositiveInteger": return XmlTypeCode.NonPositiveInteger; case "normalizedString": return XmlTypeCode.NormalizedString; case "NOTATION": return XmlTypeCode.Notation; case "positiveInteger": return XmlTypeCode.PositiveInteger; case "QName": return XmlTypeCode.QName; case "short": return XmlTypeCode.Short; case "string": return XmlTypeCode.String; case "time": return XmlTypeCode.Time; case "token": return XmlTypeCode.Token; case "unsignedByte": return XmlTypeCode.UnsignedByte; case "unsignedInt": return XmlTypeCode.UnsignedInt; case "unsignedLong": return XmlTypeCode.UnsignedLong; case "unsignedShort": return XmlTypeCode.UnsignedShort; } } throw new XmlQueryCompileException (String.Format ("Unexpected type name was specified as atomic type: {0}", name)); } %} /* -------------------------------------------------------- Tokens -------------------------------------------------------- */ /* These are for numbers */ //%token SMALL_E //"e" //%token LARGE_E //"E" %token DOT "." %token DOT2 ".." %token SEMICOLON ";" %token OPEN_PAREN "(" %token OPEN_PAREN_COLON "(:" %token PRAGMA_OPEN "(::" %token CLOSE_PAREN ")" %token COLON ":" %token COLON2 "::" %token PRAGMA_CLOSE "::)" %token CLOSE_PAREN_COLON ":)" %token COLON_EQUAL ":=" %token OPEN_BRACKET "[" %token CLOSE_BRACKET "]" %token OPEN_CURLY "{" %token CLOSE_CURLY "}" %token COMMA "," %token DOLLAR "$" %token EQUAL "=" %token NOT_EQUAL "!=" %token LESSER "<" %token LESSER2 "<<" %token LESSER_EQUAL "<=" %token GREATER ">" %token GREATER2 ">>" %token GREATER_EQUAL ">=" %token BAR "|" %token ASTERISK "*" %token PLUS "+" %token MINUS "-" %token SLASH "/" %token SLASH2 "//" %token QUESTION "?" %token XQUERY //"xquery" %token VERSION //"version" %token PRAGMA //"pragma" %token EXTENSION //"extension" %token MODULE //"module" %token NAMESPACE //"namespace" %token DECLARE //"declare" %token XMLSPACE //"xmlspace" %token PRESERVE //"preserve" %token STRIP //"strip" %token DEFAULT //"default" %token DOCUMENT_NODE //"document-node" %token DOCUMENT //"document" %token ELEMENT //"element" %token ATTRIBUTE //"attribute" %token PROCESSING_INSTRUCTION //"processing-instruction" %token COMMENT //"comment" %token TEXT //"text" %token NODE //"node" %token FUNCTION //"function" %token COLLATION //"collation" %token CONSTRUCTION //"construction" %token ORDERING //"ordering" %token ORDERED //"ordered" %token UNORDERED //"unordered" %token BASEURI //"base-uri" %token IMPORT //"import" %token SCHEMA //"schema" %token AT //"at" %token VARIABLE //"variable" %token AS //"as" %token EXTERNAL //"external" %token VALIDATION //"validation" %token LAX //"lax" %token STRICT //"strict" %token SKIP //"skip" %token RETURN //"return" %token FOR //"for" %token LET //"let" %token IN //"in" %token WHERE //"where" %token ORDER //"order" %token BY //"by" %token STABLE //"stable" %token ASCENDING //"ascending" %token DESCENDING //"descending" %token EMPTY //"empty" %token GREATEST //"greatest" %token LEAST //"least" %token SOME //"some" %token EVERY //"every" %token SATISFIES //"satisfies" %token IS //"is" %token TO //"to" %token EQ //"eq" %token NE //"ne" %token LT //"lt" %token LE //"le" %token GT //"gt" %token GE //"ge" %token AND //"and" %token OR //"or" %token INSTANCE //"instance" %token OF //"of" %token IF //"if" %token THEN //"then" %token ELSE //"else" %token TYPESWITCH //"typeswitch" %token CASE //"case" %token TREAT //"treat" %token CASTABLE //"castable" %token CAST //"as" %token DIV //"div" %token IDIV //"idiv" %token MOD //"mod" %token UNION //"union" %token INTERSECT //"intersect" %token EXCEPT //"except" %token VALIDATE //"validate" %token CONTEXT //"context" %token NILLABLE //"nillable" %token ITEM //"item" %token GLOBAL //"global" %token TYPE //"type" %token CHILD //"child" %token DESCENDANT //"descendant" %token ATTRIBUTE //"attribute" %token SELF //"self" %token DESCENDANT_OR_SELF //"descendant-or-self" %token FOLLOWING_SIBLING //"following-sibling" %token FOLLOWING //"following" %token PARENT //"parent" %token ANCESTOR //"ancestor" %token PRECEDING_SIBLING //"preceding-sibling" %token PRECEDING //"preceding" %token ANCESTOR_OR_SELF //"ancestor-or-self" %token QNAME %token NCNAME %token WILD_LOCALNAME %token WILD_PREFIX %token STRING_LITERAL %token DECIMAL_LITERAL %token DOUBLE_LITERAL %token PRAGMA_CONTENTS // characters until "::)" %token PREDEFINED_ENTITY_REF %token CHAR_REF // Used only inside Constructor %token XML_COMMENT_START // "" %token XML_PI_START // "" %token XML_CDATA_START // " %token EMPTY_TAG_CLOSE // "/>" %token END_TAG_START // " there after state is Operator. tokenizer.PushState (ParseState.Operator); tokenizer.State = ParseState.StartTag; // FIXME: tokenizer.Space = WhitespaceHandling.Significant; } QName AttributeList FollowDirElemConstructor { tokenizer.PopState (); } { ExprSequence expr = new ExprSequence (); expr.AddRange ((ICollection) $4); expr.AddRange ((ICollection) $5); $$ = new XmlElemConstructor ((XmlQualifiedName) $3, expr); } ; FollowDirElemConstructor // returns ExprSequence : EMPTY_TAG_CLOSE { $$ = new ExprSequence (); } | GREATER { tokenizer.State = ParseState.ElementContent; } ElementContentList END_TAG_START { tokenizer.State = ParseState.EndTag; } QName { // tokenizer.Space = WhitespaceHandling.Arbitrary; } GREATER { $$ = $3; } ; ElementContentList // returns ExprSequence : // empty { $$ = new ExprSequence (); } | ElementContent ElementContentList { ExprSequence el = (ExprSequence) $2; el.Insert (0, (ExprSingle) $1); $$ = el; } ; AttributeList // returns XmlAttrConstructorList : // empty { $$ = new XmlAttrConstructorList (); } | /* space */ Attribute AttributeList { XmlAttrConstructorList al = (XmlAttrConstructorList) $2; al.Insert (0, (XmlAttrConstructor) $1); $$ = al; } ; Attribute // returns XmlAttrConstructor : QName /* opt-space */ EQUAL /* opt-space */ AttributeValue { $$ = new XmlAttrConstructor ((XmlQualifiedName) $1, (ExprSequence) $3); } ; /* // FIXME: it should be more complex AttributeValue // returns ExprSequence : STRING_LITERAL { ExprSequence es = new ExprSequence (); es.Insert (0, new StringLiteralExpr ((string) $1)); $$ = es; } ; */ AttributeValue // returns ExprSequence : QUOT { tokenizer.State = ParseState.QuotAttributeContent; } AttributeValueContentSequence QUOT { tokenizer.State = ParseState.StartTag; } { $$ = $3; } | APOS { tokenizer.State = ParseState.AposAttributeContent; } AttributeValueContentSequence APOS { tokenizer.State = ParseState.StartTag; } { $$ = $3; } ; AttributeValueContentSequence // returns ExprSequence : // empty { $$ = new ExprSequence (); } | AttributeValueContent AttributeValueContentSequence { ExprSequence es = (ExprSequence) $2; es.Insert (0, (ExprSingle) $1); $$ = es; } ; AttributeValueContent // returns ExprSingle : ATT_VALUE_LITERAL // including "{{", "}}" and char/predefined entities { $$ = new StringLiteralExpr ((string) $1); } | EnclosedExpr ; EnclosedExpr // returns EnclosedExpr // FIXME: check if this state transition is valid for ElementContent and AttributeValueContent : OPEN_CURLY { switch (tokenizer.State) { case ParseState.ElementContent: case ParseState.QuotAttributeContent: case ParseState.AposAttributeContent: tokenizer.PushState (tokenizer.State); break; } tokenizer.State = ParseState.Default; } Expr CloseCurly { $$ = new EnclosedExpr ((ExprSequence) $3); } ; ElementContent // returns ExprSingle : ELEM_CONTENT_LITERAL // including "{{", "}}" and char/predefined entities { $$ = new XmlTextConstructor ((string) $1); } | DirElemConstructor | EnclosedExpr | XmlCData | XmlComment | XmlPI ; XmlCData : XML_CDATA_START XML_CDATA_TO_END { $$ = new XmlTextConstructor ((string) $2); } ; XmlComment // returns XmlCommentConstructor : XML_COMMENT_START XML_COMMENT_TO_END { $$ = new XmlCommentConstructor ((string) $2); } ; XmlPI // returns XmlPIConstructor : XML_PI_START { tokenizer.PushState (tokenizer.State); tokenizer.State = ParseState.XmlPI; } PITarget { tokenizer.State = ParseState.XmlPIContent; } XML_PI_TO_END { tokenizer.PopState (); } { string name = (string) $3; $$ = new XmlPIConstructor (name, (string) $5); } ; PITarget : NCName ; ComputedConstructor // returns ExprSingle : CompElemConstructor | CompAttrConstructor | CompDocConstructor | CompTextConstructor | CompXmlPI | CompXmlComment | CompNSConstructor ; CompElemConstructor : ELEMENT QName OPEN_CURLY Expr CloseCurly { $$ = new XmlElemConstructor ((XmlQualifiedName) $2, (ExprSequence) $4); } | ELEMENT OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly { $$ = new XmlElemConstructor ((ExprSequence) $3, (ExprSequence) $6); } ; CompAttrConstructor : ATTRIBUTE QName OPEN_CURLY Expr CloseCurly { $$ = new XmlAttrConstructor ((XmlQualifiedName) $2, (ExprSequence) $4); } | ATTRIBUTE OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly { $$ = new XmlAttrConstructor ((ExprSequence) $3, (ExprSequence) $6); } ; CompNSConstructor : NAMESPACE NCName OPEN_CURLY Expr CloseCurly { $$ = new XmlNSConstructor ((string) $2, (ExprSequence) $4); } ; CompDocConstructor : DOCUMENT OPEN_CURLY Expr CloseCurly { $$ = new XmlDocConstructor ((ExprSequence) $3); } ; CompTextConstructor : TEXT OPEN_CURLY Expr CloseCurly { $$ = new XmlTextConstructor ((ExprSequence) $3); } ; CompXmlComment : COMMENT OPEN_CURLY Expr CloseCurly { $$ = new XmlCommentConstructor ((ExprSequence) $3); } ; CompXmlPI : PROCESSING_INSTRUCTION NCName OPEN_CURLY Expr CloseCurly { $$ = new XmlPIConstructor ((string) $2, (ExprSequence) $4); } | PROCESSING_INSTRUCTION OPEN_CURLY Expr CloseCurly OPEN_CURLY Expr CloseCurly { $$ = new XmlPIConstructor ((ExprSequence) $3, (ExprSequence) $6); } ; /* ----------------- Terminal Wrappers ----------------- */ NCName // returns string : NCNAME ; QName // returns XmlQualifiedName. Note that this state is just a wrapper for state transition. : QNAME { switch (tokenizer.State) { case ParseState.Default: tokenizer.State = ParseState.Operator; break; case ParseState.ItemType: tokenizer.State = ParseState.OccurenceIndicator; break; case ParseState.KindTest: case ParseState.SchemaContextStep: tokenizer.State = ParseState.CloseKindTest; break; case ParseState.ExtKey: tokenizer.State = ParseState.ExprComment; break; } } ; Slash : SLASH { switch (tokenizer.State) { case ParseState.Operator: tokenizer.State = ParseState.Default; break; case ParseState.KindTest: tokenizer.State = ParseState.SchemaContextStep; break; } } ; Slash2 : SLASH2 { if (tokenizer.State == ParseState.Operator) tokenizer.State = ParseState.Default; } ; CloseCurly : CLOSE_CURLY { if (tokenizer.State == ParseState.Operator) tokenizer.PopState (); } ; %% } #endif