Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Tools/c-analyzer/c_parser/match.py
12 views
1
import re
2
3
from . import info as _info
4
from .parser._regexes import SIMPLE_TYPE
5
6
7
_KIND = _info.KIND
8
9
10
def match_storage(decl, expected):
11
default = _info.get_default_storage(decl)
12
#assert default
13
if expected is None:
14
expected = {default}
15
elif isinstance(expected, str):
16
expected = {expected or default}
17
elif not expected:
18
expected = _info.STORAGE
19
else:
20
expected = {v or default for v in expected}
21
storage = _info.get_effective_storage(decl, default=default)
22
return storage in expected
23
24
25
##################################
26
# decl matchers
27
28
def is_type_decl(item):
29
return _KIND.is_type_decl(item.kind)
30
31
32
def is_decl(item):
33
return _KIND.is_decl(item.kind)
34
35
36
def is_pots(typespec, *,
37
_regex=re.compile(rf'^{SIMPLE_TYPE}$', re.VERBOSE),
38
):
39
40
if not typespec:
41
return None
42
if type(typespec) is not str:
43
_, _, _, typespec, _ = _info.get_parsed_vartype(typespec)
44
return _regex.match(typespec) is not None
45
46
47
def is_funcptr(vartype):
48
if not vartype:
49
return None
50
_, _, _, _, abstract = _info.get_parsed_vartype(vartype)
51
return _is_funcptr(abstract)
52
53
54
def _is_funcptr(declstr):
55
if not declstr:
56
return None
57
# XXX Support "(<name>*)(".
58
return '(*)(' in declstr.replace(' ', '')
59
60
61
def is_forward_decl(decl):
62
if decl.kind is _KIND.TYPEDEF:
63
return False
64
elif is_type_decl(decl):
65
return not decl.data
66
elif decl.kind is _KIND.FUNCTION:
67
# XXX This doesn't work with ParsedItem.
68
return decl.signature.isforward
69
elif decl.kind is _KIND.VARIABLE:
70
# No var decls are considered forward (or all are...).
71
return False
72
else:
73
raise NotImplementedError(decl)
74
75
76
def can_have_symbol(decl):
77
return decl.kind in (_KIND.VARIABLE, _KIND.FUNCTION)
78
79
80
def has_external_symbol(decl):
81
if not can_have_symbol(decl):
82
return False
83
if _info.get_effective_storage(decl) != 'extern':
84
return False
85
if decl.kind is _KIND.FUNCTION:
86
return not decl.signature.isforward
87
else:
88
# It must be a variable, which can only be implicitly extern here.
89
return decl.storage != 'extern'
90
91
92
def has_internal_symbol(decl):
93
if not can_have_symbol(decl):
94
return False
95
return _info.get_actual_storage(decl) == 'static'
96
97
98
def is_external_reference(decl):
99
if not can_have_symbol(decl):
100
return False
101
# We have to check the declared storage rather tnan the effective.
102
if decl.storage != 'extern':
103
return False
104
if decl.kind is _KIND.FUNCTION:
105
return decl.signature.isforward
106
# Otherwise it's a variable.
107
return True
108
109
110
def is_local_var(decl):
111
if not decl.kind is _KIND.VARIABLE:
112
return False
113
return True if decl.parent else False
114
115
116
def is_global_var(decl):
117
if not decl.kind is _KIND.VARIABLE:
118
return False
119
return False if decl.parent else True
120
121
122
##################################
123
# filtering with matchers
124
125
def filter_by_kind(items, kind):
126
if kind == 'type':
127
kinds = _KIND._TYPE_DECLS
128
elif kind == 'decl':
129
kinds = _KIND._TYPE_DECLS
130
try:
131
okay = kind in _KIND
132
except TypeError:
133
kinds = set(kind)
134
else:
135
kinds = {kind} if okay else set(kind)
136
for item in items:
137
if item.kind in kinds:
138
yield item
139
140
141
##################################
142
# grouping with matchers
143
144
def group_by_category(decls, categories, *, ignore_non_match=True):
145
collated = {}
146
for decl in decls:
147
# Matchers should be mutually exclusive. (First match wins.)
148
for category, match in categories.items():
149
if match(decl):
150
if category not in collated:
151
collated[category] = [decl]
152
else:
153
collated[category].append(decl)
154
break
155
else:
156
if not ignore_non_match:
157
raise Exception(f'no match for {decl!r}')
158
return collated
159
160
161
def group_by_kind(items):
162
collated = {kind: [] for kind in _KIND}
163
for item in items:
164
try:
165
collated[item.kind].append(item)
166
except KeyError:
167
raise ValueError(f'unsupported kind in {item!r}')
168
return collated
169
170
171
def group_by_kinds(items):
172
# Collate into kind groups (decl, type, etc.).
173
collated = {_KIND.get_group(k): [] for k in _KIND}
174
for item in items:
175
group = _KIND.get_group(item.kind)
176
collated[group].append(item)
177
return collated
178
179