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 << ']';
        }
    }
}
예제 #2
0
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 << ']';
        }
    }
}
예제 #3
0
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;
    }
}
예제 #5
0
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;
    }
}