00001
00002
00003
00004
00005 #include "GraphContainer.h"
00006
00007 #include "AttributeParser.h"
00008 #include "AttributeProperties.h"
00009 #include "GraphProperties.h"
00010 #include "GraphPort.h"
00011
00012 #include "AttributeBlob_impl.h"
00013
00014 #include "ByteOutBuffer.h"
00015
00016 #include <boost/spirit/core.hpp>
00017
00018 #include <boost/spirit/tree/ast.hpp>
00019
00020 #include <boost/spirit/utility/lists.hpp>
00021 #include <boost/spirit/utility/distinct.hpp>
00022 #include <boost/spirit/utility/escape_char.hpp>
00023 #include <boost/spirit/utility/grammar_def.hpp>
00024
00025 #include <boost/spirit/dynamic/if.hpp>
00026
00027 #ifdef BOOST_SPIRIT_DEBUG
00028 #include <boost/spirit/tree/tree_to_xml.hpp>
00029 #endif
00030
00031 #include <iostream>
00032 #include <sstream>
00033
00034 namespace VGServer {
00035
00038 namespace AttributeParser {
00039
00040 using namespace boost::spirit;
00041
00042
00043 enum parser_ids
00044 {
00045 integer_const_id = 1,
00046 double_const_id,
00047 string_const_id,
00048 constant_id,
00049
00050 function_call_id,
00051 function_identifier_id,
00052
00053 attrname_id,
00054
00055 atom_expr_id,
00056
00057 unary_expr_id,
00058 mul_expr_id,
00059 add_expr_id,
00060
00061 cast_expr_id,
00062 cast_spec_id,
00063
00064 comp_expr_id,
00065 and_expr_id,
00066 or_expr_id,
00067
00068 expr_id,
00069
00070 attrlist_star_id,
00071 attrlist_exprlist_id,
00072 attrlist_id,
00073
00074 filter_expr_id,
00075 };
00076
00078 distinct_parser<> keyword_p("a-zA-Z0-9_");
00079
00081 struct AttributeGrammar : public grammar<AttributeGrammar>
00082 {
00083 template <typename ScannerT>
00084 struct definition : public grammar_def<rule<ScannerT, parser_context<>, parser_tag<attrlist_id> >,
00085 rule<ScannerT, parser_context<>, parser_tag<filter_expr_id> > >
00086 {
00087 definition(AttributeGrammar const& )
00088 {
00089
00090
00091 constant
00092 = double_const
00093 | integer_const
00094 | string_const
00095 ;
00096
00097 integer_const
00098 = int_p
00099 ;
00100
00101 double_const
00102 = strict_real_p
00103 ;
00104
00105 string_const
00106 = lexeme_d[
00107 token_node_d[ '"' >> *(c_escape_ch_p - '"') >> '"' ]
00108 ]
00109 ;
00110
00111
00112
00113 function_call
00114 = function_identifier >> discard_node_d[ ch_p('(') ]
00115 >> infix_node_d[ !list_p(expr, ch_p(',')) ]
00116 >> discard_node_d[ ch_p(')') ]
00117 ;
00118
00119 function_identifier
00120 = lexeme_d[
00121 token_node_d[ alpha_p >> *(alnum_p | ch_p('_')) ]
00122 ]
00123 ;
00124
00125
00126
00127 attrname
00128 = lexeme_d[
00129 token_node_d[ alpha_p >> *(alnum_p | ch_p('_'))
00130 >> !( ch_p('.') >> alpha_p >> *(alnum_p | ch_p('_')) ) ]
00131 ]
00132 ;
00133
00134
00135 atom_expr
00136 = constant
00137 | inner_node_d[ ch_p('(') >> expr >> ch_p(')') ]
00138
00139 | attrname
00140 ;
00141
00142 unary_expr
00143 = !( root_node_d[ch_p('+') | ch_p('-') | ch_p('!') | str_p("not")] )
00144 >> atom_expr
00145 ;
00146
00147 mul_expr
00148 = unary_expr >>
00149 *( root_node_d[ch_p('*')] >> unary_expr
00150 | root_node_d[ch_p('/')] >> unary_expr )
00151 ;
00152
00153 add_expr
00154 = mul_expr >>
00155 *( root_node_d[ch_p('+')] >> mul_expr
00156 | root_node_d[ch_p('-')] >> mul_expr )
00157 ;
00158
00159 cast_spec
00160 = as_lower_d[
00161 discard_node_d[ keyword_p("cast") ] >>
00162 (
00163 keyword_p("bool") |
00164 keyword_p("char") | keyword_p("short") | keyword_p("integer") | keyword_p("long") |
00165 keyword_p("byte") | keyword_p("word") | keyword_p("dword") | keyword_p("qword") |
00166 keyword_p("float") | keyword_p("double") |
00167 keyword_p("string") | keyword_p("longstring")
00168 )
00169 ]
00170 ;
00171
00172 cast_expr
00173 = add_expr >> root_node_d[ !cast_spec ]
00174 ;
00175
00176 comp_expr
00177 = cast_expr >>
00178 *( root_node_d[str_p("==")] >> cast_expr
00179 | root_node_d[ch_p('=')] >> cast_expr
00180 | root_node_d[str_p("!=")] >> cast_expr
00181 | root_node_d[ch_p('<')] >> cast_expr
00182 | root_node_d[ch_p('>')] >> cast_expr
00183 | root_node_d[str_p("<=")] >> cast_expr
00184 | root_node_d[str_p(">=")] >> cast_expr
00185 | root_node_d[str_p("=<")] >> cast_expr
00186 | root_node_d[str_p("=>")] >> cast_expr
00187 )
00188 ;
00189
00190 and_expr
00191 = comp_expr >>
00192 *( root_node_d[ as_lower_d[ str_p("and")] ] >> comp_expr
00193 | root_node_d[ as_lower_d[ str_p("&&")] ] >> comp_expr
00194 )
00195 ;
00196
00197 or_expr
00198 = and_expr >>
00199 *( root_node_d[ as_lower_d[ str_p("or")] ] >> and_expr
00200 | root_node_d[ as_lower_d[ str_p("||")] ] >> and_expr
00201 )
00202 ;
00203
00204 expr
00205 = or_expr
00206 ;
00207
00208
00209
00210 attrlist_star
00211 = ch_p('*')
00212 ;
00213
00214 attrlist_exprlist
00215 = infix_node_d[ !list_p(expr, ch_p(',')) ]
00216 ;
00217
00218 attrlist
00219 = attrlist_star
00220 | attrlist_exprlist
00221 ;
00222
00223
00224
00225 filter_expr
00226 = !( root_node_d[ keyword_p("vertex:")
00227 | keyword_p("vertices:")
00228 | keyword_p("vertics:")
00229 | keyword_p("v:")
00230 | keyword_p("edge:")
00231 | keyword_p("edges:")
00232 | keyword_p("e:") ]
00233 >> expr )
00234 ;
00235
00236
00237 this->start_parsers(attrlist, filter_expr);
00238
00239 #ifdef BOOST_SPIRIT_DEBUG
00240 BOOST_SPIRIT_DEBUG_RULE(constant);
00241
00242 BOOST_SPIRIT_DEBUG_RULE(integer_const);
00243 BOOST_SPIRIT_DEBUG_RULE(double_const);
00244 BOOST_SPIRIT_DEBUG_RULE(string_const);
00245
00246 BOOST_SPIRIT_DEBUG_RULE(function_call);
00247 BOOST_SPIRIT_DEBUG_RULE(function_identifier);
00248
00249 BOOST_SPIRIT_DEBUG_RULE(attrname);
00250
00251 BOOST_SPIRIT_DEBUG_RULE(atom_expr);
00252
00253 BOOST_SPIRIT_DEBUG_RULE(unary_expr);
00254 BOOST_SPIRIT_DEBUG_RULE(mul_expr);
00255 BOOST_SPIRIT_DEBUG_RULE(add_expr);
00256
00257 BOOST_SPIRIT_DEBUG_RULE(cast_spec);
00258 BOOST_SPIRIT_DEBUG_RULE(cast_expr);
00259
00260 BOOST_SPIRIT_DEBUG_RULE(comp_expr);
00261 BOOST_SPIRIT_DEBUG_RULE(and_expr);
00262 BOOST_SPIRIT_DEBUG_RULE(or_expr);
00263
00264 BOOST_SPIRIT_DEBUG_RULE(expr);
00265
00266 BOOST_SPIRIT_DEBUG_RULE(attrlist_star);
00267 BOOST_SPIRIT_DEBUG_RULE(attrlist_exprlist);
00268 BOOST_SPIRIT_DEBUG_RULE(attrlist);
00269
00270 BOOST_SPIRIT_DEBUG_RULE(filter_expr);
00271 #endif
00272 }
00273
00274 rule<ScannerT, parser_context<>, parser_tag<constant_id> > constant;
00275
00276 rule<ScannerT, parser_context<>, parser_tag<integer_const_id> > integer_const;
00277 rule<ScannerT, parser_context<>, parser_tag<double_const_id> > double_const;
00278 rule<ScannerT, parser_context<>, parser_tag<string_const_id> > string_const;
00279
00280 rule<ScannerT, parser_context<>, parser_tag<function_call_id> > function_call;
00281 rule<ScannerT, parser_context<>, parser_tag<function_identifier_id> > function_identifier;
00282
00283 rule<ScannerT, parser_context<>, parser_tag<attrname_id> > attrname;
00284
00285 rule<ScannerT, parser_context<>, parser_tag<atom_expr_id> > atom_expr;
00286
00287 rule<ScannerT, parser_context<>, parser_tag<unary_expr_id> > unary_expr;
00288 rule<ScannerT, parser_context<>, parser_tag<mul_expr_id> > mul_expr;
00289 rule<ScannerT, parser_context<>, parser_tag<add_expr_id> > add_expr;
00290
00291 rule<ScannerT, parser_context<>, parser_tag<cast_spec_id> > cast_spec;
00292 rule<ScannerT, parser_context<>, parser_tag<cast_expr_id> > cast_expr;
00293
00294 rule<ScannerT, parser_context<>, parser_tag<comp_expr_id> > comp_expr;
00295 rule<ScannerT, parser_context<>, parser_tag<and_expr_id> > and_expr;
00296 rule<ScannerT, parser_context<>, parser_tag<or_expr_id> > or_expr;
00297
00298 rule<ScannerT, parser_context<>, parser_tag<expr_id> > expr;
00299
00300 rule<ScannerT, parser_context<>, parser_tag<attrlist_star_id> > attrlist_star;
00301 rule<ScannerT, parser_context<>, parser_tag<attrlist_exprlist_id> > attrlist_exprlist;
00302 rule<ScannerT, parser_context<>, parser_tag<attrlist_id> > attrlist;
00303
00304 rule<ScannerT, parser_context<>, parser_tag<filter_expr_id> > filter_expr;
00305 };
00306 };
00307
00308
00309
00310
00313 class PNConstant : public ParseNode
00314 {
00315 private:
00317 class AnyType val;
00318
00319 public:
00321 PNConstant(attrtype_t type, std::string strvalue)
00322 : ParseNode(), val(type)
00323 {
00324 if (type == ATTRTYPE_STRING)
00325 val.setStringQuoted(strvalue);
00326 else
00327 val.setString(strvalue);
00328 }
00329
00331 PNConstant(const AnyType &_val)
00332 : val(_val)
00333 {
00334 }
00335
00337 virtual bool getValue(AnyType &dest, const class GraphContainer& , const class Changelist& ,
00338 vertex_or_edge_t , unsigned int , unsigned int ) const
00339 {
00340 dest = val;
00341 return true;
00342 }
00343
00345 virtual bool getConstVal(AnyType *dest) const
00346 {
00347 if (dest) *dest = val;
00348 return true;
00349 }
00350
00352 virtual std::string toString() const
00353 {
00354 return val.getString();
00355 }
00356 };
00357
00358 #define WITH_CHANGELIST
00359
00363 class PNAttributeName : public ParseNode
00364 {
00365 private:
00367 std::string attrname;
00368
00370 unsigned int attrid;
00371
00373 AnyType attrval;
00374
00375 public:
00377 PNAttributeName(std::string _attrname, const AttributePropertiesList &attrlist, vertex_or_edge_t voe)
00378 : ParseNode(), attrname(_attrname), attrval(ATTRTYPE_INVALID)
00379 {
00380 if (voe == VE_VERTEX and attrname == "id") {
00381 attrid = UINT_MAX;
00382 attrval = 0U;
00383 return;
00384 }
00385
00386 int _attrid = attrlist.lookupAttributeName(attrname);
00387 if (_attrid < 0)
00388 throw(AttributeParseException("Unknown attribute name " + attrname + ". Remember they are case-sensitive."));
00389
00390 attrid = _attrid;
00391 attrval = attrlist[attrid];
00392 }
00393
00396 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00397 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00398 {
00399 if (not wantedge)
00400 {
00401 if (attrid == UINT_MAX) {
00402 dest = vid1;
00403 return true;
00404 }
00405
00406 assert( attrid < gc.getProperties().vertexattr.size() );
00407 assert( gc.getProperties().vertexattr[attrid].name == attrname );
00408
00409 #ifdef WITH_CHANGELIST
00410 VertexRef vr = gc.getVertex(vid1, cl);
00411 if (!vr.valid())
00412 {
00413 dest = gc.getProperties().vertexattr[attrid];
00414 return false;
00415 }
00416 else
00417 {
00418 dest = vr.getAttr(attrid);
00419 }
00420 #else
00421 if (!gc.existVertex(vid1))
00422 return false;
00423
00424 const GraphData::Vertex* vp = static_cast<const GraphData&>(gc).getVertex(vid1);
00425
00426 dest = vp->getAttr(attrid, gc);
00427 #endif
00428 }
00429 else
00430 {
00431
00432
00433 assert( attrid < gc.getProperties().edgeattr.size() );
00434 assert( gc.getProperties().edgeattr[attrid].name == attrname );
00435
00436 #ifdef WITH_CHANGELIST
00437 EdgeRef er = gc.getEdge(vid1, vid2, cl);
00438 if (!er.valid())
00439 {
00440 dest = gc.getProperties().edgeattr[attrid];
00441 return false;
00442 }
00443 else
00444 {
00445 dest = er.getAttr(attrid);
00446 }
00447 #else
00448 const GraphData::Edge *ep = static_cast<const GraphData&>(gc).getEdge(vid1, vid2);
00449
00450 if (!ep)
00451 {
00452 dest = gc.getProperties().edgeattr[attrid];
00453 return false;
00454 }
00455 else
00456 {
00457 dest = ep->getAttr(attrid, gc);
00458 }
00459 #endif
00460 }
00461 return true;
00462 }
00463
00465 virtual bool getConstVal(AnyType *dest) const
00466 {
00467 if (dest) *dest = attrval;
00468 return false;
00469 }
00470
00472 virtual std::string toString() const
00473 {
00474 return attrname;
00475 }
00476 };
00477
00481 class PNAttributeDotName : public ParseNode
00482 {
00483 private:
00485 std::string fullname, attrname;
00486
00488 unsigned int attrid;
00489
00491 AnyType attrval;
00492
00494 bool src_or_tgt;
00495
00496 public:
00498 PNAttributeDotName(std::string _attrname, const GraphProperties &gp, vertex_or_edge_t voe)
00499 : ParseNode(), fullname(_attrname), attrval(ATTRTYPE_INVALID)
00500 {
00501 if (voe != VE_EDGE) {
00502 assert(0);
00503 throw(AttributeParseException("Program error: AttributeDotName not applicable to a vertex"));
00504 }
00505
00506
00507 size_t dotloc = _attrname.find('.');
00508 assert(dotloc != std::string::npos);
00509
00510
00511 std::string comp1 = std::string(_attrname.begin(), _attrname.begin()+dotloc);
00512
00513 if (comp1 == "src" or comp1 == "s") src_or_tgt = false;
00514 else if (comp1 == "tgt" or comp1 == "t") src_or_tgt = true;
00515 else {
00516 throw(AttributeParseException("Unknown first component in attribute name " + attrname + ". Remember they are case-sensitive."));
00517 }
00518
00519 std::string comp2 = std::string(_attrname.begin()+dotloc+1, _attrname.end());
00520
00521 if (comp2 == "id") {
00522 attrname = comp2;
00523 attrid = UINT_MAX;
00524 attrval = 0U;
00525 return;
00526 }
00527
00528 int _attrid = gp.vertexattr.lookupAttributeName(comp2);
00529 if (_attrid < 0)
00530 throw(AttributeParseException("Unknown second component in attribute name " + comp2 + ". Remember they are case-sensitive."));
00531
00532 attrname = comp2;
00533 attrid = _attrid;
00534 attrval = gp.vertexattr[attrid];
00535 }
00536
00539 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00540 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00541 {
00542 if (not wantedge) {
00543 assert(0);
00544 }
00545 else
00546 {
00547 if (attrid == UINT_MAX) {
00548 dest = src_or_tgt ? vid1 : vid2;
00549 return true;
00550 }
00551
00552
00553
00554 assert( attrid < gc.getProperties().vertexattr.size() );
00555 assert( gc.getProperties().vertexattr[attrid].name == attrname );
00556
00557 #ifdef WITH_CHANGELIST
00558 VertexRef vr = gc.getVertex( src_or_tgt == false ? vid1 : vid2 , cl);
00559
00560 if (!vr.valid())
00561 {
00562 dest = gc.getProperties().vertexattr[attrid];
00563 return false;
00564 }
00565 else
00566 {
00567 dest = vr.getAttr(attrid);
00568 }
00569 #else
00570 if (!gc.existVertex( src_or_tgt == false ? vid1 : vid2))
00571 return false;
00572
00573 const GraphData::Vertex* vp = static_cast<const GraphData&>(gc).getVertex( src_or_tgt == false ? vid1 : vid2 );
00574
00575 dest = vp->getAttr(attrid, gc);
00576 #endif
00577 }
00578 return true;
00579 }
00580
00582 virtual bool getConstVal(AnyType *dest) const
00583 {
00584 if (dest) *dest = attrval;
00585 return false;
00586 }
00587
00589 virtual std::string toString() const
00590 {
00591 return fullname;
00592 }
00593 };
00594
00597 class PNUnaryArithmExpr : public ParseNode
00598 {
00599 private:
00601 const ParseNode *opand;
00602
00605 char op;
00606
00607 public:
00608 PNUnaryArithmExpr(const ParseNode* _opand, char _op)
00609 : ParseNode(), opand(_opand), op(_op)
00610 {
00611 if (op == 'n') op = '!';
00612 }
00613
00615 virtual ~PNUnaryArithmExpr()
00616 {
00617 delete opand;
00618 }
00619
00621 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00622 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00623 {
00624 bool b = opand->getValue(dest, gc, cl, wantedge, vid1, vid2);
00625
00626 if (op == '-') {
00627 dest = -dest;
00628 }
00629 else if (op == '!')
00630 {
00631
00632 if (dest.getType() != ATTRTYPE_BOOL)
00633 throw(AttributeParseException("Invalid operand for !. Operand must be of type bool."));
00634
00635 dest = -dest;
00636 }
00637 else {
00638 assert(op == '+');
00639 }
00640
00641 return b;
00642 }
00643
00645 virtual bool getConstVal(AnyType *dest) const
00646 {
00647 if (!dest) return false;
00648
00649 bool b = opand->getConstVal(dest);
00650
00651 if (op == '-') {
00652 *dest = -(*dest);
00653 }
00654 else if (op == '!')
00655 {
00656 if (dest->getType() != ATTRTYPE_BOOL)
00657 throw(AttributeParseException("Invalid operand for !. Operand must be of type bool."));
00658
00659 *dest = -(*dest);
00660 }
00661 else {
00662 assert(op == '+');
00663 }
00664
00665 return b;
00666 }
00667
00668 virtual std::string toString() const
00669 {
00670 return std::string("(") + op + " " + opand->toString() + ")";
00671 }
00672 };
00673
00676 class PNBinaryArithmExpr : public ParseNode
00677 {
00678 private:
00680 const ParseNode *left, *right;
00681
00684 char op;
00685
00686 public:
00687 PNBinaryArithmExpr(const ParseNode* _left,
00688 const ParseNode* _right,
00689 char _op)
00690 : ParseNode(),
00691 left(_left), right(_right), op(_op)
00692 { }
00693
00695 virtual ~PNBinaryArithmExpr()
00696 {
00697 delete left;
00698 delete right;
00699 }
00700
00703 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00704 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00705 {
00706 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
00707
00708 bool bl = left->getValue(vl, gc, cl, wantedge, vid1, vid2);
00709 bool br = right->getValue(vr, gc, cl , wantedge, vid1, vid2);
00710
00711 if (op == '+') {
00712 dest = vl + vr;
00713 }
00714 else if (op == '-') {
00715 dest = vl - vr;
00716 }
00717 else if (op == '*') {
00718 dest = vl * vr;
00719 }
00720 else if (op == '/') {
00721 dest = vl / vr;
00722 }
00723
00724 return (bl and br);
00725 }
00726
00728 virtual bool getConstVal(AnyType *dest) const
00729 {
00730 if (!dest) return false;
00731
00732 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
00733
00734 bool bl = left->getConstVal(&vl);
00735 bool br = right->getConstVal(&vr);
00736
00737 if (op == '+') {
00738 *dest = vl + vr;
00739 }
00740 else if (op == '-') {
00741 *dest = vl - vr;
00742 }
00743 else if (op == '*') {
00744 *dest = vl * vr;
00745 }
00746 else if (op == '/') {
00747 *dest = vl / vr;
00748 }
00749
00750 return (bl and br);
00751 }
00752
00754 virtual std::string toString() const
00755 {
00756 return std::string("(") + left->toString() + " " + op + " " + right->toString() + ")";
00757 }
00758 };
00759
00761 class PNCastExpr : public ParseNode
00762 {
00763 private:
00765 const ParseNode *val;
00766
00768 attrtype_t type;
00769
00770 public:
00771 PNCastExpr(const ParseNode* _val,
00772 attrtype_t _type)
00773 : ParseNode(),
00774 val(_val), type(_type)
00775 { }
00776
00778 virtual ~PNCastExpr()
00779 {
00780 delete val;
00781 }
00782
00785 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00786 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00787 {
00788 bool b = val->getValue(dest, gc, cl, wantedge, vid1, vid2);
00789 dest.convertType(type);
00790 return b;
00791 }
00792
00794 virtual bool getConstVal(AnyType *dest) const
00795 {
00796 if (!dest) return false;
00797
00798 bool b = val->getConstVal(dest);
00799 dest->convertType(type);
00800 return b;
00801 }
00802
00804 virtual std::string toString() const
00805 {
00806 return std::string("(") + val->toString() + " cast " + AnyType::getTypeString(type) + std::string(")");
00807 }
00808 };
00809
00812 class PNBinaryComparisonExpr : public ParseNode
00813 {
00814 private:
00816 const ParseNode *left, *right;
00817
00819 enum { EQUAL, NOTEQUAL, LESS, GREATER, LESSEQUAL, GREATEREQUAL } op;
00820
00822 std::string opstr;
00823
00824 public:
00825 PNBinaryComparisonExpr(const ParseNode* _left,
00826 const ParseNode* _right,
00827 std::string _op)
00828 : ParseNode(),
00829 left(_left), right(_right), opstr(_op)
00830 {
00831 if (_op == "==" or _op == "=")
00832 op = EQUAL;
00833 else if (_op == "!=")
00834 op = NOTEQUAL;
00835 else if (_op == "<")
00836 op = LESS;
00837 else if (_op == ">")
00838 op = GREATER;
00839 else if (_op == "<=" or _op == "=<")
00840 op = LESSEQUAL;
00841 else if (_op == ">=" or _op == "=>")
00842 op = GREATEREQUAL;
00843 else
00844 throw(AttributeParseException("Program Error: invalid binary comparision operator."));
00845 }
00846
00848 virtual ~PNBinaryComparisonExpr()
00849 {
00850 delete left;
00851 delete right;
00852 }
00853
00856 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00857 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00858 {
00859 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
00860
00861 bool bl = left->getValue(vl, gc, cl, wantedge, vid1, vid2);
00862 bool br = right->getValue(vr, gc, cl , wantedge, vid1, vid2);
00863
00864 dest.resetType(ATTRTYPE_BOOL);
00865
00866 switch(op)
00867 {
00868 case EQUAL:
00869 dest = AnyType( vl.op_equal_to(vr) );
00870 break;
00871
00872 case NOTEQUAL:
00873 dest = AnyType( vl.op_not_equal_to(vr) );
00874 break;
00875
00876 case LESS:
00877 dest = AnyType( vl.op_less(vr) );
00878 break;
00879
00880 case GREATER:
00881 dest = AnyType( vl.op_greater(vr) );
00882 break;
00883
00884 case LESSEQUAL:
00885 dest = AnyType( vl.op_less_equal(vr) );
00886 break;
00887
00888 case GREATEREQUAL:
00889 dest = AnyType( vl.op_greater_equal(vr) );
00890 break;
00891
00892 default:
00893 assert(0);
00894 }
00895
00896 return (bl and br);
00897 }
00898
00900 virtual bool getConstVal(AnyType *dest) const
00901 {
00902 if (!dest) return false;
00903
00904 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
00905
00906 bool bl = left->getConstVal(&vl);
00907 bool br = right->getConstVal(&vr);
00908
00909 switch(op)
00910 {
00911 case EQUAL:
00912 *dest = AnyType( vl.op_equal_to(vr) );
00913 break;
00914
00915 case NOTEQUAL:
00916 *dest = AnyType( vl.op_not_equal_to(vr) );
00917 break;
00918
00919 case LESS:
00920 *dest = AnyType( vl.op_less(vr) );
00921 break;
00922
00923 case GREATER:
00924 *dest = AnyType( vl.op_greater(vr) );
00925 break;
00926
00927 case LESSEQUAL:
00928 *dest = AnyType( vl.op_less_equal(vr) );
00929 break;
00930
00931 case GREATEREQUAL:
00932 *dest = AnyType( vl.op_greater_equal(vr) );
00933 break;
00934
00935 default:
00936 assert(0);
00937 }
00938
00939 return (bl and br);
00940 }
00941
00943 virtual std::string toString() const
00944 {
00945 return std::string("(") + left->toString() + " " + opstr + " " + right->toString() + ")";
00946 }
00947 };
00948
00951 class PNBinaryLogicExpr : public ParseNode
00952 {
00953 private:
00955 const ParseNode *left, *right;
00956
00958 enum { OP_AND, OP_OR } op;
00959
00960 public:
00961 PNBinaryLogicExpr(const ParseNode* _left,
00962 const ParseNode* _right,
00963 std::string _op)
00964 : ParseNode(),
00965 left(_left), right(_right)
00966 {
00967 if (_op == "and" or _op == "&&")
00968 op = OP_AND;
00969 else if (_op == "or" or _op == "||")
00970 op = OP_OR;
00971 else
00972 throw(AttributeParseException("Program Error: invalid binary logic operator."));
00973 }
00974
00976 virtual ~PNBinaryLogicExpr()
00977 {
00978 if (left) delete left;
00979 if (right) delete right;
00980 }
00981
00983 inline bool do_operator(bool left, bool right) const
00984 {
00985 if (op == OP_AND) return left && right;
00986 else if (op == OP_OR) return left || right;
00987 else return false;
00988 }
00989
00992 virtual bool getValue(AnyType &dest, const class GraphContainer &gc, const class Changelist &cl,
00993 vertex_or_edge_t wantedge, unsigned int vid1, unsigned int vid2) const
00994 {
00995 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
00996
00997 bool bl = left->getValue(vl, gc, cl, wantedge, vid1, vid2);
00998 bool br = right->getValue(vr, gc, cl , wantedge, vid1, vid2);
00999
01000
01001 if (vl.getType() != ATTRTYPE_BOOL)
01002 throw(AttributeParseException(std::string("Invalid left operand for ") + (op == OP_AND ? "&&" : "||") + ". Both operands must be of type bool."));
01003 if (vr.getType() != ATTRTYPE_BOOL)
01004 throw(AttributeParseException(std::string("Invalid right operand for ") + (op == OP_AND ? "&&" : "||") + ". Both operands must be of type bool."));
01005
01006 int bvl = vl.getInteger();
01007 int bvr = vr.getInteger();
01008
01009 dest = AnyType( do_operator(bvl, bvr) );
01010
01011 return (bl and br);
01012 }
01013
01014 virtual bool getConstVal(AnyType *dest) const
01015 {
01016 if (!dest) return false;
01017
01018 AnyType vl(ATTRTYPE_INVALID), vr(ATTRTYPE_INVALID);
01019
01020 bool bl = left->getConstVal(&vl);
01021 bool br = right->getConstVal(&vr);
01022
01023 if (vl.getType() != ATTRTYPE_BOOL)
01024 throw(AttributeParseException(std::string("Invalid left operand for ") + (op == OP_AND ? "&&" : "||") + ". Both operands must be of type bool."));
01025 if (vr.getType() != ATTRTYPE_BOOL)
01026 throw(AttributeParseException(std::string("Invalid right operand for ") + (op == OP_AND ? "&&" : "||") + ". Both operands must be of type bool."));
01027
01028 int bvl = vl.getInteger();
01029 int bvr = vr.getInteger();
01030
01031 *dest = AnyType( do_operator(bvl, bvr) );
01032
01033 if (op == OP_AND)
01034 {
01035
01036
01037 return (bl and br) or (bl and !bvl) or (br and !bvr);
01038 }
01039 else if (op == OP_OR)
01040 {
01041
01042
01043 return (bl and br) or (bl and bvl) or (br and bvr);
01044 }
01045 else {
01046 assert(0);
01047 return false;
01048 }
01049 }
01050
01052 virtual std::string toString() const
01053 {
01054 return std::string("(") + left->toString() + " " + (op == OP_AND ? "&&" : "||") + " " + right->toString() + ")";
01055 }
01056
01058 inline const ParseNode* detach_left()
01059 {
01060 const ParseNode *n = left;
01061 left = NULL;
01062 return n;
01063 }
01064
01066 inline const ParseNode* detach_right()
01067 {
01068 const ParseNode *n = right;
01069 right = NULL;
01070 return n;
01071 }
01072 };
01073
01074
01075
01076
01077 typedef char const* InputIterT;
01078
01079 typedef tree_match<InputIterT> ParseTreeMatchT;
01080
01081 typedef ParseTreeMatchT::const_tree_iterator TreeIterT;
01082
01085 static const ParseNode* build_expr(TreeIterT const& i, const GraphProperties &gp, vertex_or_edge_t voe)
01086 {
01087 #ifdef BOOST_SPIRIT_DEBUG
01088 std::cout << "In build_expr. i->value = " <<
01089 std::string(i->value.begin(), i->value.end()) <<
01090 " i->children.size() = " << i->children.size() <<
01091 " i->value.id = " << i->value.id().to_long() << std::endl;
01092 #endif
01093
01094 switch(i->value.id().to_long())
01095 {
01096
01097 case integer_const_id:
01098 {
01099 return new PNConstant(ATTRTYPE_INTEGER,
01100 std::string(i->value.begin(), i->value.end()));
01101 }
01102
01103 case double_const_id:
01104 {
01105 return new PNConstant(ATTRTYPE_DOUBLE,
01106 std::string(i->value.begin(), i->value.end()));
01107 }
01108
01109 case string_const_id:
01110 {
01111 return new PNConstant(ATTRTYPE_STRING,
01112 std::string(i->value.begin(), i->value.end()));
01113 }
01114
01115
01116
01117 case add_expr_id:
01118 case mul_expr_id:
01119 {
01120 char arithop = *i->value.begin();
01121 assert(i->children.size() == 2);
01122
01123
01124
01125 std::auto_ptr<const ParseNode> left( build_expr(i->children.begin(), gp, voe) );
01126 std::auto_ptr<const ParseNode> right( build_expr(i->children.begin()+1, gp, voe) );
01127
01128 if (left->getConstVal(NULL) and right->getConstVal(NULL))
01129 {
01130
01131 PNBinaryArithmExpr tmpnode(left.release(), right.release(), arithop);
01132 AnyType both(ATTRTYPE_INVALID);
01133
01134 tmpnode.getConstVal(&both);
01135
01136
01137
01138 return new PNConstant(both);
01139 }
01140 else
01141 {
01142
01143 return new PNBinaryArithmExpr(left.release(), right.release(), arithop);
01144 }
01145 }
01146
01147 case unary_expr_id:
01148 {
01149 char arithop = *i->value.begin();
01150 assert(i->children.size() == 1);
01151
01152 const ParseNode *val = build_expr(i->children.begin(), gp, voe);
01153
01154 if (val->getConstVal(NULL))
01155 {
01156
01157 PNUnaryArithmExpr tmpnode(val, arithop);
01158 AnyType constval(ATTRTYPE_INVALID);
01159
01160 tmpnode.getConstVal(&constval);
01161
01162 return new PNConstant(constval);
01163 }
01164 else
01165 {
01166
01167 return new PNUnaryArithmExpr(val, arithop);
01168 }
01169 }
01170
01171
01172
01173 case cast_spec_id:
01174 {
01175 assert(i->children.size() == 1);
01176
01177 std::string tname(i->value.begin(), i->value.end());
01178 attrtype_t at = AnyType::stringToType(tname);
01179
01180 const ParseNode *val = build_expr(i->children.begin(), gp, voe);
01181
01182 if (val->getConstVal(NULL))
01183 {
01184
01185 PNCastExpr tmpnode(val, at);
01186
01187 AnyType constval(ATTRTYPE_INVALID);
01188
01189 tmpnode.getConstVal(&constval);
01190
01191 return new PNConstant(constval);
01192 }
01193 else
01194 {
01195 return new PNCastExpr(val, at);
01196 }
01197 }
01198
01199
01200
01201 case comp_expr_id:
01202 {
01203 assert(i->children.size() == 2);
01204
01205 std::string arithop(i->value.begin(), i->value.end());
01206
01207
01208
01209 std::auto_ptr<const ParseNode> left( build_expr(i->children.begin(), gp, voe) );
01210 std::auto_ptr<const ParseNode> right( build_expr(i->children.begin()+1, gp, voe) );
01211
01212 if (left->getConstVal(NULL) and right->getConstVal(NULL))
01213 {
01214
01215 PNBinaryComparisonExpr tmpnode(left.release(), right.release(), arithop);
01216 AnyType both(ATTRTYPE_INVALID);
01217
01218 tmpnode.getConstVal(&both);
01219
01220
01221
01222 return new PNConstant(both);
01223 }
01224 else
01225 {
01226
01227 return new PNBinaryComparisonExpr(left.release(), right.release(), arithop);
01228 }
01229 }
01230
01231
01232
01233 case and_expr_id:
01234 case or_expr_id:
01235 {
01236 assert(i->children.size() == 2);
01237
01238 std::string logicop(i->value.begin(), i->value.end());
01239
01240
01241
01242 std::auto_ptr<const ParseNode> left( build_expr(i->children.begin(), gp, voe) );
01243 std::auto_ptr<const ParseNode> right( build_expr(i->children.begin()+1, gp, voe) );
01244
01245 bool constleft = left->getConstVal(NULL);
01246 bool constright = right->getConstVal(NULL);
01247
01248
01249
01250 std::auto_ptr<PNBinaryLogicExpr> node( new PNBinaryLogicExpr(left.release(), right.release(), logicop) );
01251
01252 if (constleft or constright)
01253 {
01254 AnyType both(ATTRTYPE_INVALID);
01255
01256
01257 if (node->getConstVal(&both))
01258 {
01259
01260
01261 return new PNConstant(both);
01262 }
01263 }
01264 if (constleft)
01265 {
01266
01267
01268 return node->detach_right();
01269 }
01270 if (constright)
01271 {
01272
01273
01274 return node->detach_left();
01275 }
01276
01277 return node.release();
01278 }
01279
01280
01281
01282 case attrname_id:
01283 {
01284 assert(i->children.size() == 0);
01285
01286 std::string attrname(i->value.begin(), i->value.end());
01287
01288 size_t dotloc = attrname.find('.');
01289 if (dotloc == std::string::npos)
01290 {
01291
01292 return new PNAttributeName(attrname, voe == VE_VERTEX ? gp.vertexattr : gp.edgeattr, voe);
01293 }
01294 else
01295 {
01296 if (voe != VE_EDGE)
01297 throw(AttributeParseException("Invalid attribute name " + attrname + " for vertex selection."));
01298
01299
01300 return new PNAttributeDotName(attrname, gp, voe);
01301 }
01302 }
01303
01304 default:
01305 throw(AttributeParseException("Unknown ast parse tree node found. This should never happen."));
01306 }
01307 }
01308
01311 bool build_attrlist(TreeIterT const &i, const GraphProperties &gp, vertex_or_edge_t voe, class AttributeSelectorList &sellist)
01312 {
01313 #ifdef BOOST_SPIRIT_DEBUG
01314 std::cout << "In build_attrlist. i->value = " <<
01315 std::string(i->value.begin(), i->value.end()) <<
01316 " i->children.size() = " << i->children.size() <<
01317 " i->value.id = " << i->value.id().to_long() << std::endl;
01318 #endif
01319
01320 sellist.clear();
01321
01322 switch(i->value.id().to_long())
01323 {
01324 case attrlist_star_id:
01325 {
01326 sellist.selectStar(voe == VE_VERTEX ? gp.vertexattr: gp.edgeattr, voe);
01327 break;
01328 }
01329
01330 case attrlist_exprlist_id:
01331 {
01332 for(TreeIterT ci = i->children.begin(); ci != i->children.end(); ++ci)
01333 {
01334 const ParseNode *vas = build_expr(ci, gp, voe);
01335
01336
01337 sellist.addAttrsel(vas);
01338 }
01339 break;
01340 }
01341
01342 default:
01343 {
01344
01345
01346
01347 const ParseNode *vas = build_expr(i, gp, voe);
01348
01349
01350
01351 sellist.addAttrsel(vas);
01352 break;
01353 }
01354 }
01355
01356 sellist.calcAttributeLookups();
01357 return true;
01358 }
01359
01360 }
01361
01362
01363
01364 void AttributeSelectorList::selectStar(const AttributePropertiesList &otherlist, vertex_or_edge_t voe)
01365 {
01366
01367
01368 for(AttributePropertiesList::const_iterator ai = otherlist.begin(); ai != otherlist.end(); ai++)
01369 {
01370
01371 attrlist::push_back(*ai);
01372
01373
01374 sellist::push_back( new AttributeParser::PNAttributeName(ai->name, otherlist, voe) );
01375 }
01376
01377 assert( attrlist::size() == sellist::size() );
01378 }
01379
01380 void AttributeSelectorList::addAttrsel(const class ParseNode *attrsel)
01381 {
01382 assert(attrsel);
01383
01384
01385 AnyType rtype(ATTRTYPE_INVALID);
01386 attrsel->getConstVal(&rtype);
01387
01388 std::string rstring = attrsel->toString();
01389
01390
01391
01392 attrlist::push_back( AttributeProperties(rstring, rtype) );
01393
01394
01395 sellist::push_back( attrsel );
01396
01397 assert( attrlist::size() == sellist::size() );
01398 }
01399
01400 #ifdef BOOST_SPIRIT_DEBUG
01401 template <typename TreeInfo>
01402 static inline void debug_dump_xml(const std::string &input, const TreeInfo &info)
01403 {
01404 using namespace AttributeParser;
01405
01406
01407
01408 std::map<parser_id, std::string> rule_names;
01409
01410 rule_names[integer_const_id] = "integer_const";
01411 rule_names[double_const_id] = "double_const";
01412 rule_names[string_const_id] = "string_const";
01413 rule_names[constant_id] = "constant";
01414
01415 rule_names[function_call_id] = "function_call";
01416 rule_names[function_identifier_id] = "function_identifier";
01417
01418 rule_names[attrname_id] = "attrname";
01419
01420 rule_names[unary_expr_id] = "unary_expr";
01421 rule_names[mul_expr_id] = "mul_expr";
01422 rule_names[add_expr_id] = "add_expr";
01423
01424 rule_names[cast_expr_id] = "cast_expr";
01425 rule_names[cast_spec_id] = "cast_spec";
01426
01427 rule_names[comp_expr_id] = "comp_expr";
01428 rule_names[and_expr_id] = "and_expr";
01429 rule_names[or_expr_id] = "or_expr";
01430
01431 rule_names[expr_id] = "expr";
01432
01433 rule_names[attrlist_id] = "attrlist";
01434 rule_names[attrlist_exprlist_id] = "attrlist_exprlist";
01435 rule_names[attrlist_star_id] = "attrlist_star";
01436
01437 rule_names[filter_expr_id] = "filter_expr";
01438
01439 tree_to_xml(std::cout, info.trees, input.c_str(), rule_names);
01440 }
01441 #endif
01442
01443 bool AttributeSelectorList::parseString(const std::string &input, const class GraphProperties &gp, vertex_or_edge_t voe)
01444 {
01445 using namespace AttributeParser;
01446
01447
01448 AttributeGrammar g;
01449
01450 #ifdef BOOST_SPIRIT_DEBUG
01451 BOOST_SPIRIT_DEBUG_GRAMMAR(g);
01452 #endif
01453
01454 tree_parse_info<> info =
01455 boost::spirit::ast_parse(input.c_str(),
01456 g.use_parser<0>(),
01457 boost::spirit::space_p);
01458
01459 if (not info.full)
01460 {
01461 char synstr[256];
01462 g_snprintf(synstr, sizeof(synstr),
01463 "Syntax error at position %d near %.10s",
01464 static_cast<int>(info.stop - input.c_str()),
01465 info.stop);
01466 throw (AttributeParseException(synstr));
01467 }
01468
01469 #ifdef BOOST_SPIRIT_DEBUG
01470 debug_dump_xml(input, info);
01471 #endif
01472
01473 return build_attrlist(info.trees.begin(), gp, voe, *this);
01474 }
01475
01476 std::string AttributeSelectorList::toString() const
01477 {
01478 std::string sl;
01479
01480 for(sellist::const_iterator i = sellist::begin(); i != sellist::end(); i++) {
01481
01482 if (i != sellist::begin()) {
01483 sl += ", ";
01484 }
01485
01486 sl += (*i)->toString();
01487 }
01488
01489 return sl;
01490 }
01491
01492
01493
01494 bool FilterRoot::parseString(const std::string &input, const class GraphProperties &gp)
01495 {
01496
01497 vertexoredge = VE_VERTEX;
01498 if (filter) {
01499 delete filter;
01500 filter = NULL;
01501 }
01502
01503 if (input.size() == 0) return true;
01504
01505 using namespace AttributeParser;
01506
01507
01508 AttributeGrammar g;
01509
01510 #ifdef BOOST_SPIRIT_DEBUG
01511 BOOST_SPIRIT_DEBUG_GRAMMAR(g);
01512 #endif
01513
01514 tree_parse_info<> info =
01515 boost::spirit::ast_parse(input.c_str(),
01516 g.use_parser<1>(),
01517 boost::spirit::space_p);
01518
01519 if (not info.full)
01520 {
01521 char synstr[256];
01522 g_snprintf(synstr, sizeof(synstr),
01523 "Syntax error at position %d near %.10s",
01524 static_cast<int>(info.stop - input.c_str()),
01525 info.stop);
01526 throw (AttributeParseException(synstr));
01527 }
01528
01529 #ifdef BOOST_SPIRIT_DEBUG
01530 debug_dump_xml(input, info);
01531 #endif
01532
01533
01534
01535
01536
01537 {
01538 TreeIterT const &i = info.trees.begin();
01539
01540 #ifdef BOOST_SPIRIT_DEBUG
01541 std::cout << "In build_filterroot. i->value = " <<
01542 std::string(i->value.begin(), i->value.end()) <<
01543 " i->children.size() = " << i->children.size() <<
01544 " i->value.id = " << i->value.id().to_long() << std::endl;
01545 #endif
01546
01547 if (i->value.id().to_long() != filter_expr_id)
01548 throw(AttributeParseException("Unknown ast parse tree node found. This should never happen."));
01549
01550 if (i->children.size() == 0)
01551 {
01552
01553 return true;
01554 }
01555 else if (i->children.size() == 1)
01556 {
01557
01558 char voeletter = *i->value.begin();
01559 vertexoredge = (voeletter == 'v') ? VE_VERTEX : VE_EDGE;
01560
01561
01562 filter = build_expr(i->children.begin(), gp, vertexoredge);
01563
01564
01565
01566 AnyType tc(ATTRTYPE_INVALID);
01567 filter->getConstVal(&tc);
01568
01569 if (tc.getType() != ATTRTYPE_BOOL)
01570 throw(AttributeParseException("The filter expression must be of type bool. Remember there is no automatic comparison != 0 as in C."));
01571
01572 return true;
01573 }
01574 else {
01575 throw(AttributeParseException("Unknown ast parse tree node found. This should never happen."));
01576 }
01577 }
01578 }
01579
01580 std::string FilterRoot::toString() const
01581 {
01582 if (!filter) return "null-filter";
01583
01584 return std::string(vertexoredge == VE_VERTEX ? "vertex: " : "edge: ") + filter->toString();
01585 }
01586
01587 }