Mercurial > ecos
comparison host/libcdl/expr.cxx @ 163:0d2b193a635f
Merge from eCos master repository on 2001-06-22-17:38:39-BST
| author | jlarmour |
|---|---|
| date | Fri, 22 Jun 2001 18:18:44 +0000 |
| parents | 511f4dc167f6 |
| children | 74dbf4c3f2e1 |
comparison
equal
deleted
inserted
replaced
| 162:2395031e7a66 | 163:0d2b193a635f |
|---|---|
| 126 property = 0; | 126 property = 0; |
| 127 toplevel = 0; | 127 toplevel = 0; |
| 128 CYGDBG_MEMLEAK_DESTRUCTOR(); | 128 CYGDBG_MEMLEAK_DESTRUCTOR(); |
| 129 | 129 |
| 130 CYG_REPORT_RETURN(); | 130 CYG_REPORT_RETURN(); |
| 131 } | |
| 132 | |
| 133 // Given a context and a reference inside an expression, obtain the node | |
| 134 // being referenced - if it is loaded. | |
| 135 CdlNode | |
| 136 CdlEvalContext::resolve_reference(CdlExpression expr, int index) | |
| 137 { | |
| 138 CYG_REPORT_FUNCNAMETYPE("CdlEvalContext::resolve_reference", "result %"); | |
| 139 CYG_REPORT_FUNCARG2XV(expr, index); | |
| 140 CYG_PRECONDITION_THISC(); | |
| 141 CYG_PRECONDITION_CLASSC(expr); | |
| 142 CYG_PRECONDITIONC((0 <= index) && (index <= (int)expr->references.size())); | |
| 143 | |
| 144 // This expression may be happening in the context of a particular | |
| 145 // property. If so then the destination may or may not be | |
| 146 // resolved, which will have been handled when the containing package | |
| 147 // was loaded. Alternatively this expression may be evaluated inside | |
| 148 // some arbitrary Tcl code, in which case references remain unbound | |
| 149 // and need to be resolved the hard way. | |
| 150 CdlNode result = 0; | |
| 151 if (0 != this->property) { | |
| 152 // There is a property, use the bound/unbound reference. | |
| 153 result = expr->references[index].get_destination(); | |
| 154 } else { | |
| 155 // The destination name can be retrieved, but we still need some | |
| 156 // way of resolving it. | |
| 157 if (0 != this->toplevel) { | |
| 158 std::string destination_name = expr->references[index].get_destination_name(); | |
| 159 result = this->toplevel->lookup(destination_name); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 CYG_REPORT_RETVAL(result); | |
| 164 return result; | |
| 165 } | |
| 166 | |
| 167 // Ditto, but also check that the result is a valuable. | |
| 168 CdlValuable | |
| 169 CdlEvalContext::resolve_valuable_reference(CdlExpression expr, int index) | |
| 170 { | |
| 171 CYG_REPORT_FUNCNAMETYPE("CdlEvalContext::resolve_reference", "result %"); | |
| 172 CYG_REPORT_FUNCARG2XV(expr, index); | |
| 173 | |
| 174 CdlValuable result = 0; | |
| 175 CdlNode node = this->resolve_reference(expr, index); | |
| 176 if (0 != node) { | |
| 177 result = dynamic_cast<CdlValuable>(node); | |
| 178 } | |
| 179 CYG_REPORT_RETVAL(result); | |
| 180 return result; | |
| 131 } | 181 } |
| 132 | 182 |
| 133 bool | 183 bool |
| 134 CdlEvalContext::check_this(cyg_assert_class_zeal zeal) const | 184 CdlEvalContext::check_this(cyg_assert_class_zeal zeal) const |
| 135 { | 185 { |
| 232 T_And = 27, // && | 282 T_And = 27, // && |
| 233 T_Or = 28, // || | 283 T_Or = 28, // || |
| 234 T_Colon = 29, // : (in a conditional) | 284 T_Colon = 29, // : (in a conditional) |
| 235 T_StringConcat = 30, // . | 285 T_StringConcat = 30, // . |
| 236 T_Function = 31, // is_substr etc. | 286 T_Function = 31, // is_substr etc. |
| 237 T_Comma = 32 // , (inside a function) | 287 T_Comma = 32, // , (inside a function) |
| 288 T_Implies = 33, // implies | |
| 289 T_Xor = 34, // xor | |
| 290 T_Eqv = 35 // eqv | |
| 238 | 291 |
| 239 }; | 292 }; |
| 240 | 293 |
| 241 //}}} | 294 //}}} |
| 242 //{{{ Statics | 295 //{{{ Statics |
| 247 static unsigned int token_start = 0; | 300 static unsigned int token_start = 0; |
| 248 static int current_char = EOF; | 301 static int current_char = EOF; |
| 249 static token current_token = T_Invalid; | 302 static token current_token = T_Invalid; |
| 250 static std::string current_string = ""; | 303 static std::string current_string = ""; |
| 251 static std::string current_reference = ""; | 304 static std::string current_reference = ""; |
| 305 static std::string current_special = ""; | |
| 252 static cdl_int current_int = 0; | 306 static cdl_int current_int = 0; |
| 253 static double current_double = 0.0; | 307 static double current_double = 0.0; |
| 254 static CdlValueFormat current_format = CdlValueFormat_Default; | 308 static CdlValueFormat current_format = CdlValueFormat_Default; |
| 255 static int current_function_id = 0; | 309 static int current_function_id = 0; |
| 256 | 310 |
| 327 } | 381 } |
| 328 } | 382 } |
| 329 | 383 |
| 330 CYG_REPORT_RETURN(); | 384 CYG_REPORT_RETURN(); |
| 331 return result; | 385 return result; |
| 386 } | |
| 387 | |
| 388 // Export this functionality available to other modules, especially func.cxx and its | |
| 389 // argument checking routines. | |
| 390 std::string | |
| 391 CdlParse::get_expression_error_location(void) | |
| 392 { | |
| 393 return get_error_location(); | |
| 332 } | 394 } |
| 333 | 395 |
| 334 //}}} | 396 //}}} |
| 335 //{{{ Token translation | 397 //{{{ Token translation |
| 336 | 398 |
| 361 case T_BitXor: result = CdlExprOp_BitXor; break; | 423 case T_BitXor: result = CdlExprOp_BitXor; break; |
| 362 case T_BitOr: result = CdlExprOp_BitOr; break; | 424 case T_BitOr: result = CdlExprOp_BitOr; break; |
| 363 case T_And: result = CdlExprOp_And; break; | 425 case T_And: result = CdlExprOp_And; break; |
| 364 case T_Or: result = CdlExprOp_Or; break; | 426 case T_Or: result = CdlExprOp_Or; break; |
| 365 case T_StringConcat: result = CdlExprOp_StringConcat; break; | 427 case T_StringConcat: result = CdlExprOp_StringConcat; break; |
| 428 case T_Implies: result = CdlExprOp_Implies; break; | |
| 429 case T_Xor: result = CdlExprOp_Xor; break; | |
| 430 case T_Eqv: result = CdlExprOp_Eqv; break; | |
| 366 default: result = CdlExprOp_Invalid; break; | 431 default: result = CdlExprOp_Invalid; break; |
| 367 } | 432 } |
| 368 | 433 |
| 369 CYG_REPORT_RETVAL(result); | 434 CYG_REPORT_RETVAL(result); |
| 370 return result; | 435 return result; |
| 457 case T_BitOr: result = "bitwise or operator |"; break; | 522 case T_BitOr: result = "bitwise or operator |"; break; |
| 458 case T_And: result = "and operator &&"; break; | 523 case T_And: result = "and operator &&"; break; |
| 459 case T_Or: result = "or operator ||"; break; | 524 case T_Or: result = "or operator ||"; break; |
| 460 case T_Colon: result = "colon"; break; | 525 case T_Colon: result = "colon"; break; |
| 461 case T_StringConcat: result = "string concatenation operator ."; break; | 526 case T_StringConcat: result = "string concatenation operator ."; break; |
| 527 case T_Implies: result = "implies operator"; break; | |
| 528 case T_Xor: result = "logical xor operator"; break; | |
| 529 case T_Eqv: result = "logical equivalence operator eqv"; break; | |
| 462 case T_Function: result = std::string("function call ") + CdlFunction::get_name(current_function_id); break; | 530 case T_Function: result = std::string("function call ") + CdlFunction::get_name(current_function_id); break; |
| 463 case T_Invalid: | 531 case T_Invalid: |
| 464 default: result = "<invalid token>"; break; | 532 default: result = "<invalid token>"; break; |
| 465 } | 533 } |
| 466 | 534 |
| 786 bool result = false; | 854 bool result = false; |
| 787 | 855 |
| 788 if ("to" == current_reference) { | 856 if ("to" == current_reference) { |
| 789 current_token = T_Range; | 857 current_token = T_Range; |
| 790 result = true; | 858 result = true; |
| 859 } else if ("implies" == current_reference) { | |
| 860 current_token = T_Implies; | |
| 861 result = true; | |
| 862 } else if ("xor" == current_reference) { | |
| 863 current_token = T_Xor; | |
| 864 result = true; | |
| 865 } else if ("eqv" == current_reference) { | |
| 866 current_token = T_Eqv; | |
| 867 result = true; | |
| 791 } else if (CdlFunction::is_function(current_reference.c_str(), current_function_id)) { | 868 } else if (CdlFunction::is_function(current_reference.c_str(), current_function_id)) { |
| 792 current_token = T_Function; | 869 current_token = T_Function; |
| 793 result = true; | 870 result = true; |
| 794 } | 871 } |
| 795 | 872 |
| 796 if (result) { | 873 if (result) { |
| 797 current_reference = ""; | 874 current_special = current_reference; |
| 875 current_reference = ""; | |
| 798 } | 876 } |
| 799 CYG_REPORT_RETVAL(result); | 877 CYG_REPORT_RETVAL(result); |
| 800 return result; | 878 return result; |
| 801 } | 879 } |
| 802 | 880 |
| 815 | 893 |
| 816 // Make sure there is no dross left lying around from the previous call. | 894 // Make sure there is no dross left lying around from the previous call. |
| 817 current_token = T_Invalid; | 895 current_token = T_Invalid; |
| 818 current_string = ""; | 896 current_string = ""; |
| 819 current_reference = ""; | 897 current_reference = ""; |
| 898 current_special = ""; | |
| 820 current_int = 0; | 899 current_int = 0; |
| 821 current_double = 0.0; | 900 current_double = 0.0; |
| 822 current_format = CdlValueFormat_Default; | 901 current_format = CdlValueFormat_Default; |
| 823 current_function_id = 0; | 902 current_function_id = 0; |
| 824 | 903 |
| 1057 // Syntactic analysis. | 1136 // Syntactic analysis. |
| 1058 // | 1137 // |
| 1059 // The BNF of CDL expressions is something like this: | 1138 // The BNF of CDL expressions is something like this: |
| 1060 // | 1139 // |
| 1061 // <expression> ::= <conditional> | 1140 // <expression> ::= <conditional> |
| 1062 // <conditional> ::= <or> ? <conditional> : <conditional> | <or> | 1141 // <conditional> ::= <implies> ? <conditional> : <conditional> | <implies> |
| 1063 // <or> ::= <and> [<or op> <and>] || | 1142 // <implies> ::= <eqv> [<implies op> <implies>] implies |
| 1064 // <and> ::= <bitor> [<and op> <bitor>] ?? | 1143 // <eqv> ::= <or> [<eqv op> <eqv>] xor, eqv |
| 1065 // <bitor> ::= <bitxor> [<bitor op> <bitxor>] | | 1144 // <or> ::= <and> [<or op> <or>] || |
| 1066 // <bitxor> ::= <bitand> [<bitxor op> <bitand>] ^ | 1145 // <and> ::= <bitor> [<and op> <and>] && |
| 1067 // <bitand> ::= <eq> [<bitand op> <eq>] & | 1146 // <bitor> ::= <bitxor> [<bitor op> <bitor>] | |
| 1068 // <eq> ::= <comp> [<eq op> <comp>] == != | 1147 // <bitxor> ::= <bitand> [<bitxor op> <bitxor>] ^ |
| 1069 // <comp> ::= <shift> [<comp op> <shift>] < <= > >= | 1148 // <bitand> ::= <eq> [<bitand op> <and>] & |
| 1070 // <shift> ::= <add> [<shift op> <add>] << >> | 1149 // <eq> ::= <comp> [<eq op> <eq>] == != |
| 1071 // <add> ::= <mult> [<add op> <mult>] + - . | 1150 // <comp> ::= <shift> [<comp op> <comp>] < <= > >= |
| 1072 // <mult> ::= <unary> [<mult op> <unary>] * / % | 1151 // <shift> ::= <add> [<shift op> <shift>] << >> |
| 1152 // <add> ::= <mult> [<add op> <add>] + - . | |
| 1153 // <mult> ::= <unary> [<mult op> <mult>] * / % | |
| 1073 // <unary> ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> | | 1154 // <unary> ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> | |
| 1074 // ~<unary> | | 1155 // ~<unary> | |
| 1075 // <string constant> | <integer constant> | | 1156 // <string constant> | <integer constant> | |
| 1076 // <double constant> | <reference> | | 1157 // <double constant> | <reference> | |
| 1077 // ( <expression> ) | <function> | 1158 // ( <expression> ) | <function> |
| 1133 subexpr.op = CdlExprOp_Function; | 1214 subexpr.op = CdlExprOp_Function; |
| 1134 subexpr.func = current_function_id; | 1215 subexpr.func = current_function_id; |
| 1135 | 1216 |
| 1136 int number_of_args = CdlFunction::get_args_count(current_function_id); | 1217 int number_of_args = CdlFunction::get_args_count(current_function_id); |
| 1137 CYG_ASSERTC((0 < number_of_args) && (number_of_args <= CdlFunction_MaxArgs)); | 1218 CYG_ASSERTC((0 < number_of_args) && (number_of_args <= CdlFunction_MaxArgs)); |
| 1138 std::string name = current_reference; | 1219 std::string name = current_special; |
| 1139 | 1220 |
| 1140 // check for the opening bracket: xyzzy(arg1, arg2) | 1221 // check for the opening bracket: xyzzy(arg1, arg2) |
| 1141 next_token(); | 1222 next_token(); |
| 1142 if (T_OpenBracket != current_token) { | 1223 if (T_OpenBracket != current_token) { |
| 1143 throw CdlParseException(std::string("Expected opening bracket after function ") + name + "\n" + get_error_location()); | 1224 throw CdlParseException(std::string("Expected opening bracket after function ") + name + "\n" + get_error_location()); |
| 1153 throw CdlParseException(std::string("Expected comma between arguments in function ") + | 1234 throw CdlParseException(std::string("Expected comma between arguments in function ") + |
| 1154 name + "\n" + get_error_location()); | 1235 name + "\n" + get_error_location()); |
| 1155 } | 1236 } |
| 1156 next_token(); | 1237 next_token(); |
| 1157 } | 1238 } |
| 1239 } | |
| 1240 if (T_Comma == current_token) { | |
| 1241 throw CdlParseException(std::string("Too many arguments passed to function ") + name + "\n" + get_error_location()); | |
| 1158 } | 1242 } |
| 1159 if (T_CloseBracket != current_token) { | 1243 if (T_CloseBracket != current_token) { |
| 1160 throw CdlParseException(std::string("Expected closing bracket after function ") + name + "\n" + get_error_location()); | 1244 throw CdlParseException(std::string("Expected closing bracket after function ") + name + "\n" + get_error_location()); |
| 1161 } | 1245 } |
| 1162 next_token(); | 1246 next_token(); |
| 1557 | 1641 |
| 1558 CYG_REPORT_RETURN(); | 1642 CYG_REPORT_RETURN(); |
| 1559 } | 1643 } |
| 1560 | 1644 |
| 1561 static void | 1645 static void |
| 1646 parse_eqv(CdlExpression expr) | |
| 1647 { | |
| 1648 CYG_REPORT_FUNCNAME("parse_eqv"); | |
| 1649 | |
| 1650 parse_or(expr); | |
| 1651 while ((T_Xor == current_token) || (T_Eqv == current_token)) { | |
| 1652 | |
| 1653 CdlSubexpression subexpr; | |
| 1654 subexpr.op = (T_Xor == current_token) ? CdlExprOp_Xor : CdlExprOp_Eqv; | |
| 1655 subexpr.lhs_index = expr->first_subexpression; | |
| 1656 | |
| 1657 next_token(); | |
| 1658 parse_or(expr); | |
| 1659 | |
| 1660 subexpr.rhs_index = expr->first_subexpression; | |
| 1661 push_subexpression(expr, subexpr); | |
| 1662 } | |
| 1663 | |
| 1664 CYG_REPORT_RETURN(); | |
| 1665 } | |
| 1666 | |
| 1667 static void | |
| 1668 parse_implies(CdlExpression expr) | |
| 1669 { | |
| 1670 CYG_REPORT_FUNCNAME("parse_implies"); | |
| 1671 | |
| 1672 parse_eqv(expr); | |
| 1673 while (T_Implies == current_token) { | |
| 1674 | |
| 1675 CdlSubexpression subexpr; | |
| 1676 subexpr.op = CdlExprOp_Implies; | |
| 1677 subexpr.lhs_index = expr->first_subexpression; | |
| 1678 | |
| 1679 next_token(); | |
| 1680 parse_eqv(expr); | |
| 1681 | |
| 1682 subexpr.rhs_index = expr->first_subexpression; | |
| 1683 push_subexpression(expr, subexpr); | |
| 1684 } | |
| 1685 | |
| 1686 CYG_REPORT_RETURN(); | |
| 1687 } | |
| 1688 | |
| 1689 static void | |
| 1562 parse_conditional(CdlExpression expr) | 1690 parse_conditional(CdlExpression expr) |
| 1563 { | 1691 { |
| 1564 CYG_REPORT_FUNCNAME("parse_conditional"); | 1692 CYG_REPORT_FUNCNAME("parse_conditional"); |
| 1565 | 1693 |
| 1566 parse_or(expr); | 1694 parse_implies(expr); |
| 1567 if (T_Questionmark == current_token) { | 1695 if (T_Questionmark == current_token) { |
| 1568 CdlSubexpression subexpr; | 1696 CdlSubexpression subexpr; |
| 1569 subexpr.op = CdlExprOp_Cond; | 1697 subexpr.op = CdlExprOp_Cond; |
| 1570 subexpr.lhs_index = expr->first_subexpression; | 1698 subexpr.lhs_index = expr->first_subexpression; |
| 1571 | 1699 |
| 2149 result = true; | 2277 result = true; |
| 2150 } else { | 2278 } else { |
| 2151 result = false; | 2279 result = false; |
| 2152 } | 2280 } |
| 2153 } | 2281 } |
| 2282 break; | |
| 2283 } | |
| 2284 case CdlExprOp_Xor : | |
| 2285 { | |
| 2286 // x xor y. Both sides should be interpreted as boolean values. | |
| 2287 CdlSimpleValue lhs; | |
| 2288 CdlSimpleValue rhs; | |
| 2289 evaluate_subexpr(context, expr, subexpr.lhs_index, lhs); | |
| 2290 evaluate_subexpr(context, expr, subexpr.rhs_index, rhs); | |
| 2291 | |
| 2292 bool lhs_bool = lhs.get_bool_value(); | |
| 2293 bool rhs_bool = rhs.get_bool_value(); | |
| 2294 if ((lhs_bool && !rhs_bool) || (!lhs_bool && rhs_bool)) { | |
| 2295 result = true; | |
| 2296 } else { | |
| 2297 result = false; | |
| 2298 } | |
| 2299 | |
| 2300 break; | |
| 2301 } | |
| 2302 case CdlExprOp_Eqv : | |
| 2303 { | |
| 2304 // x eqv y. Both sides should be interpreted as boolean values. | |
| 2305 CdlSimpleValue lhs; | |
| 2306 CdlSimpleValue rhs; | |
| 2307 evaluate_subexpr(context, expr, subexpr.lhs_index, lhs); | |
| 2308 evaluate_subexpr(context, expr, subexpr.rhs_index, rhs); | |
| 2309 | |
| 2310 bool lhs_bool = lhs.get_bool_value(); | |
| 2311 bool rhs_bool = rhs.get_bool_value(); | |
| 2312 if ((!lhs_bool && !rhs_bool) || (lhs_bool && rhs_bool)) { | |
| 2313 result = true; | |
| 2314 } else { | |
| 2315 result = false; | |
| 2316 } | |
| 2317 | |
| 2318 break; | |
| 2319 } | |
| 2320 case CdlExprOp_Implies : | |
| 2321 { | |
| 2322 // x implies y. Both sides should be interpreted as boolean values. | |
| 2323 CdlSimpleValue lhs; | |
| 2324 CdlSimpleValue rhs; | |
| 2325 evaluate_subexpr(context, expr, subexpr.lhs_index, lhs); | |
| 2326 evaluate_subexpr(context, expr, subexpr.rhs_index, rhs); | |
| 2327 | |
| 2328 bool lhs_bool = lhs.get_bool_value(); | |
| 2329 bool rhs_bool = rhs.get_bool_value(); | |
| 2330 if (!lhs_bool || rhs_bool) { | |
| 2331 result = true; | |
| 2332 } else { | |
| 2333 result = false; | |
| 2334 } | |
| 2335 | |
| 2154 break; | 2336 break; |
| 2155 } | 2337 } |
| 2156 case CdlExprOp_Cond : | 2338 case CdlExprOp_Cond : |
| 2157 { | 2339 { |
| 2158 // x ? a : b. | 2340 // x ? a : b. |
