void print_CXX(Scanners::LOperatorPrecedenceList* OPL, std::ostream& output, int& position, Values::NodeT node, int precedence_limit, bool B_paren_equal_levels) { /* the easiest way to think about this is that any and each node has a precedence level. The precedence level of the atoms is just very high. The reason it is not explicitly programmed that way is that there are a lot of temporary variables that are used in both precedence level detection and recursion and that would be much code duplication to do two. */ if(node == NULL) print_text(output, position, "[]", false); else if(symbol_P(node)) { Values::NodeT fAssociativity = NULL; int pl = OPL->get_operator_precedence_and_associativity(node, fAssociativity); print_text(output, position, Values::get_symbol_name(node), pl != -1 && fAssociativity != Symbols::Sprefix); } else if(abstraction_P(node)) { /* abstraction */ process_abstraction(OPL, output, position, node, precedence_limit, B_paren_equal_levels); } else if(application_P(node)) { /* application */ Values::NodeT envelope = get_application_operator(node); if(!application_P(envelope)) { if(abstraction_P(envelope)) { // detect let form. Values::NodeT fAssociativity = NULL; Values::NodeT operator_ = Symbols::Slet; int pl = OPL->get_operator_precedence_and_associativity(operator_, fAssociativity); bool B_parend = maybe_print_opening_paren(output, position, operator_, pl, precedence_limit, B_paren_equal_levels); print_text_raw(output, position, "let ", false); print_CXX(OPL, output, position, Values::get_abstraction_parameter(envelope), pl, false); print_text_raw(output, position, " := ", false); print_CXX(OPL, output, position, Values::get_application_operand(node), pl, false); print_text_raw(output, position, " in ", false); // TODO add a nice-break-here print_CXX(OPL, output, position, Values::get_abstraction_body(envelope), pl, false); maybe_print_closing_paren(output, position, operator_, B_parend); return; } envelope = NULL; } //if(operator_ && application_P(operator_)) // 2 for binary ops. Values::NodeT operator_ = envelope ? get_application_operator(envelope) : NULL; Values::NodeT operatorSymbol = repr(operator_); if(!symbol1_P(operatorSymbol)) operatorSymbol = NULL; Values::NodeT operatorAssociativity = NULL; int precedence = operatorSymbol ? OPL->get_operator_precedence_and_associativity(operatorSymbol, operatorAssociativity) : -1; if(precedence != -1 && application_P(envelope)) { // is a (binary) operator and the envelope is not a builtin (i.e. (+)) bool B_parend = maybe_print_opening_paren(output, position, operator_, precedence, precedence_limit, B_paren_equal_levels); print_CXX(OPL, output, position, get_application_operand(envelope), precedence, operatorAssociativity != Symbols::Sleft); print_text_raw(output, position, Evaluators::str(operatorSymbol), precedence < OPL->apply_level); Values::NodeT operand = get_application_operand(node); if(operatorSymbol == Symbols::Sdot && application_P(operand) && Evaluators::quote_P(get_application_operator(operand))) { /* MathParser (Shunting Yard Parser) special cases the dot operator to auto-quote. So auto-unquote here. */ operand = get_application_operand(operand); } print_CXX(OPL, output, position, operand, precedence, operatorAssociativity != Symbols::Sright); maybe_print_closing_paren(output, position, operator_, B_parend); } else { // function application is fine and VERY greedy operatorAssociativity = Symbols::Sleft; precedence = OPL->apply_level; bool B_parend = maybe_print_opening_paren(output, position, operator_, precedence, precedence_limit, B_paren_equal_levels); operator_ = get_application_operator(node); Values::NodeT xoperatorAssociativity = NULL; int xprecedence = symbol1_P(operator_) ? OPL->get_operator_precedence_and_associativity(operator_, xoperatorAssociativity) : -1; if(xprecedence != -1 && xoperatorAssociativity != Symbols::Sprefix) { // incomplete binary operation ++position, output << '('; print_text_raw(output, position, Evaluators::str(operator_), precedence < OPL->apply_level); ++position, output << ')'; } else print_CXX(OPL, output, position, operator_, precedence, operatorAssociativity != Symbols::Sleft); if(operator_ != Symbols::Squote) print_text_raw(output, position, " ", false); print_CXX(OPL, output, position, get_application_operand(node), precedence, operatorAssociativity != Symbols::Sright); maybe_print_closing_paren(output, position, operator_, B_parend); // f.e. we now are at +, but came from *, i.e. 2*(3+5) } } else if(cons_P(node)) { int precedence = OPL->apply_level; output << "["; ITERATE_LAZY_CONS_NODES(node, { print_CXX(OPL, output, position, Values::get_cons_head(vnode), precedence, true); }, { print_text_raw(output, position, " ", false); print_CXX(OPL, output, position, Values::get_cons_head(vnode), precedence, true); }, { print_text_raw(output, position, ",", false); print_CXX(OPL, output, position, vnode, precedence, true); }) output << "]"; #if 0 } else if(pair_P(node)) { // comma precedence Values::NodeT operator_ = Symbols::Scomma; Values::NodeT operatorSymbol = Symbols::Scomma; Values::NodeT operatorAssociativity = NULL; int precedence = operatorSymbol ? OPL->get_operator_precedence_and_associativity(operatorSymbol, operatorAssociativity) : -1; bool B_parend = maybe_print_opening_paren(output, position, operator_, precedence, precedence_limit, B_paren_equal_levels); print_CXX(OPL, output, position, Values::get_pair_first(node), precedence, operatorAssociativity != Symbols::Sleft); print_text_raw(output, position, Evaluators::str(operatorSymbol), precedence < OPL->apply_level); print_CXX(OPL, output, position, Values::get_pair_second(node), precedence, operatorAssociativity != Symbols::Sright); maybe_print_closing_paren(output, position, operator_, B_parend); #endif } else if(Numbers::ratio_P(node)) { /* copied from the application_P() case. */ Values::NodeT operator_ = Symbols::Sslash; Values::NodeT operatorAssociativity = NULL; int precedence = symbol_P(operator_) ? OPL->get_operator_precedence_and_associativity(operator_, operatorAssociativity) : -1; assert(precedence != -1); bool B_parend = maybe_print_opening_paren(output, position, operator_, precedence, precedence_limit, B_paren_equal_levels); print_CXX(OPL, output, position, Numbers::Ratio_getA(node), precedence, operatorAssociativity != Symbols::Sleft); print_text_raw(output, position, Evaluators::str(operator_), precedence < OPL->apply_level); print_CXX(OPL, output, position, Numbers::Ratio_getB(node), precedence, operatorAssociativity != Symbols::Sright); maybe_print_closing_paren(output, position, operator_, B_parend); } else { /* literal etc */ /* this especially matches BuiltinOperators which will return their builtin name */ std::string value = str(node); Values::NodeT fAssociativity = NULL; int pl = OPL->get_operator_precedence_and_associativity(Values::symbolFromStr(value.c_str()), fAssociativity); print_text(output, position, value.c_str(), pl != -1 && fAssociativity != Symbols::Sprefix); // , pl < OPL->apply_level && pl != -1); } } void print(Values::NodeT OPL, FILE* output_file, int position, int indentation, Values::NodeT node) { std::stringstream sst; std::string value; node = repr(node); print_CXX(Scanners::legacyOPLFrom5DOPL(OPL), sst, position, node, 0, false); value = sst.str(); fprintf(output_file, "%s", value.c_str()); }