comparison host/libcdl/expr.cxx @ 159:511f4dc167f6

Merge from eCos master repository on 2001-05-18-01:30:05-BST
author jlarmour
date Fri, 18 May 2001 06:32:28 +0000
parents 6ed91473a1cd
children 0d2b193a635f
comparison
equal deleted inserted replaced
158:f2545e5de153 159:511f4dc167f6
8 // 8 //
9 //============================================================================ 9 //============================================================================
10 //####COPYRIGHTBEGIN#### 10 //####COPYRIGHTBEGIN####
11 // 11 //
12 // ---------------------------------------------------------------------------- 12 // ----------------------------------------------------------------------------
13 // Copyright (C) 1999, 2000 Red Hat, Inc. 13 // Copyright (C) 1999, 2000, 2001 Red Hat, Inc.
14 // 14 //
15 // This file is part of the eCos host tools. 15 // This file is part of the eCos host tools.
16 // 16 //
17 // This program is free software; you can redistribute it and/or modify it 17 // This program is free software; you can redistribute it and/or modify it
18 // under the terms of the GNU General Public License as published by the Free 18 // under the terms of the GNU General Public License as published by the Free
80 { 80 {
81 CYG_REPORT_FUNCNAME("CdlEvalContext::constructor"); 81 CYG_REPORT_FUNCNAME("CdlEvalContext::constructor");
82 CYG_REPORT_FUNCARG4XV(this, transaction_arg, node_arg, property_arg); 82 CYG_REPORT_FUNCARG4XV(this, transaction_arg, node_arg, property_arg);
83 83
84 transaction = transaction_arg; 84 transaction = transaction_arg;
85
86 if ((0 == property_arg) && (0 != transaction)) {
87 CdlConflict conflict = transaction->get_conflict();
88 if (0 != conflict) {
89 property_arg = conflict->get_property();
90 }
91 }
92 property = property_arg;
93
94 if ((0 == node_arg) && (0 != transaction)) {
95 CdlConflict conflict = transaction->get_conflict();
96 if (0 != conflict) {
97 node_arg = conflict->get_node();
98 }
99 }
85 node = node_arg; 100 node = node_arg;
86 property = property_arg; 101
87 if (0 == toplevel_arg) { 102 if (0 == toplevel_arg) {
88 if (0 != transaction) { 103 if (0 != transaction) {
89 toplevel = transaction->get_toplevel(); 104 toplevel_arg = transaction->get_toplevel();
90 } else if (0 != node) { 105 } else if (0 != node) {
91 toplevel = node->get_toplevel(); 106 toplevel_arg = node->get_toplevel();
92 } else { 107 }
93 toplevel = toplevel_arg; 108 }
94 } 109 toplevel = toplevel_arg;
95 } else {
96 toplevel = toplevel_arg;
97 }
98 110
99 cdlevalcontext_cookie = CdlEvalContext_Magic; 111 cdlevalcontext_cookie = CdlEvalContext_Magic;
100 CYGDBG_MEMLEAK_CONSTRUCTOR(); 112 CYGDBG_MEMLEAK_CONSTRUCTOR();
101 113
102 CYG_POSTCONDITION_THISC(); 114 CYG_POSTCONDITION_THISC();
217 T_BitAnd = 24, // & 229 T_BitAnd = 24, // &
218 T_BitXor = 25, // ^ 230 T_BitXor = 25, // ^
219 T_BitOr = 26, // | 231 T_BitOr = 26, // |
220 T_And = 27, // && 232 T_And = 27, // &&
221 T_Or = 28, // || 233 T_Or = 28, // ||
222 T_Colon = 29 // : (in a conditional) 234 T_Colon = 29, // : (in a conditional)
235 T_StringConcat = 30, // .
236 T_Function = 31, // is_substr etc.
237 T_Comma = 32 // , (inside a function)
238
223 }; 239 };
224 240
225 //}}} 241 //}}}
226 //{{{ Statics 242 //{{{ Statics
227 243
234 static std::string current_string = ""; 250 static std::string current_string = "";
235 static std::string current_reference = ""; 251 static std::string current_reference = "";
236 static cdl_int current_int = 0; 252 static cdl_int current_int = 0;
237 static double current_double = 0.0; 253 static double current_double = 0.0;
238 static CdlValueFormat current_format = CdlValueFormat_Default; 254 static CdlValueFormat current_format = CdlValueFormat_Default;
255 static int current_function_id = 0;
239 256
240 //}}} 257 //}}}
241 //{{{ Character access 258 //{{{ Character access
242 259
243 // ---------------------------------------------------------------------------- 260 // ----------------------------------------------------------------------------
343 case T_BitAnd: result = CdlExprOp_BitAnd; break; 360 case T_BitAnd: result = CdlExprOp_BitAnd; break;
344 case T_BitXor: result = CdlExprOp_BitXor; break; 361 case T_BitXor: result = CdlExprOp_BitXor; break;
345 case T_BitOr: result = CdlExprOp_BitOr; break; 362 case T_BitOr: result = CdlExprOp_BitOr; break;
346 case T_And: result = CdlExprOp_And; break; 363 case T_And: result = CdlExprOp_And; break;
347 case T_Or: result = CdlExprOp_Or; break; 364 case T_Or: result = CdlExprOp_Or; break;
348 365 case T_StringConcat: result = CdlExprOp_StringConcat; break;
349 default: result = CdlExprOp_Invalid; break; 366 default: result = CdlExprOp_Invalid; break;
350 } 367 }
351 368
352 CYG_REPORT_RETVAL(result); 369 CYG_REPORT_RETVAL(result);
353 return result; 370 return result;
354 } 371 }
377 case T_Range: result = CdlExprOp_Range; break; 394 case T_Range: result = CdlExprOp_Range; break;
378 case T_Exclamation: result = CdlExprOp_LogicalNot; break; 395 case T_Exclamation: result = CdlExprOp_LogicalNot; break;
379 case T_Tilde: result = CdlExprOp_BitNot; break; 396 case T_Tilde: result = CdlExprOp_BitNot; break;
380 case T_Questionmark: 397 case T_Questionmark:
381 case T_Colon: result = CdlExprOp_Cond; break; // best guess 398 case T_Colon: result = CdlExprOp_Cond; break; // best guess
382 399 case T_Function: result = CdlExprOp_Function; break;
383 case T_OpenBracket: 400 case T_OpenBracket:
384 case T_CloseBracket: 401 case T_CloseBracket:
385 case T_Invalid: 402 case T_Invalid:
386 default: result = CdlExprOp_Invalid; break; 403 default: result = CdlExprOp_Invalid; break;
387 } 404 }
439 case T_BitXor: result = "bitwise xor operator ^"; break; 456 case T_BitXor: result = "bitwise xor operator ^"; break;
440 case T_BitOr: result = "bitwise or operator |"; break; 457 case T_BitOr: result = "bitwise or operator |"; break;
441 case T_And: result = "and operator &&"; break; 458 case T_And: result = "and operator &&"; break;
442 case T_Or: result = "or operator ||"; break; 459 case T_Or: result = "or operator ||"; break;
443 case T_Colon: result = "colon"; break; 460 case T_Colon: result = "colon"; break;
461 case T_StringConcat: result = "string concatenation operator ."; break;
462 case T_Function: result = std::string("function call ") + CdlFunction::get_name(current_function_id); break;
444 case T_Invalid: 463 case T_Invalid:
445 default: result = "<invalid token>"; break; 464 default: result = "<invalid token>"; break;
446 } 465 }
447 466
448 CYG_REPORT_RETURN(); 467 CYG_REPORT_RETURN();
720 check_number_termination(); 739 check_number_termination();
721 CYG_REPORT_RETURN(); 740 CYG_REPORT_RETURN();
722 } 741 }
723 742
724 //}}} 743 //}}}
725 //{{{ process_reference() 744 //{{{ process_alphanumeric()
726 745
727 // The start of a reference has been detected. 746 // The start of an alphanumeric sequence has been detected. This may
728 // A reference name must be a valid C preprocessor name, so the 747 // be a reference, a function call, or an operator like eq or to. All
729 // only characters allowed are underscore, upper and lower case 748 // such sequences must be a valid C preprocessor name, so the only
730 // characters, and digits. The first character cannot be a digit, 749 // characters allowed are underscore, upper and lower case characters,
731 // but that has been checked already. 750 // and digits. The first character cannot be a digit, but that has
751 // been checked already.
732 // 752 //
733 // Some care has to be taken with locale's, the C library may decide 753 // Some care has to be taken with locale's, the C library may decide
734 // that a character is a letter even though the same character is not 754 // that a character is a letter even though the same character is not
735 // valid as far as the preprocessor is concerned. 755 // valid as far as the preprocessor is concerned.
736 static void 756 static void
737 process_reference() 757 process_alphanumeric()
738 { 758 {
739 CYG_REPORT_FUNCNAME("process_reference"); 759 CYG_REPORT_FUNCNAME("process_alphanumeric");
740 760
741 do { 761 do {
742 current_reference += (char) current_char; 762 current_reference += (char) current_char;
743 next_char(); 763 next_char();
744 } while (('_' == current_char) || isdigit(current_char) || 764 } while (('_' == current_char) || isdigit(current_char) ||
745 (('a' <= current_char) && (current_char <= 'z')) || 765 (('a' <= current_char) && (current_char <= 'z')) ||
746 (('A' <= current_char) && (current_char <= 'Z'))); 766 (('A' <= current_char) && (current_char <= 'Z')));
747 767
748 current_token = T_Reference; 768 CYG_REPORT_RETURN();
749 769 }
750 CYG_REPORT_RETURN(); 770
771 //}}}
772 //{{{ process_special()
773
774 // Usually an alphanumeric sequence of characters is a reference, e.g.
775 // CYGPKG_KERNEL. However there are only so many special characters
776 // available so some operators are implemented as a sequence, e.g.
777 // "to". CDL also supports functions like is_substr().
778 //
779 // The data will have been collected into the current_reference string
780 // by a call to process_alphanumeric().
781
782 static bool
783 process_special()
784 {
785 CYG_REPORT_FUNCNAMETYPE("process_special", "special %d");
786 bool result = false;
787
788 if ("to" == current_reference) {
789 current_token = T_Range;
790 result = true;
791 } else if (CdlFunction::is_function(current_reference.c_str(), current_function_id)) {
792 current_token = T_Function;
793 result = true;
794 }
795
796 if (result) {
797 current_reference = "";
798 }
799 CYG_REPORT_RETVAL(result);
800 return result;
751 } 801 }
752 802
753 //}}} 803 //}}}
754 804
755 //}}} 805 //}}}
768 current_string = ""; 818 current_string = "";
769 current_reference = ""; 819 current_reference = "";
770 current_int = 0; 820 current_int = 0;
771 current_double = 0.0; 821 current_double = 0.0;
772 current_format = CdlValueFormat_Default; 822 current_format = CdlValueFormat_Default;
823 current_function_id = 0;
773 824
774 // Skip leading white space. This includes newlines, tabs, etc, 825 // Skip leading white space. This includes newlines, tabs, etc,
775 // consider the case of: 826 // consider the case of:
776 // ... 827 // ...
777 // legal_values { 828 // legal_values {
929 case ':': 980 case ':':
930 current_token = T_Colon; 981 current_token = T_Colon;
931 next_char(); 982 next_char();
932 break; 983 break;
933 984
985 case '.':
986 current_token = T_StringConcat;
987 next_char();
988 break;
989
990 case ',':
991 current_token = T_Comma;
992 next_char();
993 break;
994
934 default: 995 default:
935 // String constants have been handled already. The only 996 // String constants have been handled already. The only
936 // valid tokens that are left are numbers, references and 997 // valid tokens that are left are numbers, references,
937 // the rang eoperator. 998 // "specials" such as the range and string equality
999 // operators, and functions.
938 // 1000 //
939 // Numbers should begin with a digit (plus and minus are 1001 // Numbers should begin with a digit (plus and minus are
940 // tokenized separately). 1002 // tokenized separately).
941 // 1003 //
942 // References must be valid C preprocessor symbols, i.e. 1004 // References must be valid C preprocessor symbols, i.e.
946 if (isdigit(current_char)) { 1008 if (isdigit(current_char)) {
947 process_number(); 1009 process_number();
948 } else if (('_' == current_char) || 1010 } else if (('_' == current_char) ||
949 (('a' <= current_char) && (current_char <= 'z')) || 1011 (('a' <= current_char) && (current_char <= 'z')) ||
950 (('A' <= current_char) && (current_char <= 'Z'))) { 1012 (('A' <= current_char) && (current_char <= 'Z'))) {
951 process_reference(); 1013 process_alphanumeric();
952 if ("to" == current_reference) { 1014 if (!process_special()) {
953 current_reference = "";
954 current_token = T_Range;
955 } else {
956 current_token = T_Reference; 1015 current_token = T_Reference;
957 } 1016 }
958 } else { 1017 } else {
959 std::string msg = "Unexpected character '"; 1018 std::string msg = "Unexpected character '";
960 msg += (char) current_char; 1019 msg += (char) current_char;
1007 // <bitxor> ::= <bitand> [<bitxor op> <bitand>] ^ 1066 // <bitxor> ::= <bitand> [<bitxor op> <bitand>] ^
1008 // <bitand> ::= <eq> [<bitand op> <eq>] & 1067 // <bitand> ::= <eq> [<bitand op> <eq>] &
1009 // <eq> ::= <comp> [<eq op> <comp>] == != 1068 // <eq> ::= <comp> [<eq op> <comp>] == !=
1010 // <comp> ::= <shift> [<comp op> <shift>] < <= > >= 1069 // <comp> ::= <shift> [<comp op> <shift>] < <= > >=
1011 // <shift> ::= <add> [<shift op> <add>] << >> 1070 // <shift> ::= <add> [<shift op> <add>] << >>
1012 // <add> ::= <mult> [<add op> <mult>] + - 1071 // <add> ::= <mult> [<add op> <mult>] + - .
1013 // <mult> ::= <unary> [<mult op> <unary>] * / % 1072 // <mult> ::= <unary> [<mult op> <unary>] * / %
1014 // <unary> ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> | 1073 // <unary> ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> |
1015 // ~<unary> | 1074 // ~<unary> |
1016 // <string constant> | <integer constant> | 1075 // <string constant> | <integer constant> |
1017 // <double constant> | <reference> | 1076 // <double constant> | <reference> |
1018 // ( <expression> ) 1077 // ( <expression> ) | <function>
1019 // 1078 //
1020 // There are separate functions for each of these terms. 1079 // There are separate functions for each of these terms.
1021 1080
1022 // A forward declaration, needed for bracketed subexpressions. 1081 // A forward declaration, needed for bracketed subexpressions.
1023 static void parse_expression(CdlExpression); 1082 static void parse_expression(CdlExpression);
1059 1118
1060 CdlSubexpression& result = expr->sub_expressions[expr->first_subexpression]; 1119 CdlSubexpression& result = expr->sub_expressions[expr->first_subexpression];
1061 1120
1062 CYG_REPORT_RETURN(); 1121 CYG_REPORT_RETURN();
1063 return result; 1122 return result;
1123 }
1124
1125 static void
1126 parse_function(CdlExpression expr)
1127 {
1128 CYG_REPORT_FUNCNAME("parse_function");
1129 CYG_REPORT_FUNCARG1XV(expr);
1130 CYG_PRECONDITION_CLASSC(expr);
1131
1132 CdlSubexpression subexpr;
1133 subexpr.op = CdlExprOp_Function;
1134 subexpr.func = current_function_id;
1135
1136 int number_of_args = CdlFunction::get_args_count(current_function_id);
1137 CYG_ASSERTC((0 < number_of_args) && (number_of_args <= CdlFunction_MaxArgs));
1138 std::string name = current_reference;
1139
1140 // check for the opening bracket: xyzzy(arg1, arg2)
1141 next_token();
1142 if (T_OpenBracket != current_token) {
1143 throw CdlParseException(std::string("Expected opening bracket after function ") + name + "\n" + get_error_location());
1144 }
1145 next_token();
1146
1147 int i;
1148 for (i = 0; i < number_of_args; i++) {
1149 parse_expression(expr);
1150 subexpr.args[i] = expr->first_subexpression;
1151 if (i < (number_of_args - 1)) {
1152 if (T_Comma != current_token) {
1153 throw CdlParseException(std::string("Expected comma between arguments in function ") +
1154 name + "\n" + get_error_location());
1155 }
1156 next_token();
1157 }
1158 }
1159 if (T_CloseBracket != current_token) {
1160 throw CdlParseException(std::string("Expected closing bracket after function ") + name + "\n" + get_error_location());
1161 }
1162 next_token();
1163
1164 // Allow the function implementation to check its arguments if it is so inclined.
1165 CdlFunction::check(expr, subexpr);
1166
1167 push_subexpression(expr, subexpr);
1168 CYG_REPORT_RETURN();
1064 } 1169 }
1065 1170
1066 static void 1171 static void
1067 parse_unary(CdlExpression expr) 1172 parse_unary(CdlExpression expr)
1068 { 1173 {
1075 switch(current_token) { 1180 switch(current_token) {
1076 case T_EOD : 1181 case T_EOD :
1077 { 1182 {
1078 // This warrants a special case 1183 // This warrants a special case
1079 throw CdlParseException("End of expression reached when expecting an operand.\n" + get_error_location()); 1184 throw CdlParseException("End of expression reached when expecting an operand.\n" + get_error_location());
1185 }
1186
1187 case T_Function :
1188 {
1189 parse_function(expr);
1190 break;
1080 } 1191 }
1081 1192
1082 case T_Reference : 1193 case T_Reference :
1083 { 1194 {
1084 subexpr.op = CdlExprOp_Reference; 1195 subexpr.op = CdlExprOp_Reference;
1245 parse_add(CdlExpression expr) 1356 parse_add(CdlExpression expr)
1246 { 1357 {
1247 CYG_REPORT_FUNCNAME("parse_add"); 1358 CYG_REPORT_FUNCNAME("parse_add");
1248 1359
1249 parse_multiply(expr); 1360 parse_multiply(expr);
1250 while ((T_Plus == current_token) || (T_Minus == current_token)) { 1361 while ((T_Plus == current_token) ||
1362 (T_Minus == current_token) ||
1363 (T_StringConcat == current_token)) {
1251 1364
1252 CdlSubexpression subexpr; 1365 CdlSubexpression subexpr;
1253 subexpr.op = (T_Plus == current_token) ? CdlExprOp_Add : CdlExprOp_Subtract; 1366 subexpr.op = (T_Plus == current_token) ? CdlExprOp_Add :
1367 (T_Minus == current_token) ? CdlExprOp_Subtract :
1368 CdlExprOp_StringConcat;
1254 subexpr.lhs_index = expr->first_subexpression; 1369 subexpr.lhs_index = expr->first_subexpression;
1255 1370
1256 next_token(); 1371 next_token();
1257 parse_multiply(expr); 1372 parse_multiply(expr);
1258 1373
1315 parse_equals(CdlExpression expr) 1430 parse_equals(CdlExpression expr)
1316 { 1431 {
1317 CYG_REPORT_FUNCNAME("parse_equals"); 1432 CYG_REPORT_FUNCNAME("parse_equals");
1318 1433
1319 parse_comparison(expr); 1434 parse_comparison(expr);
1320 while ((T_Equal == current_token) || (T_NotEqual == current_token)) { 1435 while ((T_Equal == current_token) ||
1436 (T_NotEqual == current_token)) {
1321 1437
1322 CdlSubexpression subexpr; 1438 CdlSubexpression subexpr;
1323 subexpr.op = (T_Equal == current_token) ? CdlExprOp_Equal : CdlExprOp_NotEqual; 1439 subexpr.op = (T_Equal == current_token) ? CdlExprOp_Equal : CdlExprOp_NotEqual;
1324 subexpr.lhs_index = expr->first_subexpression; 1440 subexpr.lhs_index = expr->first_subexpression;
1325 1441
1531 case CdlExprOp_StringConstant : 1647 case CdlExprOp_StringConstant :
1532 case CdlExprOp_IntegerConstant : 1648 case CdlExprOp_IntegerConstant :
1533 case CdlExprOp_DoubleConstant : 1649 case CdlExprOp_DoubleConstant :
1534 { 1650 {
1535 result = subexpr.constants; 1651 result = subexpr.constants;
1652 break;
1653 }
1654 case CdlExprOp_Function :
1655 {
1656 CdlFunction::eval(context, expr, subexpr, result);
1536 break; 1657 break;
1537 } 1658 }
1538 case CdlExprOp_Reference : 1659 case CdlExprOp_Reference :
1539 { 1660 {
1540 // This expression may be happening in the context of a particular 1661 // This expression may be happening in the context of a particular
2043 } else { 2164 } else {
2044 evaluate_subexpr(context, expr, subexpr.rrhs_index, result); 2165 evaluate_subexpr(context, expr, subexpr.rrhs_index, result);
2045 } 2166 }
2046 break; 2167 break;
2047 } 2168 }
2169 case CdlExprOp_StringConcat :
2170 {
2171 // a . b
2172 CdlSimpleValue lhs;
2173 CdlSimpleValue rhs;
2174 evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);
2175 evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);
2176 result = lhs.get_value() + rhs.get_value();
2177 break;
2178 }
2048 2179
2049 default: 2180 default:
2050 break; 2181 break;
2051 } 2182 }
2052 2183
2061 CYG_REPORT_FUNCARG3XV(this, &context, &result); 2192 CYG_REPORT_FUNCARG3XV(this, &context, &result);
2062 CYG_INVARIANT_THISC(CdlExpressionBody); 2193 CYG_INVARIANT_THISC(CdlExpressionBody);
2063 CYG_PRECONDITION_CLASSOC(context); 2194 CYG_PRECONDITION_CLASSOC(context);
2064 2195
2065 evaluate_subexpr(context, this, first_subexpression, result); 2196 evaluate_subexpr(context, this, first_subexpression, result);
2197
2198 CYG_REPORT_RETURN();
2199 }
2200
2201 void
2202 CdlExpressionBody::eval_subexpression(CdlEvalContext& context, int index, CdlSimpleValue& result)
2203 {
2204 CYG_REPORT_FUNCNAME("CdlExpression::eval_subexpression)");
2205 CYG_REPORT_FUNCARG4XV(this, &context, index, &result);
2206 CYG_INVARIANT_THISC(CdlExpressionBody);
2207 CYG_PRECONDITION_CLASSOC(context);
2208
2209 evaluate_subexpr(context, this, index, result);
2066 2210
2067 CYG_REPORT_RETURN(); 2211 CYG_REPORT_RETURN();
2068 } 2212 }
2069 2213
2070 //}}} 2214 //}}}