1# See bottom of file for license and copyright information 2 3=begin TML 4 5---+ package Foswiki::Query::Parser 6 7Parser for queries, using the Foswiki::Infix::Parser. 8 9The default node type in the generated parse tree is Foswiki::Query::Node, 10though you can pass your own alternative class as an option (it must implement 11Foswiki::Infix::Node) 12 13=cut 14 15package Foswiki::Query::Parser; 16 17use strict; 18use warnings; 19use Assert; 20 21BEGIN { 22 if ( $Foswiki::cfg{UseLocale} ) { 23 require locale; 24 import locale(); 25 } 26} 27 28use Foswiki::Infix::Parser (); 29our @ISA = ('Foswiki::Infix::Parser'); 30 31use Foswiki::Query::Node (); 32 33# operator name precedence 34use Foswiki::Query::OP_or (); # 100 35 36use Foswiki::Query::OP_and (); # 200 37 38use Foswiki::Query::OP_not (); # 300 39 40use Foswiki::Query::OP_comma (); # 400 41 42use Foswiki::Query::OP_lte (); # 500 43use Foswiki::Query::OP_gt (); # 500 44use Foswiki::Query::OP_gte (); # 500 45use Foswiki::Query::OP_lt (); # 500 46use Foswiki::Query::OP_match (); # 500 47use Foswiki::Query::OP_eq (); # 500 48use Foswiki::Query::OP_like (); # 500 49use Foswiki::Query::OP_ne (); # 500 50use Foswiki::Query::OP_in (); # 500 51 52use Foswiki::Query::OP_plus (); # 600 53use Foswiki::Query::OP_minus (); # 600 54 55use Foswiki::Query::OP_times (); # 700 56use Foswiki::Query::OP_div (); # 700 57 58use Foswiki::Query::OP_ref (); # 800 59use Foswiki::Query::OP_dot (); # 800 60 61use Foswiki::Query::OP_where (); # 900 62 63use Foswiki::Query::OP_lc (); # 1000 64use Foswiki::Query::OP_uc (); # 1000 65use Foswiki::Query::OP_d2n (); # 1000 66use Foswiki::Query::OP_length (); # 1000 67use Foswiki::Query::OP_neg (); # 1000 68use Foswiki::Query::OP_int (); # 1000 69 70use Foswiki::Query::OP_ob (); # 1100 71 72=begin TML 73Query Language BNF 74<verbatim> 75expr ::= and_expr 'or' expr | and_expr; 76and_expr ::= not_expr 'and' and_expr | not_expr; 77not_expr ::= 'not' comma_expr | comma_expr; 78comma_expr ::= cmp_expr ',' comma_expr | cmp_expr; 79cmp_expr ::= add_expr cmp_op cm_expr | add_expr; 80cmp_op ::= '<=' | '>=' | '<' | '>' | '=' | '=~' | '~' | '!=' | 'in'; 81add_expr ::= mul_expr add_op add_expr | mul_expr; 82mul_expr ::= ref_expr mul_op mul_expr | ref_expr; 83mul_op ::= '*' | 'div'; 84ref_expr ::= u_expr ref_op ref_expr | u_expr; 85ref_op ::= '/' | '.'; 86u_expr ::= value uop u_expr | value; 87uop ::= 'lc' | 'uc' | 'd2n' | 'length' | '-' | 'int' | '@'; 88value ::= <name> | <string> | <number>; 89</verbatim> 90String and Numbers are as defined in Foswiki::Infix::Parser. Names default 91to =/([A-Z:][A-Z0-9_:]*|({[A-Z][A-Z0-9_]*})+)/i=. 92 93See %SYSTEMWEB%.QuerySearch for details of the query language. 94 95=cut 96 97# Each operator is implemented by a class in Foswiki::Query. Note that 98# OP_empty is *not* included here; it is a pseudo-operator and does 99# not participate in parsing. 100use constant OPS => qw (match and eq lc lte not ref d2n gte length lt ob 101 uc dot gt like ne or where comma plus minus 102 neg times div in int ); 103 104sub new { 105 my ( $class, $options ) = @_; 106 107 $options->{words} ||= qr/([A-Z:][A-Z0-9_:]*|(\{[A-Z][A-Z0-9_]*\})+)/i; 108 $options->{nodeClass} ||= 'Foswiki::Query::Node'; 109 my $this = $class->SUPER::new($options); 110 foreach my $op ( OPS() ) { 111 my $on = 'Foswiki::Query::OP_' . $op; 112 $this->addOperator( $on->new() ); 113 } 114 return $this; 115} 116 117# Ensure there is at least one operand on the opstack when closing 118# a subexpression. 119sub onCloseExpr { 120 my ( $this, $opands ) = @_; 121 if ( !scalar(@$opands) ) { 122 require Foswiki::Query::OP_empty; 123 push( @$opands, $this->{node_factory}->emptyExpression() ); 124 } 125} 126 1271; 128__END__ 129Author: Crawford Currie http://c-dot.co.uk 130 131Foswiki - The Free and Open Source Wiki, http://foswiki.org/ 132 133Copyright (C) 2008-2011 Foswiki Contributors. Foswiki Contributors 134are listed in the AUTHORS file in the root of this distribution. 135NOTE: Please extend that file, not this notice. 136 137Additional copyrights apply to some or all of the code in this 138file as follows: 139 140Copyright (C) 2005-2007 TWiki Contributors. All Rights Reserved. 141TWiki Contributors are listed in the AUTHORS file in the root 142of this distribution. 143 144This program is free software; you can redistribute it and/or 145modify it under the terms of the GNU General Public License 146as published by the Free Software Foundation; either version 2 147of the License, or (at your option) any later version. For 148more details read LICENSE in the root of this distribution. 149 150This program is distributed in the hope that it will be useful, 151but WITHOUT ANY WARRANTY; without even the implied warranty of 152MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 153 154As per the GPL, removal of this notice is prohibited. 155