1 /* 2 * The contents of this file are subject to the Mozilla Public 3 * License Version 1.1 (the "License"); you may not use this file 4 * except in compliance with the License. You may obtain a copy of 5 * the License at http://www.mozilla.org/MPL/ 6 * 7 * Software distributed under the License is distributed on an "AS 8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 9 * implied. See the License for the specific language governing 10 * rights and limitations under the License. 11 * 12 * The Original Code is the Sablotron XSLT Processor. 13 * 14 * The Initial Developer of the Original Code is Ginger Alliance Ltd. 15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002 16 * Ginger Alliance Ltd. All Rights Reserved. 17 * 18 * Contributor(s): 19 * 20 * Alternatively, the contents of this file may be used under the 21 * terms of the GNU General Public License Version 2 or later (the 22 * "GPL"), in which case the provisions of the GPL are applicable 23 * instead of those above. If you wish to allow use of your 24 * version of this file only under the terms of the GPL and not to 25 * allow others to use your version of this file under the MPL, 26 * indicate your decision by deleting the provisions above and 27 * replace them with the notice and other provisions required by 28 * the GPL. If you do not delete the provisions above, a recipient 29 * may use your version of this file under either the MPL or the 30 * GPL. 31 */ 32 33 // EXPR.H 34 35 #ifndef ExprHIncl 36 #define ExprHIncl 37 38 // GP: clean 39 40 #include "base.h" 41 #include "datastr.h" 42 #include "proc.h" 43 #include "sxpath.h" 44 #include "jsext.h" 45 46 class Vertex; 47 48 /********************************************************** 49 token types 50 **********************************************************/ 51 52 enum ExToken 53 { 54 //end of parsed string 55 TOK_END, 56 57 //names 58 TOK_NAME, // name test, incl. '*' and 'prefix:*' 59 TOK_AXISNAME, // name followed by :: 60 TOK_NTNAME, // node(), text() etc. 61 TOK_FNAME, // other names followed by ( 62 63 //symbols 64 TOK_LPAREN, TOK_RPAREN, 65 TOK_LBRACKET, TOK_RBRACKET, 66 TOK_PERIOD, TOK_DPERIOD, 67 TOK_ATSIGN, TOK_COMMA, 68 TOK_DCOLON, TOK_DSLASH, 69 TOK_SLASH, 70 71 //variable reference ($...) 72 TOK_VAR, 73 //string in quotes 74 TOK_LITERAL, 75 //real number 76 TOK_NUMBER, 77 78 //operators 79 TOKGROUP_OPERATORS, 80 TOK_OR = TOKGROUP_OPERATORS, 81 TOK_AND, 82 TOK_EQ, 83 TOK_NEQ, 84 TOK_LT, 85 TOK_GT, 86 TOK_LE, 87 TOK_GE, 88 TOK_PLUS, 89 TOK_MINUS2, 90 TOK_MINUS = TOK_MINUS2, 91 TOK_MULT, 92 TOK_MOD, 93 TOK_DIV, 94 TOK_MINUS1, 95 TOK_VERT, 96 97 TOK_STAR, // as wildcard in names 98 TOK_NONE 99 }; 100 101 class TokenItem /* : public SabObj */ 102 { 103 public: 104 ExToken tok; 105 char* firstc; 106 int len; 107 void speak(DStr &, SpeakMode mode); 108 }; 109 110 //ExNodeType is defined in base.h 111 //array exNodeTypeNames in base.cpp 112 113 class Tokenizer 114 { 115 public: 116 Tokenizer(Expression &owner_); 117 ~Tokenizer(); 118 int findTop(ExToken token, int from); 119 eFlag tokenize(Sit S, const Str &astring); 120 eFlag getToken(Sit S, char *&, TokenItem&, ExToken); 121 eFlag getDelim(Sit S, int &, Bool = FALSE); 122 eFlag stripParens(Sit S, int &, int &); 123 DStr string; 124 PList<TokenItem*> items; 125 private: 126 ExToken tryShort(char *&, ExToken); 127 eFlag lookToken(Sit S, ExToken &, char*, ExToken); 128 eFlag getToken_(Sit S, ExToken &, char*&, ExToken); 129 eFlag getNumber(Sit S, char *&); 130 eFlag getName(Sit S, ExToken&, char *&, ExToken); 131 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 132 Expression &owner; 133 }; 134 135 /* 136 XPath expression types. Correspondence to Sablotron classes: 137 NUMBER class Number 138 STRING class Str 139 BOOLEAN Bool 140 NODESET class Context 141 */ 142 143 enum ExType 144 { 145 EX_NUMBER, 146 EX_STRING, 147 EX_BOOLEAN, 148 EX_NODESET, 149 EX_NODESET_PATTERN, 150 EX_NONE, 151 EX_FRAGMENT, 152 EX_EXTERNAL, 153 EX_UNKNOWN 154 155 }; 156 157 /* 158 The following enum comprises four categories of "functors": 159 (1) basic (atom, variable reference etc.) 160 (2) operators (EXFO_...) 161 (3) functions in the XPath core library (EXFF_XPATH_...) 162 (4) functions in the XSLT core library (EXFF_XSLT_...) 163 164 Groups (2) through (4) should be listed in the given order (that is, operators - 165 XPath functions - XSLT functions) and should end with an item ..._Z 166 (e.g. EXFO_Z). 167 */ 168 169 enum ExFunctor 170 { 171 EXF_ATOM, 172 EXF_VAR, 173 EXF_LOCPATH, 174 EXF_LOCSTEP, 175 EXF_OTHER_FUNC, 176 EXF_FILTER, 177 EXF_STRINGSEQ, 178 EXF_FRAGMENT, 179 EXF_NONE, 180 181 // EXFO_... (operators) 182 EXFO_OR, 183 EXFO_AND, 184 EXFO_EQ, 185 EXFO_NEQ, 186 EXFO_LT, 187 EXFO_LE, 188 EXFO_GT, 189 EXFO_GE, 190 EXFO_PLUS, 191 EXFO_MINUS2, 192 EXFO_MINUS = EXFO_MINUS2, 193 EXFO_MULT, 194 EXFO_DIV, 195 EXFO_MOD, 196 EXFO_MINUS1, 197 EXFO_UNION, 198 EXFO_Z, //last in group 199 200 //functions (fall into 2 groups: core XPath and core XSLT) 201 EXF_FUNCTION, 202 203 // XPath, NODESET 204 EXFF_LAST, 205 EXFF_POSITION, 206 EXFF_COUNT, 207 EXFF_ID, 208 EXFF_LOCAL_NAME, 209 EXFF_NAMESPACE_URI, 210 EXFF_NAME, 211 212 // XPath, STRING 213 EXFF_STRING, 214 EXFF_CONCAT, 215 EXFF_STARTS_WITH, 216 EXFF_CONTAINS, 217 EXFF_SUBSTRING_BEFORE, 218 EXFF_SUBSTRING_AFTER, 219 EXFF_SUBSTRING, 220 EXFF_STRING_LENGTH, 221 EXFF_NORMALIZE_SPACE, 222 EXFF_TRANSLATE, 223 224 // XPath, BOOLEAN 225 EXFF_BOOLEAN, 226 EXFF_NOT, 227 EXFF_TRUE, 228 EXFF_FALSE, 229 EXFF_LANG, 230 231 // XPath, NUMBER 232 EXFF_NUMBER, 233 EXFF_SUM, 234 EXFF_FLOOR, 235 EXFF_CEILING, 236 EXFF_ROUND, 237 238 // XSLT core 239 EXFF_DOCUMENT, 240 EXFF_KEY, 241 EXFF_FORMAT_NUMBER, 242 EXFF_CURRENT, 243 EXFF_UNPARSED_ENTITY_URI, 244 EXFF_GENERATE_ID, 245 EXFF_SYSTEM_PROPERTY, 246 247 //XSLT extensions 248 EXFF_FUNCTION_AVAILABLE, 249 EXFF_ELEMENT_AVAILABLE, 250 251 //GA extensions 252 EXFF_EVAL, 253 254 EXFF_NONE 255 }; 256 257 class Expression; 258 259 /********************************************************** 260 N u m b e r 261 **********************************************************/ 262 263 class Number /* : public SabObj */ 264 { 265 public: 266 Number(); 267 Number(double); 268 Number& operator= (double); 269 Number& operator= (const Str &); 270 operator double () const; 271 Bool operator== (double); 272 Bool operator< (double); 273 Bool operator> (double); 274 Bool operator== (Number&); 275 Bool operator< (Number&); 276 Bool operator> (Number&); 277 Bool isNaN(); 278 Bool isInf(); 279 void setNaN(); 280 int round(); 281 private: 282 double x; 283 }; 284 285 /********************************************************** 286 External 287 **********************************************************/ 288 #ifdef ENABLE_JS 289 class External 290 { 291 public: External()292 External() : priv(NULL) {}; 293 External(void *prv, void *val); 294 External(External& other); 295 ~External(); 296 void* getValue(); 297 void assign(const External& other); 298 private: 299 void decref(); 300 JSExternalPrivate *priv; 301 }; 302 #endif 303 304 /********************************************************** 305 L o c S t e p 306 **********************************************************/ 307 308 class Element; 309 310 class LocStep /* : public SabObj */ 311 { 312 friend class Expression; 313 public: 314 LocStep(Element &ownerV_, ExAxis = AXIS_NONE, ExNodeType = EXNODE_NONE); 315 ~LocStep(); 316 void set(ExAxis, ExNodeType); 317 eFlag parse(Sit S, Tokenizer&, int&, Bool defaultToo = FALSE); 318 ExAxis ax; 319 ExNodeType ntype; 320 QName ntest; 321 Str piname; //name for the processing-instruction() node test 322 ExprList preds; 323 void speak(Sit S, DStr &s, SpeakMode mode); 324 Bool matchesWithoutPreds(Sit S, NodeHandle v); 325 // eFlag createContextNoPreds(Context *&, int); 326 eFlag shift(Sit S, NodeHandle &v, NodeHandle baseV); 327 Bool positional; 328 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); getOwnerElement()329 Element &getOwnerElement() {return ownerV;} 330 private: 331 int badPreds; 332 Element &ownerV; 333 }; 334 335 336 /********************************************************** 337 E x p r e s s i o n 338 **********************************************************/ 339 340 class Element; 341 342 class Expression 343 { 344 public: 345 Expression(Element & owner_, ExFunctor = EXF_NONE); 346 ~Expression(); 347 void clearContent(); 348 void setLS(ExAxis, ExNodeType); 349 eFlag speak(Sit S, DStr &,SpeakMode); 350 eFlag parse(Sit S, const DStr &, Bool = FALSE, Bool defaultToo = FALSE); 351 eFlag parse(Sit S, Tokenizer&, int, int, Bool defaultToo = FALSE); 352 eFlag eval(Sit S, Expression &, Context *, Bool resolvingGlobals = FALSE); 353 Number tonumber(Sit S); 354 #ifdef ENABLE_JS 355 External& toexternal(Sit S); 356 #endif 357 eFlag tostring(Sit S, Str& result); 358 const Str& tostringRef() const; 359 Bool tobool(); 360 Context& tonodeset(); 361 const Context& tonodesetRef(); 362 eFlag matchesPattern(Sit S, Context *, Bool &result); 363 eFlag trueFor(Sit S, Context *, Bool&); 364 // 365 ExType type; 366 ExFunctor functor; 367 ExprList args; 368 eFlag createContext(Sit S, Context *&, int = -1); 369 LocStep *step; 370 int hasPath; 371 void setAtom(Context*); 372 void setAtom(const Number&); 373 void setAtom(const DStr&); 374 void setAtom(Bool); 375 #ifdef ENABLE_JS 376 void setAtom(const External&); 377 #endif 378 Tree* setFragment(); 379 Tree* pTree; 380 381 // optimizePositional() sets usesLast and positional 382 // returns: 2 if pred contains last() ( -> usesLast && positional ) 383 // 1 if position() only ( -> positional ) 384 // 0 if neither 385 int optimizePositional(int level); 386 387 // optimizePositionBounds() sets optimizePosition... 388 void optimizePositionBounds(); 389 390 // inBounds: 391 // returns 0 if the position is within bounds, -1 if before, 1 if after 392 int inBounds(int position) const; 393 Element& getOwnerElement() const; 394 Tree& getOwnerTree() const; 395 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 396 Bool containsFunctor(ExFunctor func); 397 protected: 398 private: 399 union 400 { 401 QName *pName; //of function or variable 402 Str *patomstring; 403 Bool atombool; 404 Number *patomnumber; 405 Context *patomnodeset; 406 #ifdef ENABLE_JS 407 External *patomexternal; 408 #endif 409 }; 410 Bool compareCC(Sit S, ExFunctor, const Context &, const Context &); 411 Bool compareCS(Sit S, ExFunctor, const Context &, const Str &); 412 Bool compareCN(Sit S, ExFunctor, const Context &, const Number &); 413 eFlag compare(Sit S, Bool &, Expression &, ExFunctor); 414 Bool isOp(ExToken, int &); 415 eFlag callOp(Sit S, Expression&, ExprList&); 416 eFlag callFunc(Sit S, Expression&, ExprList&, Context *); 417 eFlag parseBasic(Sit S, Tokenizer &, int, int, Bool defaultToo = FALSE); 418 eFlag parseLP(Sit S, Tokenizer&, int &, Bool dropRoot, Bool defaultToo = FALSE); 419 eFlag matchesSinglePath(Sit S, NodeHandle v, int lastIndex, Bool &result); 420 eFlag matchesSingleStep(Sit S, NodeHandle v, Bool &result); 421 eFlag createLPContextLevel(Sit S, int stepLevel, int stepsCount, 422 NodeHandle base, Context& info, Context *theResult); 423 eFlag createLPContext(Sit S, Context *&, int, NodeHandle globalCurrent = NULL); 424 eFlag createLPContextSum(Sit S, Context *&, NodeHandle globalCurrent = NULL); 425 eFlag getDocument_(Sit S, NodeHandle& newroot, 426 const Str& location, const Str& baseUri, Processor *proc); 427 428 Bool 429 isPattern; 430 eFlag patternOK(Sit S); 431 void setAtomNoCopy(Context &); 432 433 // in a predicate, these give the bounds to context positions that 434 // suffice to be processed 435 int optimizePositionFrom, 436 optimizePositionTo; 437 438 // in a predicate, this is true iff the predicate depends on last() 439 Bool usesLast, 440 positional; 441 442 Element &owner; 443 }; 444 445 #endif //ifndef ExprHIncl 446