📄 expr.cxx
字号:
CYG_REPORT_FUNCNAME("parse_bitxor"); parse_bitand(expr); while (T_BitXor == current_token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_BitXor; subexpr.lhs_index = expr->first_subexpression; next_token(); parse_bitand(expr); subexpr.rhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } CYG_REPORT_RETURN();}static voidparse_bitor(CdlExpression expr){ CYG_REPORT_FUNCNAME("parse_bitor"); parse_bitxor(expr); while (T_BitOr == current_token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_BitOr; subexpr.lhs_index = expr->first_subexpression; next_token(); parse_bitxor(expr); subexpr.rhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } CYG_REPORT_RETURN();}static voidparse_and(CdlExpression expr){ CYG_REPORT_FUNCNAME("parse_and"); parse_bitor(expr); while (T_And == current_token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_And; subexpr.lhs_index = expr->first_subexpression; next_token(); parse_bitor(expr); subexpr.rhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } CYG_REPORT_RETURN();}static voidparse_or(CdlExpression expr){ CYG_REPORT_FUNCNAME("parse_or"); parse_and(expr); while (T_Or == current_token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_Or; subexpr.lhs_index = expr->first_subexpression; next_token(); parse_and(expr); subexpr.rhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } CYG_REPORT_RETURN();}static voidparse_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 voidparse_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 voidparse_conditional(CdlExpression expr){ CYG_REPORT_FUNCNAME("parse_conditional"); parse_implies(expr); if (T_Questionmark == current_token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_Cond; subexpr.lhs_index = expr->first_subexpression; next_token(); parse_conditional(expr); subexpr.rhs_index = expr->first_subexpression; if (T_Colon != current_token) { throw CdlParseException("Expected colon in conditional expression.\n" + get_error_location()); } next_token(); parse_conditional(expr); subexpr.rrhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } CYG_REPORT_RETURN();}static voidparse_expression(CdlExpression expr){ CYG_REPORT_FUNCNAME("parse_expression"); parse_conditional(expr); CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------// The entry point.voidCdlExpressionBody::continue_parse(CdlExpression expr, std::string data, int& index, CdlExprOp& token, int& token_end){ CYG_REPORT_FUNCNAME("CdlExpression::continue_parse"); CYG_REPORT_FUNCARG1XV(expr); CYG_PRECONDITION_CLASSC(expr); CYG_PRECONDITIONC((CdlExprOp_Invalid == token) || (CdlExprOp_And == token)); int current_subexpr = expr->first_subexpression; initialise_tokenisation(data, index); parse_expression(expr); if (CdlExprOp_And == token) { CdlSubexpression subexpr; subexpr.op = CdlExprOp_And; subexpr.lhs_index = current_subexpr; subexpr.rhs_index = expr->first_subexpression; push_subexpression(expr, subexpr); } token = token_to_expr_op(); index = token_start; token_end = current_index; CYG_REPORT_RETURN();}//}}}//}}}//{{{ Expression Evaluation // ----------------------------------------------------------------------------// Expression evaluation. This always happens in the context of a// particular toplevel. The parsed expression is held in what amounts// to a simple tree, so evaluation involves some recursion and a big// switch statement.static voidevaluate_subexpr(CdlEvalContext& context, CdlExpression expr, int subexpr_index, CdlSimpleValue& result){ CYG_REPORT_FUNCNAME("evaluate_subexpr"); CYG_REPORT_FUNCARG2XV(expr, subexpr_index); CYG_ASSERTC((subexpr_index >= 0) && ((unsigned int)subexpr_index < expr->sub_expressions.size())); const CdlSubexpression& subexpr = expr->sub_expressions[subexpr_index]; switch(subexpr.op) { case CdlExprOp_StringConstant : case CdlExprOp_IntegerConstant : case CdlExprOp_DoubleConstant : { result = subexpr.constants; break; } case CdlExprOp_Function : { CdlFunction::eval(context, expr, subexpr, result); break; } case CdlExprOp_Reference : { // This expression may be happening in the context of a particular // property. If so then the destination may or may not be resolved, // and this is significant in the context of loading and unloading. // Alternatively this expression may be being evaluated inside // some Tcl code, with no particular context. CdlNode destination = 0; if (0 != context.property) { // There is a property, use the bound/unbound reference. destination = expr->references[subexpr.reference_index].get_destination(); } else { // The destination name can be retrieved, but we still need some // way of resolving it. if (0 != context.toplevel) { std::string destination_name = expr->references[subexpr.reference_index].get_destination_name(); destination = context.toplevel->lookup(destination_name); } } if (0 == destination) { // There are two ways of handling this. // 1) throw an eval exception, which will usually result // in a new conflict object // 2) substitute a value of 0. // There should already be a conflict object for an // unresolved reference, and having two conflicts for // essentially the same error is not useful. Using a value // of 0 allows things to continue for a bit longer. It is // consistent with active vs. inactive values, gives // basically the right result for "requires" properties, // and so on. // // For now option (2) has it, but this decision may be // reversed in future. result = false; } else { CdlValuable valuable = dynamic_cast<CdlValuable>(destination); if (0 == valuable) { // This is a serious problem, an exception is warranted. throw CdlEvalException("The expression references `" + destination->get_class_name() + " " + destination->get_name() + "' which does not have a value."); } else { CdlSimpleValue::eval_valuable(context, valuable, result); } } break; } case CdlExprOp_Negate : { // Unary -. Evaluate the target. If it is numeric, fine. Otherwise // an error is warranted. evaluate_subexpr(context, expr, subexpr.lhs_index, result); if (result.has_integer_value()) { result.set_integer_value(-1 * result.get_integer_value()); } else if (result.has_double_value()) { result.set_double_value(-1.0 * result.get_double_value()); } else { throw CdlEvalException("Attempt to negate non-numeric value `" + result.get_value() + "'."); } break; } case CdlExprOp_Plus : { // Unary +. Essentially this just checks that the current value is numeric. evaluate_subexpr(context, expr, subexpr.lhs_index, result); if ((!result.has_integer_value()) && (!result.has_double_value())) { throw CdlEvalException("Attempt to apply unary + operator to non-numeric value `" + result.get_value() + "'."); } break; } case CdlExprOp_LogicalNot : { // !x evaluate_subexpr(context, expr, subexpr.lhs_index, result); if (result.get_bool_value()) { result = false;; } else { result = true; } result.set_value_format(CdlValueFormat_Default); break; } case CdlExprOp_BitNot : { // ~x. The operand must be an integer value. evaluate_subexpr(context, expr, subexpr.lhs_index, result); if (result.has_integer_value()) { cdl_int tmp = result.get_integer_value(); result = ~tmp; } else { throw CdlEvalException("Attempt to apply unary ~ operator to non-integer value `" + result.get_value() + "'."); } break; } case CdlExprOp_Indirect : { // *x. The operand must evaluate to a string, and that string should be // the name of a CdlValuable object. CdlNode destination = 0; evaluate_subexpr(context, expr, subexpr.lhs_index, result); std::string name = result.get_value(); if (0 != context.toplevel) { destination = context.toplevel->lookup(name); } else { CYG_FAIL("This situation should probably never happen."); } if (0 == destination) { throw CdlEvalException("Attempt to apply unary indirection operator * to `" + name + "', which is not the name of a known CDL entity."); } else { CdlValuable valuable = dynamic_cast<CdlValuable>(destination); if (0 == valuable) { throw CdlEvalException("Attempt to apply unary indirection operator * to `" + name + "', which does not have a value."); } else { CdlSimpleValue::eval_valuable(context, valuable, result); } } break; } case CdlExprOp_Active : { // ?x. If x is currently unresolved then default to 0. // See the CdlExprOp_Reference code above for a similar case. CdlNode destination = 0; if (0 != context.property) { destination = expr->references[subexpr.reference_index].get_destination(); } else { if (0 != context.toplevel) { std::string destination_name = expr->references[subexpr.reference_index].get_destination_name(); destination = context.toplevel->lookup(destination_name); } } bool active = false; if ((0 != destination) && context.transaction->is_active(destination)) { active = true; } if (active) { result = true; } else { result = false; } break; } case CdlExprOp_Multiply : { // x * y. For now this only makes sense for numerical data, // but it is possible to mix and match integer and double // precision data. // // Strictly speaking the rhs need only be evaluated if it // is known that the lhs is numeric. CdlSimpleValue lhs; CdlSimpleValue rhs; evaluate_subexpr(context, expr, subexpr.lhs_index, lhs); evaluate_subexpr(context, expr, subexpr.rhs_index, rhs); if ((!(lhs.has_integer_value() || lhs.has_double_value())) || (!(rhs.has_integer_value() || rhs.has_double_value()))) { throw CdlEvalException("Attempt to multiply non-numerical values: `" + lhs.get_value() + "' * `" + rhs.get_value() +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -