Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
ast_transforms.py165 linesDownload Raw Back to pycparser
1#------------------------------------------------------------------------------2# pycparser: ast_transforms.py3#4# Some utilities used by the parser to create a friendlier AST.5#6# Eli Bendersky [https://eli.thegreenplace.net/]7# License: BSD8#------------------------------------------------------------------------------9 10from . import c_ast11 12 13def fix_switch_cases(switch_node):14    """ The 'case' statements in a 'switch' come out of parsing with one15        child node, so subsequent statements are just tucked to the parent16        Compound. Additionally, consecutive (fall-through) case statements17        come out messy. This is a peculiarity of the C grammar. The following:18 19            switch (myvar) {20                case 10:21                    k = 10;22                    p = k + 1;23                    return 10;24                case 20:25                case 30:26                    return 20;27                default:28                    break;29            }30 31        Creates this tree (pseudo-dump):32 33            Switch34                ID: myvar35                Compound:36                    Case 10:37                        k = 1038                    p = k + 139                    return 1040                    Case 20:41                        Case 30:42                            return 2043                    Default:44                        break45 46        The goal of this transform is to fix this mess, turning it into the47        following:48 49            Switch50                ID: myvar51                Compound:52                    Case 10:53                        k = 1054                        p = k + 155                        return 1056                    Case 20:57                    Case 30:58                        return 2059                    Default:60                        break61 62        A fixed AST node is returned. The argument may be modified.63    """64    assert isinstance(switch_node, c_ast.Switch)65    if not isinstance(switch_node.stmt, c_ast.Compound):66        return switch_node67 68    # The new Compound child for the Switch, which will collect children in the69    # correct order70    new_compound = c_ast.Compound([], switch_node.stmt.coord)71 72    # The last Case/Default node73    last_case = None74 75    # Goes over the children of the Compound below the Switch, adding them76    # either directly below new_compound or below the last Case as appropriate77    # (for `switch(cond) {}`, block_items would have been None)78    for child in (switch_node.stmt.block_items or []):79        if isinstance(child, (c_ast.Case, c_ast.Default)):80            # If it's a Case/Default:81            # 1. Add it to the Compound and mark as "last case"82            # 2. If its immediate child is also a Case or Default, promote it83            #    to a sibling.84            new_compound.block_items.append(child)85            _extract_nested_case(child, new_compound.block_items)86            last_case = new_compound.block_items[-1]87        else:88            # Other statements are added as children to the last case, if it89            # exists.90            if last_case is None:91                new_compound.block_items.append(child)92            else:93                last_case.stmts.append(child)94 95    switch_node.stmt = new_compound96    return switch_node97 98 99def _extract_nested_case(case_node, stmts_list):100    """ Recursively extract consecutive Case statements that are made nested101        by the parser and add them to the stmts_list.102    """103    if isinstance(case_node.stmts[0], (c_ast.Case, c_ast.Default)):104        stmts_list.append(case_node.stmts.pop())105        _extract_nested_case(stmts_list[-1], stmts_list)106 107 108def fix_atomic_specifiers(decl):109    """ Atomic specifiers like _Atomic(type) are unusually structured,110        conferring a qualifier upon the contained type.111 112        This function fixes a decl with atomic specifiers to have a sane AST113        structure, by removing spurious Typename->TypeDecl pairs and attaching114        the _Atomic qualifier in the right place.115    """116    # There can be multiple levels of _Atomic in a decl; fix them until a117    # fixed point is reached.118    while True:119        decl, found = _fix_atomic_specifiers_once(decl)120        if not found:121            break122 123    # Make sure to add an _Atomic qual on the topmost decl if needed. Also124    # restore the declname on the innermost TypeDecl (it gets placed in the125    # wrong place during construction).126    typ = decl127    while not isinstance(typ, c_ast.TypeDecl):128        try:129            typ = typ.type130        except AttributeError:131            return decl132    if '_Atomic' in typ.quals and '_Atomic' not in decl.quals:133        decl.quals.append('_Atomic')134    if typ.declname is None:135        typ.declname = decl.name136 137    return decl138 139 140def _fix_atomic_specifiers_once(decl):141    """ Performs one 'fix' round of atomic specifiers.142        Returns (modified_decl, found) where found is True iff a fix was made.143    """144    parent = decl145    grandparent = None146    node = decl.type147    while node is not None:148        if isinstance(node, c_ast.Typename) and '_Atomic' in node.quals:149            break150        try:151            grandparent = parent152            parent = node153            node = node.type154        except AttributeError:155            # If we've reached a node without a `type` field, it means we won't156            # find what we're looking for at this point; give up the search157            # and return the original decl unmodified.158            return decl, False159 160    assert isinstance(parent, c_ast.TypeDecl)161    grandparent.type = node.type162    if '_Atomic' not in node.type.quals:163        node.type.quals.append('_Atomic')164    return decl, True165 
codekingpro/portable-devtools · Team Ai