00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "ExpressionParser.h"
00028
00029 #include <boost/spirit/core.hpp>
00030
00031 #include <boost/spirit/tree/ast.hpp>
00032 #include <boost/spirit/tree/tree_to_xml.hpp>
00033
00034 #include <boost/spirit/utility/lists.hpp>
00035 #include <boost/spirit/utility/distinct.hpp>
00036 #include <boost/spirit/utility/escape_char.hpp>
00037 #include <boost/spirit/utility/grammar_def.hpp>
00038
00039 #include <iostream>
00040 #include <sstream>
00041 #include <cmath>
00042
00043
00044
00045 namespace stx {
00046
00049 namespace Grammar {
00050
00051 using namespace boost::spirit;
00052
00054 enum parser_ids
00055 {
00056 boolean_const_id = 1,
00057 integer_const_id,
00058 long_const_id,
00059 double_const_id,
00060 string_const_id,
00061 constant_id,
00062
00063 function_call_id,
00064 function_identifier_id,
00065
00066 varname_id,
00067
00068 atom_expr_id,
00069
00070 unary_expr_id,
00071 mul_expr_id,
00072 add_expr_id,
00073
00074 cast_expr_id,
00075 cast_spec_id,
00076
00077 comp_expr_id,
00078 and_expr_id,
00079 or_expr_id,
00080
00081 expr_id,
00082 exprlist_id,
00083 };
00084
00086 distinct_parser<> keyword_p("a-zA-Z0-9_");
00087
00089 struct ExpressionGrammar : public grammar<ExpressionGrammar>
00090 {
00093 template <typename ScannerT>
00094 struct definition : public grammar_def<rule<ScannerT, parser_context<>, parser_tag<expr_id> >,
00095 rule<ScannerT, parser_context<>, parser_tag<exprlist_id> > >
00096 {
00098 definition(ExpressionGrammar const& )
00099 {
00100
00101
00102 constant
00103 = double_const
00104 | integer_const
00105 | long_const
00106 | boolean_const
00107 | string_const
00108 ;
00109
00110 boolean_const
00111 = as_lower_d[keyword_p("true") | keyword_p("false")]
00112 ;
00113
00114 integer_const
00115 = int_p
00116 ;
00117
00118
00119
00120 long_const
00121 = token_node_d[ lexeme_d[ !( ch_p('+') | ch_p('-' ) ) >> +( range_p('0','9') ) ] ]
00122 ;
00123
00124 double_const
00125 = strict_real_p
00126 ;
00127
00128 string_const
00129 = lexeme_d[
00130 token_node_d[ '"' >> *(c_escape_ch_p - '"') >> '"' ]
00131 ]
00132 ;
00133
00134
00135
00136 function_call
00137 = root_node_d[function_identifier]
00138 >> discard_node_d[ ch_p('(') ] >> exprlist >> discard_node_d[ ch_p(')') ]
00139 ;
00140
00141 function_identifier
00142 = lexeme_d[
00143 token_node_d[ alpha_p >> *(alnum_p | ch_p('_')) ]
00144 ]
00145 ;
00146
00147
00148
00149 varname
00150 = lexeme_d[
00151 token_node_d[ alpha_p >> *(alnum_p | ch_p('_')) ]
00152 ]
00153 ;
00154
00155
00156
00157 atom_expr
00158 = constant
00159 | inner_node_d[ ch_p('(') >> expr >> ch_p(')') ]
00160 | function_call
00161 | varname
00162 ;
00163
00164 unary_expr
00165 = !( root_node_d[ as_lower_d[ch_p('+') | ch_p('-') | ch_p('!') | str_p("not")] ] )
00166 >> atom_expr
00167 ;
00168
00169 cast_spec
00170 = discard_node_d[ ch_p('(') ]
00171 >> (
00172 keyword_p("bool") |
00173 keyword_p("char") | keyword_p("short") | keyword_p("int") | keyword_p("integer") | keyword_p("long") |
00174 keyword_p("byte") | keyword_p("word") | keyword_p("dword") | keyword_p("qword") |
00175 keyword_p("float") | keyword_p("double") |
00176 keyword_p("string")
00177 )
00178 >> discard_node_d[ ch_p(')') ]
00179 ;
00180
00181 cast_expr
00182 = root_node_d[ !cast_spec ] >> unary_expr
00183 ;
00184
00185 mul_expr
00186 = cast_expr
00187 >> *( root_node_d[ch_p('*') | ch_p('/')] >> cast_expr )
00188 ;
00189
00190 add_expr
00191 = mul_expr
00192 >> *( root_node_d[ch_p('+') | ch_p('-')] >> mul_expr )
00193 ;
00194
00195 comp_expr
00196 = add_expr
00197 >> *( root_node_d[( str_p("==") | str_p("!=") |
00198 str_p("<=") | str_p(">=") | str_p("=<") | str_p("=>") |
00199 ch_p('=') | ch_p('<') | ch_p('>') )] >> add_expr )
00200 ;
00201
00202 and_expr
00203 = comp_expr
00204 >> *( root_node_d[ as_lower_d[str_p("and") | str_p("&&")] ] >> comp_expr )
00205 ;
00206
00207 or_expr
00208 = and_expr
00209 >> *( root_node_d[ as_lower_d[str_p("or") | str_p("||")] ] >> and_expr )
00210 ;
00211
00212
00213
00214 expr
00215 = or_expr
00216 ;
00217
00218 exprlist
00219 = infix_node_d[ !list_p(expr, ch_p(',')) ]
00220 ;
00221
00222
00223 this->start_parsers(expr, exprlist);
00224
00225 #ifdef STX_DEBUG_PARSER
00226 BOOST_SPIRIT_DEBUG_RULE(constant);
00227
00228 BOOST_SPIRIT_DEBUG_RULE(boolean_const);
00229 BOOST_SPIRIT_DEBUG_RULE(integer_const);
00230 BOOST_SPIRIT_DEBUG_RULE(long_const);
00231 BOOST_SPIRIT_DEBUG_RULE(double_const);
00232 BOOST_SPIRIT_DEBUG_RULE(string_const);
00233
00234 BOOST_SPIRIT_DEBUG_RULE(function_call);
00235 BOOST_SPIRIT_DEBUG_RULE(function_identifier);
00236
00237 BOOST_SPIRIT_DEBUG_RULE(varname);
00238
00239 BOOST_SPIRIT_DEBUG_RULE(atom_expr);
00240
00241 BOOST_SPIRIT_DEBUG_RULE(unary_expr);
00242 BOOST_SPIRIT_DEBUG_RULE(mul_expr);
00243 BOOST_SPIRIT_DEBUG_RULE(add_expr);
00244
00245 BOOST_SPIRIT_DEBUG_RULE(cast_spec);
00246 BOOST_SPIRIT_DEBUG_RULE(cast_expr);
00247
00248 BOOST_SPIRIT_DEBUG_RULE(comp_expr);
00249 BOOST_SPIRIT_DEBUG_RULE(and_expr);
00250 BOOST_SPIRIT_DEBUG_RULE(or_expr);
00251
00252 BOOST_SPIRIT_DEBUG_RULE(expr);
00253 BOOST_SPIRIT_DEBUG_RULE(exprlist);
00254 #endif
00255 }
00256
00259 rule<ScannerT, parser_context<>, parser_tag<constant_id> > constant;
00260
00262 rule<ScannerT, parser_context<>, parser_tag<boolean_const_id> > boolean_const;
00264 rule<ScannerT, parser_context<>, parser_tag<integer_const_id> > integer_const;
00266 rule<ScannerT, parser_context<>, parser_tag<long_const_id> > long_const;
00268 rule<ScannerT, parser_context<>, parser_tag<double_const_id> > double_const;
00270 rule<ScannerT, parser_context<>, parser_tag<string_const_id> > string_const;
00271
00273 rule<ScannerT, parser_context<>, parser_tag<function_call_id> > function_call;
00276 rule<ScannerT, parser_context<>, parser_tag<function_identifier_id> > function_identifier;
00277
00279 rule<ScannerT, parser_context<>, parser_tag<varname_id> > varname;
00280
00282 rule<ScannerT, parser_context<>, parser_tag<atom_expr_id> > atom_expr;
00283
00285 rule<ScannerT, parser_context<>, parser_tag<unary_expr_id> > unary_expr;
00288 rule<ScannerT, parser_context<>, parser_tag<mul_expr_id> > mul_expr;
00290 rule<ScannerT, parser_context<>, parser_tag<add_expr_id> > add_expr;
00291
00293 rule<ScannerT, parser_context<>, parser_tag<cast_spec_id> > cast_spec;
00295 rule<ScannerT, parser_context<>, parser_tag<cast_expr_id> > cast_expr;
00296
00298 rule<ScannerT, parser_context<>, parser_tag<comp_expr_id> > comp_expr;
00301 rule<ScannerT, parser_context<>, parser_tag<and_expr_id> > and_expr;
00304 rule<ScannerT, parser_context<>, parser_tag<or_expr_id> > or_expr;
00305
00307 rule<ScannerT, parser_context<>, parser_tag<expr_id> > expr;
00310 rule<ScannerT, parser_context<>, parser_tag<exprlist_id> > exprlist;
00311 };
00312 };
00313
00314
00315
00316
00319 class PNConstant : public ParseNode
00320 {
00321 private:
00323 class AnyScalar value;
00324
00325 public:
00327 PNConstant(AnyScalar::attrtype_t type, std::string strvalue)
00328 : ParseNode(), value(type)
00329 {
00330
00331 if (type == AnyScalar::ATTRTYPE_STRING)
00332 value.setStringQuoted(strvalue);
00333 else
00334 value.setString(strvalue);
00335 }
00336
00338 PNConstant(const AnyScalar &_value)
00339 : value(_value)
00340 {
00341 }
00342
00344 virtual AnyScalar evaluate(const class SymbolTable &) const
00345 {
00346 return value;
00347 }
00348
00350 virtual bool evaluate_const(AnyScalar *dest) const
00351 {
00352 if (dest) *dest = value;
00353 return true;
00354 }
00355
00357 virtual std::string toString() const
00358 {
00359 if (value.getType() == AnyScalar::ATTRTYPE_STRING) {
00360 return value.getStringQuoted();
00361 }
00362 return value.getString();
00363 }
00364 };
00365
00368 class PNVariable : public ParseNode
00369 {
00370 private:
00372 std::string varname;
00373
00374 public:
00376 PNVariable(std::string _varname)
00377 : ParseNode(), varname(_varname)
00378 {
00379 }
00380
00382 virtual AnyScalar evaluate(const class SymbolTable &st) const
00383 {
00384 return st.lookupVariable(varname);
00385 }
00386
00388 virtual bool evaluate_const(AnyScalar *) const
00389 {
00390 return false;
00391 }
00392
00394 virtual std::string toString() const
00395 {
00396 return varname;
00397 }
00398 };
00399
00402 class PNFunction : public ParseNode
00403 {
00404 public:
00406 typedef std::vector<const class ParseNode*> paramlist_type;
00407
00408 private:
00410 std::string funcname;
00411
00413 paramlist_type paramlist;
00414
00415 public:
00417 PNFunction(std::string _funcname, const paramlist_type& _paramlist)
00418 : ParseNode(), funcname(_funcname), paramlist(_paramlist)
00419 {
00420 }
00421
00423 ~PNFunction()
00424 {
00425 for(unsigned int i = 0; i < paramlist.size(); ++i)
00426 delete paramlist[i];
00427 }
00428
00430 virtual AnyScalar evaluate(const class SymbolTable &st) const
00431 {
00432 std::vector<AnyScalar> paramvalues;
00433
00434 for(unsigned int i = 0; i < paramlist.size(); ++i)
00435 {
00436 paramvalues.push_back( paramlist[i]->evaluate(st) );
00437 }
00438
00439 return st.processFunction(funcname, paramvalues);
00440 }
00441
00443 virtual bool evaluate_const(AnyScalar *) const
00444 {
00445 return false;
00446 }
00447
00449 virtual std::string toString() const
00450 {
00451 std::string str = funcname + "(";
00452 for(unsigned int i = 0; i < paramlist.size(); ++i)
00453 {
00454 if (i != 0) str += ",";
00455 str += paramlist[i]->toString();
00456 }
00457 return str + ")";
00458 }
00459 };
00460
00463 class PNUnaryArithmExpr : public ParseNode
00464 {
00465 private:
00467 const ParseNode *operand;
00468
00471 char op;
00472
00473 public:
00475 PNUnaryArithmExpr(const ParseNode* _operand, char _op)
00476 : ParseNode(), operand(_operand), op(_op)
00477 {
00478 if (op == 'n' || op == 'N') op = '!';
00479 }
00480
00482 virtual ~PNUnaryArithmExpr()
00483 {
00484 delete operand;
00485 }
00486
00488 virtual AnyScalar evaluate(const class SymbolTable &st) const
00489 {
00490 AnyScalar dest = operand->evaluate(st);
00491
00492 if (op == '-') {
00493 dest = -dest;
00494 }
00495 else if (op == '!')
00496 {
00497
00498 if (dest.getType() != AnyScalar::ATTRTYPE_BOOL)
00499 throw(BadSyntaxException("Invalid operand for !. Operand must be of type bool."));
00500
00501 dest = -dest;
00502 }
00503 else {
00504 assert(op == '+');
00505 }
00506
00507 return dest;
00508 }
00509
00511 virtual bool evaluate_const(AnyScalar *dest) const
00512 {
00513 if (!dest) return false;
00514
00515 bool b = operand->evaluate_const(dest);
00516
00517 if (op == '-') {
00518 *dest = -(*dest);
00519 }
00520 else if (op == '!')
00521 {
00522 if (dest->getType() != AnyScalar::ATTRTYPE_BOOL)
00523 throw(BadSyntaxException("Invalid operand for !. Operand must be of type bool."));
00524
00525 *dest = -(*dest);
00526 }
00527 else {
00528 assert(op == '+');
00529 }
00530
00531 return b;
00532 }
00533
00535 virtual std::string toString() const
00536 {
00537 return std::string("(") + op + " " + operand->toString() + ")";
00538 }
00539 };
00540
00543 class PNBinaryArithmExpr : public ParseNode
00544 {
00545 private:
00547 const ParseNode *left;
00548
00550 const ParseNode *right;
00551
00554 char op;
00555
00556 public:
00558 PNBinaryArithmExpr(const ParseNode* _left,
00559 const ParseNode* _right,
00560 char _op)
00561 : ParseNode(),
00562 left(_left), right(_right), op(_op)
00563 { }
00564
00566 virtual ~PNBinaryArithmExpr()
00567 {
00568 delete left;
00569 delete right;
00570 }
00571
00574 virtual AnyScalar evaluate(const class SymbolTable &st) const
00575 {
00576 AnyScalar vl = left->evaluate(st);
00577 AnyScalar vr = right->evaluate(st);
00578
00579 if (op == '+') {
00580 return (vl + vr);
00581 }
00582 else if (op == '-') {
00583 return (vl - vr);
00584 }
00585 else if (op == '*') {
00586 return (vl * vr);
00587 }
00588 else if (op == '/') {
00589 return (vl / vr);
00590 }
00591
00592 assert(0);
00593 return 0;
00594 }
00595
00598 virtual bool evaluate_const(AnyScalar *dest) const
00599 {
00600 if (!dest) return false;
00601
00602 AnyScalar vl(AnyScalar::ATTRTYPE_INVALID), vr(AnyScalar::ATTRTYPE_INVALID);
00603
00604 bool bl = left->evaluate_const(&vl);
00605 bool br = right->evaluate_const(&vr);
00606
00607 if (op == '+') {
00608 *dest = vl + vr;
00609 }
00610 else if (op == '-') {
00611 *dest = vl - vr;
00612 }
00613 else if (op == '*') {
00614 *dest = vl * vr;
00615 }
00616 else if (op == '/') {
00617 *dest = vl / vr;
00618 }
00619
00620 return (bl && br);
00621 }
00622
00624 virtual std::string toString() const
00625 {
00626 return std::string("(") + left->toString() + " " + op + " " + right->toString() + ")";
00627 }
00628 };
00629
00631 class PNCastExpr : public ParseNode
00632 {
00633 private:
00635 const ParseNode* operand;
00636
00638 AnyScalar::attrtype_t type;
00639
00640 public:
00643 PNCastExpr(const ParseNode* _operand, AnyScalar::attrtype_t _type)
00644 : ParseNode(),
00645 operand(_operand), type(_type)
00646 { }
00647
00649 virtual ~PNCastExpr()
00650 {
00651 delete operand;
00652 }
00653
00656 virtual AnyScalar evaluate(const class SymbolTable &st) const
00657 {
00658 AnyScalar val = operand->evaluate(st);
00659 val.convertType(type);
00660 return val;
00661 }
00662
00664 virtual bool evaluate_const(AnyScalar *dest) const
00665 {
00666 if (!dest) return false;
00667
00668 bool b = operand->evaluate_const(dest);
00669 dest->convertType(type);
00670 return b;
00671 }
00672
00674 virtual std::string toString() const
00675 {
00676 return std::string("((") + AnyScalar::getTypeString(type) + ")" + operand->toString() + ")";
00677 }
00678 };
00679
00682 class PNBinaryComparisonExpr : public ParseNode
00683 {
00684 private:
00686 const ParseNode *left;
00687
00689 const ParseNode *right;
00690
00692 enum { EQUAL, NOTEQUAL, LESS, GREATER, LESSEQUAL, GREATEREQUAL } op;
00693
00695 std::string opstr;
00696
00697 public:
00699 PNBinaryComparisonExpr(const ParseNode* _left,
00700 const ParseNode* _right,
00701 std::string _op)
00702 : ParseNode(),
00703 left(_left), right(_right), opstr(_op)
00704 {
00705 if (_op == "==" || _op == "=")
00706 op = EQUAL;
00707 else if (_op == "!=")
00708 op = NOTEQUAL;
00709 else if (_op == "<")
00710 op = LESS;
00711 else if (_op == ">")
00712 op = GREATER;
00713 else if (_op == "<=" || _op == "=<")
00714 op = LESSEQUAL;
00715 else if (_op == ">=" || _op == "=>")
00716 op = GREATEREQUAL;
00717 else
00718 throw(BadSyntaxException("Program Error: invalid binary comparision operator."));
00719 }
00720
00722 virtual ~PNBinaryComparisonExpr()
00723 {
00724 delete left;
00725 delete right;
00726 }
00727
00731 virtual AnyScalar evaluate(const class SymbolTable &st) const
00732 {
00733 AnyScalar vl = left->evaluate(st);
00734 AnyScalar vr = right->evaluate(st);
00735
00736 AnyScalar dest(AnyScalar::ATTRTYPE_BOOL);
00737
00738 switch(op)
00739 {
00740 case EQUAL:
00741 dest = AnyScalar( vl.equal_to(vr) );
00742 break;
00743
00744 case NOTEQUAL:
00745 dest = AnyScalar( vl.not_equal_to(vr) );
00746 break;
00747
00748 case LESS:
00749 dest = AnyScalar( vl.less(vr) );
00750 break;
00751
00752 case GREATER:
00753 dest = AnyScalar( vl." greater-than.">greater(vr) );
00754 break;
00755
00756 case LESSEQUAL:
00757 dest = AnyScalar( vl.less_equal(vr) );
00758 break;
00759
00760 case GREATEREQUAL:
00761 dest = AnyScalar( vl.=" greater-or-equal-than.">greater_equal(vr) );
00762 break;
00763
00764 default:
00765 assert(0);
00766 }
00767
00768 return dest;
00769 }
00770
00772 virtual bool evaluate_const(AnyScalar *dest) const
00773 {
00774 if (!dest) return false;
00775
00776 AnyScalar vl(AnyScalar::ATTRTYPE_INVALID), vr(AnyScalar::ATTRTYPE_INVALID);
00777
00778 bool bl = left->evaluate_const(&vl);
00779 bool br = right->evaluate_const(&vr);
00780
00781 switch(op)
00782 {
00783 case EQUAL:
00784 *dest = AnyScalar( vl.equal_to(vr) );
00785 break;
00786
00787 case NOTEQUAL:
00788 *dest = AnyScalar( vl.not_equal_to(vr) );
00789 break;
00790
00791 case LESS:
00792 *dest = AnyScalar( vl.less(vr) );
00793 break;
00794
00795 case GREATER:
00796 *dest = AnyScalar( vl.greater(vr) );
00797 break;
00798
00799 case LESSEQUAL:
00800 *dest = AnyScalar( vl.less_equal(vr) );
00801 break;
00802
00803 case GREATEREQUAL:
00804 *dest = AnyScalar( vl.greater_equal(vr) );
00805 break;
00806
00807 default:
00808 assert(0);
00809 }
00810
00811 return (bl && br);
00812 }
00813
00815 virtual std::string toString() const
00816 {
00817 return std::string("(") + left->toString() + " " + opstr + " " + right->toString() + ")";
00818 }
00819 };
00820
00823 class PNBinaryLogicExpr : public ParseNode
00824 {
00825 private:
00827 ParseNode* left;
00828
00830 ParseNode* right;
00831
00833 enum { OP_AND, OP_OR } op;
00834
00835 public:
00837 PNBinaryLogicExpr(ParseNode* _left,
00838 ParseNode* _right,
00839 std::string _op)
00840 : ParseNode(),
00841 left(_left), right(_right)
00842 {
00843 if (_op == "and" |