1 /* 2 * XSLPattern parser (XSLPattern => XPath) 3 * 4 * Copyright 2010 Adam Martinson for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 %{ 22 #include "config.h" 23 #include "wine/port.h" 24 25 #ifdef HAVE_LIBXML2 26 #include "xslpattern.h" 27 #include <libxml/xpathInternals.h> 28 #include "wine/debug.h" 29 30 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 31 32 33 static const xmlChar NameTest_mod_pre[] = "*[name()='"; 34 static const xmlChar NameTest_mod_post[] = "']"; 35 36 #define U(str) BAD_CAST str 37 38 static inline BOOL is_literal(xmlChar const* tok) 39 { 40 return (tok && tok[0] && tok[1] && 41 tok[0]== tok[xmlStrlen(tok)-1] && 42 (tok[0] == '\'' || tok[0] == '"')); 43 } 44 45 static void xslpattern_error(parser_param* param, void const* scanner, char const* msg) 46 { 47 FIXME("%s:\n" 48 " param {\n" 49 " yyscanner=%p\n" 50 " ctx=%p\n" 51 " in=\"%s\"\n" 52 " pos=%i\n" 53 " len=%i\n" 54 " out=\"%s\"\n" 55 " err=%i\n" 56 " }\n" 57 " scanner=%p\n", 58 msg, param->yyscanner, param->ctx, param->in, param->pos, 59 param->len, param->out, ++param->err, scanner); 60 } 61 62 %} 63 64 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon 65 %token TOK_OpAnd TOK_OpOr TOK_OpNot 66 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq 67 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq 68 %token TOK_OpAll TOK_OpAny 69 %token TOK_NCName TOK_Literal TOK_Number 70 71 %start XSLPattern 72 73 %pure-parser 74 %parse-param {parser_param* p} 75 %parse-param {void* scanner} 76 %lex-param {yyscan_t* scanner} 77 78 %left TOK_OpAnd TOK_OpOr 79 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq 80 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq 81 82 %expect 14 83 84 %% 85 86 XSLPattern : Expr 87 { 88 p->out = $1; 89 } 90 ; 91 92 /* Mostly verbatim from the w3c XML Namespaces standard. 93 * <http://www.w3.org/TR/REC-xml-names/> */ 94 95 /* [4] Qualified Names */ 96 QName : PrefixedName 97 | UnprefixedName 98 ; 99 PrefixedName : TOK_NCName TOK_Colon TOK_NCName 100 { 101 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3); 102 $$=$1; 103 $$=xmlStrcat($$,U(":")); 104 $$=xmlStrcat($$,$3); 105 xmlFree($3); 106 } 107 ; 108 UnprefixedName : TOK_NCName 109 { 110 TRACE("Got UnprefixedName: \"%s\"\n", $1); 111 $$=$1; 112 } 113 ; 114 115 /* Based on the w3c XPath standard, adapted where needed. 116 * <http://www.w3.org/TR/xpath/> */ 117 118 /* [2] Location Paths */ 119 LocationPath : RelativeLocationPath 120 | AbsoluteLocationPath 121 ; 122 AbsoluteLocationPath : TOK_FSlash RelativeLocationPath 123 { 124 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2); 125 $$=xmlStrdup(U("/")); 126 $$=xmlStrcat($$,$2); 127 xmlFree($2); 128 } 129 | TOK_FSlash 130 { 131 TRACE("Got AbsoluteLocationPath: \"/\"\n"); 132 $$=xmlStrdup(U("/")); 133 } 134 | AbbreviatedAbsoluteLocationPath 135 ; 136 RelativeLocationPath : Step 137 | RelativeLocationPath TOK_FSlash Step 138 { 139 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3); 140 $$=$1; 141 $$=xmlStrcat($$,U("/")); 142 $$=xmlStrcat($$,$3); 143 xmlFree($3); 144 } 145 | AbbreviatedRelativeLocationPath 146 ; 147 /* [2.1] Location Steps */ 148 Step : AxisSpecifier NodeTest Predicates 149 { 150 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3); 151 $$=$1; 152 $$=xmlStrcat($$,$2); 153 xmlFree($2); 154 $$=xmlStrcat($$,$3); 155 xmlFree($3); 156 } 157 | NodeTest Predicates 158 { 159 TRACE("Got Step: \"%s%s\"\n", $1, $2); 160 $$=$1; 161 $$=xmlStrcat($$,$2); 162 xmlFree($2); 163 } 164 | AxisSpecifier NodeTest 165 { 166 TRACE("Got Step: \"%s%s\"\n", $1, $2); 167 $$=$1; 168 $$=xmlStrcat($$,$2); 169 xmlFree($2); 170 } 171 | NodeTest 172 | Attribute 173 | AbbreviatedStep 174 ; 175 AxisSpecifier : TOK_NCName TOK_Axis 176 { 177 TRACE("Got AxisSpecifier: \"%s::\"\n", $1); 178 $$=$1; 179 $$=xmlStrcat($$,U("::")); 180 } 181 ; 182 Attribute : '@' QName 183 { 184 TRACE("Got Attribute: \"@%s\"\n", $2); 185 $$=xmlStrdup(U("@")); 186 $$=xmlStrcat($$,$2); 187 xmlFree($2); 188 } 189 | '@' '*' 190 { 191 TRACE("Got All attributes pattern: \"@*\"\n"); 192 $$=xmlStrdup(U("@*")); 193 } 194 ; 195 196 /* [2.3] Node Tests */ 197 NodeTest : NameTest 198 | FunctionCall 199 ; 200 NameTest : '*' 201 { 202 TRACE("Got NameTest: \"*\"\n"); 203 $$=xmlStrdup(U("*")); 204 } 205 | TOK_NCName TOK_Colon '*' 206 { 207 TRACE("Got NameTest: \"%s:*\"\n", $1); 208 $$=$1; 209 $$=xmlStrcat($$,U(":*")); 210 } 211 | TOK_NCName TOK_Colon TOK_NCName 212 { /* PrefixedName */ 213 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1); 214 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3); 215 216 if (registeredNsURI) 217 $$=xmlStrdup(U("")); 218 else 219 $$=xmlStrdup(NameTest_mod_pre); 220 221 $$=xmlStrcat($$,$1); 222 xmlFree($1); 223 $$=xmlStrcat($$,U(":")); 224 $$=xmlStrcat($$,$3); 225 xmlFree($3); 226 227 if (!registeredNsURI) 228 $$=xmlStrcat($$,NameTest_mod_post); 229 } 230 | UnprefixedName 231 { 232 $$=xmlStrdup(NameTest_mod_pre); 233 $$=xmlStrcat($$,$1); 234 xmlFree($1); 235 $$=xmlStrcat($$,NameTest_mod_post); 236 } 237 /* [2.4] Predicates */ 238 Predicates : Predicates Predicate 239 { 240 $$=$1; 241 $$=xmlStrcat($$,$2); 242 xmlFree($2); 243 } 244 | Predicate 245 ; 246 Predicate : '[' PredicateExpr ']' 247 { 248 TRACE("Got Predicate: \"[%s]\"\n", $2); 249 $$=xmlStrdup(U("[")); 250 $$=xmlStrcat($$,$2); 251 xmlFree($2); 252 $$=xmlStrcat($$,U("]")); 253 } 254 ; 255 PredicateExpr : TOK_Number 256 { 257 $$=xmlStrdup(U("index()=")); 258 $$=xmlStrcat($$,$1); 259 xmlFree($1); 260 } 261 | BoolExpr 262 | Attribute 263 | TOK_NCName 264 ; 265 /* [2.5] Abbreviated Syntax */ 266 AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath 267 { 268 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2); 269 $$=xmlStrdup(U("//")); 270 $$=xmlStrcat($$,$2); 271 xmlFree($2); 272 } 273 ; 274 AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step 275 { 276 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3); 277 $$=$1; 278 $$=xmlStrcat($$,U("//")); 279 $$=xmlStrcat($$,$3); 280 xmlFree($3); 281 } 282 ; 283 AbbreviatedStep : TOK_Parent 284 { 285 TRACE("Got AbbreviatedStep: \"..\"\n"); 286 $$=xmlStrdup(U("..")); 287 } 288 | TOK_Self 289 { 290 TRACE("Got AbbreviatedStep: \".\"\n"); 291 $$=xmlStrdup(U(".")); 292 } 293 ; 294 295 /* [3] Expressions */ 296 /* [3.1] Basics */ 297 Expr : OrExpr 298 ; 299 BoolExpr : FunctionCall 300 | BoolUnaryExpr 301 | BoolRelationalExpr 302 | BoolEqualityExpr 303 | BoolAndExpr 304 | BoolOrExpr 305 ; 306 PrimaryExpr : '(' Expr ')' 307 { 308 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1); 309 $$=xmlStrdup(U("(")); 310 $$=xmlStrcat($$,$2); 311 xmlFree($2); 312 $$=xmlStrcat($$,U(")")); 313 } 314 | PathExpr '!' FunctionCall 315 { 316 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3); 317 $$=$1; 318 $$=xmlStrcat($$,U("/")); 319 $$=xmlStrcat($$,$3); 320 xmlFree($3); 321 } 322 | TOK_Literal 323 | TOK_Number 324 ; 325 /* [3.2] Function Calls */ 326 FunctionCall : QName '(' Arguments ')' 327 { 328 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3); 329 if (xmlStrEqual($1,U("ancestor"))) 330 { 331 $$=$1; 332 $$=xmlStrcat($$,U("::")); 333 $$=xmlStrcat($$,$3); 334 xmlFree($3); 335 } 336 else if (xmlStrEqual($1,U("attribute"))) 337 { 338 if (is_literal($3)) 339 { 340 $$=xmlStrdup(U("@*[name()=")); 341 xmlFree($1); 342 $$=xmlStrcat($$,$3); 343 xmlFree($3); 344 $$=xmlStrcat($$,U("]")); 345 } 346 else 347 { 348 /* XML_XPATH_INVALID_TYPE */ 349 $$=xmlStrdup(U("error(1211, 'Error: attribute(")); 350 xmlFree($1); 351 $$=xmlStrcat($$,$3); 352 xmlFree($3); 353 $$=xmlStrcat($$,U("): invalid argument')")); 354 } 355 } 356 else if (xmlStrEqual($1,U("element"))) 357 { 358 if (is_literal($3)) 359 { 360 $$=xmlStrdup(U("node()[nodeType()=1][name()=")); 361 xmlFree($1); 362 $$=xmlStrcat($$,$3); 363 xmlFree($3); 364 $$=xmlStrcat($$,U("]")); 365 } 366 else 367 { 368 /* XML_XPATH_INVALID_TYPE */ 369 $$=xmlStrdup(U("error(1211, 'Error: element(")); 370 xmlFree($1); 371 $$=xmlStrcat($$,$3); 372 xmlFree($3); 373 $$=xmlStrcat($$,U("): invalid argument')")); 374 } 375 } 376 else 377 { 378 $$=$1; 379 $$=xmlStrcat($$,U("(")); 380 $$=xmlStrcat($$,$3); 381 xmlFree($3); 382 $$=xmlStrcat($$,U(")")); 383 } 384 } 385 | QName '(' ')' 386 { 387 TRACE("Got FunctionCall: \"%s()\"\n", $1); 388 /* comment() & node() work the same in XPath */ 389 if (xmlStrEqual($1,U("attribute"))) 390 { 391 $$=xmlStrdup(U("@*")); 392 xmlFree($1); 393 } 394 else if (xmlStrEqual($1,U("element"))) 395 { 396 $$=xmlStrdup(U("node()[nodeType()=1]")); 397 xmlFree($1); 398 } 399 else if (xmlStrEqual($1,U("pi"))) 400 { 401 $$=xmlStrdup(U("processing-instruction()")); 402 xmlFree($1); 403 } 404 else if (xmlStrEqual($1,U("textnode"))) 405 { 406 $$=xmlStrdup(U("text()")); 407 xmlFree($1); 408 } 409 else 410 { 411 $$=$1; 412 $$=xmlStrcat($$,U("()")); 413 } 414 } 415 ; 416 Arguments : Argument ',' Arguments 417 { 418 $$=$1; 419 $$=xmlStrcat($$,U(",")); 420 $$=xmlStrcat($$,$3); 421 xmlFree($3); 422 } 423 | Argument 424 ; 425 Argument : Expr 426 ; 427 /* [3.3] Node-sets */ 428 UnionExpr : PathExpr 429 | UnionExpr '|' PathExpr 430 { 431 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3); 432 $$=$1; 433 $$=xmlStrcat($$,U("|")); 434 $$=xmlStrcat($$,$3); 435 xmlFree($3); 436 } 437 ; 438 PathExpr : LocationPath 439 | FilterExpr TOK_FSlash RelativeLocationPath 440 { 441 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3); 442 $$=$1; 443 $$=xmlStrcat($$,U("/")); 444 $$=xmlStrcat($$,$3); 445 xmlFree($3); 446 } 447 | FilterExpr TOK_DblFSlash RelativeLocationPath 448 { 449 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3); 450 $$=$1; 451 $$=xmlStrcat($$,U("//")); 452 $$=xmlStrcat($$,$3); 453 xmlFree($3); 454 } 455 | FilterExpr 456 ; 457 FilterExpr : PrimaryExpr 458 | FilterExpr Predicate 459 { 460 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2); 461 $$=$1; 462 $$=xmlStrcat($$,$2); 463 xmlFree($2); 464 } 465 ; 466 /* [3.4] Booleans */ 467 OrExpr : AndExpr 468 | BoolOrExpr 469 ; 470 BoolOrExpr : OrExpr TOK_OpOr AndExpr 471 { 472 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3); 473 $$=$1; 474 $$=xmlStrcat($$,U(" or ")); 475 $$=xmlStrcat($$,$3); 476 xmlFree($3); 477 } 478 ; 479 AndExpr : EqualityExpr 480 | BoolAndExpr 481 ; 482 BoolAndExpr : AndExpr TOK_OpAnd EqualityExpr 483 { 484 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3); 485 $$=$1; 486 $$=xmlStrcat($$,U(" and ")); 487 $$=xmlStrcat($$,$3); 488 xmlFree($3); 489 } 490 ; 491 EqualityExpr : RelationalExpr 492 | BoolEqualityExpr 493 ; 494 BoolEqualityExpr : EqualityExpr TOK_OpEq RelationalExpr 495 { 496 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3); 497 $$=$1; 498 $$=xmlStrcat($$,U("=")); 499 $$=xmlStrcat($$,$3); 500 xmlFree($3); 501 } 502 | EqualityExpr TOK_OpIEq RelationalExpr 503 { 504 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3); 505 $$=xmlStrdup(U("OP_IEq(")); 506 $$=xmlStrcat($$,$1); 507 xmlFree($1); 508 $$=xmlStrcat($$,U(",")); 509 $$=xmlStrcat($$,$3); 510 xmlFree($3); 511 $$=xmlStrcat($$,U(")")); 512 } 513 | EqualityExpr TOK_OpNEq RelationalExpr 514 { 515 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3); 516 $$=$1; 517 $$=xmlStrcat($$,U("!=")); 518 $$=xmlStrcat($$,$3); 519 xmlFree($3); 520 } 521 | EqualityExpr TOK_OpINEq RelationalExpr 522 { 523 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3); 524 $$=xmlStrdup(U("OP_INEq(")); 525 $$=xmlStrcat($$,$1); 526 xmlFree($1); 527 $$=xmlStrcat($$,U(",")); 528 $$=xmlStrcat($$,$3); 529 xmlFree($3); 530 $$=xmlStrcat($$,U(")")); 531 } 532 ; 533 RelationalExpr : UnaryExpr 534 | BoolRelationalExpr 535 ; 536 BoolRelationalExpr : RelationalExpr TOK_OpLt UnaryExpr 537 { 538 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3); 539 $$=$1; 540 $$=xmlStrcat($$,U("<")); 541 $$=xmlStrcat($$,$3); 542 xmlFree($3); 543 } 544 | RelationalExpr TOK_OpILt UnaryExpr 545 { 546 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3); 547 $$=xmlStrdup(U("OP_ILt(")); 548 $$=xmlStrcat($$,$1); 549 xmlFree($1); 550 $$=xmlStrcat($$,U(",")); 551 $$=xmlStrcat($$,$3); 552 xmlFree($3); 553 $$=xmlStrcat($$,U(")")); 554 } 555 | RelationalExpr TOK_OpGt UnaryExpr 556 { 557 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3); 558 $$=$1; 559 $$=xmlStrcat($$,U(">")); 560 $$=xmlStrcat($$,$3); 561 xmlFree($3); 562 } 563 | RelationalExpr TOK_OpIGt UnaryExpr 564 { 565 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3); 566 $$=xmlStrdup(U("OP_IGt(")); 567 $$=xmlStrcat($$,$1); 568 xmlFree($1); 569 $$=xmlStrcat($$,U(",")); 570 $$=xmlStrcat($$,$3); 571 xmlFree($3); 572 $$=xmlStrcat($$,U(")")); 573 } 574 | RelationalExpr TOK_OpLEq UnaryExpr 575 { 576 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3); 577 $$=$1; 578 $$=xmlStrcat($$,U("<=")); 579 $$=xmlStrcat($$,$3); 580 xmlFree($3); 581 } 582 | RelationalExpr TOK_OpILEq UnaryExpr 583 { 584 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3); 585 $$=xmlStrdup(U("OP_ILEq(")); 586 $$=xmlStrcat($$,$1); 587 xmlFree($1); 588 $$=xmlStrcat($$,U(",")); 589 $$=xmlStrcat($$,$3); 590 xmlFree($3); 591 $$=xmlStrcat($$,U(")")); 592 } 593 | RelationalExpr TOK_OpGEq UnaryExpr 594 { 595 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3); 596 $$=$1; 597 $$=xmlStrcat($$,U(">=")); 598 $$=xmlStrcat($$,$3); 599 xmlFree($3); 600 } 601 | RelationalExpr TOK_OpIGEq UnaryExpr 602 { 603 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3); 604 $$=xmlStrdup(U("OP_IGEq(")); 605 $$=xmlStrcat($$,$1); 606 xmlFree($1); 607 $$=xmlStrcat($$,U(",")); 608 $$=xmlStrcat($$,$3); 609 xmlFree($3); 610 $$=xmlStrcat($$,U(")")); 611 } 612 ; 613 614 /* [3.5] Numbers */ 615 UnaryExpr : UnionExpr 616 | BoolUnaryExpr 617 ; 618 BoolUnaryExpr : TOK_OpNot UnaryExpr 619 { 620 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2); 621 $$=xmlStrdup(U(" not(")); 622 $$=xmlStrcat($$,$2); 623 xmlFree($2); 624 $$=xmlStrcat($$,U(")")); 625 } 626 | TOK_OpAny Expr 627 { 628 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2); 629 $$=xmlStrdup(U("boolean(")); 630 $$=xmlStrcat($$,$2); 631 xmlFree($2); 632 $$=xmlStrcat($$,U(")")); 633 } 634 | TOK_OpAll AllExpr 635 { 636 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2); 637 $$=xmlStrdup(U("not(")); 638 $$=xmlStrcat($$,$2); 639 xmlFree($2); 640 $$=xmlStrcat($$,U(")")); 641 } 642 | TOK_OpAll 643 { 644 FIXME("Unrecognized $all$ expression - ignoring\n"); 645 $$=xmlStrdup(U("")); 646 } 647 ; 648 AllExpr : PathExpr TOK_OpEq PathExpr 649 { 650 $$=$1; 651 $$=xmlStrcat($$,U("!=")); 652 $$=xmlStrcat($$,$3); 653 xmlFree($3); 654 } 655 | PathExpr TOK_OpNEq PathExpr 656 { 657 $$=$1; 658 $$=xmlStrcat($$,U("=")); 659 $$=xmlStrcat($$,$3); 660 xmlFree($3); 661 } 662 | PathExpr TOK_OpLt PathExpr 663 { 664 $$=$1; 665 $$=xmlStrcat($$,U(">=")); 666 $$=xmlStrcat($$,$3); 667 xmlFree($3); 668 } 669 | PathExpr TOK_OpLEq PathExpr 670 { 671 $$=$1; 672 $$=xmlStrcat($$,U(">")); 673 $$=xmlStrcat($$,$3); 674 xmlFree($3); 675 } 676 | PathExpr TOK_OpGt PathExpr 677 { 678 $$=$1; 679 $$=xmlStrcat($$,U("<=")); 680 $$=xmlStrcat($$,$3); 681 xmlFree($3); 682 } 683 | PathExpr TOK_OpGEq PathExpr 684 { 685 $$=$1; 686 $$=xmlStrcat($$,U("<")); 687 $$=xmlStrcat($$,$3); 688 xmlFree($3); 689 } 690 | PathExpr TOK_OpIEq PathExpr 691 { 692 $$=xmlStrdup(U("OP_INEq(")); 693 $$=xmlStrcat($$,$1); 694 xmlFree($1); 695 $$=xmlStrcat($$,U(",")); 696 $$=xmlStrcat($$,$3); 697 xmlFree($3); 698 $$=xmlStrcat($$,U(")")); 699 } 700 | PathExpr TOK_OpINEq PathExpr 701 { 702 $$=xmlStrdup(U("OP_IEq(")); 703 $$=xmlStrcat($$,$1); 704 xmlFree($1); 705 $$=xmlStrcat($$,U(",")); 706 $$=xmlStrcat($$,$3); 707 xmlFree($3); 708 $$=xmlStrcat($$,U(")")); 709 } 710 | PathExpr TOK_OpILt PathExpr 711 { 712 $$=xmlStrdup(U("OP_IGEq(")); 713 $$=xmlStrcat($$,$1); 714 xmlFree($1); 715 $$=xmlStrcat($$,U(",")); 716 $$=xmlStrcat($$,$3); 717 xmlFree($3); 718 $$=xmlStrcat($$,U(")")); 719 } 720 | PathExpr TOK_OpILEq PathExpr 721 { 722 $$=xmlStrdup(U("OP_IGt(")); 723 $$=xmlStrcat($$,$1); 724 xmlFree($1); 725 $$=xmlStrcat($$,U(",")); 726 $$=xmlStrcat($$,$3); 727 xmlFree($3); 728 $$=xmlStrcat($$,U(")")); 729 } 730 | PathExpr TOK_OpIGt PathExpr 731 { 732 $$=xmlStrdup(U("OP_ILEq(")); 733 $$=xmlStrcat($$,$1); 734 xmlFree($1); 735 $$=xmlStrcat($$,U(",")); 736 $$=xmlStrcat($$,$3); 737 xmlFree($3); 738 $$=xmlStrcat($$,U(")")); 739 } 740 | PathExpr TOK_OpIGEq PathExpr 741 { 742 $$=xmlStrdup(U("OP_ILt(")); 743 $$=xmlStrcat($$,$1); 744 xmlFree($1); 745 $$=xmlStrcat($$,U(",")); 746 $$=xmlStrcat($$,$3); 747 xmlFree($3); 748 $$=xmlStrcat($$,U(")")); 749 } 750 ; 751 752 %% 753 754 #endif /* HAVE_LIBXML2 */ 755