diff 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
line wrap: on
line diff
--- a/host/libcdl/expr.cxx
+++ b/host/libcdl/expr.cxx
@@ -130,6 +130,56 @@ CdlEvalContext::~CdlEvalContext()
     CYG_REPORT_RETURN();
 }
 
+// Given a context and a reference inside an expression, obtain the node
+// being referenced - if it is loaded.
+CdlNode
+CdlEvalContext::resolve_reference(CdlExpression expr, int index)
+{
+    CYG_REPORT_FUNCNAMETYPE("CdlEvalContext::resolve_reference", "result %");
+    CYG_REPORT_FUNCARG2XV(expr, index);
+    CYG_PRECONDITION_THISC();
+    CYG_PRECONDITION_CLASSC(expr);
+    CYG_PRECONDITIONC((0 <= index) && (index <= (int)expr->references.size()));
+
+    // This expression may be happening in the context of a particular
+    // property. If so then the destination may or may not be
+    // resolved, which will have been handled when the containing package
+    // was loaded. Alternatively this expression may be evaluated inside
+    // some arbitrary Tcl code, in which case references remain unbound
+    // and need to be resolved the hard way.
+    CdlNode result = 0;
+    if (0 != this->property) {
+        // There is a property, use the bound/unbound reference.
+        result = expr->references[index].get_destination();
+    } else {
+        // The destination name can be retrieved, but we still need some
+        // way of resolving it.
+        if (0 != this->toplevel) {
+            std::string destination_name = expr->references[index].get_destination_name();
+            result = this->toplevel->lookup(destination_name);
+        }
+    }
+    
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
+// Ditto, but also check that the result is a valuable.
+CdlValuable
+CdlEvalContext::resolve_valuable_reference(CdlExpression expr, int index)
+{
+    CYG_REPORT_FUNCNAMETYPE("CdlEvalContext::resolve_reference", "result %");
+    CYG_REPORT_FUNCARG2XV(expr, index);
+
+    CdlValuable result  = 0;
+    CdlNode     node = this->resolve_reference(expr, index);
+    if (0 != node) {
+        result = dynamic_cast<CdlValuable>(node);
+    }
+    CYG_REPORT_RETVAL(result);
+    return result;
+}
+
 bool
 CdlEvalContext::check_this(cyg_assert_class_zeal zeal) const
 {
@@ -234,7 +284,10 @@ enum token {
     T_Colon             = 29,   // : (in a conditional)
     T_StringConcat      = 30,   // .
     T_Function          = 31,   // is_substr etc.
-    T_Comma             = 32    // , (inside a function)
+    T_Comma             = 32,   // , (inside a function)
+    T_Implies           = 33,   // implies
+    T_Xor               = 34,   // xor
+    T_Eqv               = 35    // eqv
     
 };
 
@@ -249,6 +302,7 @@ static int              current_char    
 static token            current_token           = T_Invalid;
 static std::string      current_string          = "";
 static std::string      current_reference       = "";
+static std::string      current_special         = "";
 static cdl_int          current_int             = 0;
 static double           current_double          = 0.0;
 static CdlValueFormat   current_format          = CdlValueFormat_Default;
@@ -331,6 +385,14 @@ get_error_location()
     return result;
 }
 
+// Export this functionality available to other modules, especially func.cxx and its
+// argument checking routines.
+std::string
+CdlParse::get_expression_error_location(void)
+{
+    return get_error_location();
+}
+
 //}}}
 //{{{  Token translation                
 
@@ -363,6 +425,9 @@ token_to_binary_expr_op()
       case T_And:               result = CdlExprOp_And; break;
       case T_Or:                result = CdlExprOp_Or; break;
       case T_StringConcat:      result = CdlExprOp_StringConcat; break;
+      case T_Implies:           result = CdlExprOp_Implies; break;
+      case T_Xor:               result = CdlExprOp_Xor; break;
+      case T_Eqv:               result = CdlExprOp_Eqv; break;
       default:                  result = CdlExprOp_Invalid; break;
     }
     
@@ -459,6 +524,9 @@ token_to_string()
       case T_Or:                result = "or operator ||"; break;
       case T_Colon:             result = "colon"; break;
       case T_StringConcat:      result = "string concatenation operator ."; break;
+      case T_Implies:           result = "implies operator"; break;
+      case T_Xor:               result = "logical xor operator"; break;
+      case T_Eqv:               result = "logical equivalence operator eqv"; break;
       case T_Function:          result = std::string("function call ") + CdlFunction::get_name(current_function_id); break;
       case T_Invalid:
       default:                  result = "<invalid token>"; break;
@@ -788,13 +856,23 @@ process_special()
     if ("to" == current_reference) {
         current_token  = T_Range;
         result = true;
+    } else if ("implies" == current_reference) {
+        current_token  = T_Implies;
+        result = true;
+    } else if ("xor" == current_reference) {
+        current_token  = T_Xor;
+        result = true;
+    } else if ("eqv" == current_reference) {
+        current_token  = T_Eqv;
+        result = true;
     } else if (CdlFunction::is_function(current_reference.c_str(), current_function_id)) {
-        current_token           = T_Function;
+        current_token  = T_Function;
         result = true;
     }
 
     if (result) {
-        current_reference = "";
+        current_special     = current_reference;
+        current_reference   = "";
     }
     CYG_REPORT_RETVAL(result);
     return result;
@@ -817,6 +895,7 @@ next_token()
     current_token       = T_Invalid;
     current_string      = "";
     current_reference   = "";
+    current_special     = "";
     current_int         = 0;
     current_double      = 0.0;
     current_format      = CdlValueFormat_Default;
@@ -1059,17 +1138,19 @@ initialise_tokenisation(std::string data
 // The BNF of CDL expressions is something like this:
 //
 //   <expression>   ::= <conditional>
-//   <conditional>  ::= <or> ? <conditional> : <conditional> | <or>
-//   <or>           ::= <and>    [<or op>     <and>]           ||
-//   <and>          ::= <bitor>  [<and op>    <bitor>]         ??
-//   <bitor>        ::= <bitxor> [<bitor op>  <bitxor>]        |
-//   <bitxor>       ::= <bitand> [<bitxor op> <bitand>]        ^
-//   <bitand>       ::= <eq>     [<bitand op> <eq>]            &
-//   <eq>           ::= <comp>   [<eq op>     <comp>]          == !=
-//   <comp>         ::= <shift>  [<comp op>   <shift>]         < <= > >=
-//   <shift>        ::= <add>    [<shift op>  <add>]           << >>
-//   <add>          ::= <mult>   [<add op>    <mult>]          + - .
-//   <mult>         ::= <unary>  [<mult op>   <unary>]         * / %
+//   <conditional>  ::= <implies> ? <conditional> : <conditional> | <implies>
+//   <implies>      ::= <eqv>    [<implies op>  <implies>]      implies
+//   <eqv>          ::= <or>     [<eqv op>      <eqv>]          xor, eqv        
+//   <or>           ::= <and>    [<or op>       <or>]           ||
+//   <and>          ::= <bitor>  [<and op>      <and>]          &&
+//   <bitor>        ::= <bitxor> [<bitor op>    <bitor>]        |
+//   <bitxor>       ::= <bitand> [<bitxor op>   <bitxor>]       ^
+//   <bitand>       ::= <eq>     [<bitand op>   <and>]          &
+//   <eq>           ::= <comp>   [<eq op>       <eq>]           == !=
+//   <comp>         ::= <shift>  [<comp op>     <comp>]         < <= > >=
+//   <shift>        ::= <add>    [<shift op>    <shift>]        << >>
+//   <add>          ::= <mult>   [<add op>      <add>]          + - .
+//   <mult>         ::= <unary>  [<mult op>     <mult>]         * / %
 //   <unary>        ::= -<unary> | +<unary> | !<unary> | *<unary> | ?<unary> |
 //                      ~<unary> |
 //                      <string constant> | <integer constant> |
@@ -1135,7 +1216,7 @@ parse_function(CdlExpression expr)
 
     int number_of_args  = CdlFunction::get_args_count(current_function_id);
     CYG_ASSERTC((0 < number_of_args) && (number_of_args <= CdlFunction_MaxArgs));
-    std::string name    = current_reference;
+    std::string name    = current_special;
 
     // check for the opening bracket: xyzzy(arg1, arg2)
     next_token();
@@ -1156,6 +1237,9 @@ parse_function(CdlExpression expr)
             next_token();
         }
     }
+    if (T_Comma == current_token) {
+        throw CdlParseException(std::string("Too many arguments passed to function ") + name + "\n" + get_error_location());
+    }
     if (T_CloseBracket != current_token) {
         throw CdlParseException(std::string("Expected closing bracket after function ") + name + "\n" + get_error_location());
     }
@@ -1559,11 +1643,55 @@ parse_or(CdlExpression expr)
 }
 
 static void
+parse_eqv(CdlExpression expr)
+{
+    CYG_REPORT_FUNCNAME("parse_eqv");
+
+    parse_or(expr);
+    while ((T_Xor == current_token) || (T_Eqv == current_token)) {
+        
+        CdlSubexpression subexpr;
+        subexpr.op = (T_Xor == current_token) ? CdlExprOp_Xor : CdlExprOp_Eqv;
+        subexpr.lhs_index = expr->first_subexpression;
+        
+        next_token();
+        parse_or(expr);
+
+        subexpr.rhs_index = expr->first_subexpression;
+        push_subexpression(expr, subexpr);
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
+parse_implies(CdlExpression expr)
+{
+    CYG_REPORT_FUNCNAME("parse_implies");
+
+    parse_eqv(expr);
+    while (T_Implies == current_token) {
+        
+        CdlSubexpression subexpr;
+        subexpr.op = CdlExprOp_Implies;
+        subexpr.lhs_index = expr->first_subexpression;
+        
+        next_token();
+        parse_eqv(expr);
+
+        subexpr.rhs_index = expr->first_subexpression;
+        push_subexpression(expr, subexpr);
+    }
+    
+    CYG_REPORT_RETURN();
+}
+
+static void
 parse_conditional(CdlExpression expr)
 {
     CYG_REPORT_FUNCNAME("parse_conditional");
 
-    parse_or(expr);
+    parse_implies(expr);
     if (T_Questionmark == current_token) {
         CdlSubexpression subexpr;
         subexpr.op = CdlExprOp_Cond;
@@ -2153,6 +2281,60 @@ evaluate_subexpr(CdlEvalContext& context
         }
         break;
     }
+    case CdlExprOp_Xor :
+    {
+        // x xor y. Both sides should be interpreted as boolean values.
+        CdlSimpleValue lhs;
+        CdlSimpleValue rhs;
+        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);
+        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);
+
+        bool lhs_bool = lhs.get_bool_value();
+        bool rhs_bool = rhs.get_bool_value();
+        if ((lhs_bool && !rhs_bool) || (!lhs_bool && rhs_bool)) {
+            result = true;
+        } else {
+            result = false;
+        }
+        
+        break;
+    }
+    case CdlExprOp_Eqv :
+    {
+        // x eqv y. Both sides should be interpreted as boolean values.
+        CdlSimpleValue lhs;
+        CdlSimpleValue rhs;
+        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);
+        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);
+
+        bool lhs_bool = lhs.get_bool_value();
+        bool rhs_bool = rhs.get_bool_value();
+        if ((!lhs_bool && !rhs_bool) || (lhs_bool && rhs_bool)) {
+            result = true;
+        } else {
+            result = false;
+        }
+        
+        break;
+    }
+    case CdlExprOp_Implies :
+    {
+        // x implies y. Both sides should be interpreted as boolean values.
+        CdlSimpleValue lhs;
+        CdlSimpleValue rhs;
+        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);
+        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);
+
+        bool lhs_bool = lhs.get_bool_value();
+        bool rhs_bool = rhs.get_bool_value();
+        if (!lhs_bool || rhs_bool) {
+            result = true;
+        } else {
+            result = false;
+        }
+        
+        break;
+    }
     case CdlExprOp_Cond :
     {
         // x ? a : b.