void asl_cel_format::stack_event(stream_type& os, bool is_push) { const format_element_t& top(stack_top()); name_t self(top.tag()); name_t parent(stack_depth() >= 2 ? stack_n(1).tag() : name_t()); if (self == atom_name_g) { handle_atom(os, is_push); } else if (is_push) { if (self == bag_name_g) { os << '{'; up(); } else if (self == seq_name_g && parent != bag_name_g) { os << "[ "; } } else { if (self == bag_name_g) { down(); if (top.num_out_m > 0) os << '\n' << indents(depth()); else os << ' '; os << '}'; } else if (self == seq_name_g && parent != bag_name_g) { if (top.num_out_m > 0) os << ' '; os << ']'; } } }
void pdf_format::stack_event(stream_type& os, bool is_push) { const format_element_t& top(stack_top()); name_t self(top.tag()); name_t parent(stack_depth() >= 2 ? stack_n(1).tag() : name_t()); name_t grandparent(stack_depth() >= 3 ? stack_n(2).tag() : name_t()); if (self == atom_name_g) { handle_atom(os, is_push); } else if (is_push) { if (self == static_name_t("pdf")) { os << "% start pdf" << std::endl; } else if (self == bag_name_g) { os << "<<"; up(); } else if (self == seq_name_g && parent != bag_name_g) { os << "[ "; } } else { if (self == static_name_t("pdf")) { os << "\n% end pdf"; } else if (self == bag_name_g) { down(); if (top.num_out_m > 0) os << '\n' << indents(depth()); else os << ' '; os << ">>"; } else if (self == seq_name_g && parent != bag_name_g) { if (top.num_out_m > 0) os << ' '; os << ']'; } } }
std::vector<int> parse_util_compute_indents(const wcstring &src) { /* Make a vector the same size as the input string, which contains the indents. Initialize them to -1. */ const size_t src_size = src.size(); std::vector<int> indents(src_size, -1); /* Parse the string. We pass continue_after_error to produce a forest; the trailing indent of the last node we visited becomes the input indent of the next. I.e. in the case of 'switch foo ; cas', we get an invalid parse tree (since 'cas' is not valid) but we indent it as if it were a case item list */ parse_node_tree_t tree; parse_tree_from_string(src, parse_flag_continue_after_error | parse_flag_include_comments | parse_flag_accept_incomplete_tokens, &tree, NULL /* errors */); /* Start indenting at the first node. If we have a parse error, we'll have to start indenting from the top again */ node_offset_t start_node_idx = 0; int last_trailing_indent = 0; while (start_node_idx < tree.size()) { /* The indent that we'll get for the last line */ int trailing_indent = 0; /* Biggest offset we visited */ node_offset_t max_visited_node_idx = 0; /* Invoke the recursive version. As a hack, pass job_list for the 'parent' token type, which will prevent the really-root job list from indenting */ compute_indents_recursive(tree, start_node_idx, last_trailing_indent, symbol_job_list, &indents, &trailing_indent, &max_visited_node_idx); /* We may have more to indent. The trailing indent becomes our current indent. Start at the node after the last we visited. */ last_trailing_indent = trailing_indent; start_node_idx = max_visited_node_idx + 1; } /* Handle comments. Each comment node has a parent (which is whatever the top of the symbol stack was when the comment was encountered). So the source range of the comment has the same indent as its parent. */ const size_t tree_size = tree.size(); for (node_offset_t i=0; i < tree_size; i++) { const parse_node_t &node = tree.at(i); if (node.type == parse_special_type_comment && node.has_source() && node.parent < tree_size) { const parse_node_t &parent = tree.at(node.parent); if (parent.source_start != SOURCE_OFFSET_INVALID) { indents.at(node.source_start) = indents.at(parent.source_start); } } } /* Now apply the indents. The indents array has -1 for places where the indent does not change, so start at each value and extend it along the run of -1s */ int last_indent = 0; for (size_t i=0; i<src_size; i++) { int this_indent = indents.at(i); if (this_indent < 0) { indents.at(i) = last_indent; } else { /* New indent level */ last_indent = this_indent; /* Make all whitespace before a token have the new level. This avoid using the wrong indentation level if a new line starts with whitespace. */ size_t prev_char_idx = i; while (prev_char_idx--) { if (!wcschr(L" \n\t\r", src.at(prev_char_idx))) break; indents.at(prev_char_idx) = last_indent; } } } /* Ensure trailing whitespace has the trailing indent. This makes sure a new line is correctly indented even if it is empty. */ size_t suffix_idx = src_size; while (suffix_idx--) { if (!wcschr(L" \n\t\r", src.at(suffix_idx))) break; indents.at(suffix_idx) = last_trailing_indent; } return indents; }
void asl_cel_format::handle_atom(stream_type& os, bool is_push) { const format_element_t& top(stack_top()); name_t parent(stack_depth() >= 2 ? stack_n(1).tag() : name_t()); name_t grandparent(stack_depth() >= 3 ? stack_n(2).tag() : name_t()); const any_regular_t& value(top.value()); bool outputting_bag(parent == seq_name_g && grandparent == bag_name_g); std::size_t& num_out(outputting_bag ? stack_n(2).num_out_m : stack_n(1).num_out_m); bool named_argument(outputting_bag && (num_out & 0x1) == 0); if (is_push) { // if this is not the first item in the element, add a comma and set up a newline if (num_out > 0) { if (!outputting_bag) { os << ", "; } else if (named_argument) { os << ",\n" << indents(depth()); } } else if (outputting_bag) { os << '\n' << indents(depth()); } if (value.type_info() == typeid(string)) { bool escape(needs_entity_escape(value.cast<string>())); if (escape_m && escape) os << "xml_unescape("; os << '\"' << (escape_m && escape ? entity_escape(value.cast<string>()) : value.cast<string>()) << '\"'; if (escape_m && escape) os << ")"; } else if (value.type_info() == typeid(name_t)) { if (!named_argument) os << '@'; os << value.cast<name_t>(); if (outputting_bag && named_argument) os << ": "; } else if (value.type_info() == typeid(bool)) { os << (value.cast<bool>() ? "true" : "false"); } else if (value.type_info() == typeid(double)) { double dbl_val(value.cast<double>()); boost::int64_t int_val(static_cast<boost::int64_t>(dbl_val)); if (dbl_val == int_val) { os << int_val; } else { // For asl_cel, we want to output floating-point values in decimal-based // fixed-point notation (asl_cel doesn't support any other format) with // a very high precision for accceptable roundtrip values. os.setf(std::ios_base::dec, std::ios_base::basefield); os.setf(std::ios_base::fixed, std::ios_base::floatfield); os.precision(16); os << dbl_val; } } else if (value.type_info() == typeid(empty_t)) { os << value.cast<empty_t>(); } else if (value.type_info() == typeid(dictionary_t)) { os << value.cast<dictionary_t>(); } else if (value.type_info() == typeid(array_t)) { os << value.cast<array_t>(); } else { os << "'" << value.type_info().name() << "'"; } } else { // up the number of outputted items for the parent to this atom ++num_out; } }
void pdf_format::handle_atom(stream_type& os, bool is_push) { const format_element_t& top(stack_top()); name_t self(top.tag()); name_t parent(stack_depth() >= 2 ? stack_n(1).tag() : name_t()); name_t grandparent(stack_depth() >= 3 ? stack_n(2).tag() : name_t()); const any_regular_t& value(top.value()); bool outputting_bag(parent == seq_name_g && grandparent == bag_name_g); std::size_t& num_out(outputting_bag ? stack_n(2).num_out_m : stack_n(1).num_out_m); bool named_argument(outputting_bag && num_out % 2 == 0); if (is_push) { // if this is not the first item in the element, add a comma and set up a newline if (num_out > 0) { if (!outputting_bag) { os << ' '; } else if (named_argument) { os << '\n' << indents(depth()); } } else if (outputting_bag) { os << '\n' << indents(depth()); } if (value.type_info() == adobe::type_info<string_t>()) { os << '(' << value.cast<string_t>() << ')'; } else if (value.type_info() == adobe::type_info<name_t>()) { os << '/' << value.cast<name_t>(); if (outputting_bag && named_argument) os << " "; } else if (value.type_info() == adobe::type_info<bool>()) { os << (value.cast<bool>() ? "true" : "false"); } else if (value.type_info() == adobe::type_info<double>()) { double dbl_val(value.cast<double>()); boost::int64_t int_val(static_cast<boost::int64_t>(dbl_val)); if (dbl_val == int_val) { os << int_val; } else { // For pdf, we want to output floating-point values in decimal-based // fixed-point notation (asl_cel doesn't support any other format) with // a very high precision for accceptable roundtrip values. os.setf(std::ios_base::dec, std::ios_base::basefield); os.setf(std::ios_base::fixed, std::ios_base::floatfield); os.precision(16); os << dbl_val; } } else if (value.type_info() == adobe::type_info<empty_t>()) { os << "null"; } else if (value.type_info() == adobe::type_info<dictionary_t>()) { os << value.cast<dictionary_t>(); } else if (value.type_info() == adobe::type_info<array_t>()) { os << value.cast<array_t>(); } else { os << "(pdf_unknown: " << value.type_info().name() << ")"; } } else { // up the number of outputted items for the parent to this atom ++num_out; } }