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" || _op == "&&")
00844 op = OP_AND;
00845 else if (_op == "or" || _op == "||")
00846 op = OP_OR;
00847 else
00848 throw(BadSyntaxException("Program Error: invalid binary logic operator."));
00849 }
00850
00852 virtual ~PNBinaryLogicExpr()
00853 {
00854 if (left) delete left;
00855 if (right) delete right;
00856 }
00857
00859 inline bool do_operator(bool left, bool right) const
00860 {
00861 if (op == OP_AND)
00862 return left && right;
00863 else if (op == OP_OR)
00864 return left || right;
00865 else
00866 return false;
00867 }
00868
00870 inline std::string get_opstr() const
00871 {
00872 return (op == OP_AND) ? "&&" : "||";
00873 }
00874
00877 virtual AnyScalar evaluate(const class SymbolTable &st) const
00878 {
00879 AnyScalar vl = left->evaluate(st);
00880 AnyScalar vr = right->evaluate(st);
00881
00882
00883 if (vl.getType() != AnyScalar::ATTRTYPE_BOOL)
00884 throw(BadSyntaxException(std::string("Invalid left operand for ") + get_opstr() + ". Both operands must be of type bool."));
00885 if (vr.getType() != AnyScalar::ATTRTYPE_BOOL)
00886 throw(BadSyntaxException(std::string("Invalid right operand for ") + get_opstr() + ". Both operands must be of type bool."));
00887
00888 int bvl = vl.getInteger();
00889 int bvr = vr.getInteger();
00890
00891 return AnyScalar( do_operator(bvl, bvr) );
00892 }
00893
00898 virtual bool evaluate_const(AnyScalar *dest) const
00899 {
00900 if (!dest) return false;
00901
00902 AnyScalar vl(AnyScalar::ATTRTYPE_INVALID), vr(AnyScalar::ATTRTYPE_INVALID);
00903
00904 bool bl = left->evaluate_const(&vl);
00905 bool br = right->evaluate_const(&vr);
00906
00907 if (vl.getType() != AnyScalar::ATTRTYPE_BOOL)
00908 throw(BadSyntaxException(std::string("Invalid left operand for ") + get_opstr() + ". Both operands must be of type bool."));
00909 if (vr.getType() != AnyScalar::ATTRTYPE_BOOL)
00910 throw(BadSyntaxException(std::string("Invalid right operand for ") + get_opstr() + ". Both operands must be of type bool."));
00911
00912 int bvl = vl.getInteger();
00913 int bvr = vr.getInteger();
00914
00915 *dest = AnyScalar( do_operator(bvl, bvr) );
00916
00917 if (op == OP_AND)
00918 {
00919
00920
00921 return (bl && br) || (bl && !bvl) || (br && !bvr);
00922 }
00923 else if (op == OP_OR)
00924 {
00925
00926
00927 return (bl && br) || (bl && bvl) || (br && bvr);
00928 }
00929 else {
00930 assert(0);
00931 return false;
00932 }
00933 }
00934
00936 virtual std::string toString() const
00937 {
00938 return std::string("(") + left->toString() + " " + get_opstr() + " " + right->toString() + ")";
00939 }
00940
00942 inline ParseNode* detach_left()
00943 {
00944 ParseNode *n = left;
00945 left = NULL;
00946 return n;
00947 }
00948
00950 inline ParseNode* detach_right()
00951 {
00952 ParseNode *n = right;
00953 right = NULL;
00954 return n;
00955 }
00956 };
00957
00958
00959
00960
00962 typedef std::string::const_iterator InputIterT;
00963
00965 typedef tree_match<InputIterT> ParseTreeMatchT;
00966
00968 typedef ParseTreeMatchT::const_tree_iterator TreeIterT;
00969
00972 static ParseNode* build_expr(TreeIterT const& i)
00973 {
00974 #ifdef STX_DEBUG_PARSER
00975 std::cout << "In build_expr. i->value = " <<
00976 std::string(i->value.begin(), i->value.end()) <<
00977 " i->children.size() = " << i->children.size() <<
00978 " i->value.id = " << i->value.id().to_long() << std::endl;
00979 #endif
00980
00981 switch(i->value.id().to_long())
00982 {
00983
00984
00985 case boolean_const_id:
00986 {
00987 return new PNConstant(AnyScalar::ATTRTYPE_BOOL,
00988 std::string(i->value.begin(), i->value.end()));
00989 }
00990
00991 case integer_const_id:
00992 {
00993 return new PNConstant(AnyScalar::ATTRTYPE_INTEGER,
00994 std::string(i->value.begin(), i->value.end()));
00995 }
00996
00997 case long_const_id:
00998 {
00999 return new PNConstant(AnyScalar::ATTRTYPE_LONG,
01000 std::string(i->value.begin(), i->value.end()));
01001 }
01002
01003 case double_const_id:
01004 {
01005 return new PNConstant(AnyScalar::ATTRTYPE_DOUBLE,
01006 std::string(i->value.begin(), i->value.end()));
01007 }
01008
01009 case string_const_id:
01010 {
01011 return new PNConstant(AnyScalar::ATTRTYPE_STRING,
01012 std::string(i->value.begin(), i->value.end()));
01013 }
01014
01015
01016
01017 case unary_expr_id:
01018 {
01019 char arithop = *i->value.begin();
01020 assert(i->children.size() == 1);
01021
01022 const ParseNode *val = build_expr(i->children.begin());
01023
01024 if (val->evaluate_const(NULL))
01025 {
01026
01027 PNUnaryArithmExpr tmpnode(val, arithop);
01028 AnyScalar constval(AnyScalar::ATTRTYPE_INVALID);
01029
01030 tmpnode.evaluate_const(&constval);
01031
01032 return new PNConstant(constval);
01033 }
01034 else
01035 {
01036
01037 return new PNUnaryArithmExpr(val, arithop);
01038 }
01039 }
01040
01041 case add_expr_id:
01042 case mul_expr_id:
01043 {
01044 char arithop = *i->value.begin();
01045 assert(i->children.size() == 2);
01046
01047
01048
01049 std::auto_ptr<const ParseNode> left( build_expr(i->children.begin()) );
01050 std::auto_ptr<const ParseNode> right( build_expr(i->children.begin()+1) );
01051
01052 if (left->evaluate_const(NULL) && right->evaluate_const(NULL))
01053 {
01054
01055 PNBinaryArithmExpr tmpnode(left.release(), right.release(), arithop);
01056 AnyScalar both(AnyScalar::ATTRTYPE_INVALID);
01057
01058 tmpnode.evaluate_const(&both);
01059
01060
01061
01062 return new PNConstant(both);
01063 }
01064 else
01065 {
01066
01067 return new PNBinaryArithmExpr(left.release(), right.release(), arithop);
01068 }
01069 }
01070
01071
01072
01073 case cast_spec_id:
01074 {
01075 assert(i->children.size() == 1);
01076
01077 std::string tname(i->value.begin(), i->value.end());
01078 AnyScalar::attrtype_t at = AnyScalar::stringToType(tname);
01079
01080 const ParseNode *val = build_expr(i->children.begin());
01081
01082 if (val->evaluate_const(NULL))
01083 {
01084
01085 PNCastExpr tmpnode(val, at);
01086
01087 AnyScalar constval(AnyScalar::ATTRTYPE_INVALID);
01088
01089 tmpnode.evaluate_const(&constval);
01090
01091 return new PNConstant(constval);
01092 }
01093 else
01094 {
01095 return new PNCastExpr(val, at);
01096 }
01097 }
01098
01099
01100
01101 case comp_expr_id:
01102 {
01103 assert(i->children.size() == 2);
01104
01105 std::string arithop(i->value.begin(), i->value.end());
01106
01107
01108
01109 std::auto_ptr<const ParseNode> left( build_expr(i->children.begin()) );
01110 std::auto_ptr<const ParseNode> right( build_expr(i->children.begin()+1) );
01111
01112 if (left->evaluate_const(NULL) && right->evaluate_const(NULL))
01113 {
01114
01115 PNBinaryComparisonExpr tmpnode(left.release(), right.release(), arithop);
01116 AnyScalar both(AnyScalar::ATTRTYPE_INVALID);
01117
01118 tmpnode.evaluate_const(&both);
01119
01120
01121
01122 return new PNConstant(both);
01123 }
01124 else
01125 {
01126
01127 return new PNBinaryComparisonExpr(left.release(), right.release(), arithop);
01128 }
01129 }
01130
01131
01132
01133 case and_expr_id:
01134 case or_expr_id:
01135 {
01136 assert(i->children.size() == 2);
01137
01138 std::string logicop(i->value.begin(), i->value.end());
01139 std::transform(logicop.begin(), logicop.end(), logicop.begin(), tolower);
01140
01141
01142
01143 std::auto_ptr<ParseNode> left( build_expr(i->children.begin()) );
01144 std::auto_ptr<ParseNode> right( build_expr(i->children.begin()+1) );
01145
01146 bool constleft = left->evaluate_const(NULL);
01147 bool constright = right->evaluate_const(NULL);
01148
01149
01150
01151 std::auto_ptr<PNBinaryLogicExpr> node( new PNBinaryLogicExpr(left.release(), right.release(), logicop) );
01152
01153 if (constleft || constright)
01154 {
01155 AnyScalar both(AnyScalar::ATTRTYPE_INVALID);
01156
01157
01158 if (node->evaluate_const(&both))
01159 {
01160
01161
01162 return new PNConstant(both);
01163 }
01164 }
01165 if (constleft)
01166 {
01167
01168
01169 return node->detach_right();
01170 }
01171 if (constright)
01172 {
01173
01174
01175 return node->detach_left();
01176 }
01177
01178 return node.release();
01179 }
01180
01181
01182
01183 case varname_id:
01184 {
01185 assert(i->children.size() == 0);
01186
01187 std::string varname(i->value.begin(), i->value.end());
01188
01189 return new PNVariable(varname);
01190 }
01191
01192 case function_identifier_id:
01193 {
01194 std::string funcname(i->value.begin(), i->value.end());
01195 std::vector<const class ParseNode*> paramlist;
01196
01197 if (i->children.size() > 0)
01198 {
01199 TreeIterT const& paramlistchild = i->children.begin();
01200
01201 if (paramlistchild->value.id().to_long() == exprlist_id)
01202 {
01203 try
01204 {
01205 for(TreeIterT ci = paramlistchild->children.begin(); ci != paramlistchild->children.end(); ++ci)
01206 {
01207 const ParseNode *pas = build_expr(ci);
01208 paramlist.push_back(pas);
01209 }
01210 }
01211 catch (...)
01212 {
01213 for(unsigned int i = 0; i < paramlist.size(); ++i)
01214 delete paramlist[i];
01215 throw;
01216 }
01217 }
01218 else
01219 {
01220
01221 paramlist.push_back( build_expr(paramlistchild) );
01222 }
01223 }
01224
01225 return new PNFunction(funcname, paramlist);
01226 }
01227
01228 default:
01229 throw(ExpressionParserException("Unknown AST parse tree node found. This should never happen."));
01230 }
01231 }
01232
01235 ParseTreeList build_exprlist(TreeIterT const &i)
01236 {
01237 #ifdef STX_DEBUG_PARSER
01238 std::cout << "In build_exprlist. i->value = " <<
01239 std::string(i->value.begin(), i->value.end()) <<
01240 " i->children.size() = " << i->children.size() <<
01241 " i->value.id = " << i->value.id().to_long() << std::endl;
01242 #endif
01243
01244 ParseTreeList ptlist;
01245
01246 for(TreeIterT ci = i->children.begin(); ci != i->children.end(); ++ci)
01247 {
01248 ParseNode *vas = build_expr(ci);
01249
01250 ptlist.push_back( ParseTree(vas) );
01251 }
01252
01253 return ptlist;
01254 }
01255
01257 static inline void tree_dump_xml(std::ostream &os, const std::string &input, const tree_parse_info<InputIterT> &info)
01258 {
01259
01260
01261 std::map<parser_id, std::string> rule_names;
01262
01263 rule_names[boolean_const_id] = "boolean_const";
01264 rule_names[integer_const_id] = "integer_const";
01265 rule_names[long_const_id] = "long_const";
01266 rule_names[double_const_id] = "double_const";
01267 rule_names[string_const_id] = "string_const";
01268 rule_names[constant_id] = "constant";
01269
01270 rule_names[function_call_id] = "function_call";
01271 rule_names[function_identifier_id] = "function_identifier";
01272
01273 rule_names[varname_id] = "varname";
01274
01275 rule_names[unary_expr_id] = "unary_expr";
01276 rule_names[mul_expr_id] = "mul_expr";
01277 rule_names[add_expr_id] = "add_expr";
01278
01279 rule_names[cast_expr_id] = "cast_expr";
01280 rule_names[cast_spec_id] = "cast_spec";
01281
01282 rule_names[comp_expr_id] = "comp_expr";
01283 rule_names[and_expr_id] = "and_expr";
01284 rule_names[or_expr_id] = "or_expr";
01285
01286 rule_names[expr_id] = "expr";
01287 rule_names[exprlist_id] = "exprlist";
01288
01289 tree_to_xml(os, info.trees, input.c_str(), rule_names);
01290 }
01291
01292 }
01293
01294 const ParseTree parseExpression(const std::string &input)
01295 {
01296
01297 Grammar::ExpressionGrammar g;
01298
01299 #ifdef STX_DEBUG_PARSER
01300 BOOST_SPIRIT_DEBUG_GRAMMAR(g);
01301 #endif
01302
01303 Grammar::tree_parse_info<Grammar::InputIterT> info =
01304 boost::spirit::ast_parse(input.begin(), input.end(),
01305 g.use_parser<0>(),
01306 boost::spirit::space_p);
01307
01308 if (!info.full)
01309 {
01310 std::ostringstream oss;
01311 oss << "Syntax error at position "
01312 << static_cast<int>(info.stop - input.begin())
01313 << " near "
01314 << std::string(info.stop, input.end());
01315
01316 throw(BadSyntaxException(oss.str()));
01317 }
01318
01319 return ParseTree( Grammar::build_expr(info.trees.begin()) );
01320 }
01321
01322 std::string parseExpressionXML(const std::string &input)
01323 {
01324
01325 Grammar::ExpressionGrammar g;
01326
01327 #ifdef STX_DEBUG_PARSER
01328 BOOST_SPIRIT_DEBUG_GRAMMAR(g);
01329 #endif
01330
01331 Grammar::tree_parse_info<Grammar::InputIterT> info =
01332 boost::spirit::ast_parse(input.begin(), input.end(),
01333 g.use_parser<0>(),
01334 boost::spirit::space_p);
01335
01336 if (!info.full)
01337 {
01338 std::ostringstream oss;
01339 oss << "Syntax error at position "
01340 << static_cast<int>(info.stop - input.begin())
01341 << " near "
01342 << std::string(info.stop, input.end());
01343
01344 throw(BadSyntaxException(oss.str()));
01345 }
01346
01347 std::ostringstream oss;
01348 Grammar::tree_dump_xml(oss, input, info);
01349 return oss.str();
01350 }
01351
01352 ParseTreeList parseExpressionList(const std::string &input)
01353 {
01354
01355 Grammar::ExpressionGrammar g;
01356
01357 #ifdef STX_DEBUG_PARSER
01358 BOOST_SPIRIT_DEBUG_GRAMMAR(g);
01359 #endif
01360
01361 Grammar::tree_parse_info<Grammar::InputIterT> info =
01362 boost::spirit::ast_parse(input.begin(), input.end(),
01363 g.use_parser<1>(),
01364 boost::spirit::space_p);
01365
01366 if (!info.full)
01367 {
01368 std::ostringstream oss;
01369 oss << "Syntax error at position "
01370 << static_cast<int>(info.stop - input.begin())
01371 << " near "
01372 << std::string(info.stop, input.end());
01373
01374 throw(BadSyntaxException(oss.str()));
01375 }
01376
01377 return Grammar::build_exprlist(info.trees.begin());
01378 }
01379
01380 std::vector<AnyScalar> ParseTreeList::evaluate(const class SymbolTable &st) const
01381 {
01382 std::vector<AnyScalar> vl;
01383
01384 for(parent_type::const_iterator i = parent_type::begin(); i != parent_type::end(); i++)
01385 {
01386 vl.push_back( i->evaluate(st) );
01387 }
01388
01389 return vl;
01390 }
01391
01392 std::string ParseTreeList::toString() const
01393 {
01394 std::string sl;
01395
01396 for(parent_type::const_iterator i = parent_type::begin(); i != parent_type::end(); i++)
01397 {
01398 if (i != parent_type::begin()) {
01399 sl += ", ";
01400 }
01401
01402 sl += i->toString();
01403 }
01404
01405 return sl;
01406 }
01407
01409
01410 SymbolTable::~SymbolTable()
01411 {
01412 }
01413
01414 EmptySymbolTable::~EmptySymbolTable()
01415 {
01416 }
01417
01418 AnyScalar EmptySymbolTable::lookupVariable(const std::string &varname) const
01419 {
01420 throw(UnknownSymbolException(std::string("Unknown variable ") + varname));
01421 }
01422
01423 AnyScalar EmptySymbolTable::processFunction(const std::string &funcname,
01424 const paramlist_type &) const
01425 {
01426 throw(UnknownSymbolException(std::string("Unknown function ") + funcname + "()"));
01427 }
01428
01429 BasicSymbolTable::BasicSymbolTable()
01430 {
01431 addStandardFunctions();
01432 }
01433
01434 BasicSymbolTable::~BasicSymbolTable()
01435 {
01436 }
01437
01438 void BasicSymbolTable::setVariable(const std::string& varname, const AnyScalar &value)
01439 {
01440 std::string vn = varname;
01441 std::transform(vn.begin(), vn.end(), vn.begin(), tolower);
01442
01443 variablemap[vn] = value;
01444 }
01445
01446 void BasicSymbolTable::setFunction(const std::string& funcname, int arguments, functionptr_type funcptr)
01447 {
01448 std::string fn = funcname;
01449 std::transform(fn.begin(), fn.end(), fn.begin(), toupper);
01450
01451 functionmap[fn] = FunctionInfo(arguments, funcptr);
01452 }
01453
01454 void BasicSymbolTable::clearVariables()
01455 {
01456 variablemap.clear();
01457 }
01458
01459 void BasicSymbolTable::clearFunctions()
01460 {
01461 functionmap.clear();
01462 }
01463
01464 AnyScalar BasicSymbolTable::funcPI(const paramlist_type &)
01465 {
01466 return AnyScalar(3.14159265358979323846);
01467 }
01468
01469 AnyScalar BasicSymbolTable::funcSIN(const paramlist_type ¶mlist)
01470 {
01471 return AnyScalar( std::sin(paramlist[0].getDouble()) );
01472 }
01473
01474 AnyScalar BasicSymbolTable::funcCOS(const paramlist_type ¶mlist)
01475 {
01476 return AnyScalar( std::cos(paramlist[0].getDouble()) );
01477 }
01478
01479 AnyScalar BasicSymbolTable::funcTAN(const paramlist_type ¶mlist)
01480 {
01481 return AnyScalar( std::tan(paramlist[0].getDouble()) );
01482 }
01483
01484 AnyScalar BasicSymbolTable::funcABS(const paramlist_type ¶mlist)
01485 {
01486 if (paramlist[0].isIntegerType()) {
01487 return AnyScalar( std::abs(paramlist[0].getInteger()) );
01488 }
01489 else if (paramlist[0].isFloatingType()) {
01490 return AnyScalar( std::fabs(paramlist[0].getDouble()) );
01491 }
01492 else {
01493 throw(BadFunctionCallException("Function ABS() takes exactly one parameter"));
01494 }
01495 }
01496
01497 AnyScalar BasicSymbolTable::funcEXP(const paramlist_type ¶mlist)
01498 {
01499 return AnyScalar( std::exp(paramlist[0].getDouble()) );
01500 }
01501
01502 AnyScalar BasicSymbolTable::funcLOGN(const paramlist_type ¶mlist)
01503 {
01504 return AnyScalar( std::log(paramlist[0].getDouble()) );
01505 }
01506
01507 AnyScalar BasicSymbolTable::funcPOW(const paramlist_type ¶mlist)
01508 {
01509 return AnyScalar( std::pow(paramlist[0].getDouble(), paramlist[1].getDouble()) );
01510 }
01511
01512 AnyScalar BasicSymbolTable::funcSQRT(const paramlist_type ¶mlist)
01513 {
01514 return AnyScalar( std::sqrt(paramlist[0].getDouble()) );
01515 }
01516
01517 void BasicSymbolTable::addStandardFunctions()
01518 {
01519 setFunction("PI", 0, funcPI);
01520
01521 setFunction("SIN", 1, funcSIN);
01522 setFunction("COS", 1, funcCOS);
01523 setFunction("TAN", 1, funcTAN);
01524
01525 setFunction("ABS", 1, funcABS);
01526 setFunction("EXP", 1, funcEXP);
01527 setFunction("LOGN", 1, funcLOGN);
01528 setFunction("POW", 2, funcPOW);
01529 setFunction("SQRT", 1, funcSQRT);
01530 }
01531
01532 AnyScalar BasicSymbolTable::lookupVariable(const std::string &_varname) const
01533 {
01534 std::string varname = _varname;
01535 std::transform(varname.begin(), varname.end(), varname.begin(), tolower);
01536
01537 variablemap_type::const_iterator fi = variablemap.find(varname);
01538
01539 if (fi != variablemap.end())
01540 {
01541 return fi->second;
01542 }
01543
01544 throw(UnknownSymbolException(std::string("Unknown variable ") + varname));
01545 }
01546
01547 AnyScalar BasicSymbolTable::processFunction(const std::string &_funcname,
01548 const paramlist_type ¶mlist) const
01549 {
01550 std::string funcname = _funcname;
01551 std::transform(funcname.begin(), funcname.end(), funcname.begin(), toupper);
01552
01553 functionmap_type::const_iterator fi = functionmap.find(funcname);
01554
01555 if (fi != functionmap.end())
01556 {
01557 if (fi->second.arguments >= 0)
01558 {
01559 if (fi->second.arguments == 0 && paramlist.size() != 0)
01560 {
01561 throw(BadFunctionCallException(std::string("Function ") + funcname + "() does not take any parameter."));
01562 }
01563 else if (fi->second.arguments == 1 && paramlist.size() != 1)
01564 {
01565 throw(BadFunctionCallException(std::string("Function ") + funcname + "() takes exactly one parameter."));
01566 }
01567 else if (static_cast<unsigned int>(fi->second.arguments) != paramlist.size())
01568 {
01569 std::ostringstream oss;
01570 oss << "Function " << funcname << "() takes exactly " << fi->second.arguments << " parameters.";
01571 throw(BadFunctionCallException(oss.str()));
01572 }
01573 }
01574 return fi->second.func(paramlist);
01575 }
01576
01577 throw(UnknownSymbolException(std::string("Unknown function ") + funcname + "()"));
01578 }
01579
01580 }