Sphinx 8.1.3__py3-none-any.whl → 8.2.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +8 -4
- sphinx/__main__.py +2 -0
- sphinx/_cli/__init__.py +2 -5
- sphinx/_cli/util/colour.py +34 -11
- sphinx/_cli/util/errors.py +128 -61
- sphinx/addnodes.py +51 -35
- sphinx/application.py +362 -230
- sphinx/builders/__init__.py +87 -64
- sphinx/builders/_epub_base.py +65 -56
- sphinx/builders/changes.py +17 -23
- sphinx/builders/dirhtml.py +8 -13
- sphinx/builders/epub3.py +70 -38
- sphinx/builders/gettext.py +93 -73
- sphinx/builders/html/__init__.py +240 -186
- sphinx/builders/html/_assets.py +9 -2
- sphinx/builders/html/_build_info.py +3 -0
- sphinx/builders/latex/__init__.py +64 -54
- sphinx/builders/latex/constants.py +14 -11
- sphinx/builders/latex/nodes.py +2 -0
- sphinx/builders/latex/theming.py +8 -9
- sphinx/builders/latex/transforms.py +7 -5
- sphinx/builders/linkcheck.py +193 -149
- sphinx/builders/manpage.py +17 -17
- sphinx/builders/singlehtml.py +28 -16
- sphinx/builders/texinfo.py +28 -21
- sphinx/builders/text.py +10 -15
- sphinx/builders/xml.py +10 -19
- sphinx/cmd/build.py +49 -119
- sphinx/cmd/make_mode.py +35 -31
- sphinx/cmd/quickstart.py +78 -62
- sphinx/config.py +265 -163
- sphinx/directives/__init__.py +51 -54
- sphinx/directives/admonitions.py +107 -0
- sphinx/directives/code.py +24 -19
- sphinx/directives/other.py +21 -42
- sphinx/directives/patches.py +28 -16
- sphinx/domains/__init__.py +54 -31
- sphinx/domains/_domains_container.py +22 -17
- sphinx/domains/_index.py +5 -8
- sphinx/domains/c/__init__.py +366 -245
- sphinx/domains/c/_ast.py +378 -256
- sphinx/domains/c/_ids.py +89 -31
- sphinx/domains/c/_parser.py +283 -214
- sphinx/domains/c/_symbol.py +269 -198
- sphinx/domains/changeset.py +39 -24
- sphinx/domains/citation.py +54 -24
- sphinx/domains/cpp/__init__.py +517 -362
- sphinx/domains/cpp/_ast.py +999 -682
- sphinx/domains/cpp/_ids.py +133 -65
- sphinx/domains/cpp/_parser.py +746 -588
- sphinx/domains/cpp/_symbol.py +692 -489
- sphinx/domains/index.py +10 -8
- sphinx/domains/javascript.py +152 -74
- sphinx/domains/math.py +48 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +114 -57
- sphinx/domains/python/_object.py +151 -67
- sphinx/domains/rst.py +94 -49
- sphinx/domains/std/__init__.py +510 -249
- sphinx/environment/__init__.py +345 -61
- sphinx/environment/adapters/asset.py +7 -1
- sphinx/environment/adapters/indexentries.py +15 -20
- sphinx/environment/adapters/toctree.py +19 -9
- sphinx/environment/collectors/__init__.py +3 -1
- sphinx/environment/collectors/asset.py +18 -15
- sphinx/environment/collectors/dependencies.py +8 -10
- sphinx/environment/collectors/metadata.py +6 -4
- sphinx/environment/collectors/title.py +3 -1
- sphinx/environment/collectors/toctree.py +4 -4
- sphinx/errors.py +1 -3
- sphinx/events.py +4 -4
- sphinx/ext/apidoc/__init__.py +21 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +66 -0
- sphinx/ext/autodoc/__init__.py +829 -480
- sphinx/ext/autodoc/directive.py +57 -21
- sphinx/ext/autodoc/importer.py +184 -67
- sphinx/ext/autodoc/mock.py +25 -10
- sphinx/ext/autodoc/preserve_defaults.py +17 -9
- sphinx/ext/autodoc/type_comment.py +56 -29
- sphinx/ext/autodoc/typehints.py +49 -26
- sphinx/ext/autosectionlabel.py +28 -11
- sphinx/ext/autosummary/__init__.py +271 -143
- sphinx/ext/autosummary/generate.py +121 -51
- sphinx/ext/coverage.py +152 -91
- sphinx/ext/doctest.py +169 -101
- sphinx/ext/duration.py +12 -6
- sphinx/ext/extlinks.py +33 -21
- sphinx/ext/githubpages.py +8 -8
- sphinx/ext/graphviz.py +175 -109
- sphinx/ext/ifconfig.py +11 -6
- sphinx/ext/imgconverter.py +48 -25
- sphinx/ext/imgmath.py +127 -97
- sphinx/ext/inheritance_diagram.py +177 -103
- sphinx/ext/intersphinx/__init__.py +22 -13
- sphinx/ext/intersphinx/__main__.py +3 -1
- sphinx/ext/intersphinx/_cli.py +18 -14
- sphinx/ext/intersphinx/_load.py +91 -82
- sphinx/ext/intersphinx/_resolve.py +108 -74
- sphinx/ext/intersphinx/_shared.py +2 -2
- sphinx/ext/linkcode.py +28 -12
- sphinx/ext/mathjax.py +60 -29
- sphinx/ext/napoleon/__init__.py +19 -7
- sphinx/ext/napoleon/docstring.py +229 -231
- sphinx/ext/todo.py +44 -49
- sphinx/ext/viewcode.py +105 -57
- sphinx/extension.py +3 -1
- sphinx/highlighting.py +13 -7
- sphinx/io.py +9 -13
- sphinx/jinja2glue.py +29 -26
- sphinx/locale/__init__.py +8 -9
- sphinx/parsers.py +8 -7
- sphinx/project.py +2 -2
- sphinx/pycode/__init__.py +31 -21
- sphinx/pycode/ast.py +6 -3
- sphinx/pycode/parser.py +14 -8
- sphinx/pygments_styles.py +4 -5
- sphinx/registry.py +192 -92
- sphinx/roles.py +58 -7
- sphinx/search/__init__.py +75 -54
- sphinx/search/en.py +11 -13
- sphinx/search/fi.py +1 -1
- sphinx/search/ja.py +8 -6
- sphinx/search/nl.py +1 -1
- sphinx/search/zh.py +19 -21
- sphinx/testing/fixtures.py +26 -29
- sphinx/testing/path.py +26 -62
- sphinx/testing/restructuredtext.py +14 -8
- sphinx/testing/util.py +21 -19
- sphinx/texinputs/make.bat.jinja +50 -50
- sphinx/texinputs/sphinx.sty +4 -3
- sphinx/texinputs/sphinxlatexadmonitions.sty +1 -1
- sphinx/texinputs/sphinxlatexobjects.sty +29 -10
- sphinx/themes/basic/static/searchtools.js +8 -5
- sphinx/theming.py +49 -61
- sphinx/transforms/__init__.py +17 -38
- sphinx/transforms/compact_bullet_list.py +5 -3
- sphinx/transforms/i18n.py +8 -21
- sphinx/transforms/post_transforms/__init__.py +142 -93
- sphinx/transforms/post_transforms/code.py +5 -5
- sphinx/transforms/post_transforms/images.py +28 -24
- sphinx/transforms/references.py +3 -1
- sphinx/util/__init__.py +109 -60
- sphinx/util/_files.py +39 -23
- sphinx/util/_importer.py +4 -1
- sphinx/util/_inventory_file_reader.py +76 -0
- sphinx/util/_io.py +2 -2
- sphinx/util/_lines.py +6 -3
- sphinx/util/_pathlib.py +40 -2
- sphinx/util/build_phase.py +2 -0
- sphinx/util/cfamily.py +19 -14
- sphinx/util/console.py +44 -179
- sphinx/util/display.py +9 -10
- sphinx/util/docfields.py +140 -122
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +118 -77
- sphinx/util/fileutil.py +25 -26
- sphinx/util/http_date.py +2 -0
- sphinx/util/i18n.py +77 -64
- sphinx/util/images.py +8 -6
- sphinx/util/inspect.py +147 -38
- sphinx/util/inventory.py +215 -116
- sphinx/util/logging.py +33 -33
- sphinx/util/matching.py +12 -4
- sphinx/util/nodes.py +18 -13
- sphinx/util/osutil.py +38 -39
- sphinx/util/parallel.py +22 -13
- sphinx/util/parsing.py +2 -1
- sphinx/util/png.py +6 -2
- sphinx/util/requests.py +33 -2
- sphinx/util/rst.py +3 -2
- sphinx/util/tags.py +1 -1
- sphinx/util/template.py +18 -10
- sphinx/util/texescape.py +8 -6
- sphinx/util/typing.py +148 -122
- sphinx/versioning.py +3 -3
- sphinx/writers/html.py +3 -1
- sphinx/writers/html5.py +61 -50
- sphinx/writers/latex.py +80 -65
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +44 -45
- sphinx/writers/text.py +48 -30
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/METADATA +23 -15
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/RECORD +190 -186
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/WHEEL +1 -1
- sphinx/builders/html/transforms.py +0 -90
- sphinx/ext/apidoc.py +0 -721
- sphinx/util/exceptions.py +0 -74
- {sphinx-8.1.3.dist-info → sphinx-8.2.0rc1.dist-info}/entry_points.txt +0 -0
sphinx/domains/c/_parser.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from sphinx.domains.c._ast import (
|
|
6
6
|
ASTAlignofExpr,
|
|
@@ -12,7 +12,6 @@ from sphinx.domains.c._ast import (
|
|
|
12
12
|
ASTCastExpr,
|
|
13
13
|
ASTCharLiteral,
|
|
14
14
|
ASTDeclaration,
|
|
15
|
-
ASTDeclarator,
|
|
16
15
|
ASTDeclaratorNameBitField,
|
|
17
16
|
ASTDeclaratorNameParam,
|
|
18
17
|
ASTDeclaratorParen,
|
|
@@ -21,13 +20,11 @@ from sphinx.domains.c._ast import (
|
|
|
21
20
|
ASTDeclSpecsSimple,
|
|
22
21
|
ASTEnum,
|
|
23
22
|
ASTEnumerator,
|
|
24
|
-
ASTExpression,
|
|
25
23
|
ASTFallbackExpr,
|
|
26
24
|
ASTFunctionParameter,
|
|
27
25
|
ASTIdentifier,
|
|
28
26
|
ASTIdExpression,
|
|
29
27
|
ASTInitializer,
|
|
30
|
-
ASTLiteral,
|
|
31
28
|
ASTMacro,
|
|
32
29
|
ASTMacroParameter,
|
|
33
30
|
ASTNestedName,
|
|
@@ -41,12 +38,10 @@ from sphinx.domains.c._ast import (
|
|
|
41
38
|
ASTPostfixExpr,
|
|
42
39
|
ASTPostfixInc,
|
|
43
40
|
ASTPostfixMemberOfPointer,
|
|
44
|
-
ASTPostfixOp,
|
|
45
41
|
ASTSizeofExpr,
|
|
46
42
|
ASTSizeofType,
|
|
47
43
|
ASTStringLiteral,
|
|
48
44
|
ASTStruct,
|
|
49
|
-
ASTTrailingTypeSpec,
|
|
50
45
|
ASTTrailingTypeSpecFundamental,
|
|
51
46
|
ASTTrailingTypeSpecName,
|
|
52
47
|
ASTType,
|
|
@@ -80,8 +75,16 @@ from sphinx.util.cfamily import (
|
|
|
80
75
|
|
|
81
76
|
if TYPE_CHECKING:
|
|
82
77
|
from collections.abc import Callable, Sequence
|
|
78
|
+
from typing import Any
|
|
83
79
|
|
|
84
|
-
from sphinx.domains.c._ast import
|
|
80
|
+
from sphinx.domains.c._ast import (
|
|
81
|
+
ASTDeclarator,
|
|
82
|
+
ASTExpression,
|
|
83
|
+
ASTLiteral,
|
|
84
|
+
ASTPostfixOp,
|
|
85
|
+
ASTTrailingTypeSpec,
|
|
86
|
+
DeclarationType,
|
|
87
|
+
)
|
|
85
88
|
|
|
86
89
|
|
|
87
90
|
class DefinitionParser(BaseParser):
|
|
@@ -100,12 +103,12 @@ class DefinitionParser(BaseParser):
|
|
|
100
103
|
def _parse_string(self) -> str | None:
|
|
101
104
|
if self.current_char != '"':
|
|
102
105
|
return None
|
|
103
|
-
|
|
106
|
+
start_pos = self.pos
|
|
104
107
|
self.pos += 1
|
|
105
108
|
escape = False
|
|
106
109
|
while True:
|
|
107
110
|
if self.eof:
|
|
108
|
-
self.fail(
|
|
111
|
+
self.fail('Unexpected end during inside string.')
|
|
109
112
|
elif self.current_char == '"' and not escape:
|
|
110
113
|
self.pos += 1
|
|
111
114
|
break
|
|
@@ -114,7 +117,7 @@ class DefinitionParser(BaseParser):
|
|
|
114
117
|
else:
|
|
115
118
|
escape = False
|
|
116
119
|
self.pos += 1
|
|
117
|
-
return self.definition[
|
|
120
|
+
return self.definition[start_pos : self.pos]
|
|
118
121
|
|
|
119
122
|
def _parse_literal(self) -> ASTLiteral | None:
|
|
120
123
|
# -> integer-literal
|
|
@@ -130,12 +133,16 @@ class DefinitionParser(BaseParser):
|
|
|
130
133
|
pos = self.pos
|
|
131
134
|
if self.match(float_literal_re):
|
|
132
135
|
self.match(float_literal_suffix_re)
|
|
133
|
-
return ASTNumberLiteral(self.definition[pos:self.pos])
|
|
134
|
-
for regex in (
|
|
135
|
-
|
|
136
|
+
return ASTNumberLiteral(self.definition[pos : self.pos])
|
|
137
|
+
for regex in (
|
|
138
|
+
binary_literal_re,
|
|
139
|
+
hex_literal_re,
|
|
140
|
+
integer_literal_re,
|
|
141
|
+
octal_literal_re,
|
|
142
|
+
):
|
|
136
143
|
if self.match(regex):
|
|
137
144
|
self.match(integers_literal_suffix_re)
|
|
138
|
-
return ASTNumberLiteral(self.definition[pos:self.pos])
|
|
145
|
+
return ASTNumberLiteral(self.definition[pos : self.pos])
|
|
139
146
|
|
|
140
147
|
string = self._parse_string()
|
|
141
148
|
if string is not None:
|
|
@@ -148,10 +155,14 @@ class DefinitionParser(BaseParser):
|
|
|
148
155
|
try:
|
|
149
156
|
return ASTCharLiteral(prefix, data)
|
|
150
157
|
except UnicodeDecodeError as e:
|
|
151
|
-
self.fail(
|
|
158
|
+
self.fail(
|
|
159
|
+
'Can not handle character literal. Internal error was: %s' % e
|
|
160
|
+
)
|
|
152
161
|
except UnsupportedMultiCharacterCharLiteral:
|
|
153
|
-
self.fail(
|
|
154
|
-
|
|
162
|
+
self.fail(
|
|
163
|
+
'Can not handle character literal'
|
|
164
|
+
' resulting in multiple decoded characters.'
|
|
165
|
+
)
|
|
155
166
|
return None
|
|
156
167
|
|
|
157
168
|
def _parse_paren_expression(self) -> ASTExpression | None:
|
|
@@ -181,8 +192,9 @@ class DefinitionParser(BaseParser):
|
|
|
181
192
|
return ASTIdExpression(nn)
|
|
182
193
|
return None
|
|
183
194
|
|
|
184
|
-
def _parse_initializer_list(
|
|
185
|
-
|
|
195
|
+
def _parse_initializer_list(
|
|
196
|
+
self, name: str, open: str, close: str
|
|
197
|
+
) -> tuple[list[ASTExpression] | None, bool | None]:
|
|
186
198
|
# Parse open and close with the actual initializer-list in between
|
|
187
199
|
# -> initializer-clause '...'[opt]
|
|
188
200
|
# | initializer-list ',' initializer-clause '...'[opt]
|
|
@@ -194,7 +206,7 @@ class DefinitionParser(BaseParser):
|
|
|
194
206
|
return [], False
|
|
195
207
|
|
|
196
208
|
exprs = []
|
|
197
|
-
|
|
209
|
+
trailing_comma = False
|
|
198
210
|
while True:
|
|
199
211
|
self.skip_ws()
|
|
200
212
|
expr = self._parse_expression()
|
|
@@ -207,9 +219,9 @@ class DefinitionParser(BaseParser):
|
|
|
207
219
|
self.fail(f"Error in {name}, expected ',' or '{close}'.")
|
|
208
220
|
if self.current_char == close == '}':
|
|
209
221
|
self.pos += 1
|
|
210
|
-
|
|
222
|
+
trailing_comma = True
|
|
211
223
|
break
|
|
212
|
-
return exprs,
|
|
224
|
+
return exprs, trailing_comma
|
|
213
225
|
|
|
214
226
|
def _parse_paren_expression_list(self) -> ASTParenExprList | None:
|
|
215
227
|
# -> '(' expression-list ')'
|
|
@@ -218,8 +230,9 @@ class DefinitionParser(BaseParser):
|
|
|
218
230
|
#
|
|
219
231
|
# expression-list
|
|
220
232
|
# -> initializer-list
|
|
221
|
-
exprs,
|
|
222
|
-
|
|
233
|
+
exprs, trailing_comma = self._parse_initializer_list(
|
|
234
|
+
'parenthesized expression-list', '(', ')'
|
|
235
|
+
)
|
|
223
236
|
if exprs is None:
|
|
224
237
|
return None
|
|
225
238
|
return ASTParenExprList(exprs)
|
|
@@ -227,10 +240,12 @@ class DefinitionParser(BaseParser):
|
|
|
227
240
|
def _parse_braced_init_list(self) -> ASTBracedInitList | None:
|
|
228
241
|
# -> '{' initializer-list ','[opt] '}'
|
|
229
242
|
# | '{' '}'
|
|
230
|
-
exprs,
|
|
243
|
+
exprs, trailing_comma = self._parse_initializer_list(
|
|
244
|
+
'braced-init-list', '{', '}'
|
|
245
|
+
)
|
|
231
246
|
if exprs is None:
|
|
232
247
|
return None
|
|
233
|
-
return ASTBracedInitList(exprs,
|
|
248
|
+
return ASTBracedInitList(exprs, trailing_comma)
|
|
234
249
|
|
|
235
250
|
def _parse_postfix_expression(self) -> ASTPostfixExpr:
|
|
236
251
|
# -> primary
|
|
@@ -245,7 +260,7 @@ class DefinitionParser(BaseParser):
|
|
|
245
260
|
prefix = self._parse_primary_expression()
|
|
246
261
|
|
|
247
262
|
# and now parse postfixes
|
|
248
|
-
|
|
263
|
+
post_fixes: list[ASTPostfixOp] = []
|
|
249
264
|
while True:
|
|
250
265
|
self.skip_ws()
|
|
251
266
|
if self.skip_string_and_ws('['):
|
|
@@ -253,7 +268,7 @@ class DefinitionParser(BaseParser):
|
|
|
253
268
|
self.skip_ws()
|
|
254
269
|
if not self.skip_string(']'):
|
|
255
270
|
self.fail("Expected ']' in end of postfix expression.")
|
|
256
|
-
|
|
271
|
+
post_fixes.append(ASTPostfixArray(expr))
|
|
257
272
|
continue
|
|
258
273
|
if self.skip_string('->'):
|
|
259
274
|
if self.skip_string('*'):
|
|
@@ -261,20 +276,20 @@ class DefinitionParser(BaseParser):
|
|
|
261
276
|
self.pos -= 3
|
|
262
277
|
else:
|
|
263
278
|
name = self._parse_nested_name()
|
|
264
|
-
|
|
279
|
+
post_fixes.append(ASTPostfixMemberOfPointer(name))
|
|
265
280
|
continue
|
|
266
281
|
if self.skip_string('++'):
|
|
267
|
-
|
|
282
|
+
post_fixes.append(ASTPostfixInc())
|
|
268
283
|
continue
|
|
269
284
|
if self.skip_string('--'):
|
|
270
|
-
|
|
285
|
+
post_fixes.append(ASTPostfixDec())
|
|
271
286
|
continue
|
|
272
287
|
lst = self._parse_paren_expression_list()
|
|
273
288
|
if lst is not None:
|
|
274
|
-
|
|
289
|
+
post_fixes.append(ASTPostfixCallExpr(lst))
|
|
275
290
|
continue
|
|
276
291
|
break
|
|
277
|
-
return ASTPostfixExpr(prefix,
|
|
292
|
+
return ASTPostfixExpr(prefix, post_fixes)
|
|
278
293
|
|
|
279
294
|
def _parse_unary_expression(self) -> ASTExpression:
|
|
280
295
|
# -> postfix
|
|
@@ -325,16 +340,18 @@ class DefinitionParser(BaseParser):
|
|
|
325
340
|
self.fail("Expected ')' in cast expression.")
|
|
326
341
|
expr = self._parse_cast_expression()
|
|
327
342
|
return ASTCastExpr(typ, expr)
|
|
328
|
-
except DefinitionError as
|
|
343
|
+
except DefinitionError as ex_cast:
|
|
329
344
|
self.pos = pos
|
|
330
345
|
try:
|
|
331
346
|
return self._parse_unary_expression()
|
|
332
|
-
except DefinitionError as
|
|
333
|
-
errs = [
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
347
|
+
except DefinitionError as ex_unary:
|
|
348
|
+
errs = [
|
|
349
|
+
(ex_cast, 'If type cast expression'),
|
|
350
|
+
(ex_unary, 'If unary expression'),
|
|
351
|
+
]
|
|
352
|
+
raise self._make_multi_error(
|
|
353
|
+
errs, 'Error in cast expression.'
|
|
354
|
+
) from ex_unary
|
|
338
355
|
else:
|
|
339
356
|
return self._parse_unary_expression()
|
|
340
357
|
|
|
@@ -350,21 +367,25 @@ class DefinitionParser(BaseParser):
|
|
|
350
367
|
# additive = multiplicative +, -
|
|
351
368
|
# multiplicative = pm *, /, %
|
|
352
369
|
# pm = cast .*, ->*
|
|
353
|
-
def _parse_bin_op_expr(self: DefinitionParser,
|
|
354
|
-
if
|
|
370
|
+
def _parse_bin_op_expr(self: DefinitionParser, op_id: int) -> ASTExpression:
|
|
371
|
+
if op_id + 1 == len(_expression_bin_ops):
|
|
372
|
+
|
|
355
373
|
def parser() -> ASTExpression:
|
|
356
374
|
return self._parse_cast_expression()
|
|
375
|
+
|
|
357
376
|
else:
|
|
377
|
+
|
|
358
378
|
def parser() -> ASTExpression:
|
|
359
|
-
return _parse_bin_op_expr(self,
|
|
379
|
+
return _parse_bin_op_expr(self, op_id + 1)
|
|
380
|
+
|
|
360
381
|
exprs = []
|
|
361
382
|
ops = []
|
|
362
383
|
exprs.append(parser())
|
|
363
384
|
while True:
|
|
364
385
|
self.skip_ws()
|
|
365
386
|
pos = self.pos
|
|
366
|
-
|
|
367
|
-
for op in _expression_bin_ops[
|
|
387
|
+
one_more = False
|
|
388
|
+
for op in _expression_bin_ops[op_id]:
|
|
368
389
|
if op[0] in 'abcnox':
|
|
369
390
|
if not self.skip_word(op):
|
|
370
391
|
continue
|
|
@@ -380,16 +401,19 @@ class DefinitionParser(BaseParser):
|
|
|
380
401
|
expr = parser()
|
|
381
402
|
exprs.append(expr)
|
|
382
403
|
ops.append(op)
|
|
383
|
-
|
|
404
|
+
one_more = True
|
|
384
405
|
break
|
|
385
406
|
except DefinitionError:
|
|
386
407
|
self.pos = pos
|
|
387
|
-
if not
|
|
408
|
+
if not one_more:
|
|
388
409
|
break
|
|
389
410
|
return ASTBinOpExpr(exprs, ops) # type: ignore[return-value]
|
|
411
|
+
|
|
390
412
|
return _parse_bin_op_expr(self, 0)
|
|
391
413
|
|
|
392
|
-
def _parse_conditional_expression_tail(
|
|
414
|
+
def _parse_conditional_expression_tail(
|
|
415
|
+
self, or_expr_head: Any
|
|
416
|
+
) -> ASTExpression | None:
|
|
393
417
|
# -> "?" expression ":" assignment-expression
|
|
394
418
|
return None
|
|
395
419
|
|
|
@@ -402,11 +426,11 @@ class DefinitionParser(BaseParser):
|
|
|
402
426
|
# | logical-or-expression assignment-operator initializer-clause
|
|
403
427
|
exprs = []
|
|
404
428
|
ops = []
|
|
405
|
-
|
|
406
|
-
exprs.append(
|
|
429
|
+
or_expr = self._parse_logical_or_expression()
|
|
430
|
+
exprs.append(or_expr)
|
|
407
431
|
# TODO: handle ternary with _parse_conditional_expression_tail
|
|
408
432
|
while True:
|
|
409
|
-
|
|
433
|
+
one_more = False
|
|
410
434
|
self.skip_ws()
|
|
411
435
|
for op in _expression_assignment_ops:
|
|
412
436
|
if op[0] in 'abcnox':
|
|
@@ -418,16 +442,16 @@ class DefinitionParser(BaseParser):
|
|
|
418
442
|
expr = self._parse_logical_or_expression()
|
|
419
443
|
exprs.append(expr)
|
|
420
444
|
ops.append(op)
|
|
421
|
-
|
|
422
|
-
if not
|
|
445
|
+
one_more = True
|
|
446
|
+
if not one_more:
|
|
423
447
|
break
|
|
424
448
|
return ASTAssignmentExpr(exprs, ops)
|
|
425
449
|
|
|
426
450
|
def _parse_constant_expression(self) -> ASTExpression:
|
|
427
451
|
# -> conditional-expression
|
|
428
|
-
|
|
452
|
+
or_expr = self._parse_logical_or_expression()
|
|
429
453
|
# TODO: use _parse_conditional_expression_tail
|
|
430
|
-
return
|
|
454
|
+
return or_expr
|
|
431
455
|
|
|
432
456
|
def _parse_expression(self) -> ASTExpression:
|
|
433
457
|
# -> assignment-expression
|
|
@@ -436,14 +460,13 @@ class DefinitionParser(BaseParser):
|
|
|
436
460
|
return self._parse_assignment_expression()
|
|
437
461
|
|
|
438
462
|
def _parse_expression_fallback(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
allow: bool = True) -> ASTExpression:
|
|
463
|
+
self, end: list[str], parser: Callable[[], ASTExpression], allow: bool = True
|
|
464
|
+
) -> ASTExpression:
|
|
442
465
|
# Stupidly "parse" an expression.
|
|
443
466
|
# 'end' should be a list of characters which ends the expression.
|
|
444
467
|
|
|
445
468
|
# first try to use the provided parser
|
|
446
|
-
|
|
469
|
+
prev_pos = self.pos
|
|
447
470
|
try:
|
|
448
471
|
return parser()
|
|
449
472
|
except DefinitionError as e:
|
|
@@ -451,13 +474,15 @@ class DefinitionParser(BaseParser):
|
|
|
451
474
|
# and for testing we may want to globally disable it
|
|
452
475
|
if not allow or not self.allowFallbackExpressionParsing:
|
|
453
476
|
raise
|
|
454
|
-
self.warn(
|
|
455
|
-
|
|
456
|
-
|
|
477
|
+
self.warn(
|
|
478
|
+
'Parsing of expression failed. Using fallback parser.'
|
|
479
|
+
' Error was:\n%s' % e
|
|
480
|
+
)
|
|
481
|
+
self.pos = prev_pos
|
|
457
482
|
# and then the fallback scanning
|
|
458
483
|
assert end is not None
|
|
459
484
|
self.skip_ws()
|
|
460
|
-
|
|
485
|
+
start_pos = self.pos
|
|
461
486
|
if self.match(_string_re):
|
|
462
487
|
value = self.matched_text
|
|
463
488
|
else:
|
|
@@ -465,7 +490,7 @@ class DefinitionParser(BaseParser):
|
|
|
465
490
|
brackets = {'(': ')', '{': '}', '[': ']'}
|
|
466
491
|
symbols: list[str] = []
|
|
467
492
|
while not self.eof:
|
|
468
|
-
if
|
|
493
|
+
if len(symbols) == 0 and self.current_char in end:
|
|
469
494
|
break
|
|
470
495
|
if self.current_char in brackets:
|
|
471
496
|
symbols.append(brackets[self.current_char])
|
|
@@ -473,9 +498,10 @@ class DefinitionParser(BaseParser):
|
|
|
473
498
|
symbols.pop()
|
|
474
499
|
self.pos += 1
|
|
475
500
|
if len(end) > 0 and self.eof:
|
|
476
|
-
self.fail(
|
|
477
|
-
|
|
478
|
-
|
|
501
|
+
self.fail(
|
|
502
|
+
'Could not find end of expression starting at %d.' % start_pos
|
|
503
|
+
)
|
|
504
|
+
value = self.definition[start_pos : self.pos].strip()
|
|
479
505
|
return ASTFallbackExpr(value.strip())
|
|
480
506
|
|
|
481
507
|
def _parse_nested_name(self) -> ASTNestedName:
|
|
@@ -488,20 +514,20 @@ class DefinitionParser(BaseParser):
|
|
|
488
514
|
while 1:
|
|
489
515
|
self.skip_ws()
|
|
490
516
|
if not self.match(identifier_re):
|
|
491
|
-
self.fail(
|
|
517
|
+
self.fail('Expected identifier in nested name.')
|
|
492
518
|
identifier = self.matched_text
|
|
493
519
|
# make sure there isn't a keyword
|
|
494
520
|
if identifier in _keywords:
|
|
495
|
-
self.fail(
|
|
496
|
-
|
|
521
|
+
self.fail(
|
|
522
|
+
'Expected identifier in nested name, got keyword: %s' % identifier
|
|
523
|
+
)
|
|
497
524
|
if self.matched_text in self.config.c_extra_keywords:
|
|
498
525
|
msg = (
|
|
499
526
|
'Expected identifier, got user-defined keyword: %s.'
|
|
500
527
|
' Remove it from c_extra_keywords to allow it as identifier.\n'
|
|
501
528
|
'Currently c_extra_keywords is %s.'
|
|
502
529
|
)
|
|
503
|
-
self.fail(msg % (self.matched_text,
|
|
504
|
-
str(self.config.c_extra_keywords)))
|
|
530
|
+
self.fail(msg % (self.matched_text, str(self.config.c_extra_keywords)))
|
|
505
531
|
ident = ASTIdentifier(identifier)
|
|
506
532
|
names.append(ident)
|
|
507
533
|
|
|
@@ -549,13 +575,13 @@ class DefinitionParser(BaseParser):
|
|
|
549
575
|
prefix = k
|
|
550
576
|
break
|
|
551
577
|
|
|
552
|
-
|
|
553
|
-
return ASTTrailingTypeSpecName(prefix,
|
|
578
|
+
nested_name = self._parse_nested_name()
|
|
579
|
+
return ASTTrailingTypeSpecName(prefix, nested_name)
|
|
554
580
|
|
|
555
|
-
def _parse_parameters(self,
|
|
581
|
+
def _parse_parameters(self, param_mode: str) -> ASTParameters | None:
|
|
556
582
|
self.skip_ws()
|
|
557
583
|
if not self.skip_string('('):
|
|
558
|
-
if
|
|
584
|
+
if param_mode == 'function':
|
|
559
585
|
self.fail('Expecting "(" in parameters.')
|
|
560
586
|
else:
|
|
561
587
|
return None
|
|
@@ -582,17 +608,19 @@ class DefinitionParser(BaseParser):
|
|
|
582
608
|
continue
|
|
583
609
|
if self.skip_string(')'):
|
|
584
610
|
break
|
|
585
|
-
self.fail(
|
|
611
|
+
self.fail(
|
|
612
|
+
f'Expecting "," or ")" in parameters, got "{self.current_char}".'
|
|
613
|
+
)
|
|
586
614
|
|
|
587
615
|
attrs = self._parse_attribute_list()
|
|
588
616
|
return ASTParameters(args, attrs)
|
|
589
617
|
|
|
590
618
|
def _parse_decl_specs_simple(
|
|
591
|
-
self, outer: str | None, typed: bool
|
|
619
|
+
self, outer: str | None, typed: bool
|
|
592
620
|
) -> ASTDeclSpecsSimple:
|
|
593
621
|
"""Just parse the simple ones."""
|
|
594
622
|
storage = None
|
|
595
|
-
|
|
623
|
+
thread_local = None
|
|
596
624
|
inline = None
|
|
597
625
|
restrict = None
|
|
598
626
|
volatile = None
|
|
@@ -608,19 +636,19 @@ class DefinitionParser(BaseParser):
|
|
|
608
636
|
if self.skip_word('register'):
|
|
609
637
|
storage = 'register'
|
|
610
638
|
continue
|
|
611
|
-
if outer in
|
|
639
|
+
if outer in {'member', 'function'}:
|
|
612
640
|
if self.skip_word('static'):
|
|
613
641
|
storage = 'static'
|
|
614
642
|
continue
|
|
615
643
|
if self.skip_word('extern'):
|
|
616
644
|
storage = 'extern'
|
|
617
645
|
continue
|
|
618
|
-
if outer == 'member' and not
|
|
646
|
+
if outer == 'member' and not thread_local:
|
|
619
647
|
if self.skip_word('thread_local'):
|
|
620
|
-
|
|
648
|
+
thread_local = 'thread_local'
|
|
621
649
|
continue
|
|
622
650
|
if self.skip_word('_Thread_local'):
|
|
623
|
-
|
|
651
|
+
thread_local = '_Thread_local'
|
|
624
652
|
continue
|
|
625
653
|
if outer == 'function' and not inline:
|
|
626
654
|
inline = self.skip_word('inline')
|
|
@@ -644,50 +672,59 @@ class DefinitionParser(BaseParser):
|
|
|
644
672
|
attrs.append(attr)
|
|
645
673
|
continue
|
|
646
674
|
break
|
|
647
|
-
return ASTDeclSpecsSimple(
|
|
648
|
-
|
|
675
|
+
return ASTDeclSpecsSimple(
|
|
676
|
+
storage,
|
|
677
|
+
thread_local,
|
|
678
|
+
inline,
|
|
679
|
+
restrict,
|
|
680
|
+
volatile,
|
|
681
|
+
const,
|
|
682
|
+
ASTAttributeList(attrs),
|
|
683
|
+
)
|
|
649
684
|
|
|
650
685
|
def _parse_decl_specs(self, outer: str | None, typed: bool = True) -> ASTDeclSpecs:
|
|
651
686
|
if outer:
|
|
652
|
-
if outer not in
|
|
687
|
+
if outer not in {'type', 'member', 'function'}:
|
|
653
688
|
raise Exception('Internal error, unknown outer "%s".' % outer)
|
|
654
|
-
|
|
655
|
-
|
|
689
|
+
left_specs = self._parse_decl_specs_simple(outer, typed)
|
|
690
|
+
right_specs = None
|
|
656
691
|
|
|
657
692
|
if typed:
|
|
658
693
|
trailing = self._parse_trailing_type_spec()
|
|
659
|
-
|
|
694
|
+
right_specs = self._parse_decl_specs_simple(outer, typed)
|
|
660
695
|
else:
|
|
661
696
|
trailing = None
|
|
662
|
-
return ASTDeclSpecs(outer,
|
|
697
|
+
return ASTDeclSpecs(outer, left_specs, right_specs, trailing)
|
|
663
698
|
|
|
664
699
|
def _parse_declarator_name_suffix(
|
|
665
|
-
|
|
700
|
+
self, named: bool | str, param_mode: str, typed: bool
|
|
666
701
|
) -> ASTDeclarator:
|
|
667
|
-
assert named in
|
|
702
|
+
assert named in {True, False, 'single'}
|
|
668
703
|
# now we should parse the name, and then suffixes
|
|
669
704
|
if named == 'single':
|
|
670
705
|
if self.match(identifier_re):
|
|
671
706
|
if self.matched_text in _keywords:
|
|
672
|
-
self.fail(
|
|
673
|
-
|
|
707
|
+
self.fail(
|
|
708
|
+
'Expected identifier, got keyword: %s' % self.matched_text
|
|
709
|
+
)
|
|
674
710
|
if self.matched_text in self.config.c_extra_keywords:
|
|
675
711
|
msg = (
|
|
676
712
|
'Expected identifier, got user-defined keyword: %s. '
|
|
677
713
|
'Remove it from c_extra_keywords to allow it as identifier.\n'
|
|
678
714
|
'Currently c_extra_keywords is %s.'
|
|
679
715
|
)
|
|
680
|
-
self.fail(
|
|
681
|
-
|
|
716
|
+
self.fail(
|
|
717
|
+
msg % (self.matched_text, str(self.config.c_extra_keywords))
|
|
718
|
+
)
|
|
682
719
|
identifier = ASTIdentifier(self.matched_text)
|
|
683
|
-
|
|
720
|
+
decl_id = ASTNestedName([identifier], rooted=False)
|
|
684
721
|
else:
|
|
685
|
-
|
|
722
|
+
decl_id = None
|
|
686
723
|
elif named:
|
|
687
|
-
|
|
724
|
+
decl_id = self._parse_nested_name()
|
|
688
725
|
else:
|
|
689
|
-
|
|
690
|
-
|
|
726
|
+
decl_id = None
|
|
727
|
+
array_ops = []
|
|
691
728
|
while 1:
|
|
692
729
|
self.skip_ws()
|
|
693
730
|
if typed and self.skip_string('['):
|
|
@@ -726,31 +763,31 @@ class DefinitionParser(BaseParser):
|
|
|
726
763
|
|
|
727
764
|
def parser() -> ASTExpression:
|
|
728
765
|
return self._parse_expression()
|
|
766
|
+
|
|
729
767
|
size = self._parse_expression_fallback([']'], parser)
|
|
730
768
|
self.skip_ws()
|
|
731
769
|
if not self.skip_string(']'):
|
|
732
770
|
self.fail("Expected ']' in end of array operator.")
|
|
733
|
-
|
|
771
|
+
array_ops.append(ASTArray(static, const, volatile, restrict, vla, size))
|
|
734
772
|
else:
|
|
735
773
|
break
|
|
736
|
-
param = self._parse_parameters(
|
|
737
|
-
if param is None and len(
|
|
774
|
+
param = self._parse_parameters(param_mode)
|
|
775
|
+
if param is None and len(array_ops) == 0:
|
|
738
776
|
# perhaps a bit-field
|
|
739
|
-
if named and
|
|
777
|
+
if named and param_mode == 'type' and typed:
|
|
740
778
|
self.skip_ws()
|
|
741
779
|
if self.skip_string(':'):
|
|
742
780
|
size = self._parse_constant_expression()
|
|
743
|
-
return ASTDeclaratorNameBitField(declId=
|
|
744
|
-
return ASTDeclaratorNameParam(declId=
|
|
745
|
-
param=param)
|
|
781
|
+
return ASTDeclaratorNameBitField(declId=decl_id, size=size)
|
|
782
|
+
return ASTDeclaratorNameParam(declId=decl_id, arrayOps=array_ops, param=param)
|
|
746
783
|
|
|
747
|
-
def _parse_declarator(
|
|
748
|
-
|
|
784
|
+
def _parse_declarator(
|
|
785
|
+
self, named: bool | str, param_mode: str, typed: bool = True
|
|
786
|
+
) -> ASTDeclarator:
|
|
749
787
|
# 'typed' here means 'parse return type stuff'
|
|
750
|
-
if
|
|
751
|
-
raise Exception(
|
|
752
|
-
|
|
753
|
-
prevErrors = []
|
|
788
|
+
if param_mode not in {'type', 'function'}:
|
|
789
|
+
raise Exception("Internal error, unknown param_mode '%s'." % param_mode)
|
|
790
|
+
prev_errors = []
|
|
754
791
|
self.skip_ws()
|
|
755
792
|
if typed and self.skip_string('*'):
|
|
756
793
|
self.skip_ws()
|
|
@@ -776,24 +813,27 @@ class DefinitionParser(BaseParser):
|
|
|
776
813
|
attrs.append(attr)
|
|
777
814
|
continue
|
|
778
815
|
break
|
|
779
|
-
next = self._parse_declarator(named,
|
|
780
|
-
return ASTDeclaratorPtr(
|
|
781
|
-
|
|
782
|
-
|
|
816
|
+
next = self._parse_declarator(named, param_mode, typed)
|
|
817
|
+
return ASTDeclaratorPtr(
|
|
818
|
+
next=next,
|
|
819
|
+
restrict=restrict,
|
|
820
|
+
volatile=volatile,
|
|
821
|
+
const=const,
|
|
822
|
+
attrs=ASTAttributeList(attrs),
|
|
823
|
+
)
|
|
783
824
|
if typed and self.current_char == '(': # note: peeking, not skipping
|
|
784
825
|
# maybe this is the beginning of params, try that first,
|
|
785
826
|
# otherwise assume it's noptr->declarator > ( ptr-declarator )
|
|
786
827
|
pos = self.pos
|
|
787
828
|
try:
|
|
788
829
|
# assume this is params
|
|
789
|
-
res = self._parse_declarator_name_suffix(named,
|
|
790
|
-
typed)
|
|
830
|
+
res = self._parse_declarator_name_suffix(named, param_mode, typed)
|
|
791
831
|
return res
|
|
792
|
-
except DefinitionError as
|
|
793
|
-
msg =
|
|
794
|
-
if
|
|
832
|
+
except DefinitionError as ex_param_qual:
|
|
833
|
+
msg = 'If declarator-id with parameters'
|
|
834
|
+
if param_mode == 'function':
|
|
795
835
|
msg += " (e.g., 'void f(int arg)')"
|
|
796
|
-
|
|
836
|
+
prev_errors.append((ex_param_qual, msg))
|
|
797
837
|
self.pos = pos
|
|
798
838
|
try:
|
|
799
839
|
assert self.current_char == '('
|
|
@@ -801,121 +841,128 @@ class DefinitionParser(BaseParser):
|
|
|
801
841
|
# TODO: hmm, if there is a name, it must be in inner, right?
|
|
802
842
|
# TODO: hmm, if there must be parameters, they must b
|
|
803
843
|
# inside, right?
|
|
804
|
-
inner = self._parse_declarator(named,
|
|
844
|
+
inner = self._parse_declarator(named, param_mode, typed)
|
|
805
845
|
if not self.skip_string(')'):
|
|
806
|
-
self.fail(
|
|
807
|
-
next = self._parse_declarator(
|
|
808
|
-
|
|
809
|
-
|
|
846
|
+
self.fail('Expected \')\' in "( ptr-declarator )"')
|
|
847
|
+
next = self._parse_declarator(
|
|
848
|
+
named=False, param_mode='type', typed=typed
|
|
849
|
+
)
|
|
810
850
|
return ASTDeclaratorParen(inner=inner, next=next)
|
|
811
|
-
except DefinitionError as
|
|
851
|
+
except DefinitionError as ex_no_ptr_paren:
|
|
812
852
|
self.pos = pos
|
|
813
|
-
msg =
|
|
814
|
-
if
|
|
853
|
+
msg = 'If parenthesis in noptr-declarator'
|
|
854
|
+
if param_mode == 'function':
|
|
815
855
|
msg += " (e.g., 'void (*f(int arg))(double)')"
|
|
816
|
-
|
|
817
|
-
header =
|
|
818
|
-
raise self._make_multi_error(
|
|
856
|
+
prev_errors.append((ex_no_ptr_paren, msg))
|
|
857
|
+
header = 'Error in declarator'
|
|
858
|
+
raise self._make_multi_error(
|
|
859
|
+
prev_errors, header
|
|
860
|
+
) from ex_no_ptr_paren
|
|
819
861
|
pos = self.pos
|
|
820
862
|
try:
|
|
821
|
-
return self._parse_declarator_name_suffix(named,
|
|
863
|
+
return self._parse_declarator_name_suffix(named, param_mode, typed)
|
|
822
864
|
except DefinitionError as e:
|
|
823
865
|
self.pos = pos
|
|
824
|
-
|
|
825
|
-
header =
|
|
826
|
-
raise self._make_multi_error(
|
|
866
|
+
prev_errors.append((e, 'If declarator-id'))
|
|
867
|
+
header = 'Error in declarator or parameters'
|
|
868
|
+
raise self._make_multi_error(prev_errors, header) from e
|
|
827
869
|
|
|
828
|
-
def _parse_initializer(
|
|
829
|
-
|
|
870
|
+
def _parse_initializer(
|
|
871
|
+
self, outer: str | None = None, allow_fallback: bool = True
|
|
872
|
+
) -> ASTInitializer | None:
|
|
830
873
|
self.skip_ws()
|
|
831
|
-
if outer == 'member' and False: # NoQA: SIM223 # TODO
|
|
832
|
-
|
|
833
|
-
if
|
|
834
|
-
return ASTInitializer(
|
|
874
|
+
if outer == 'member' and False: # NoQA: SIM223,TD005 # TODO
|
|
875
|
+
braced_init = self._parse_braced_init_list()
|
|
876
|
+
if braced_init is not None:
|
|
877
|
+
return ASTInitializer(braced_init, hasAssign=False)
|
|
835
878
|
|
|
836
879
|
if not self.skip_string('='):
|
|
837
880
|
return None
|
|
838
881
|
|
|
839
|
-
|
|
840
|
-
if
|
|
841
|
-
return ASTInitializer(
|
|
882
|
+
braced_init = self._parse_braced_init_list()
|
|
883
|
+
if braced_init is not None:
|
|
884
|
+
return ASTInitializer(braced_init)
|
|
842
885
|
|
|
843
886
|
if outer == 'member':
|
|
844
|
-
|
|
887
|
+
fallback_end: list[str] = []
|
|
845
888
|
elif outer is None: # function parameter
|
|
846
|
-
|
|
889
|
+
fallback_end = [',', ')']
|
|
847
890
|
else:
|
|
848
|
-
self.fail(
|
|
849
|
-
|
|
891
|
+
self.fail(
|
|
892
|
+
"Internal error, initializer for outer '%s' not implemented." % outer
|
|
893
|
+
)
|
|
850
894
|
|
|
851
895
|
def parser() -> ASTExpression:
|
|
852
896
|
return self._parse_assignment_expression()
|
|
853
897
|
|
|
854
|
-
value = self._parse_expression_fallback(
|
|
898
|
+
value = self._parse_expression_fallback(
|
|
899
|
+
fallback_end, parser, allow=allow_fallback
|
|
900
|
+
)
|
|
855
901
|
return ASTInitializer(value)
|
|
856
902
|
|
|
857
903
|
def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType:
|
|
858
|
-
"""
|
|
859
|
-
named=False|'single'|True: 'single' is e.g., for function objects which
|
|
904
|
+
"""named=False|'single'|True: 'single' is e.g., for function objects which
|
|
860
905
|
doesn't need to name the arguments, but otherwise is a single name
|
|
861
906
|
"""
|
|
862
907
|
if outer: # always named
|
|
863
|
-
if outer not in
|
|
908
|
+
if outer not in {'type', 'member', 'function'}:
|
|
864
909
|
raise Exception('Internal error, unknown outer "%s".' % outer)
|
|
865
910
|
assert named
|
|
866
911
|
|
|
867
912
|
if outer == 'type':
|
|
868
913
|
# We allow type objects to just be a name.
|
|
869
|
-
|
|
870
|
-
|
|
914
|
+
prev_errors = []
|
|
915
|
+
start_pos = self.pos
|
|
871
916
|
# first try without the type
|
|
872
917
|
try:
|
|
873
|
-
|
|
874
|
-
decl = self._parse_declarator(named=True,
|
|
875
|
-
typed=False)
|
|
918
|
+
decl_specs = self._parse_decl_specs(outer=outer, typed=False)
|
|
919
|
+
decl = self._parse_declarator(named=True, param_mode=outer, typed=False)
|
|
876
920
|
self.assert_end(allowSemicolon=True)
|
|
877
|
-
except DefinitionError as
|
|
878
|
-
desc =
|
|
879
|
-
|
|
880
|
-
self.pos =
|
|
921
|
+
except DefinitionError as ex_untyped:
|
|
922
|
+
desc = 'If just a name'
|
|
923
|
+
prev_errors.append((ex_untyped, desc))
|
|
924
|
+
self.pos = start_pos
|
|
881
925
|
try:
|
|
882
|
-
|
|
883
|
-
decl = self._parse_declarator(named=True,
|
|
884
|
-
except DefinitionError as
|
|
885
|
-
self.pos =
|
|
886
|
-
desc =
|
|
887
|
-
|
|
926
|
+
decl_specs = self._parse_decl_specs(outer=outer)
|
|
927
|
+
decl = self._parse_declarator(named=True, param_mode=outer)
|
|
928
|
+
except DefinitionError as ex_typed:
|
|
929
|
+
self.pos = start_pos
|
|
930
|
+
desc = 'If typedef-like declaration'
|
|
931
|
+
prev_errors.append((ex_typed, desc))
|
|
888
932
|
# Retain the else branch for easier debugging.
|
|
889
933
|
# TODO: it would be nice to save the previous stacktrace
|
|
890
934
|
# and output it here.
|
|
891
935
|
if True:
|
|
892
|
-
header =
|
|
893
|
-
header +=
|
|
894
|
-
raise self._make_multi_error(
|
|
895
|
-
else:
|
|
936
|
+
header = 'Type must be either just a name or a '
|
|
937
|
+
header += 'typedef-like declaration.'
|
|
938
|
+
raise self._make_multi_error(prev_errors, header) from ex_typed
|
|
939
|
+
else:
|
|
896
940
|
# For testing purposes.
|
|
897
941
|
# do it again to get the proper traceback (how do you
|
|
898
942
|
# reliably save a traceback when an exception is
|
|
899
943
|
# constructed?)
|
|
900
|
-
self.pos =
|
|
944
|
+
self.pos = start_pos
|
|
901
945
|
typed = True
|
|
902
|
-
|
|
903
|
-
decl = self._parse_declarator(
|
|
904
|
-
|
|
946
|
+
decl_specs = self._parse_decl_specs(outer=outer, typed=typed)
|
|
947
|
+
decl = self._parse_declarator(
|
|
948
|
+
named=True, param_mode=outer, typed=typed
|
|
949
|
+
)
|
|
905
950
|
elif outer == 'function':
|
|
906
|
-
|
|
907
|
-
decl = self._parse_declarator(named=True,
|
|
951
|
+
decl_specs = self._parse_decl_specs(outer=outer)
|
|
952
|
+
decl = self._parse_declarator(named=True, param_mode=outer)
|
|
908
953
|
else:
|
|
909
|
-
|
|
954
|
+
param_mode = 'type'
|
|
910
955
|
if outer == 'member': # i.e., member
|
|
911
956
|
named = True
|
|
912
|
-
|
|
913
|
-
decl = self._parse_declarator(named=named,
|
|
914
|
-
return ASTType(
|
|
957
|
+
decl_specs = self._parse_decl_specs(outer=outer)
|
|
958
|
+
decl = self._parse_declarator(named=named, param_mode=param_mode)
|
|
959
|
+
return ASTType(decl_specs, decl)
|
|
915
960
|
|
|
916
|
-
def _parse_type_with_init(
|
|
961
|
+
def _parse_type_with_init(
|
|
962
|
+
self, named: bool | str, outer: str | None
|
|
963
|
+
) -> ASTTypeWithInit:
|
|
917
964
|
if outer:
|
|
918
|
-
assert outer in
|
|
965
|
+
assert outer in {'type', 'member', 'function'}
|
|
919
966
|
type = self._parse_type(outer=outer, named=named)
|
|
920
967
|
init = self._parse_initializer(outer=outer)
|
|
921
968
|
return ASTTypeWithInit(type, init)
|
|
@@ -924,7 +971,7 @@ class DefinitionParser(BaseParser):
|
|
|
924
971
|
self.skip_ws()
|
|
925
972
|
ident = self._parse_nested_name()
|
|
926
973
|
if ident is None:
|
|
927
|
-
self.fail(
|
|
974
|
+
self.fail('Expected identifier in macro definition.')
|
|
928
975
|
self.skip_ws()
|
|
929
976
|
if not self.skip_string_and_ws('('):
|
|
930
977
|
return ASTMacro(ident, None)
|
|
@@ -940,7 +987,7 @@ class DefinitionParser(BaseParser):
|
|
|
940
987
|
self.fail('Expected ")" after "..." in macro parameters.')
|
|
941
988
|
break
|
|
942
989
|
if not self.match(identifier_re):
|
|
943
|
-
self.fail(
|
|
990
|
+
self.fail('Expected identifier in macro parameters.')
|
|
944
991
|
nn = ASTNestedName([ASTIdentifier(self.matched_text)], rooted=False)
|
|
945
992
|
# Allow named variadic args:
|
|
946
993
|
# https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
|
|
@@ -982,43 +1029,64 @@ class DefinitionParser(BaseParser):
|
|
|
982
1029
|
def parser() -> ASTExpression:
|
|
983
1030
|
return self._parse_constant_expression()
|
|
984
1031
|
|
|
985
|
-
|
|
986
|
-
init = ASTInitializer(
|
|
1032
|
+
init_val = self._parse_expression_fallback([], parser)
|
|
1033
|
+
init = ASTInitializer(init_val)
|
|
987
1034
|
return ASTEnumerator(name, init, attrs)
|
|
988
1035
|
|
|
989
1036
|
def parse_declaration(self, objectType: str, directiveType: str) -> ASTDeclaration:
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1037
|
+
object_type = objectType
|
|
1038
|
+
directive_type = directiveType
|
|
1039
|
+
if object_type not in {
|
|
1040
|
+
'function',
|
|
1041
|
+
'member',
|
|
1042
|
+
'macro',
|
|
1043
|
+
'struct',
|
|
1044
|
+
'union',
|
|
1045
|
+
'enum',
|
|
1046
|
+
'enumerator',
|
|
1047
|
+
'type',
|
|
1048
|
+
}:
|
|
1049
|
+
raise Exception('Internal error, unknown objectType "%s".' % object_type)
|
|
1050
|
+
if directive_type not in {
|
|
1051
|
+
'function',
|
|
1052
|
+
'member',
|
|
1053
|
+
'var',
|
|
1054
|
+
'macro',
|
|
1055
|
+
'struct',
|
|
1056
|
+
'union',
|
|
1057
|
+
'enum',
|
|
1058
|
+
'enumerator',
|
|
1059
|
+
'type',
|
|
1060
|
+
}:
|
|
1061
|
+
raise Exception(
|
|
1062
|
+
'Internal error, unknown directiveType "%s".' % directive_type
|
|
1063
|
+
)
|
|
996
1064
|
|
|
997
1065
|
declaration: DeclarationType | None = None
|
|
998
|
-
if
|
|
1066
|
+
if object_type == 'member':
|
|
999
1067
|
declaration = self._parse_type_with_init(named=True, outer='member')
|
|
1000
|
-
elif
|
|
1068
|
+
elif object_type == 'function':
|
|
1001
1069
|
declaration = self._parse_type(named=True, outer='function')
|
|
1002
|
-
elif
|
|
1070
|
+
elif object_type == 'macro':
|
|
1003
1071
|
declaration = self._parse_macro()
|
|
1004
|
-
elif
|
|
1072
|
+
elif object_type == 'struct':
|
|
1005
1073
|
declaration = self._parse_struct()
|
|
1006
|
-
elif
|
|
1074
|
+
elif object_type == 'union':
|
|
1007
1075
|
declaration = self._parse_union()
|
|
1008
|
-
elif
|
|
1076
|
+
elif object_type == 'enum':
|
|
1009
1077
|
declaration = self._parse_enum()
|
|
1010
|
-
elif
|
|
1078
|
+
elif object_type == 'enumerator':
|
|
1011
1079
|
declaration = self._parse_enumerator()
|
|
1012
|
-
elif
|
|
1080
|
+
elif object_type == 'type':
|
|
1013
1081
|
declaration = self._parse_type(named=True, outer='type')
|
|
1014
1082
|
else:
|
|
1015
1083
|
raise AssertionError
|
|
1016
|
-
if
|
|
1084
|
+
if object_type != 'macro':
|
|
1017
1085
|
self.skip_ws()
|
|
1018
1086
|
semicolon = self.skip_string(';')
|
|
1019
1087
|
else:
|
|
1020
1088
|
semicolon = False
|
|
1021
|
-
return ASTDeclaration(
|
|
1089
|
+
return ASTDeclaration(object_type, directive_type, declaration, semicolon)
|
|
1022
1090
|
|
|
1023
1091
|
def parse_namespace_object(self) -> ASTNestedName:
|
|
1024
1092
|
return self._parse_nested_name()
|
|
@@ -1038,16 +1106,17 @@ class DefinitionParser(BaseParser):
|
|
|
1038
1106
|
res = self._parse_expression()
|
|
1039
1107
|
self.skip_ws()
|
|
1040
1108
|
self.assert_end()
|
|
1041
|
-
except DefinitionError as
|
|
1109
|
+
except DefinitionError as ex_expr:
|
|
1042
1110
|
self.pos = pos
|
|
1043
1111
|
try:
|
|
1044
1112
|
res = self._parse_type(False)
|
|
1045
1113
|
self.skip_ws()
|
|
1046
1114
|
self.assert_end()
|
|
1047
|
-
except DefinitionError as
|
|
1048
|
-
header =
|
|
1049
|
-
errs = [
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1115
|
+
except DefinitionError as ex_type:
|
|
1116
|
+
header = 'Error when parsing (type) expression.'
|
|
1117
|
+
errs = [
|
|
1118
|
+
(ex_expr, 'If expression'),
|
|
1119
|
+
(ex_type, 'If type'),
|
|
1120
|
+
]
|
|
1121
|
+
raise self._make_multi_error(errs, header) from ex_type
|
|
1053
1122
|
return res
|