Ejemplo n.º 1
0
// Dump a parse tree node in a form helpful to someone debugging the behavior of this program.
static void dump_node(indent_t node_indent, const parse_node_t &node, const wcstring &source) {
    wchar_t nextc = L' ';
    wchar_t prevc = L' ';
    wcstring source_txt = L"";
    if (node.source_start != SOURCE_OFFSET_INVALID && node.source_length != SOURCE_OFFSET_INVALID) {
        int nextc_idx = node.source_start + node.source_length;
        if ((size_t)nextc_idx < source.size()) {
            nextc = source[node.source_start + node.source_length];
        }
        if (node.source_start > 0) prevc = source[node.source_start - 1];
        source_txt = source.substr(node.source_start, node.source_length);
    }
    wchar_t prevc_str[4] = {prevc, 0, 0, 0};
    wchar_t nextc_str[4] = {nextc, 0, 0, 0};
    if (prevc < L' ') {
        prevc_str[0] = L'\\';
        prevc_str[1] = L'c';
        prevc_str[2] = prevc + '@';
    }
    if (nextc < L' ') {
        nextc_str[0] = L'\\';
        nextc_str[1] = L'c';
        nextc_str[2] = nextc + '@';
    }
    fwprintf(stderr, L"{off %4u, len %4u, indent %2u, kw %ls, %ls} [%ls|%ls|%ls]\n",
             node.source_start, node.source_length, node_indent, keyword_description(node.keyword),
             token_type_description(node.type), prevc_str, source_txt.c_str(), nextc_str);
}
Ejemplo n.º 2
0
// Dump a parse tree node in a form helpful to someone debugging the behavior of this program.
static void dump_node(indent_t node_indent, const parse_node_t &node, const wcstring &source)
{
    int nextc_idx = node.source_start + node.source_length;
    wchar_t prevc = node.source_start > 0 ? source[node.source_start - 1] : L' ';
    wchar_t nextc = nextc_idx < source.size() ? source[nextc_idx] : L' ';
    wchar_t prevc_str[4] = {prevc, 0, 0, 0};
    wchar_t nextc_str[4] = {nextc, 0, 0, 0};
    if (prevc < L' ')
    {
        prevc_str[0] = L'\\';
        prevc_str[1] = L'c';
        prevc_str[2] = prevc + '@';
    }
    if (nextc < L' ')
    {
        nextc_str[0] = L'\\';
        nextc_str[1] = L'c';
        nextc_str[2] = nextc + '@';
    }
    fwprintf(stderr, L"{off %4d, len %4d, indent %2u, kw %ls, %ls} [%ls|%ls|%ls]\n",
            node.source_start, node.source_length, node_indent,
            keyword_description(node.keyword), token_type_description(node.type),
            prevc_str, source.substr(node.source_start, node.source_length).c_str(), nextc_str);
}
Ejemplo n.º 3
0
static void prettify_node_recursive(const wcstring &source, const parse_node_tree_t &tree,
                                    node_offset_t node_idx, indent_t node_indent,
                                    parse_token_type_t parent_type, bool *has_new_line,
                                    wcstring *out_result, bool do_indent) {
    const parse_node_t &node = tree.at(node_idx);
    const parse_token_type_t node_type = node.type;
    const parse_token_type_t prev_node_type =
        node_idx > 0 ? tree.at(node_idx - 1).type : token_type_invalid;

    // Increment the indent if we are either a root job_list, or root case_item_list, or in an if or
    // while header (#1665).
    const bool is_root_job_list = node_type == symbol_job_list && parent_type != symbol_job_list;
    const bool is_root_case_list =
        node_type == symbol_case_item_list && parent_type != symbol_case_item_list;
    const bool is_if_while_header =
        (node_type == symbol_job_conjunction || node_type == symbol_andor_job_list) &&
        (parent_type == symbol_if_clause || parent_type == symbol_while_header);

    if (is_root_job_list || is_root_case_list || is_if_while_header) {
        node_indent += 1;
    }

    if (dump_parse_tree) dump_node(node_indent, node, source);

    if (node.has_comments())  // handle comments, which come before the text
    {
        auto comment_nodes = tree.comment_nodes_for_node(node);
        for (const auto &comment : comment_nodes) {
            append_whitespace(node_indent, do_indent, *has_new_line, out_result);
            auto source_range = comment.source_range();
            out_result->append(source, source_range->start, source_range->length);
        }
    }

    if (node_type == parse_token_type_end) {
        out_result->push_back(L'\n');
        *has_new_line = true;
    } else if ((node_type >= FIRST_PARSE_TOKEN_TYPE && node_type <= LAST_PARSE_TOKEN_TYPE) ||
               node_type == parse_special_type_parse_error) {
        if (node.keyword != parse_keyword_none) {
            append_whitespace(node_indent, do_indent, *has_new_line, out_result);
            out_result->append(keyword_description(node.keyword));
            *has_new_line = false;
        } else if (node.has_source()) {
            // Some type representing a particular token.
            if (prev_node_type != parse_token_type_redirection) {
                append_whitespace(node_indent, do_indent, *has_new_line, out_result);
            }
            out_result->append(source, node.source_start, node.source_length);
            *has_new_line = false;
        }
    }

    // Recurse to all our children.
    for (node_offset_t idx = 0; idx < node.child_count; idx++) {
        // Note: We pass our type to our child, which becomes its parent node type.
        // Note: While node.child_start could be -1 (NODE_OFFSET_INVALID) the addition is safe
        // because we won't execute this call in that case since node.child_count should be zero.
        prettify_node_recursive(source, tree, node.child_start + idx, node_indent, node_type,
                                has_new_line, out_result, do_indent);
    }
}