/home/andreas/src/svn/mapnik/include/mapnik/filter_parser.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * 
00003  * This file is part of Mapnik (c++ mapping toolkit)
00004  *
00005  * Copyright (C) 2006 Artem Pavlenko
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  *****************************************************************************/
00022 
00023 
00024 //$Id$
00025 
00026 #ifndef FILTER_PARSER_HPP
00027 #define FILTER_PARSER_HPP
00028 // stl
00029 #include <stack>
00030 #include <iostream>
00031 // boost
00032 #include <boost/shared_ptr.hpp>
00033 #include <boost/spirit/core.hpp>
00034 #include <boost/spirit/symbols.hpp>
00035 #include <boost/spirit/utility/confix.hpp>
00036 #include <boost/spirit/utility/escape_char.hpp>
00037 #include <boost/spirit/utility/chset.hpp> 
00038 // mapnik
00039 #include <mapnik/value.hpp>
00040 #include <mapnik/comparison.hpp>
00041 #include <mapnik/math_expr.hpp>
00042 #include <mapnik/expression.hpp>
00043 #include <mapnik/filter.hpp>
00044 #include <mapnik/regex_filter.hpp>
00045 #include <mapnik/logical.hpp>
00046 
00047 using namespace boost::spirit;
00048 using boost::shared_ptr;
00049 
00050 namespace mapnik
00051 {    
00052     using std::string;
00053     using std::clog;
00054     using std::stack;
00055 
00056     template <typename FeatureT>
00057     struct push_integer
00058     {
00059         push_integer(stack<shared_ptr<expression<FeatureT> > >& exprs)
00060             : exprs_(exprs) {}
00061         
00062         void operator() (int val) const
00063         {
00064             exprs_.push(shared_ptr<expression<FeatureT> >
00065                         ( new literal<FeatureT>(val)));
00066         }
00067         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00068     };
00069    
00070     template <typename FeatureT>
00071     struct push_real
00072     {
00073         push_real(stack<shared_ptr<expression<FeatureT> > >& exprs)
00074             : exprs_(exprs) {}
00075         void operator() (double val) const
00076         {
00077             exprs_.push(shared_ptr<expression<FeatureT> >(new literal<FeatureT>(val)));
00078         }
00079         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00080     };
00081     
00082     template <typename FeatureT>
00083     struct push_string
00084     {
00085         push_string(stack<shared_ptr<expression<FeatureT> > >& exprs)
00086             : exprs_(exprs) {}
00087         
00088         template <typename Iter>
00089         void operator() (Iter start,Iter end) const
00090         {
00091             std::wstring str(start,end);
00092             std::wstring quote = L"\\";
00093             std::wstring::size_type idx;
00094             idx = str.find(quote);
00095             while (idx != string::npos)
00096             {                   
00097                 str.erase(idx,1);
00098                 idx = str.find(quote);
00099             }
00100             exprs_.push(shared_ptr<expression<FeatureT> >(new literal<FeatureT>(str)));
00101         }
00102         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00103     };
00104     
00105     template <typename FeatureT>
00106     struct push_property
00107     {
00108         push_property(stack<shared_ptr<expression<FeatureT> > >& exprs)
00109             : exprs_(exprs) {}
00110         
00111         template <typename Iter>
00112         void operator() (Iter start,Iter end) const
00113         {
00114             string str(start,end);
00115             exprs_.push(shared_ptr<expression<FeatureT> >(new property<FeatureT>(str)));
00116         }
00117         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00118     };
00119 
00120     template <typename FeatureT,typename Op>
00121     struct compose_expression
00122     {
00123         compose_expression(stack<shared_ptr<expression<FeatureT> > >& exprs)
00124             : exprs_(exprs) {}
00125 
00126         template <typename Iter>
00127         void operator() (Iter,Iter) const
00128         {
00129             if (exprs_.size()>=2)
00130             {
00131                 shared_ptr<expression<FeatureT> > right = exprs_.top();
00132                 exprs_.pop();
00133                 shared_ptr<expression<FeatureT> > left = exprs_.top();
00134                 exprs_.pop();
00135                 if (left && right)
00136                 {
00137                     exprs_.push(shared_ptr<expression<FeatureT> >
00138                                 (new mapnik::math_expr_b<FeatureT,Op>(*left,*right)));
00139                 }
00140             }
00141         }
00142         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00143     };
00144     
00145     template <typename FeatureT>
00146     struct compose_regex
00147     {
00148         compose_regex(stack<shared_ptr<filter<FeatureT> > >& filters,
00149                       stack<shared_ptr<expression<FeatureT> > >& exprs)
00150             : filters_(filters),exprs_(exprs) {}
00151 
00152         template <typename Iter>
00153         void operator() (Iter start,Iter end) const
00154         {
00155             if (exprs_.size()>=1)
00156             {
00157                 shared_ptr<expression<FeatureT> > exp = exprs_.top();
00158                 exprs_.pop();
00159                 if (exp)
00160                 {                   
00161                     std::string pattern(start,end);
00162                     try 
00163                     {
00164                         filters_.push(shared_ptr<filter<FeatureT> >
00165                                       (new regex_filter<FeatureT>(*exp,pattern)));
00166                     }
00167                     catch (...)//boost::regex_error& ex)
00168                     {
00169                         clog<<"error\n";//ex.what()<<"\n";
00170                     }
00171                     
00172                 }
00173             }
00174         }
00175         stack<shared_ptr<filter<FeatureT> > >& filters_;
00176         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00177     };
00178 
00179   
00180     template <typename FeatureT,typename Op>
00181     struct compose_filter
00182     {
00183         compose_filter(stack<shared_ptr<filter<FeatureT> > >& filters,
00184                        stack<shared_ptr<expression<FeatureT> > >& exprs)
00185             : filters_(filters),exprs_(exprs) {}
00186 
00187         template <typename Iter>
00188         void operator() (Iter,Iter) const
00189         {
00190             if (exprs_.size()>=2)
00191             {
00192                 shared_ptr<expression<FeatureT> > right = exprs_.top();
00193                 exprs_.pop();
00194                 shared_ptr<expression<FeatureT> > left = exprs_.top();
00195                 exprs_.pop();
00196                 if (left && right)
00197                 {
00198                     filters_.push(shared_ptr<filter<FeatureT> >(new compare_filter<FeatureT,Op>(*left,*right)));
00199                 }
00200             }
00201         }
00202         stack<shared_ptr<filter<FeatureT> > >& filters_;
00203         stack<shared_ptr<expression<FeatureT> > >& exprs_;
00204     };
00205     
00206     template <typename FeatureT>
00207     struct compose_and_filter
00208     {
00209         compose_and_filter(stack<shared_ptr<filter<FeatureT> > >& filters)
00210             : filters_(filters) {}
00211 
00212         template <typename Iter>
00213         void operator() (Iter,Iter) const
00214         {
00215             if (filters_.size()>=2)
00216             {
00217                 shared_ptr<filter<FeatureT> > right = filters_.top();
00218                 filters_.pop();
00219                 shared_ptr<filter<FeatureT> > left = filters_.top();
00220                 filters_.pop();
00221                 if (left && right)
00222                 {
00223                     filters_.push(shared_ptr<filter<FeatureT> >
00224                                   (new logical_and<FeatureT>(*left,*right)));
00225                 }
00226             }
00227         }
00228         stack<shared_ptr<filter<FeatureT> > >& filters_;
00229     };
00230     
00231     template <typename FeatureT>
00232     struct compose_or_filter
00233     {
00234         compose_or_filter(stack<shared_ptr<filter<FeatureT> > >& filters)
00235             : filters_(filters) {}
00236 
00237         template <typename Iter>
00238         void operator() (Iter,Iter) const
00239         {
00240             if (filters_.size()>=2)
00241             {
00242                 shared_ptr<filter<FeatureT> > right = filters_.top();
00243                 filters_.pop();
00244                 shared_ptr<filter<FeatureT> > left = filters_.top();
00245                 filters_.pop();
00246                 if (left && right)
00247                 {
00248                     filters_.push(shared_ptr<filter<FeatureT> >
00249                                   (new logical_or<FeatureT>(*left,*right)));
00250                 }
00251             }
00252         }
00253         stack<shared_ptr<filter<FeatureT> > >& filters_;
00254     };
00255     
00256     template <typename FeatureT>
00257     struct compose_not_filter
00258     {
00259         compose_not_filter(stack<shared_ptr<filter<FeatureT> > >& filters)
00260             : filters_(filters) {}
00261 
00262         template <typename Iter>
00263         void operator() (Iter,Iter) const
00264         {
00265             if (filters_.size()>=1)
00266             {
00267                 shared_ptr<filter<FeatureT> > filter_ = filters_.top();
00268                 filters_.pop();
00269                 if (filter_)
00270                 {
00271                     filters_.push(shared_ptr<filter<FeatureT> >(new logical_not<FeatureT>(*filter_)));
00272                 }
00273             }
00274         }
00275         stack<shared_ptr<filter<FeatureT> > >& filters_;
00276     };
00277     
00278     template <typename FeatureT>
00279     struct filter_grammar : public grammar<filter_grammar<FeatureT> >
00280     {
00281         filter_grammar(stack<shared_ptr<filter<FeatureT> > >& filters_,
00282                        stack<shared_ptr<expression<FeatureT> > >& exprs_)
00283             : filters(filters_),exprs(exprs_) {}
00284         
00285         template <typename ScannerT>
00286         struct definition
00287         {
00288             definition(filter_grammar const& self)
00289             {   
00290                 typedef boost::spirit::chset<wchar_t> chset_t;
00291 
00292                 func1_op = "sqrt","sin","cos";
00293                 func2_op = "min","max";
00294                 spatial_op = "Equals","Disjoint","Touches","Within","Overlaps",
00295                     "Crosses","Intersects","Contains","DWithin","Beyond","BBOX";
00296                 
00297                 chset_t BaseChar (L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E"
00298                                   L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217"
00299                                   L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE"
00300                                   L"\x3D0-\x3D6\x3DA\x3DC\x3DE\x3E0\x3E2-\x3F3\x401-\x40C\x40E-\x44F"
00301                                   L"\x451-\x45C\x45E-\x481\x490-\x4C4\x4C7-\x4C8\x4CB-\x4CC\x4D0-\x4EB"
00302                                   L"\x4EE-\x4F5\x4F8-\x4F9\x531-\x556\x559\x561-\x586\x5D0-\x5EA"
00303                                   L"\x5F0-\x5F2\x621-\x63A\x641-\x64A\x671-\x6B7\x6BA-\x6BE\x6C0-\x6CE"
00304                                   L"\x6D0-\x6D3\x6D5\x6E5-\x6E6\x905-\x939\x93D\x958-\x961\x985-\x98C"
00305                                   L"\x98F-\x990\x993-\x9A8\x9AA-\x9B0\x9B2\x9B6-\x9B9\x9DC-\x9DD"
00306                                   L"\x9DF-\x9E1\x9F0-\x9F1\xA05-\xA0A\xA0F-\xA10\xA13-\xA28\xA2A-\xA30"
00307                                   L"\xA32-\xA33\xA35-\xA36\xA38-\xA39\xA59-\xA5C\xA5E\xA72-\xA74"
00308                                   L"\xA85-\xA8B\xA8D\xA8F-\xA91\xA93-\xAA8\xAAA-\xAB0\xAB2-\xAB3"
00309                                   L"\xAB5-\xAB9\xABD\xAE0\xB05-\xB0C\xB0F-\xB10\xB13-\xB28\xB2A-\xB30"
00310                                   L"\xB32-\xB33\xB36-\xB39\xB3D\xB5C-\xB5D\xB5F-\xB61\xB85-\xB8A"
00311                                   L"\xB8E-\xB90\xB92-\xB95\xB99-\xB9A\xB9C\xB9E-\xB9F\xBA3-\xBA4"
00312                                   L"\xBA8-\xBAA\xBAE-\xBB5\xBB7-\xBB9\xC05-\xC0C\xC0E-\xC10\xC12-\xC28"
00313                                   L"\xC2A-\xC33\xC35-\xC39\xC60-\xC61\xC85-\xC8C\xC8E-\xC90\xC92-\xCA8"
00314                                   L"\xCAA-\xCB3\xCB5-\xCB9\xCDE\xCE0-\xCE1\xD05-\xD0C\xD0E-\xD10"
00315                                   L"\xD12-\xD28\xD2A-\xD39\xD60-\xD61\xE01-\xE2E\xE30\xE32-\xE33"
00316                                   L"\xE40-\xE45\xE81-\xE82\xE84\xE87-\xE88\xE8A\xE8D\xE94-\xE97"
00317                                   L"\xE99-\xE9F\xEA1-\xEA3\xEA5\xEA7\xEAA-\xEAB\xEAD-\xEAE\xEB0"
00318                                   L"\xEB2-\xEB3\xEBD\xEC0-\xEC4\xF40-\xF47\xF49-\xF69\x10A0-\x10C5"
00319                                   L"\x10D0-\x10F6\x1100\x1102-\x1103\x1105-\x1107\x1109\x110B-\x110C"
00320                                   L"\x110E-\x1112\x113C\x113E\x1140\x114C\x114E\x1150\x1154-\x1155"
00321                                   L"\x1159\x115F-\x1161\x1163\x1165\x1167\x1169\x116D-\x116E"
00322                                   L"\x1172-\x1173\x1175\x119E\x11A8\x11AB\x11AE-\x11AF\x11B7-\x11B8"
00323                                   L"\x11BA\x11BC-\x11C2\x11EB\x11F0\x11F9\x1E00-\x1E9B\x1EA0-\x1EF9"
00324                                   L"\x1F00-\x1F15\x1F18-\x1F1D\x1F20-\x1F45\x1F48-\x1F4D\x1F50-\x1F57"
00325                                   L"\x1F59\x1F5B\x1F5D\x1F5F-\x1F7D\x1F80-\x1FB4\x1FB6-\x1FBC\x1FBE"
00326                                   L"\x1FC2-\x1FC4\x1FC6-\x1FCC\x1FD0-\x1FD3\x1FD6-\x1FDB\x1FE0-\x1FEC"
00327                                   L"\x1FF2-\x1FF4\x1FF6-\x1FFC\x2126\x212A-\x212B\x212E\x2180-\x2182"
00328                                   L"\x3041-\x3094\x30A1-\x30FA\x3105-\x312C\xAC00-\xD7A3");
00329             
00330                 chset_t Ideographic(L"\x4E00-\x9FA5\x3007\x3021-\x3029");
00331                 chset_t Letter = BaseChar | Ideographic;
00332             
00333                 chset_t CombiningChar(L"\x0300-\x0345\x0360-\x0361\x0483-\x0486\x0591-\x05A1\x05A3-\x05B9"
00334                                       L"\x05BB-\x05BD\x05BF\x05C1-\x05C2\x05C4\x064B-\x0652\x0670"
00335                                       L"\x06D6-\x06DC\x06DD-\x06DF\x06E0-\x06E4\x06E7-\x06E8\x06EA-\x06ED"
00336                                       L"\x0901-\x0903\x093C\x093E-\x094C\x094D\x0951-\x0954\x0962-\x0963"
00337                                       L"\x0981-\x0983\x09BC\x09BE\x09BF\x09C0-\x09C4\x09C7-\x09C8"
00338                                       L"\x09CB-\x09CD\x09D7\x09E2-\x09E3\x0A02\x0A3C\x0A3E\x0A3F"
00339                                       L"\x0A40-\x0A42\x0A47-\x0A48\x0A4B-\x0A4D\x0A70-\x0A71\x0A81-\x0A83"
00340                                       L"\x0ABC\x0ABE-\x0AC5\x0AC7-\x0AC9\x0ACB-\x0ACD\x0B01-\x0B03\x0B3C"
00341                                       L"\x0B3E-\x0B43\x0B47-\x0B48\x0B4B-\x0B4D\x0B56-\x0B57\x0B82-\x0B83"
00342                                       L"\x0BBE-\x0BC2\x0BC6-\x0BC8\x0BCA-\x0BCD\x0BD7\x0C01-\x0C03"
00343                                       L"\x0C3E-\x0C44\x0C46-\x0C48\x0C4A-\x0C4D\x0C55-\x0C56\x0C82-\x0C83"
00344                                       L"\x0CBE-\x0CC4\x0CC6-\x0CC8\x0CCA-\x0CCD\x0CD5-\x0CD6\x0D02-\x0D03"
00345                                       L"\x0D3E-\x0D43\x0D46-\x0D48\x0D4A-\x0D4D\x0D57\x0E31\x0E34-\x0E3A"
00346                                       L"\x0E47-\x0E4E\x0EB1\x0EB4-\x0EB9\x0EBB-\x0EBC\x0EC8-\x0ECD"
00347                                       L"\x0F18-\x0F19\x0F35\x0F37\x0F39\x0F3E\x0F3F\x0F71-\x0F84"
00348                                       L"\x0F86-\x0F8B\x0F90-\x0F95\x0F97\x0F99-\x0FAD\x0FB1-\x0FB7\x0FB9"
00349                                       L"\x20D0-\x20DC\x20E1\x302A-\x302F\x3099\x309A");
00350             
00351                 chset_t Digit(L"\x0030-\x0039\x0660-\x0669\x06F0-\x06F9\x0966-\x096F\x09E6-\x09EF"
00352                               L"\x0A66-\x0A6F\x0AE6-\x0AEF\x0B66-\x0B6F\x0BE7-\x0BEF\x0C66-\x0C6F"
00353                               L"\x0CE6-\x0CEF\x0D66-\x0D6F\x0E50-\x0E59\x0ED0-\x0ED9\x0F20-\x0F29");
00354                 
00355                 chset_t Extender(L"\x00B7\x02D0\x02D1\x0387\x0640\x0E46\x0EC6\x3005\x3031-\x3035"
00356                                  L"\x309D-\x309E\x30FC-\x30FE");
00357                 
00358                 chset_t NameChar =
00359                     Letter 
00360                     | Digit 
00361                     | L'.'
00362                     | L'-'
00363                     | L'_'
00364                     | L':'
00365                     | CombiningChar 
00366                     | Extender;
00367                                 
00368                 number = strict_real_p [push_real<FeatureT>(self.exprs)] 
00369                     | int_p [push_integer<FeatureT>(self.exprs)];
00370                 
00371                 string_ = confix_p(L'\'',(*lex_escape_ch_p)
00372                                    [push_string<FeatureT>(self.exprs)],
00373                                    L'\'');
00374                 
00375                 property = L'[' >> ( (Letter | L'_' | L':') 
00376                                      >> *NameChar )[push_property<FeatureT>(self.exprs)] >> L']';
00377                 
00378                 literal = number | string_ | property;
00379                 
00380                 function = literal | ( func1_op >> L'('>> literal >> L')') | 
00381                     (func2_op >> L'(' >> literal >> L','>> literal >> L')');
00382                 
00383                 factor = function 
00384                     | L'(' >> or_expr >> L')'
00385                     | ( L'-' >> factor) 
00386                     ;
00387                 term = factor
00388                     >> *((L'*' >> factor) [compose_expression<FeatureT,mapnik::mult<value> >(self.exprs)] 
00389                          | (L'/' >> factor) [compose_expression<FeatureT,mapnik::div<value> >(self.exprs)]);
00390                 
00391                 expression = term >> *((L'+' >> term) [compose_expression<FeatureT,mapnik::add<value> >(self.exprs)] 
00392                                        | (L'-' >> term) [compose_expression<FeatureT,mapnik::sub<value> >(self.exprs)]);
00393 
00394                 regex = str_p(L".match")>>L'('>>confix_p(L'\'',(*lex_escape_ch_p)
00395                                                          [compose_regex<FeatureT>(self.filters,self.exprs)],
00396                                                          L'\'') >>L')';
00397 
00398                 relation   = expression 
00399                     >> *((L">=" >> expression) 
00400                          [compose_filter<FeatureT,greater_than_or_equal<value> >(self.filters,self.exprs)]
00401                          | (L'>' >> expression)
00402                          [compose_filter<FeatureT,mapnik::greater_than<value> >(self.filters,self.exprs)]
00403                          | (L'<' >> expression)
00404                          [compose_filter<FeatureT,mapnik::less_than<value> >(self.filters,self.exprs)]
00405                          | (L"<=" >> expression)
00406                          [compose_filter<FeatureT,less_than_or_equal<value> >(self.filters,self.exprs)]
00407                          | regex );
00408 
00409                 equation = relation >> *( ( L'=' >> relation)
00410                                           [compose_filter<FeatureT,mapnik::equals<value> >(self.filters,self.exprs)]
00411                                           | ( L"<>" >> relation)
00412                                           [compose_filter<FeatureT,not_equals<value> >(self.filters,self.exprs)]);
00413 
00414                 not_expr = equation | *(str_p(L"not") >> equation)[compose_not_filter<FeatureT>(self.filters)];
00415 
00416                 and_expr = not_expr >> *(L"and" >> not_expr)[compose_and_filter<FeatureT>(self.filters)];
00417 
00418                 or_expr  = and_expr >> *(L"or" >> and_expr)[compose_or_filter<FeatureT>(self.filters)];
00419 
00420                 filter_statement = or_expr;     
00421             }
00422             
00423             boost::spirit::rule<ScannerT> const& start() const
00424             {
00425                 return filter_statement;
00426             }
00427                     
00428             boost::spirit::rule<ScannerT> factor; 
00429             boost::spirit::rule<ScannerT> term;
00430             boost::spirit::rule<ScannerT> expression;
00431             boost::spirit::rule<ScannerT> relation;
00432             boost::spirit::rule<ScannerT> equation;
00433             boost::spirit::rule<ScannerT> not_expr;
00434             boost::spirit::rule<ScannerT> and_expr;
00435             boost::spirit::rule<ScannerT> or_expr;
00436             
00437             boost::spirit::rule<ScannerT> filter_statement;   
00438             boost::spirit::rule<ScannerT> literal;
00439             boost::spirit::rule<ScannerT> number;
00440             boost::spirit::rule<ScannerT> string_;
00441             boost::spirit::rule<ScannerT> property;
00442             boost::spirit::rule<ScannerT> function;
00443             boost::spirit::rule<ScannerT> regex;
00444             symbols<string> func1_op;
00445             symbols<string> func2_op;
00446             symbols<string> spatial_op;
00447         };
00448         stack<shared_ptr<filter<FeatureT> > >& filters;
00449         stack<shared_ptr<expression<FeatureT> > >& exprs;
00450     };    
00451 }
00452 
00453 #endif //FILTER_PARSER_HPP 

Generated on Thu Jul 19 17:59:26 2007 for Mapnik by  doxygen 1.4.7