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.