Sphinx 8.1.2__py3-none-any.whl → 8.2.0__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 +50 -40
- sphinx/domains/python/__init__.py +402 -211
- sphinx/domains/python/_annotations.py +134 -61
- sphinx/domains/python/_object.py +155 -68
- 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 +66 -0
- sphinx/ext/apidoc/__main__.py +9 -0
- sphinx/ext/apidoc/_cli.py +356 -0
- sphinx/ext/apidoc/_extension.py +262 -0
- sphinx/ext/apidoc/_generate.py +356 -0
- sphinx/ext/apidoc/_shared.py +99 -0
- sphinx/ext/autodoc/__init__.py +837 -483
- 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 +281 -142
- 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/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2155 -2050
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2175 -2070
- sphinx/locale/ca/LC_MESSAGES/sphinx.js +3 -3
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +2690 -2585
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.js +63 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca@valencia/LC_MESSAGES/sphinx.po +4216 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2096 -1991
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2248 -2143
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2201 -2096
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2282 -2177
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2261 -2156
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2604 -2499
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2078 -1973
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +2633 -2528
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2449 -2344
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2241 -2136
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +513 -509
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2644 -2539
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +504 -500
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +501 -497
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2609 -2504
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +499 -495
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2265 -2160
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2621 -2516
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2567 -2462
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +2631 -2526
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2214 -2109
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2218 -2113
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2088 -1983
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2247 -2142
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2227 -2122
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2316 -2211
- sphinx/locale/pl/LC_MESSAGES/sphinx.js +2 -2
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2442 -2336
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2657 -2552
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2243 -2138
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2244 -2139
- sphinx/locale/ru/LC_MESSAGES/sphinx.js +1 -1
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2660 -2555
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2134 -2029
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2614 -2509
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/sphinx.pot +2069 -1964
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2661 -2556
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2213 -2108
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2229 -2124
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2608 -2503
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2167 -2062
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2204 -2099
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2045 -1940
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +2659 -2554
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2045 -1940
- 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 +63 -52
- sphinx/writers/latex.py +83 -67
- sphinx/writers/manpage.py +19 -38
- sphinx/writers/texinfo.py +47 -47
- sphinx/writers/text.py +50 -32
- sphinx/writers/xml.py +11 -8
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/LICENSE.rst +1 -1
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/METADATA +25 -15
- sphinx-8.2.0.dist-info/RECORD +606 -0
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.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.2.dist-info/RECORD +0 -598
- {sphinx-8.1.2.dist-info → sphinx-8.2.0.dist-info}/entry_points.txt +0 -0
sphinx/domains/cpp/_parser.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from sphinx.domains.cpp._ast import (
|
|
7
7
|
ASTAlignofExpr,
|
|
@@ -18,7 +18,6 @@ from sphinx.domains.cpp._ast import (
|
|
|
18
18
|
ASTConcept,
|
|
19
19
|
ASTConditionalExpr,
|
|
20
20
|
ASTDeclaration,
|
|
21
|
-
ASTDeclarator,
|
|
22
21
|
ASTDeclaratorMemPtr,
|
|
23
22
|
ASTDeclaratorNameBitField,
|
|
24
23
|
ASTDeclaratorNameParamQual,
|
|
@@ -33,14 +32,12 @@ from sphinx.domains.cpp._ast import (
|
|
|
33
32
|
ASTEnumerator,
|
|
34
33
|
ASTExplicitCast,
|
|
35
34
|
ASTExplicitSpec,
|
|
36
|
-
ASTExpression,
|
|
37
35
|
ASTFallbackExpr,
|
|
38
36
|
ASTFoldExpr,
|
|
39
37
|
ASTFunctionParameter,
|
|
40
38
|
ASTIdentifier,
|
|
41
39
|
ASTIdExpression,
|
|
42
40
|
ASTInitializer,
|
|
43
|
-
ASTLiteral,
|
|
44
41
|
ASTNamespace,
|
|
45
42
|
ASTNestedName,
|
|
46
43
|
ASTNestedNameElement,
|
|
@@ -48,7 +45,6 @@ from sphinx.domains.cpp._ast import (
|
|
|
48
45
|
ASTNoexceptExpr,
|
|
49
46
|
ASTNoexceptSpec,
|
|
50
47
|
ASTNumberLiteral,
|
|
51
|
-
ASTOperator,
|
|
52
48
|
ASTOperatorBuildIn,
|
|
53
49
|
ASTOperatorLiteral,
|
|
54
50
|
ASTOperatorType,
|
|
@@ -64,7 +60,6 @@ from sphinx.domains.cpp._ast import (
|
|
|
64
60
|
ASTPostfixInc,
|
|
65
61
|
ASTPostfixMember,
|
|
66
62
|
ASTPostfixMemberOfPointer,
|
|
67
|
-
ASTPostfixOp,
|
|
68
63
|
ASTRequiresClause,
|
|
69
64
|
ASTSizeofExpr,
|
|
70
65
|
ASTSizeofParamPack,
|
|
@@ -76,14 +71,12 @@ from sphinx.domains.cpp._ast import (
|
|
|
76
71
|
ASTTemplateIntroduction,
|
|
77
72
|
ASTTemplateIntroductionParameter,
|
|
78
73
|
ASTTemplateKeyParamPackIdDefault,
|
|
79
|
-
ASTTemplateParam,
|
|
80
74
|
ASTTemplateParamConstrainedTypeWithInit,
|
|
81
75
|
ASTTemplateParamNonType,
|
|
82
76
|
ASTTemplateParams,
|
|
83
77
|
ASTTemplateParamTemplateType,
|
|
84
78
|
ASTTemplateParamType,
|
|
85
79
|
ASTThisLiteral,
|
|
86
|
-
ASTTrailingTypeSpec,
|
|
87
80
|
ASTTrailingTypeSpecDecltype,
|
|
88
81
|
ASTTrailingTypeSpecDecltypeAuto,
|
|
89
82
|
ASTTrailingTypeSpecFundamental,
|
|
@@ -128,6 +121,17 @@ from sphinx.util.cfamily import (
|
|
|
128
121
|
|
|
129
122
|
if TYPE_CHECKING:
|
|
130
123
|
from collections.abc import Callable, Sequence
|
|
124
|
+
from typing import Any
|
|
125
|
+
|
|
126
|
+
from sphinx.domains.cpp._ast import (
|
|
127
|
+
ASTDeclarator,
|
|
128
|
+
ASTExpression,
|
|
129
|
+
ASTLiteral,
|
|
130
|
+
ASTOperator,
|
|
131
|
+
ASTPostfixOp,
|
|
132
|
+
ASTTemplateParam,
|
|
133
|
+
ASTTrailingTypeSpec,
|
|
134
|
+
)
|
|
131
135
|
|
|
132
136
|
logger = logging.getLogger(__name__)
|
|
133
137
|
|
|
@@ -148,12 +152,12 @@ class DefinitionParser(BaseParser):
|
|
|
148
152
|
def _parse_string(self) -> str:
|
|
149
153
|
if self.current_char != '"':
|
|
150
154
|
return None
|
|
151
|
-
|
|
155
|
+
start_pos = self.pos
|
|
152
156
|
self.pos += 1
|
|
153
157
|
escape = False
|
|
154
158
|
while True:
|
|
155
159
|
if self.eof:
|
|
156
|
-
self.fail(
|
|
160
|
+
self.fail('Unexpected end during inside string.')
|
|
157
161
|
elif self.current_char == '"' and not escape:
|
|
158
162
|
self.pos += 1
|
|
159
163
|
break
|
|
@@ -162,7 +166,7 @@ class DefinitionParser(BaseParser):
|
|
|
162
166
|
else:
|
|
163
167
|
escape = False
|
|
164
168
|
self.pos += 1
|
|
165
|
-
return self.definition[
|
|
169
|
+
return self.definition[start_pos : self.pos]
|
|
166
170
|
|
|
167
171
|
def _parse_literal(self) -> ASTLiteral:
|
|
168
172
|
# -> integer-literal
|
|
@@ -190,21 +194,25 @@ class DefinitionParser(BaseParser):
|
|
|
190
194
|
return ASTBooleanLiteral(False)
|
|
191
195
|
pos = self.pos
|
|
192
196
|
if self.match(float_literal_re):
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if
|
|
196
|
-
return
|
|
197
|
+
has_suffix = self.match(float_literal_suffix_re)
|
|
198
|
+
float_lit = ASTNumberLiteral(self.definition[pos : self.pos])
|
|
199
|
+
if has_suffix:
|
|
200
|
+
return float_lit
|
|
197
201
|
else:
|
|
198
|
-
return _udl(
|
|
199
|
-
for regex in (
|
|
200
|
-
|
|
202
|
+
return _udl(float_lit)
|
|
203
|
+
for regex in (
|
|
204
|
+
binary_literal_re,
|
|
205
|
+
hex_literal_re,
|
|
206
|
+
integer_literal_re,
|
|
207
|
+
octal_literal_re,
|
|
208
|
+
):
|
|
201
209
|
if self.match(regex):
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if
|
|
205
|
-
return
|
|
210
|
+
has_suffix = self.match(integers_literal_suffix_re)
|
|
211
|
+
int_lit = ASTNumberLiteral(self.definition[pos : self.pos])
|
|
212
|
+
if has_suffix:
|
|
213
|
+
return int_lit
|
|
206
214
|
else:
|
|
207
|
-
return _udl(
|
|
215
|
+
return _udl(int_lit)
|
|
208
216
|
|
|
209
217
|
string = self._parse_string()
|
|
210
218
|
if string is not None:
|
|
@@ -215,13 +223,17 @@ class DefinitionParser(BaseParser):
|
|
|
215
223
|
prefix = self.last_match.group(1) # may be None when no prefix
|
|
216
224
|
data = self.last_match.group(2)
|
|
217
225
|
try:
|
|
218
|
-
|
|
226
|
+
char_lit = ASTCharLiteral(prefix, data)
|
|
219
227
|
except UnicodeDecodeError as e:
|
|
220
|
-
self.fail(
|
|
228
|
+
self.fail(
|
|
229
|
+
'Can not handle character literal. Internal error was: %s' % e
|
|
230
|
+
)
|
|
221
231
|
except UnsupportedMultiCharacterCharLiteral:
|
|
222
|
-
self.fail(
|
|
223
|
-
|
|
224
|
-
|
|
232
|
+
self.fail(
|
|
233
|
+
'Can not handle character literal'
|
|
234
|
+
' resulting in multiple decoded characters.'
|
|
235
|
+
)
|
|
236
|
+
return _udl(char_lit)
|
|
225
237
|
return None
|
|
226
238
|
|
|
227
239
|
def _parse_fold_or_paren_expression(self) -> ASTExpression | None:
|
|
@@ -234,28 +246,30 @@ class DefinitionParser(BaseParser):
|
|
|
234
246
|
return None
|
|
235
247
|
self.pos += 1
|
|
236
248
|
self.skip_ws()
|
|
237
|
-
if self.skip_string_and_ws(
|
|
249
|
+
if self.skip_string_and_ws('...'):
|
|
238
250
|
# ( ... fold-operator cast-expression )
|
|
239
251
|
if not self.match(_fold_operator_re):
|
|
240
252
|
self.fail("Expected fold operator after '...' in fold expression.")
|
|
241
253
|
op = self.matched_text
|
|
242
|
-
|
|
254
|
+
right_expr = self._parse_cast_expression()
|
|
243
255
|
if not self.skip_string(')'):
|
|
244
256
|
self.fail("Expected ')' in end of fold expression.")
|
|
245
|
-
return ASTFoldExpr(None, op,
|
|
257
|
+
return ASTFoldExpr(None, op, right_expr)
|
|
246
258
|
# try first parsing a unary right fold, or a binary fold
|
|
247
259
|
pos = self.pos
|
|
248
260
|
try:
|
|
249
261
|
self.skip_ws()
|
|
250
|
-
|
|
262
|
+
left_expr = self._parse_cast_expression()
|
|
251
263
|
self.skip_ws()
|
|
252
264
|
if not self.match(_fold_operator_re):
|
|
253
|
-
self.fail(
|
|
265
|
+
self.fail(
|
|
266
|
+
'Expected fold operator after left expression in fold expression.'
|
|
267
|
+
)
|
|
254
268
|
op = self.matched_text
|
|
255
269
|
self.skip_ws()
|
|
256
270
|
if not self.skip_string_and_ws('...'):
|
|
257
271
|
self.fail("Expected '...' after fold operator in fold expression.")
|
|
258
|
-
except DefinitionError as
|
|
272
|
+
except DefinitionError as e_fold:
|
|
259
273
|
self.pos = pos
|
|
260
274
|
# fall back to a paren expression
|
|
261
275
|
try:
|
|
@@ -263,25 +277,30 @@ class DefinitionParser(BaseParser):
|
|
|
263
277
|
self.skip_ws()
|
|
264
278
|
if not self.skip_string(')'):
|
|
265
279
|
self.fail("Expected ')' in end of parenthesized expression.")
|
|
266
|
-
except DefinitionError as
|
|
267
|
-
raise self._make_multi_error(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
280
|
+
except DefinitionError as e_expr:
|
|
281
|
+
raise self._make_multi_error(
|
|
282
|
+
[
|
|
283
|
+
(e_fold, 'If fold expression'),
|
|
284
|
+
(e_expr, 'If parenthesized expression'),
|
|
285
|
+
],
|
|
286
|
+
'Error in fold expression or parenthesized expression.',
|
|
287
|
+
) from e_expr
|
|
271
288
|
return ASTParenExpr(res)
|
|
272
289
|
# now it definitely is a fold expression
|
|
273
290
|
if self.skip_string(')'):
|
|
274
|
-
return ASTFoldExpr(
|
|
291
|
+
return ASTFoldExpr(left_expr, op, None)
|
|
275
292
|
if not self.match(_fold_operator_re):
|
|
276
293
|
self.fail("Expected fold operator or ')' after '...' in fold expression.")
|
|
277
294
|
if op != self.matched_text:
|
|
278
|
-
self.fail(
|
|
279
|
-
|
|
280
|
-
|
|
295
|
+
self.fail(
|
|
296
|
+
"Operators are different in binary fold: '%s' and '%s'."
|
|
297
|
+
% (op, self.matched_text)
|
|
298
|
+
)
|
|
299
|
+
right_expr = self._parse_cast_expression()
|
|
281
300
|
self.skip_ws()
|
|
282
301
|
if not self.skip_string(')'):
|
|
283
302
|
self.fail("Expected ')' to end binary fold expression.")
|
|
284
|
-
return ASTFoldExpr(
|
|
303
|
+
return ASTFoldExpr(left_expr, op, right_expr)
|
|
285
304
|
|
|
286
305
|
def _parse_primary_expression(self) -> ASTExpression:
|
|
287
306
|
# literal
|
|
@@ -295,7 +314,7 @@ class DefinitionParser(BaseParser):
|
|
|
295
314
|
if res is not None:
|
|
296
315
|
return res
|
|
297
316
|
self.skip_ws()
|
|
298
|
-
if self.skip_word(
|
|
317
|
+
if self.skip_word('this'):
|
|
299
318
|
return ASTThisLiteral()
|
|
300
319
|
# TODO: try lambda expression
|
|
301
320
|
res = self._parse_fold_or_paren_expression()
|
|
@@ -306,9 +325,9 @@ class DefinitionParser(BaseParser):
|
|
|
306
325
|
return ASTIdExpression(nn)
|
|
307
326
|
return None
|
|
308
327
|
|
|
309
|
-
def _parse_initializer_list(
|
|
310
|
-
|
|
311
|
-
|
|
328
|
+
def _parse_initializer_list(
|
|
329
|
+
self, name: str, open: str, close: str
|
|
330
|
+
) -> tuple[list[ASTExpression | ASTBracedInitList], bool]:
|
|
312
331
|
# Parse open and close with the actual initializer-list in between
|
|
313
332
|
# -> initializer-clause '...'[opt]
|
|
314
333
|
# | initializer-list ',' initializer-clause '...'[opt]
|
|
@@ -319,7 +338,7 @@ class DefinitionParser(BaseParser):
|
|
|
319
338
|
return [], False
|
|
320
339
|
|
|
321
340
|
exprs: list[ASTExpression | ASTBracedInitList] = []
|
|
322
|
-
|
|
341
|
+
trailing_comma = False
|
|
323
342
|
while True:
|
|
324
343
|
self.skip_ws()
|
|
325
344
|
expr = self._parse_initializer_clause()
|
|
@@ -335,9 +354,9 @@ class DefinitionParser(BaseParser):
|
|
|
335
354
|
self.fail(f"Error in {name}, expected ',' or '{close}'.")
|
|
336
355
|
if self.current_char == close == '}':
|
|
337
356
|
self.pos += 1
|
|
338
|
-
|
|
357
|
+
trailing_comma = True
|
|
339
358
|
break
|
|
340
|
-
return exprs,
|
|
359
|
+
return exprs, trailing_comma
|
|
341
360
|
|
|
342
361
|
def _parse_paren_expression_list(self) -> ASTParenExprList:
|
|
343
362
|
# -> '(' expression-list ')'
|
|
@@ -346,25 +365,28 @@ class DefinitionParser(BaseParser):
|
|
|
346
365
|
#
|
|
347
366
|
# expression-list
|
|
348
367
|
# -> initializer-list
|
|
349
|
-
exprs,
|
|
350
|
-
|
|
368
|
+
exprs, trailing_comma = self._parse_initializer_list(
|
|
369
|
+
'parenthesized expression-list', '(', ')'
|
|
370
|
+
)
|
|
351
371
|
if exprs is None:
|
|
352
372
|
return None
|
|
353
373
|
return ASTParenExprList(exprs)
|
|
354
374
|
|
|
355
375
|
def _parse_initializer_clause(self) -> ASTExpression | ASTBracedInitList:
|
|
356
|
-
|
|
357
|
-
if
|
|
358
|
-
return
|
|
359
|
-
return self._parse_assignment_expression(
|
|
376
|
+
braced_init_list = self._parse_braced_init_list()
|
|
377
|
+
if braced_init_list is not None:
|
|
378
|
+
return braced_init_list
|
|
379
|
+
return self._parse_assignment_expression(in_template=False)
|
|
360
380
|
|
|
361
381
|
def _parse_braced_init_list(self) -> ASTBracedInitList:
|
|
362
382
|
# -> '{' initializer-list ','[opt] '}'
|
|
363
383
|
# | '{' '}'
|
|
364
|
-
exprs,
|
|
384
|
+
exprs, trailing_comma = self._parse_initializer_list(
|
|
385
|
+
'braced-init-list', '{', '}'
|
|
386
|
+
)
|
|
365
387
|
if exprs is None:
|
|
366
388
|
return None
|
|
367
|
-
return ASTBracedInitList(exprs,
|
|
389
|
+
return ASTBracedInitList(exprs, trailing_comma)
|
|
368
390
|
|
|
369
391
|
def _parse_expression_list_or_braced_init_list(
|
|
370
392
|
self,
|
|
@@ -396,7 +418,7 @@ class DefinitionParser(BaseParser):
|
|
|
396
418
|
# | "typeid" "(" expression ")"
|
|
397
419
|
# | "typeid" "(" type-id ")"
|
|
398
420
|
|
|
399
|
-
|
|
421
|
+
prefix_type = None
|
|
400
422
|
prefix: Any = None
|
|
401
423
|
self.skip_ws()
|
|
402
424
|
|
|
@@ -406,25 +428,26 @@ class DefinitionParser(BaseParser):
|
|
|
406
428
|
cast = c
|
|
407
429
|
break
|
|
408
430
|
if cast is not None:
|
|
409
|
-
|
|
410
|
-
if not self.skip_string(
|
|
431
|
+
prefix_type = 'cast'
|
|
432
|
+
if not self.skip_string('<'):
|
|
411
433
|
self.fail("Expected '<' after '%s'." % cast)
|
|
412
434
|
typ = self._parse_type(False)
|
|
413
435
|
self.skip_ws()
|
|
414
|
-
if not self.skip_string_and_ws(
|
|
436
|
+
if not self.skip_string_and_ws('>'):
|
|
415
437
|
self.fail("Expected '>' after type in '%s'." % cast)
|
|
416
|
-
if not self.skip_string(
|
|
438
|
+
if not self.skip_string('('):
|
|
417
439
|
self.fail("Expected '(' in '%s'." % cast)
|
|
418
440
|
|
|
419
441
|
def parser() -> ASTExpression:
|
|
420
442
|
return self._parse_expression()
|
|
443
|
+
|
|
421
444
|
expr = self._parse_expression_fallback([')'], parser)
|
|
422
445
|
self.skip_ws()
|
|
423
|
-
if not self.skip_string(
|
|
446
|
+
if not self.skip_string(')'):
|
|
424
447
|
self.fail("Expected ')' to end '%s'." % cast)
|
|
425
448
|
prefix = ASTExplicitCast(cast, typ, expr)
|
|
426
|
-
elif self.skip_word_and_ws(
|
|
427
|
-
|
|
449
|
+
elif self.skip_word_and_ws('typeid'):
|
|
450
|
+
prefix_type = 'typeid'
|
|
428
451
|
if not self.skip_string_and_ws('('):
|
|
429
452
|
self.fail("Expected '(' after 'typeid'.")
|
|
430
453
|
pos = self.pos
|
|
@@ -433,63 +456,66 @@ class DefinitionParser(BaseParser):
|
|
|
433
456
|
prefix = ASTTypeId(typ, isType=True)
|
|
434
457
|
if not self.skip_string(')'):
|
|
435
458
|
self.fail("Expected ')' to end 'typeid' of type.")
|
|
436
|
-
except DefinitionError as
|
|
459
|
+
except DefinitionError as e_type:
|
|
437
460
|
self.pos = pos
|
|
438
461
|
try:
|
|
439
462
|
|
|
440
463
|
def parser() -> ASTExpression:
|
|
441
464
|
return self._parse_expression()
|
|
465
|
+
|
|
442
466
|
expr = self._parse_expression_fallback([')'], parser)
|
|
443
467
|
prefix = ASTTypeId(expr, isType=False)
|
|
444
468
|
if not self.skip_string(')'):
|
|
445
469
|
self.fail("Expected ')' to end 'typeid' of expression.")
|
|
446
|
-
except DefinitionError as
|
|
470
|
+
except DefinitionError as e_expr:
|
|
447
471
|
self.pos = pos
|
|
448
472
|
header = "Error in 'typeid(...)'."
|
|
449
|
-
header +=
|
|
450
|
-
errors = [
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
473
|
+
header += ' Expected type or expression.'
|
|
474
|
+
errors = [
|
|
475
|
+
(e_type, 'If type'),
|
|
476
|
+
(e_expr, 'If expression'),
|
|
477
|
+
]
|
|
478
|
+
raise self._make_multi_error(errors, header) from e_expr
|
|
454
479
|
else: # a primary expression or a type
|
|
455
480
|
pos = self.pos
|
|
456
481
|
try:
|
|
457
482
|
prefix = self._parse_primary_expression()
|
|
458
|
-
|
|
459
|
-
except DefinitionError as
|
|
483
|
+
prefix_type = 'expr'
|
|
484
|
+
except DefinitionError as e_outer:
|
|
460
485
|
self.pos = pos
|
|
461
486
|
try:
|
|
462
487
|
# we are potentially casting, so save parens for us
|
|
463
488
|
# TODO: hmm, would we need to try both with operatorCast and with None?
|
|
464
489
|
prefix = self._parse_type(False, 'operatorCast')
|
|
465
|
-
|
|
490
|
+
prefix_type = 'typeOperatorCast'
|
|
466
491
|
# | simple-type-specifier "(" expression-list [opt] ")"
|
|
467
492
|
# | simple-type-specifier braced-init-list
|
|
468
493
|
# | typename-specifier "(" expression-list [opt] ")"
|
|
469
494
|
# | typename-specifier braced-init-list
|
|
470
495
|
self.skip_ws()
|
|
471
|
-
if self.current_char
|
|
496
|
+
if self.current_char not in {'(', '{'}:
|
|
472
497
|
self.fail("Expecting '(' or '{' after type in cast expression.")
|
|
473
|
-
except DefinitionError as
|
|
498
|
+
except DefinitionError as e_inner:
|
|
474
499
|
self.pos = pos
|
|
475
|
-
header =
|
|
476
|
-
header +=
|
|
477
|
-
errors = [
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
500
|
+
header = 'Error in postfix expression,'
|
|
501
|
+
header += ' expected primary expression or type.'
|
|
502
|
+
errors = [
|
|
503
|
+
(e_outer, 'If primary expression'),
|
|
504
|
+
(e_inner, 'If type'),
|
|
505
|
+
]
|
|
506
|
+
raise self._make_multi_error(errors, header) from e_inner
|
|
481
507
|
|
|
482
508
|
# and now parse postfixes
|
|
483
|
-
|
|
509
|
+
post_fixes: list[ASTPostfixOp] = []
|
|
484
510
|
while True:
|
|
485
511
|
self.skip_ws()
|
|
486
|
-
if
|
|
512
|
+
if prefix_type in {'expr', 'cast', 'typeid'}:
|
|
487
513
|
if self.skip_string_and_ws('['):
|
|
488
514
|
expr = self._parse_expression()
|
|
489
515
|
self.skip_ws()
|
|
490
516
|
if not self.skip_string(']'):
|
|
491
517
|
self.fail("Expected ']' in end of postfix expression.")
|
|
492
|
-
|
|
518
|
+
post_fixes.append(ASTPostfixArray(expr))
|
|
493
519
|
continue
|
|
494
520
|
if self.skip_string('.'):
|
|
495
521
|
if self.skip_string('*'):
|
|
@@ -500,7 +526,7 @@ class DefinitionParser(BaseParser):
|
|
|
500
526
|
self.pos -= 3
|
|
501
527
|
else:
|
|
502
528
|
name = self._parse_nested_name()
|
|
503
|
-
|
|
529
|
+
post_fixes.append(ASTPostfixMember(name))
|
|
504
530
|
continue
|
|
505
531
|
if self.skip_string('->'):
|
|
506
532
|
if self.skip_string('*'):
|
|
@@ -508,20 +534,20 @@ class DefinitionParser(BaseParser):
|
|
|
508
534
|
self.pos -= 3
|
|
509
535
|
else:
|
|
510
536
|
name = self._parse_nested_name()
|
|
511
|
-
|
|
537
|
+
post_fixes.append(ASTPostfixMemberOfPointer(name))
|
|
512
538
|
continue
|
|
513
539
|
if self.skip_string('++'):
|
|
514
|
-
|
|
540
|
+
post_fixes.append(ASTPostfixInc())
|
|
515
541
|
continue
|
|
516
542
|
if self.skip_string('--'):
|
|
517
|
-
|
|
543
|
+
post_fixes.append(ASTPostfixDec())
|
|
518
544
|
continue
|
|
519
545
|
lst = self._parse_expression_list_or_braced_init_list()
|
|
520
546
|
if lst is not None:
|
|
521
|
-
|
|
547
|
+
post_fixes.append(ASTPostfixCallExpr(lst))
|
|
522
548
|
continue
|
|
523
549
|
break
|
|
524
|
-
return ASTPostfixExpr(prefix,
|
|
550
|
+
return ASTPostfixExpr(prefix, post_fixes)
|
|
525
551
|
|
|
526
552
|
def _parse_unary_expression(self) -> ASTExpression:
|
|
527
553
|
# -> postfix
|
|
@@ -554,7 +580,7 @@ class DefinitionParser(BaseParser):
|
|
|
554
580
|
self.fail("Expecting identifier for 'sizeof...'.")
|
|
555
581
|
ident = ASTIdentifier(self.matched_text)
|
|
556
582
|
self.skip_ws()
|
|
557
|
-
if not self.skip_string(
|
|
583
|
+
if not self.skip_string(')'):
|
|
558
584
|
self.fail("Expecting ')' to end 'sizeof...'.")
|
|
559
585
|
return ASTSizeofParamPack(ident)
|
|
560
586
|
if self.skip_string_and_ws('('):
|
|
@@ -590,20 +616,24 @@ class DefinitionParser(BaseParser):
|
|
|
590
616
|
else:
|
|
591
617
|
# new-placement[opt] new-type-id new-initializer[opt]
|
|
592
618
|
# new-placement[opt] ( type-id ) new-initializer[opt]
|
|
593
|
-
|
|
619
|
+
is_new_type_id = True
|
|
594
620
|
if self.skip_string_and_ws('('):
|
|
595
621
|
# either this is a new-placement or it's the second production
|
|
596
622
|
# without placement, and it's actually the ( type-id ) part
|
|
597
|
-
self.fail(
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
623
|
+
self.fail(
|
|
624
|
+
'Sorry, neither new-placement nor parenthesised type-id '
|
|
625
|
+
'in new-epression is supported yet.'
|
|
626
|
+
)
|
|
627
|
+
# set is_new_type_id = False if it's (type-id)
|
|
628
|
+
if is_new_type_id:
|
|
629
|
+
decl_specs = self._parse_decl_specs(outer=None)
|
|
630
|
+
decl = self._parse_declarator(named=False, param_mode='new')
|
|
603
631
|
else:
|
|
604
|
-
self.fail(
|
|
632
|
+
self.fail(
|
|
633
|
+
'Sorry, parenthesised type-id in new expression not yet supported.'
|
|
634
|
+
)
|
|
605
635
|
lst = self._parse_expression_list_or_braced_init_list()
|
|
606
|
-
return ASTNewExpr(rooted,
|
|
636
|
+
return ASTNewExpr(rooted, is_new_type_id, ASTType(decl_specs, decl), lst)
|
|
607
637
|
# delete-expression
|
|
608
638
|
pos = self.pos
|
|
609
639
|
rooted = self.skip_string('::')
|
|
@@ -629,20 +659,22 @@ class DefinitionParser(BaseParser):
|
|
|
629
659
|
self.fail("Expected ')' in cast expression.")
|
|
630
660
|
expr = self._parse_cast_expression()
|
|
631
661
|
return ASTCastExpr(typ, expr)
|
|
632
|
-
except DefinitionError as
|
|
662
|
+
except DefinitionError as ex_cast:
|
|
633
663
|
self.pos = pos
|
|
634
664
|
try:
|
|
635
665
|
return self._parse_unary_expression()
|
|
636
|
-
except DefinitionError as
|
|
637
|
-
errs = [
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
666
|
+
except DefinitionError as ex_unary:
|
|
667
|
+
errs = [
|
|
668
|
+
(ex_cast, 'If type cast expression'),
|
|
669
|
+
(ex_unary, 'If unary expression'),
|
|
670
|
+
]
|
|
671
|
+
raise self._make_multi_error(
|
|
672
|
+
errs, 'Error in cast expression.'
|
|
673
|
+
) from ex_unary
|
|
642
674
|
else:
|
|
643
675
|
return self._parse_unary_expression()
|
|
644
676
|
|
|
645
|
-
def _parse_logical_or_expression(self,
|
|
677
|
+
def _parse_logical_or_expression(self, in_template: bool) -> ASTExpression:
|
|
646
678
|
# logical-or = logical-and ||
|
|
647
679
|
# logical-and = inclusive-or &&
|
|
648
680
|
# inclusive-or = exclusive-or |
|
|
@@ -654,24 +686,29 @@ class DefinitionParser(BaseParser):
|
|
|
654
686
|
# additive = multiplicative +, -
|
|
655
687
|
# multiplicative = pm *, /, %
|
|
656
688
|
# pm = cast .*, ->*
|
|
657
|
-
def _parse_bin_op_expr(
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
689
|
+
def _parse_bin_op_expr(
|
|
690
|
+
self: DefinitionParser, op_id: int, in_template: bool
|
|
691
|
+
) -> ASTExpression:
|
|
692
|
+
if op_id + 1 == len(_expression_bin_ops):
|
|
693
|
+
|
|
694
|
+
def parser(in_template: bool) -> ASTExpression:
|
|
661
695
|
return self._parse_cast_expression()
|
|
696
|
+
|
|
662
697
|
else:
|
|
663
|
-
|
|
664
|
-
|
|
698
|
+
|
|
699
|
+
def parser(in_template: bool) -> ASTExpression:
|
|
700
|
+
return _parse_bin_op_expr(self, op_id + 1, in_template=in_template)
|
|
701
|
+
|
|
665
702
|
exprs = []
|
|
666
703
|
ops = []
|
|
667
|
-
exprs.append(parser(
|
|
704
|
+
exprs.append(parser(in_template=in_template))
|
|
668
705
|
while True:
|
|
669
706
|
self.skip_ws()
|
|
670
|
-
if
|
|
707
|
+
if in_template and self.current_char == '>':
|
|
671
708
|
break
|
|
672
709
|
pos = self.pos
|
|
673
|
-
|
|
674
|
-
for op in _expression_bin_ops[
|
|
710
|
+
one_more = False
|
|
711
|
+
for op in _expression_bin_ops[op_id]:
|
|
675
712
|
if op[0] in 'abcnox':
|
|
676
713
|
if not self.skip_word(op):
|
|
677
714
|
continue
|
|
@@ -684,34 +721,36 @@ class DefinitionParser(BaseParser):
|
|
|
684
721
|
# and btw. && has lower precedence, so we are done
|
|
685
722
|
break
|
|
686
723
|
try:
|
|
687
|
-
expr = parser(
|
|
724
|
+
expr = parser(in_template=in_template)
|
|
688
725
|
exprs.append(expr)
|
|
689
726
|
ops.append(op)
|
|
690
|
-
|
|
727
|
+
one_more = True
|
|
691
728
|
break
|
|
692
729
|
except DefinitionError:
|
|
693
730
|
self.pos = pos
|
|
694
|
-
if not
|
|
731
|
+
if not one_more:
|
|
695
732
|
break
|
|
696
733
|
return ASTBinOpExpr(exprs, ops)
|
|
697
|
-
return _parse_bin_op_expr(self, 0, inTemplate=inTemplate)
|
|
698
734
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
735
|
+
return _parse_bin_op_expr(self, 0, in_template=in_template)
|
|
736
|
+
|
|
737
|
+
def _parse_conditional_expression_tail(
|
|
738
|
+
self, or_expr_head: ASTExpression, in_template: bool
|
|
739
|
+
) -> ASTConditionalExpr | None:
|
|
740
|
+
# Consumes the or_expr_head on success.
|
|
702
741
|
|
|
703
742
|
# -> "?" expression ":" assignment-expression
|
|
704
743
|
self.skip_ws()
|
|
705
|
-
if not self.skip_string(
|
|
744
|
+
if not self.skip_string('?'):
|
|
706
745
|
return None
|
|
707
|
-
|
|
746
|
+
then_expr = self._parse_expression()
|
|
708
747
|
self.skip_ws()
|
|
709
|
-
if not self.skip_string(
|
|
748
|
+
if not self.skip_string(':'):
|
|
710
749
|
self.fail('Expected ":" after then-expression in conditional expression.')
|
|
711
|
-
|
|
712
|
-
return ASTConditionalExpr(
|
|
750
|
+
else_expr = self._parse_assignment_expression(in_template)
|
|
751
|
+
return ASTConditionalExpr(or_expr_head, then_expr, else_expr)
|
|
713
752
|
|
|
714
|
-
def _parse_assignment_expression(self,
|
|
753
|
+
def _parse_assignment_expression(self, in_template: bool) -> ASTExpression:
|
|
715
754
|
# -> conditional-expression
|
|
716
755
|
# | logical-or-expression assignment-operator initializer-clause
|
|
717
756
|
# | yield-expression -> "co_yield" assignment-expression
|
|
@@ -724,11 +763,11 @@ class DefinitionParser(BaseParser):
|
|
|
724
763
|
# logical-or-expression
|
|
725
764
|
# | logical-or-expression "?" expression ":" assignment-expression
|
|
726
765
|
# | logical-or-expression assignment-operator initializer-clause
|
|
727
|
-
|
|
766
|
+
left_expr = self._parse_logical_or_expression(in_template=in_template)
|
|
728
767
|
# the ternary operator
|
|
729
|
-
|
|
730
|
-
if
|
|
731
|
-
return
|
|
768
|
+
cond_expr = self._parse_conditional_expression_tail(left_expr, in_template)
|
|
769
|
+
if cond_expr is not None:
|
|
770
|
+
return cond_expr
|
|
732
771
|
# and actual assignment
|
|
733
772
|
for op in _expression_assignment_ops:
|
|
734
773
|
if op[0] in 'anox':
|
|
@@ -737,43 +776,43 @@ class DefinitionParser(BaseParser):
|
|
|
737
776
|
else:
|
|
738
777
|
if not self.skip_string(op):
|
|
739
778
|
continue
|
|
740
|
-
|
|
741
|
-
return ASTAssignmentExpr(
|
|
779
|
+
right_expr = self._parse_initializer_clause()
|
|
780
|
+
return ASTAssignmentExpr(left_expr, op, right_expr)
|
|
742
781
|
# just a logical-or-expression
|
|
743
|
-
return
|
|
782
|
+
return left_expr
|
|
744
783
|
|
|
745
|
-
def _parse_constant_expression(self,
|
|
784
|
+
def _parse_constant_expression(self, in_template: bool) -> ASTExpression:
|
|
746
785
|
# -> conditional-expression ->
|
|
747
786
|
# logical-or-expression
|
|
748
787
|
# | logical-or-expression "?" expression ":" assignment-expression
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
if
|
|
752
|
-
return
|
|
753
|
-
return
|
|
788
|
+
or_expr = self._parse_logical_or_expression(in_template=in_template)
|
|
789
|
+
cond_expr = self._parse_conditional_expression_tail(or_expr, in_template)
|
|
790
|
+
if cond_expr is not None:
|
|
791
|
+
return cond_expr
|
|
792
|
+
return or_expr
|
|
754
793
|
|
|
755
794
|
def _parse_expression(self) -> ASTExpression:
|
|
756
795
|
# -> assignment-expression
|
|
757
796
|
# | expression "," assignment-expression
|
|
758
|
-
exprs = [self._parse_assignment_expression(
|
|
797
|
+
exprs = [self._parse_assignment_expression(in_template=False)]
|
|
759
798
|
while True:
|
|
760
799
|
self.skip_ws()
|
|
761
800
|
if not self.skip_string(','):
|
|
762
801
|
break
|
|
763
|
-
exprs.append(self._parse_assignment_expression(
|
|
802
|
+
exprs.append(self._parse_assignment_expression(in_template=False))
|
|
764
803
|
if len(exprs) == 1:
|
|
765
804
|
return exprs[0]
|
|
766
805
|
else:
|
|
767
806
|
return ASTCommaExpr(exprs)
|
|
768
807
|
|
|
769
|
-
def _parse_expression_fallback(
|
|
770
|
-
|
|
771
|
-
|
|
808
|
+
def _parse_expression_fallback(
|
|
809
|
+
self, end: list[str], parser: Callable[[], ASTExpression], allow: bool = True
|
|
810
|
+
) -> ASTExpression:
|
|
772
811
|
# Stupidly "parse" an expression.
|
|
773
812
|
# 'end' should be a list of characters which ends the expression.
|
|
774
813
|
|
|
775
814
|
# first try to use the provided parser
|
|
776
|
-
|
|
815
|
+
prev_pos = self.pos
|
|
777
816
|
try:
|
|
778
817
|
return parser()
|
|
779
818
|
except DefinitionError as e:
|
|
@@ -781,13 +820,15 @@ class DefinitionParser(BaseParser):
|
|
|
781
820
|
# and for testing we may want to globally disable it
|
|
782
821
|
if not allow or not self.allowFallbackExpressionParsing:
|
|
783
822
|
raise
|
|
784
|
-
self.warn(
|
|
785
|
-
|
|
786
|
-
|
|
823
|
+
self.warn(
|
|
824
|
+
'Parsing of expression failed. Using fallback parser.'
|
|
825
|
+
' Error was:\n%s' % e
|
|
826
|
+
)
|
|
827
|
+
self.pos = prev_pos
|
|
787
828
|
# and then the fallback scanning
|
|
788
829
|
assert end is not None
|
|
789
830
|
self.skip_ws()
|
|
790
|
-
|
|
831
|
+
start_pos = self.pos
|
|
791
832
|
if self.match(_string_re):
|
|
792
833
|
value = self.matched_text
|
|
793
834
|
else:
|
|
@@ -795,7 +836,7 @@ class DefinitionParser(BaseParser):
|
|
|
795
836
|
brackets = {'(': ')', '{': '}', '[': ']', '<': '>'}
|
|
796
837
|
symbols: list[str] = []
|
|
797
838
|
while not self.eof:
|
|
798
|
-
if
|
|
839
|
+
if len(symbols) == 0 and self.current_char in end:
|
|
799
840
|
break
|
|
800
841
|
if self.current_char in brackets:
|
|
801
842
|
symbols.append(brackets[self.current_char])
|
|
@@ -803,9 +844,10 @@ class DefinitionParser(BaseParser):
|
|
|
803
844
|
symbols.pop()
|
|
804
845
|
self.pos += 1
|
|
805
846
|
if len(end) > 0 and self.eof:
|
|
806
|
-
self.fail(
|
|
807
|
-
|
|
808
|
-
|
|
847
|
+
self.fail(
|
|
848
|
+
'Could not find end of expression starting at %d.' % start_pos
|
|
849
|
+
)
|
|
850
|
+
value = self.definition[start_pos : self.pos].strip()
|
|
809
851
|
return ASTFallbackExpr(value.strip())
|
|
810
852
|
|
|
811
853
|
# ==========================================================================
|
|
@@ -833,13 +875,13 @@ class DefinitionParser(BaseParser):
|
|
|
833
875
|
if self.skip_string('""'):
|
|
834
876
|
self.skip_ws()
|
|
835
877
|
if not self.match(identifier_re):
|
|
836
|
-
self.fail(
|
|
878
|
+
self.fail('Expected user-defined literal suffix.')
|
|
837
879
|
identifier = ASTIdentifier(self.matched_text)
|
|
838
880
|
return ASTOperatorLiteral(identifier)
|
|
839
881
|
|
|
840
882
|
# oh well, looks like a cast operator definition.
|
|
841
883
|
# In that case, eat another type.
|
|
842
|
-
type = self._parse_type(named=False, outer=
|
|
884
|
+
type = self._parse_type(named=False, outer='operatorCast')
|
|
843
885
|
return ASTOperatorType(type)
|
|
844
886
|
|
|
845
887
|
def _parse_template_argument_list(self) -> ASTTemplateArgs:
|
|
@@ -855,58 +897,62 @@ class DefinitionParser(BaseParser):
|
|
|
855
897
|
return None
|
|
856
898
|
if self.skip_string('>'):
|
|
857
899
|
return ASTTemplateArgs([], False)
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
900
|
+
prev_errors = []
|
|
901
|
+
template_args: list[ASTType | ASTTemplateArgConstant] = []
|
|
902
|
+
pack_expansion = False
|
|
861
903
|
while 1:
|
|
862
904
|
pos = self.pos
|
|
863
|
-
|
|
864
|
-
|
|
905
|
+
parsed_comma = False
|
|
906
|
+
parsed_end = False
|
|
865
907
|
try:
|
|
866
908
|
type = self._parse_type(named=False)
|
|
867
909
|
self.skip_ws()
|
|
868
910
|
if self.skip_string_and_ws('...'):
|
|
869
|
-
|
|
870
|
-
|
|
911
|
+
pack_expansion = True
|
|
912
|
+
parsed_end = True
|
|
871
913
|
if not self.skip_string('>'):
|
|
872
914
|
self.fail('Expected ">" after "..." in template argument list.')
|
|
873
915
|
elif self.skip_string('>'):
|
|
874
|
-
|
|
916
|
+
parsed_end = True
|
|
875
917
|
elif self.skip_string(','):
|
|
876
|
-
|
|
918
|
+
parsed_comma = True
|
|
877
919
|
else:
|
|
878
920
|
self.fail('Expected "...>", ">" or "," in template argument list.')
|
|
879
|
-
|
|
921
|
+
template_args.append(type)
|
|
880
922
|
except DefinitionError as e:
|
|
881
|
-
|
|
923
|
+
prev_errors.append((e, 'If type argument'))
|
|
882
924
|
self.pos = pos
|
|
883
925
|
try:
|
|
884
|
-
value = self._parse_constant_expression(
|
|
926
|
+
value = self._parse_constant_expression(in_template=True)
|
|
885
927
|
self.skip_ws()
|
|
886
928
|
if self.skip_string_and_ws('...'):
|
|
887
|
-
|
|
888
|
-
|
|
929
|
+
pack_expansion = True
|
|
930
|
+
parsed_end = True
|
|
889
931
|
if not self.skip_string('>'):
|
|
890
|
-
self.fail(
|
|
932
|
+
self.fail(
|
|
933
|
+
'Expected ">" after "..." in template argument list.'
|
|
934
|
+
)
|
|
891
935
|
elif self.skip_string('>'):
|
|
892
|
-
|
|
936
|
+
parsed_end = True
|
|
893
937
|
elif self.skip_string(','):
|
|
894
|
-
|
|
938
|
+
parsed_comma = True
|
|
895
939
|
else:
|
|
896
|
-
self.fail(
|
|
897
|
-
|
|
940
|
+
self.fail(
|
|
941
|
+
'Expected "...>", ">" or "," in template argument list.'
|
|
942
|
+
)
|
|
943
|
+
template_args.append(ASTTemplateArgConstant(value))
|
|
898
944
|
except DefinitionError as e:
|
|
899
945
|
self.pos = pos
|
|
900
|
-
|
|
901
|
-
header =
|
|
902
|
-
raise self._make_multi_error(
|
|
903
|
-
if
|
|
904
|
-
assert not
|
|
946
|
+
prev_errors.append((e, 'If non-type argument'))
|
|
947
|
+
header = 'Error in parsing template argument list.'
|
|
948
|
+
raise self._make_multi_error(prev_errors, header) from e
|
|
949
|
+
if parsed_end:
|
|
950
|
+
assert not parsed_comma
|
|
905
951
|
break
|
|
906
|
-
assert not
|
|
907
|
-
return ASTTemplateArgs(
|
|
952
|
+
assert not pack_expansion
|
|
953
|
+
return ASTTemplateArgs(template_args, pack_expansion)
|
|
908
954
|
|
|
909
|
-
def _parse_nested_name(self,
|
|
955
|
+
def _parse_nested_name(self, member_pointer: bool = False) -> ASTNestedName:
|
|
910
956
|
names: list[ASTNestedNameElement] = []
|
|
911
957
|
templates: list[bool] = []
|
|
912
958
|
|
|
@@ -921,35 +967,37 @@ class DefinitionParser(BaseParser):
|
|
|
921
967
|
else:
|
|
922
968
|
template = False
|
|
923
969
|
templates.append(template)
|
|
924
|
-
|
|
970
|
+
ident_or_op: ASTIdentifier | ASTOperator | None = None
|
|
925
971
|
if self.skip_word_and_ws('operator'):
|
|
926
|
-
|
|
972
|
+
ident_or_op = self._parse_operator()
|
|
927
973
|
else:
|
|
928
974
|
if not self.match(identifier_re):
|
|
929
|
-
if
|
|
975
|
+
if member_pointer and len(names) > 0:
|
|
930
976
|
templates.pop()
|
|
931
977
|
break
|
|
932
|
-
self.fail(
|
|
978
|
+
self.fail('Expected identifier in nested name.')
|
|
933
979
|
identifier = self.matched_text
|
|
934
980
|
# make sure there isn't a keyword
|
|
935
981
|
if identifier in _keywords:
|
|
936
|
-
self.fail(
|
|
937
|
-
|
|
938
|
-
|
|
982
|
+
self.fail(
|
|
983
|
+
'Expected identifier in nested name, '
|
|
984
|
+
'got keyword: %s' % identifier
|
|
985
|
+
)
|
|
986
|
+
ident_or_op = ASTIdentifier(identifier)
|
|
939
987
|
# try greedily to get template arguments,
|
|
940
988
|
# but otherwise a < might be because we are in an expression
|
|
941
989
|
pos = self.pos
|
|
942
990
|
try:
|
|
943
|
-
|
|
991
|
+
template_args = self._parse_template_argument_list()
|
|
944
992
|
except DefinitionError as ex:
|
|
945
993
|
self.pos = pos
|
|
946
|
-
|
|
994
|
+
template_args = None
|
|
947
995
|
self.otherErrors.append(ex)
|
|
948
|
-
names.append(ASTNestedNameElement(
|
|
996
|
+
names.append(ASTNestedNameElement(ident_or_op, template_args))
|
|
949
997
|
|
|
950
998
|
self.skip_ws()
|
|
951
999
|
if not self.skip_string('::'):
|
|
952
|
-
if
|
|
1000
|
+
if member_pointer:
|
|
953
1001
|
self.fail("Expected '::' in pointer to member (function).")
|
|
954
1002
|
break
|
|
955
1003
|
return ASTNestedName(names, templates, rooted)
|
|
@@ -967,84 +1015,88 @@ class DefinitionParser(BaseParser):
|
|
|
967
1015
|
while self.match(_simple_type_specifiers_re):
|
|
968
1016
|
t = self.matched_text
|
|
969
1017
|
names.append(t)
|
|
970
|
-
if t in
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1018
|
+
if t in {
|
|
1019
|
+
'auto', 'void', 'bool',
|
|
1020
|
+
'char', 'wchar_t', 'char8_t', 'char16_t', 'char32_t',
|
|
1021
|
+
'int', '__int64', '__int128',
|
|
1022
|
+
'float', 'double',
|
|
1023
|
+
'__float80', '_Float64x', '__float128', '_Float128',
|
|
1024
|
+
}: # fmt: skip
|
|
975
1025
|
if typ is not None:
|
|
976
|
-
self.fail(f
|
|
1026
|
+
self.fail(f'Can not have both {t} and {typ}.')
|
|
977
1027
|
typ = t
|
|
978
|
-
elif t in
|
|
1028
|
+
elif t in {'signed', 'unsigned'}:
|
|
979
1029
|
if signedness is not None:
|
|
980
|
-
self.fail(f
|
|
1030
|
+
self.fail(f'Can not have both {t} and {signedness}.')
|
|
981
1031
|
signedness = t
|
|
982
1032
|
elif t == 'short':
|
|
983
1033
|
if len(width) != 0:
|
|
984
|
-
self.fail(f
|
|
1034
|
+
self.fail(f'Can not have both {t} and {width[0]}.')
|
|
985
1035
|
width.append(t)
|
|
986
1036
|
elif t == 'long':
|
|
987
1037
|
if len(width) != 0 and width[0] != 'long':
|
|
988
|
-
self.fail(f
|
|
1038
|
+
self.fail(f'Can not have both {t} and {width[0]}.')
|
|
989
1039
|
width.append(t)
|
|
990
|
-
elif t in
|
|
1040
|
+
elif t in {'_Imaginary', '_Complex'}:
|
|
991
1041
|
if modifier is not None:
|
|
992
|
-
self.fail(f
|
|
1042
|
+
self.fail(f'Can not have both {t} and {modifier}.')
|
|
993
1043
|
modifier = t
|
|
994
1044
|
self.skip_ws()
|
|
995
1045
|
if len(names) == 0:
|
|
996
1046
|
return None
|
|
997
1047
|
|
|
998
|
-
if typ in
|
|
999
|
-
|
|
1000
|
-
|
|
1048
|
+
if typ in {
|
|
1049
|
+
'auto', 'void', 'bool',
|
|
1050
|
+
'wchar_t', 'char8_t', 'char16_t', 'char32_t',
|
|
1051
|
+
'__float80', '_Float64x', '__float128', '_Float128',
|
|
1052
|
+
}: # fmt: skip
|
|
1001
1053
|
if modifier is not None:
|
|
1002
|
-
self.fail(f
|
|
1054
|
+
self.fail(f'Can not have both {typ} and {modifier}.')
|
|
1003
1055
|
if signedness is not None:
|
|
1004
|
-
self.fail(f
|
|
1056
|
+
self.fail(f'Can not have both {typ} and {signedness}.')
|
|
1005
1057
|
if len(width) != 0:
|
|
1006
|
-
self.fail(f
|
|
1058
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1007
1059
|
elif typ == 'char':
|
|
1008
1060
|
if modifier is not None:
|
|
1009
|
-
self.fail(f
|
|
1061
|
+
self.fail(f'Can not have both {typ} and {modifier}.')
|
|
1010
1062
|
if len(width) != 0:
|
|
1011
|
-
self.fail(f
|
|
1063
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1012
1064
|
elif typ == 'int':
|
|
1013
1065
|
if modifier is not None:
|
|
1014
|
-
self.fail(f
|
|
1015
|
-
elif typ in
|
|
1066
|
+
self.fail(f'Can not have both {typ} and {modifier}.')
|
|
1067
|
+
elif typ in {'__int64', '__int128'}:
|
|
1016
1068
|
if modifier is not None:
|
|
1017
|
-
self.fail(f
|
|
1069
|
+
self.fail(f'Can not have both {typ} and {modifier}.')
|
|
1018
1070
|
if len(width) != 0:
|
|
1019
|
-
self.fail(f
|
|
1071
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1020
1072
|
elif typ == 'float':
|
|
1021
1073
|
if signedness is not None:
|
|
1022
|
-
self.fail(f
|
|
1074
|
+
self.fail(f'Can not have both {typ} and {signedness}.')
|
|
1023
1075
|
if len(width) != 0:
|
|
1024
|
-
self.fail(f
|
|
1076
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1025
1077
|
elif typ == 'double':
|
|
1026
1078
|
if signedness is not None:
|
|
1027
|
-
self.fail(f
|
|
1079
|
+
self.fail(f'Can not have both {typ} and {signedness}.')
|
|
1028
1080
|
if len(width) > 1:
|
|
1029
|
-
self.fail(f
|
|
1081
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1030
1082
|
if len(width) == 1 and width[0] != 'long':
|
|
1031
|
-
self.fail(f
|
|
1083
|
+
self.fail(f'Can not have both {typ} and {" ".join(width)}.')
|
|
1032
1084
|
elif typ is None:
|
|
1033
1085
|
if modifier is not None:
|
|
1034
|
-
self.fail(f
|
|
1086
|
+
self.fail(f'Can not have {modifier} without a floating point type.')
|
|
1035
1087
|
else:
|
|
1036
1088
|
msg = f'Unhandled type {typ}'
|
|
1037
1089
|
raise AssertionError(msg)
|
|
1038
1090
|
|
|
1039
|
-
|
|
1091
|
+
canon_names: list[str] = []
|
|
1040
1092
|
if modifier is not None:
|
|
1041
|
-
|
|
1093
|
+
canon_names.append(modifier)
|
|
1042
1094
|
if signedness is not None:
|
|
1043
|
-
|
|
1044
|
-
|
|
1095
|
+
canon_names.append(signedness)
|
|
1096
|
+
canon_names.extend(width)
|
|
1045
1097
|
if typ is not None:
|
|
1046
|
-
|
|
1047
|
-
return ASTTrailingTypeSpecFundamental(names,
|
|
1098
|
+
canon_names.append(typ)
|
|
1099
|
+
return ASTTrailingTypeSpecFundamental(names, canon_names)
|
|
1048
1100
|
|
|
1049
1101
|
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
|
|
1050
1102
|
# fundamental types, https://en.cppreference.com/w/cpp/language/type
|
|
@@ -1076,29 +1128,35 @@ class DefinitionParser(BaseParser):
|
|
|
1076
1128
|
if self.skip_word_and_ws(k):
|
|
1077
1129
|
prefix = k
|
|
1078
1130
|
break
|
|
1079
|
-
|
|
1131
|
+
nested_name = self._parse_nested_name()
|
|
1080
1132
|
self.skip_ws()
|
|
1081
|
-
|
|
1133
|
+
placeholder_type = None
|
|
1082
1134
|
if self.skip_word('auto'):
|
|
1083
|
-
|
|
1135
|
+
placeholder_type = 'auto'
|
|
1084
1136
|
elif self.skip_word_and_ws('decltype'):
|
|
1085
1137
|
if not self.skip_string_and_ws('('):
|
|
1086
|
-
self.fail(
|
|
1138
|
+
self.fail(
|
|
1139
|
+
"Expected '(' after 'decltype' in placeholder type specifier."
|
|
1140
|
+
)
|
|
1087
1141
|
if not self.skip_word_and_ws('auto'):
|
|
1088
|
-
self.fail(
|
|
1142
|
+
self.fail(
|
|
1143
|
+
"Expected 'auto' after 'decltype(' in placeholder type specifier."
|
|
1144
|
+
)
|
|
1089
1145
|
if not self.skip_string_and_ws(')'):
|
|
1090
|
-
self.fail(
|
|
1091
|
-
|
|
1092
|
-
|
|
1146
|
+
self.fail(
|
|
1147
|
+
"Expected ')' after 'decltype(auto' in placeholder type specifier."
|
|
1148
|
+
)
|
|
1149
|
+
placeholder_type = 'decltype(auto)'
|
|
1150
|
+
return ASTTrailingTypeSpecName(prefix, nested_name, placeholder_type)
|
|
1093
1151
|
|
|
1094
1152
|
def _parse_parameters_and_qualifiers(
|
|
1095
|
-
self,
|
|
1153
|
+
self, param_mode: str
|
|
1096
1154
|
) -> ASTParametersQualifiers | None:
|
|
1097
|
-
if
|
|
1155
|
+
if param_mode == 'new':
|
|
1098
1156
|
return None
|
|
1099
1157
|
self.skip_ws()
|
|
1100
1158
|
if not self.skip_string('('):
|
|
1101
|
-
if
|
|
1159
|
+
if param_mode == 'function':
|
|
1102
1160
|
self.fail('Expecting "(" in parameters-and-qualifiers.')
|
|
1103
1161
|
else:
|
|
1104
1162
|
return None
|
|
@@ -1111,8 +1169,9 @@ class DefinitionParser(BaseParser):
|
|
|
1111
1169
|
args.append(ASTFunctionParameter(None, True))
|
|
1112
1170
|
self.skip_ws()
|
|
1113
1171
|
if not self.skip_string(')'):
|
|
1114
|
-
self.fail(
|
|
1115
|
-
|
|
1172
|
+
self.fail(
|
|
1173
|
+
'Expected ")" after "..." in parameters-and-qualifiers.'
|
|
1174
|
+
)
|
|
1116
1175
|
break
|
|
1117
1176
|
# note: it seems that function arguments can always be named,
|
|
1118
1177
|
# even in function pointers and similar.
|
|
@@ -1125,8 +1184,10 @@ class DefinitionParser(BaseParser):
|
|
|
1125
1184
|
continue
|
|
1126
1185
|
if self.skip_string(')'):
|
|
1127
1186
|
break
|
|
1128
|
-
self.fail(
|
|
1129
|
-
|
|
1187
|
+
self.fail(
|
|
1188
|
+
'Expecting "," or ")" in parameters-and-qualifiers, '
|
|
1189
|
+
f'got "{self.current_char}".'
|
|
1190
|
+
)
|
|
1130
1191
|
|
|
1131
1192
|
self.skip_ws()
|
|
1132
1193
|
const = self.skip_word_and_ws('const')
|
|
@@ -1134,13 +1195,13 @@ class DefinitionParser(BaseParser):
|
|
|
1134
1195
|
if not const: # the can be permuted
|
|
1135
1196
|
const = self.skip_word_and_ws('const')
|
|
1136
1197
|
|
|
1137
|
-
|
|
1198
|
+
ref_qual = None
|
|
1138
1199
|
if self.skip_string('&&'):
|
|
1139
|
-
|
|
1140
|
-
if not
|
|
1141
|
-
|
|
1200
|
+
ref_qual = '&&'
|
|
1201
|
+
if not ref_qual and self.skip_string('&'):
|
|
1202
|
+
ref_qual = '&'
|
|
1142
1203
|
|
|
1143
|
-
|
|
1204
|
+
exception_spec = None
|
|
1144
1205
|
self.skip_ws()
|
|
1145
1206
|
if self.skip_string('noexcept'):
|
|
1146
1207
|
if self.skip_string_and_ws('('):
|
|
@@ -1148,29 +1209,28 @@ class DefinitionParser(BaseParser):
|
|
|
1148
1209
|
self.skip_ws()
|
|
1149
1210
|
if not self.skip_string(')'):
|
|
1150
1211
|
self.fail("Expecting ')' to end 'noexcept'.")
|
|
1151
|
-
|
|
1212
|
+
exception_spec = ASTNoexceptSpec(expr)
|
|
1152
1213
|
else:
|
|
1153
|
-
|
|
1214
|
+
exception_spec = ASTNoexceptSpec(None)
|
|
1154
1215
|
|
|
1155
1216
|
self.skip_ws()
|
|
1156
1217
|
if self.skip_string('->'):
|
|
1157
|
-
|
|
1218
|
+
trailing_return = self._parse_type(named=False)
|
|
1158
1219
|
else:
|
|
1159
|
-
|
|
1220
|
+
trailing_return = None
|
|
1160
1221
|
|
|
1161
1222
|
self.skip_ws()
|
|
1162
1223
|
override = self.skip_word_and_ws('override')
|
|
1163
1224
|
final = self.skip_word_and_ws('final')
|
|
1164
1225
|
if not override:
|
|
1165
|
-
override = self.skip_word_and_ws(
|
|
1166
|
-
'override') # they can be permuted
|
|
1226
|
+
override = self.skip_word_and_ws('override') # they can be permuted
|
|
1167
1227
|
|
|
1168
1228
|
attrs = self._parse_attribute_list()
|
|
1169
1229
|
|
|
1170
1230
|
self.skip_ws()
|
|
1171
1231
|
initializer = None
|
|
1172
1232
|
# if this is a function pointer we should not swallow an initializer
|
|
1173
|
-
if
|
|
1233
|
+
if param_mode == 'function' and self.skip_string('='):
|
|
1174
1234
|
self.skip_ws()
|
|
1175
1235
|
valid = ('0', 'delete', 'default')
|
|
1176
1236
|
for w in valid:
|
|
@@ -1179,20 +1239,29 @@ class DefinitionParser(BaseParser):
|
|
|
1179
1239
|
break
|
|
1180
1240
|
if not initializer:
|
|
1181
1241
|
self.fail(
|
|
1182
|
-
'Expected "%s" in initializer-specifier.'
|
|
1183
|
-
|
|
1242
|
+
'Expected "%s" in initializer-specifier.' % '" or "'.join(valid)
|
|
1243
|
+
)
|
|
1184
1244
|
|
|
1185
1245
|
return ASTParametersQualifiers(
|
|
1186
|
-
args,
|
|
1187
|
-
|
|
1246
|
+
args,
|
|
1247
|
+
volatile,
|
|
1248
|
+
const,
|
|
1249
|
+
ref_qual,
|
|
1250
|
+
exception_spec,
|
|
1251
|
+
trailing_return,
|
|
1252
|
+
override,
|
|
1253
|
+
final,
|
|
1254
|
+
attrs,
|
|
1255
|
+
initializer,
|
|
1256
|
+
)
|
|
1188
1257
|
|
|
1189
1258
|
def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple:
|
|
1190
1259
|
"""Just parse the simple ones."""
|
|
1191
1260
|
storage = None
|
|
1192
|
-
|
|
1261
|
+
thread_local = None
|
|
1193
1262
|
inline = None
|
|
1194
1263
|
virtual = None
|
|
1195
|
-
|
|
1264
|
+
explicit_spec = None
|
|
1196
1265
|
consteval = None
|
|
1197
1266
|
constexpr = None
|
|
1198
1267
|
constinit = None
|
|
@@ -1211,7 +1280,7 @@ class DefinitionParser(BaseParser):
|
|
|
1211
1280
|
if volatile:
|
|
1212
1281
|
continue
|
|
1213
1282
|
if not storage:
|
|
1214
|
-
if outer in
|
|
1283
|
+
if outer in {'member', 'function'}:
|
|
1215
1284
|
if self.skip_word('static'):
|
|
1216
1285
|
storage = 'static'
|
|
1217
1286
|
continue
|
|
@@ -1225,12 +1294,12 @@ class DefinitionParser(BaseParser):
|
|
|
1225
1294
|
if self.skip_word('register'):
|
|
1226
1295
|
storage = 'register'
|
|
1227
1296
|
continue
|
|
1228
|
-
if not inline and outer in
|
|
1297
|
+
if not inline and outer in {'function', 'member'}:
|
|
1229
1298
|
inline = self.skip_word('inline')
|
|
1230
1299
|
if inline:
|
|
1231
1300
|
continue
|
|
1232
|
-
if not constexpr and outer in
|
|
1233
|
-
constexpr = self.skip_word(
|
|
1301
|
+
if not constexpr and outer in {'member', 'function'}:
|
|
1302
|
+
constexpr = self.skip_word('constexpr')
|
|
1234
1303
|
if constexpr:
|
|
1235
1304
|
continue
|
|
1236
1305
|
|
|
@@ -1239,9 +1308,9 @@ class DefinitionParser(BaseParser):
|
|
|
1239
1308
|
constinit = self.skip_word('constinit')
|
|
1240
1309
|
if constinit:
|
|
1241
1310
|
continue
|
|
1242
|
-
if not
|
|
1243
|
-
|
|
1244
|
-
if
|
|
1311
|
+
if not thread_local:
|
|
1312
|
+
thread_local = self.skip_word('thread_local')
|
|
1313
|
+
if thread_local:
|
|
1245
1314
|
continue
|
|
1246
1315
|
if outer == 'function':
|
|
1247
1316
|
if not consteval:
|
|
@@ -1256,32 +1325,45 @@ class DefinitionParser(BaseParser):
|
|
|
1256
1325
|
virtual = self.skip_word('virtual')
|
|
1257
1326
|
if virtual:
|
|
1258
1327
|
continue
|
|
1259
|
-
if not
|
|
1328
|
+
if not explicit_spec:
|
|
1260
1329
|
explicit = self.skip_word_and_ws('explicit')
|
|
1261
1330
|
if explicit:
|
|
1262
1331
|
expr: ASTExpression = None
|
|
1263
1332
|
if self.skip_string('('):
|
|
1264
|
-
expr = self._parse_constant_expression(
|
|
1333
|
+
expr = self._parse_constant_expression(in_template=False)
|
|
1265
1334
|
if not expr:
|
|
1266
|
-
self.fail(
|
|
1267
|
-
|
|
1335
|
+
self.fail(
|
|
1336
|
+
"Expected constant expression after '('"
|
|
1337
|
+
' in explicit specifier.'
|
|
1338
|
+
)
|
|
1268
1339
|
self.skip_ws()
|
|
1269
1340
|
if not self.skip_string(')'):
|
|
1270
1341
|
self.fail("Expected ')' to end explicit specifier.")
|
|
1271
|
-
|
|
1342
|
+
explicit_spec = ASTExplicitSpec(expr)
|
|
1272
1343
|
continue
|
|
1273
1344
|
attr = self._parse_attribute()
|
|
1274
1345
|
if attr:
|
|
1275
1346
|
attrs.append(attr)
|
|
1276
1347
|
continue
|
|
1277
1348
|
break
|
|
1278
|
-
return ASTDeclSpecsSimple(
|
|
1279
|
-
|
|
1280
|
-
|
|
1349
|
+
return ASTDeclSpecsSimple(
|
|
1350
|
+
storage,
|
|
1351
|
+
thread_local,
|
|
1352
|
+
inline,
|
|
1353
|
+
virtual,
|
|
1354
|
+
explicit_spec,
|
|
1355
|
+
consteval,
|
|
1356
|
+
constexpr,
|
|
1357
|
+
constinit,
|
|
1358
|
+
volatile,
|
|
1359
|
+
const,
|
|
1360
|
+
friend,
|
|
1361
|
+
ASTAttributeList(attrs),
|
|
1362
|
+
)
|
|
1281
1363
|
|
|
1282
1364
|
def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs:
|
|
1283
1365
|
if outer:
|
|
1284
|
-
if outer not in
|
|
1366
|
+
if outer not in {'type', 'member', 'function', 'templateParam'}:
|
|
1285
1367
|
raise Exception('Internal error, unknown outer "%s".' % outer)
|
|
1286
1368
|
"""
|
|
1287
1369
|
storage-class-specifier function-specifier "constexpr"
|
|
@@ -1296,84 +1378,85 @@ class DefinitionParser(BaseParser):
|
|
|
1296
1378
|
|
|
1297
1379
|
"constexpr" (only for member_object and function_object)
|
|
1298
1380
|
"""
|
|
1299
|
-
|
|
1300
|
-
|
|
1381
|
+
left_specs = self._parse_decl_specs_simple(outer, typed)
|
|
1382
|
+
right_specs = None
|
|
1301
1383
|
|
|
1302
1384
|
if typed:
|
|
1303
1385
|
trailing = self._parse_trailing_type_spec()
|
|
1304
|
-
|
|
1386
|
+
right_specs = self._parse_decl_specs_simple(outer, typed)
|
|
1305
1387
|
else:
|
|
1306
1388
|
trailing = None
|
|
1307
|
-
return ASTDeclSpecs(outer,
|
|
1389
|
+
return ASTDeclSpecs(outer, left_specs, right_specs, trailing)
|
|
1308
1390
|
|
|
1309
1391
|
def _parse_declarator_name_suffix(
|
|
1310
|
-
self, named: bool | str,
|
|
1392
|
+
self, named: bool | str, param_mode: str, typed: bool
|
|
1311
1393
|
) -> ASTDeclaratorNameParamQual | ASTDeclaratorNameBitField:
|
|
1312
1394
|
# now we should parse the name, and then suffixes
|
|
1313
1395
|
if named == 'maybe':
|
|
1314
1396
|
pos = self.pos
|
|
1315
1397
|
try:
|
|
1316
|
-
|
|
1398
|
+
decl_id = self._parse_nested_name()
|
|
1317
1399
|
except DefinitionError:
|
|
1318
1400
|
self.pos = pos
|
|
1319
|
-
|
|
1401
|
+
decl_id = None
|
|
1320
1402
|
elif named == 'single':
|
|
1321
1403
|
if self.match(identifier_re):
|
|
1322
1404
|
identifier = ASTIdentifier(self.matched_text)
|
|
1323
1405
|
nne = ASTNestedNameElement(identifier, None)
|
|
1324
|
-
|
|
1406
|
+
decl_id = ASTNestedName([nne], [False], rooted=False)
|
|
1325
1407
|
# if it's a member pointer, we may have '::', which should be an error
|
|
1326
1408
|
self.skip_ws()
|
|
1327
1409
|
if self.current_char == ':':
|
|
1328
1410
|
self.fail("Unexpected ':' after identifier.")
|
|
1329
1411
|
else:
|
|
1330
|
-
|
|
1412
|
+
decl_id = None
|
|
1331
1413
|
elif named:
|
|
1332
|
-
|
|
1414
|
+
decl_id = self._parse_nested_name()
|
|
1333
1415
|
else:
|
|
1334
|
-
|
|
1335
|
-
|
|
1416
|
+
decl_id = None
|
|
1417
|
+
array_ops = []
|
|
1336
1418
|
while 1:
|
|
1337
1419
|
self.skip_ws()
|
|
1338
1420
|
if typed and self.skip_string('['):
|
|
1339
1421
|
self.skip_ws()
|
|
1340
1422
|
if self.skip_string(']'):
|
|
1341
|
-
|
|
1423
|
+
array_ops.append(ASTArray(None))
|
|
1342
1424
|
continue
|
|
1343
1425
|
|
|
1344
1426
|
def parser() -> ASTExpression:
|
|
1345
1427
|
return self._parse_expression()
|
|
1428
|
+
|
|
1346
1429
|
value = self._parse_expression_fallback([']'], parser)
|
|
1347
1430
|
if not self.skip_string(']'):
|
|
1348
1431
|
self.fail("Expected ']' in end of array operator.")
|
|
1349
|
-
|
|
1432
|
+
array_ops.append(ASTArray(value))
|
|
1350
1433
|
continue
|
|
1351
1434
|
break
|
|
1352
|
-
|
|
1353
|
-
if
|
|
1435
|
+
param_qual = self._parse_parameters_and_qualifiers(param_mode)
|
|
1436
|
+
if param_qual is None and len(array_ops) == 0:
|
|
1354
1437
|
# perhaps a bit-field
|
|
1355
|
-
if named and
|
|
1438
|
+
if named and param_mode == 'type' and typed:
|
|
1356
1439
|
self.skip_ws()
|
|
1357
1440
|
if self.skip_string(':'):
|
|
1358
|
-
size = self._parse_constant_expression(
|
|
1359
|
-
return ASTDeclaratorNameBitField(declId=
|
|
1360
|
-
return ASTDeclaratorNameParamQual(
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1441
|
+
size = self._parse_constant_expression(in_template=False)
|
|
1442
|
+
return ASTDeclaratorNameBitField(declId=decl_id, size=size)
|
|
1443
|
+
return ASTDeclaratorNameParamQual(
|
|
1444
|
+
declId=decl_id, arrayOps=array_ops, paramQual=param_qual
|
|
1445
|
+
)
|
|
1446
|
+
|
|
1447
|
+
def _parse_declarator(
|
|
1448
|
+
self, named: bool | str, param_mode: str, typed: bool = True
|
|
1449
|
+
) -> ASTDeclarator:
|
|
1366
1450
|
# 'typed' here means 'parse return type stuff'
|
|
1367
|
-
if
|
|
1368
|
-
raise Exception(
|
|
1369
|
-
|
|
1370
|
-
prevErrors = []
|
|
1451
|
+
if param_mode not in {'type', 'function', 'operatorCast', 'new'}:
|
|
1452
|
+
raise Exception("Internal error, unknown param_mode '%s'." % param_mode)
|
|
1453
|
+
prev_errors = []
|
|
1371
1454
|
self.skip_ws()
|
|
1372
1455
|
if typed and self.skip_string('*'):
|
|
1373
1456
|
self.skip_ws()
|
|
1374
1457
|
volatile = False
|
|
1375
1458
|
const = False
|
|
1376
|
-
|
|
1459
|
+
attr_list = []
|
|
1377
1460
|
while 1:
|
|
1378
1461
|
if not volatile:
|
|
1379
1462
|
volatile = self.skip_word_and_ws('volatile')
|
|
@@ -1385,37 +1468,43 @@ class DefinitionParser(BaseParser):
|
|
|
1385
1468
|
continue
|
|
1386
1469
|
attr = self._parse_attribute()
|
|
1387
1470
|
if attr is not None:
|
|
1388
|
-
|
|
1471
|
+
attr_list.append(attr)
|
|
1389
1472
|
continue
|
|
1390
1473
|
break
|
|
1391
|
-
next = self._parse_declarator(named,
|
|
1392
|
-
return ASTDeclaratorPtr(
|
|
1393
|
-
|
|
1474
|
+
next = self._parse_declarator(named, param_mode, typed)
|
|
1475
|
+
return ASTDeclaratorPtr(
|
|
1476
|
+
next=next,
|
|
1477
|
+
volatile=volatile,
|
|
1478
|
+
const=const,
|
|
1479
|
+
attrs=ASTAttributeList(attr_list),
|
|
1480
|
+
)
|
|
1394
1481
|
# TODO: shouldn't we parse an R-value ref here first?
|
|
1395
|
-
if typed and self.skip_string(
|
|
1482
|
+
if typed and self.skip_string('&'):
|
|
1396
1483
|
attrs = self._parse_attribute_list()
|
|
1397
|
-
next = self._parse_declarator(named,
|
|
1484
|
+
next = self._parse_declarator(named, param_mode, typed)
|
|
1398
1485
|
return ASTDeclaratorRef(next=next, attrs=attrs)
|
|
1399
|
-
if typed and self.skip_string(
|
|
1400
|
-
next = self._parse_declarator(named,
|
|
1486
|
+
if typed and self.skip_string('...'):
|
|
1487
|
+
next = self._parse_declarator(named, param_mode, False)
|
|
1401
1488
|
return ASTDeclaratorParamPack(next=next)
|
|
1402
1489
|
if typed and self.current_char == '(': # note: peeking, not skipping
|
|
1403
|
-
if
|
|
1490
|
+
if param_mode == 'operatorCast':
|
|
1404
1491
|
# TODO: we should be able to parse cast operators which return
|
|
1405
1492
|
# function pointers. For now, just hax it and ignore.
|
|
1406
|
-
return ASTDeclaratorNameParamQual(
|
|
1407
|
-
|
|
1493
|
+
return ASTDeclaratorNameParamQual(
|
|
1494
|
+
declId=None, arrayOps=[], paramQual=None
|
|
1495
|
+
)
|
|
1408
1496
|
# maybe this is the beginning of params and quals,try that first,
|
|
1409
1497
|
# otherwise assume it's noptr->declarator > ( ptr-declarator )
|
|
1410
1498
|
pos = self.pos
|
|
1411
1499
|
try:
|
|
1412
1500
|
# assume this is params and quals
|
|
1413
|
-
res = self._parse_declarator_name_suffix(named,
|
|
1414
|
-
typed)
|
|
1501
|
+
res = self._parse_declarator_name_suffix(named, param_mode, typed)
|
|
1415
1502
|
return res
|
|
1416
|
-
except DefinitionError as
|
|
1417
|
-
|
|
1418
|
-
|
|
1503
|
+
except DefinitionError as ex_param_qual:
|
|
1504
|
+
prev_errors.append((
|
|
1505
|
+
ex_param_qual,
|
|
1506
|
+
'If declarator-id with parameters-and-qualifiers',
|
|
1507
|
+
))
|
|
1419
1508
|
self.pos = pos
|
|
1420
1509
|
try:
|
|
1421
1510
|
assert self.current_char == '('
|
|
@@ -1423,29 +1512,34 @@ class DefinitionParser(BaseParser):
|
|
|
1423
1512
|
# TODO: hmm, if there is a name, it must be in inner, right?
|
|
1424
1513
|
# TODO: hmm, if there must be parameters, they must be
|
|
1425
1514
|
# inside, right?
|
|
1426
|
-
inner = self._parse_declarator(named,
|
|
1515
|
+
inner = self._parse_declarator(named, param_mode, typed)
|
|
1427
1516
|
if not self.skip_string(')'):
|
|
1428
|
-
self.fail(
|
|
1429
|
-
next = self._parse_declarator(
|
|
1430
|
-
|
|
1431
|
-
|
|
1517
|
+
self.fail('Expected \')\' in "( ptr-declarator )"')
|
|
1518
|
+
next = self._parse_declarator(
|
|
1519
|
+
named=False, param_mode='type', typed=typed
|
|
1520
|
+
)
|
|
1432
1521
|
return ASTDeclaratorParen(inner=inner, next=next)
|
|
1433
|
-
except DefinitionError as
|
|
1522
|
+
except DefinitionError as ex_no_ptr_paren:
|
|
1434
1523
|
self.pos = pos
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1524
|
+
prev_errors.append((
|
|
1525
|
+
ex_no_ptr_paren,
|
|
1526
|
+
'If parenthesis in noptr-declarator',
|
|
1527
|
+
))
|
|
1528
|
+
header = 'Error in declarator'
|
|
1529
|
+
raise self._make_multi_error(
|
|
1530
|
+
prev_errors, header
|
|
1531
|
+
) from ex_no_ptr_paren
|
|
1438
1532
|
if typed: # pointer to member
|
|
1439
1533
|
pos = self.pos
|
|
1440
1534
|
try:
|
|
1441
|
-
name = self._parse_nested_name(
|
|
1535
|
+
name = self._parse_nested_name(member_pointer=True)
|
|
1442
1536
|
self.skip_ws()
|
|
1443
1537
|
if not self.skip_string('*'):
|
|
1444
1538
|
self.fail("Expected '*' in pointer to member declarator.")
|
|
1445
1539
|
self.skip_ws()
|
|
1446
1540
|
except DefinitionError as e:
|
|
1447
1541
|
self.pos = pos
|
|
1448
|
-
|
|
1542
|
+
prev_errors.append((e, 'If pointer to member declarator'))
|
|
1449
1543
|
else:
|
|
1450
1544
|
volatile = False
|
|
1451
1545
|
const = False
|
|
@@ -1459,24 +1553,25 @@ class DefinitionParser(BaseParser):
|
|
|
1459
1553
|
if const:
|
|
1460
1554
|
continue
|
|
1461
1555
|
break
|
|
1462
|
-
next = self._parse_declarator(named,
|
|
1556
|
+
next = self._parse_declarator(named, param_mode, typed)
|
|
1463
1557
|
return ASTDeclaratorMemPtr(name, const, volatile, next=next)
|
|
1464
1558
|
pos = self.pos
|
|
1465
1559
|
try:
|
|
1466
|
-
res = self._parse_declarator_name_suffix(named,
|
|
1560
|
+
res = self._parse_declarator_name_suffix(named, param_mode, typed)
|
|
1467
1561
|
# this is a heuristic for error messages, for when there is a < after a
|
|
1468
1562
|
# nested name, but it was not a successful template argument list
|
|
1469
1563
|
if self.current_char == '<':
|
|
1470
|
-
self.otherErrors.append(self._make_multi_error(
|
|
1564
|
+
self.otherErrors.append(self._make_multi_error(prev_errors, ''))
|
|
1471
1565
|
return res
|
|
1472
1566
|
except DefinitionError as e:
|
|
1473
1567
|
self.pos = pos
|
|
1474
|
-
|
|
1475
|
-
header =
|
|
1476
|
-
raise self._make_multi_error(
|
|
1568
|
+
prev_errors.append((e, 'If declarator-id'))
|
|
1569
|
+
header = 'Error in declarator or parameters-and-qualifiers'
|
|
1570
|
+
raise self._make_multi_error(prev_errors, header) from e
|
|
1477
1571
|
|
|
1478
|
-
def _parse_initializer(
|
|
1479
|
-
|
|
1572
|
+
def _parse_initializer(
|
|
1573
|
+
self, outer: str | None = None, allow_fallback: bool = True
|
|
1574
|
+
) -> ASTInitializer | None:
|
|
1480
1575
|
# initializer # global vars
|
|
1481
1576
|
# -> brace-or-equal-initializer
|
|
1482
1577
|
# | '(' expression-list ')'
|
|
@@ -1496,143 +1591,151 @@ class DefinitionParser(BaseParser):
|
|
|
1496
1591
|
# | '=' braced-init-list
|
|
1497
1592
|
self.skip_ws()
|
|
1498
1593
|
if outer == 'member':
|
|
1499
|
-
|
|
1500
|
-
if
|
|
1501
|
-
return ASTInitializer(
|
|
1594
|
+
braced_init = self._parse_braced_init_list()
|
|
1595
|
+
if braced_init is not None:
|
|
1596
|
+
return ASTInitializer(braced_init, hasAssign=False)
|
|
1502
1597
|
|
|
1503
1598
|
if not self.skip_string('='):
|
|
1504
1599
|
return None
|
|
1505
1600
|
|
|
1506
|
-
|
|
1507
|
-
if
|
|
1508
|
-
return ASTInitializer(
|
|
1601
|
+
braced_init = self._parse_braced_init_list()
|
|
1602
|
+
if braced_init is not None:
|
|
1603
|
+
return ASTInitializer(braced_init)
|
|
1509
1604
|
|
|
1510
1605
|
if outer == 'member':
|
|
1511
|
-
|
|
1606
|
+
fallback_end: list[str] = []
|
|
1512
1607
|
elif outer == 'templateParam':
|
|
1513
|
-
|
|
1608
|
+
fallback_end = [',', '>']
|
|
1514
1609
|
elif outer is None: # function parameter
|
|
1515
|
-
|
|
1610
|
+
fallback_end = [',', ')']
|
|
1516
1611
|
else:
|
|
1517
|
-
self.fail(
|
|
1518
|
-
|
|
1612
|
+
self.fail(
|
|
1613
|
+
"Internal error, initializer for outer '%s' not implemented." % outer
|
|
1614
|
+
)
|
|
1519
1615
|
|
|
1520
|
-
|
|
1616
|
+
in_template = outer == 'templateParam'
|
|
1521
1617
|
|
|
1522
1618
|
def parser() -> ASTExpression:
|
|
1523
|
-
return self._parse_assignment_expression(
|
|
1524
|
-
|
|
1619
|
+
return self._parse_assignment_expression(in_template=in_template)
|
|
1620
|
+
|
|
1621
|
+
value = self._parse_expression_fallback(
|
|
1622
|
+
fallback_end, parser, allow=allow_fallback
|
|
1623
|
+
)
|
|
1525
1624
|
return ASTInitializer(value)
|
|
1526
1625
|
|
|
1527
1626
|
def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType:
|
|
1528
|
-
"""
|
|
1529
|
-
named=False|'maybe'|True: 'maybe' is e.g., for function objects which
|
|
1627
|
+
"""named=False|'maybe'|True: 'maybe' is e.g., for function objects which
|
|
1530
1628
|
doesn't need to name the arguments
|
|
1531
1629
|
|
|
1532
1630
|
outer == operatorCast: annoying case, we should not take the params
|
|
1533
1631
|
"""
|
|
1534
1632
|
if outer: # always named
|
|
1535
|
-
if outer not in
|
|
1536
|
-
|
|
1633
|
+
if outer not in {
|
|
1634
|
+
'type',
|
|
1635
|
+
'member',
|
|
1636
|
+
'function',
|
|
1637
|
+
'operatorCast',
|
|
1638
|
+
'templateParam',
|
|
1639
|
+
}:
|
|
1537
1640
|
raise Exception('Internal error, unknown outer "%s".' % outer)
|
|
1538
1641
|
if outer != 'operatorCast':
|
|
1539
1642
|
assert named
|
|
1540
|
-
if outer in
|
|
1643
|
+
if outer in {'type', 'function'}:
|
|
1541
1644
|
# We allow type objects to just be a name.
|
|
1542
1645
|
# Some functions don't have normal return types: constructors,
|
|
1543
1646
|
# destructors, cast operators
|
|
1544
|
-
|
|
1545
|
-
|
|
1647
|
+
prev_errors = []
|
|
1648
|
+
start_pos = self.pos
|
|
1546
1649
|
# first try without the type
|
|
1547
1650
|
try:
|
|
1548
|
-
|
|
1549
|
-
decl = self._parse_declarator(named=True,
|
|
1550
|
-
|
|
1551
|
-
mustEnd = True
|
|
1651
|
+
decl_specs = self._parse_decl_specs(outer=outer, typed=False)
|
|
1652
|
+
decl = self._parse_declarator(named=True, param_mode=outer, typed=False)
|
|
1653
|
+
must_end = True
|
|
1552
1654
|
if outer == 'function':
|
|
1553
1655
|
# Allow trailing requires on functions.
|
|
1554
1656
|
self.skip_ws()
|
|
1555
1657
|
if re.compile(r'requires\b').match(self.definition, self.pos):
|
|
1556
|
-
|
|
1557
|
-
if
|
|
1658
|
+
must_end = False
|
|
1659
|
+
if must_end:
|
|
1558
1660
|
self.assert_end(allowSemicolon=True)
|
|
1559
|
-
except DefinitionError as
|
|
1661
|
+
except DefinitionError as ex_untyped:
|
|
1560
1662
|
if outer == 'type':
|
|
1561
|
-
desc =
|
|
1663
|
+
desc = 'If just a name'
|
|
1562
1664
|
elif outer == 'function':
|
|
1563
|
-
desc =
|
|
1665
|
+
desc = 'If the function has no return type'
|
|
1564
1666
|
else:
|
|
1565
|
-
raise AssertionError from
|
|
1566
|
-
|
|
1567
|
-
self.pos =
|
|
1667
|
+
raise AssertionError from ex_untyped
|
|
1668
|
+
prev_errors.append((ex_untyped, desc))
|
|
1669
|
+
self.pos = start_pos
|
|
1568
1670
|
try:
|
|
1569
|
-
|
|
1570
|
-
decl = self._parse_declarator(named=True,
|
|
1571
|
-
except DefinitionError as
|
|
1572
|
-
self.pos =
|
|
1671
|
+
decl_specs = self._parse_decl_specs(outer=outer)
|
|
1672
|
+
decl = self._parse_declarator(named=True, param_mode=outer)
|
|
1673
|
+
except DefinitionError as ex_typed:
|
|
1674
|
+
self.pos = start_pos
|
|
1573
1675
|
if outer == 'type':
|
|
1574
|
-
desc =
|
|
1676
|
+
desc = 'If typedef-like declaration'
|
|
1575
1677
|
elif outer == 'function':
|
|
1576
|
-
desc =
|
|
1678
|
+
desc = 'If the function has a return type'
|
|
1577
1679
|
else:
|
|
1578
|
-
raise AssertionError from
|
|
1579
|
-
|
|
1680
|
+
raise AssertionError from ex_untyped
|
|
1681
|
+
prev_errors.append((ex_typed, desc))
|
|
1580
1682
|
# Retain the else branch for easier debugging.
|
|
1581
1683
|
# TODO: it would be nice to save the previous stacktrace
|
|
1582
1684
|
# and output it here.
|
|
1583
1685
|
if True:
|
|
1584
1686
|
if outer == 'type':
|
|
1585
|
-
header =
|
|
1586
|
-
header +=
|
|
1687
|
+
header = 'Type must be either just a name or a '
|
|
1688
|
+
header += 'typedef-like declaration.'
|
|
1587
1689
|
elif outer == 'function':
|
|
1588
|
-
header =
|
|
1690
|
+
header = 'Error when parsing function declaration.'
|
|
1589
1691
|
else:
|
|
1590
|
-
raise AssertionError from
|
|
1591
|
-
raise self._make_multi_error(
|
|
1592
|
-
else:
|
|
1692
|
+
raise AssertionError from ex_untyped
|
|
1693
|
+
raise self._make_multi_error(prev_errors, header) from ex_typed
|
|
1694
|
+
else:
|
|
1593
1695
|
# For testing purposes.
|
|
1594
1696
|
# do it again to get the proper traceback (how do you
|
|
1595
1697
|
# reliably save a traceback when an exception is
|
|
1596
1698
|
# constructed?)
|
|
1597
|
-
self.pos =
|
|
1699
|
+
self.pos = start_pos
|
|
1598
1700
|
typed = True
|
|
1599
|
-
|
|
1600
|
-
decl = self._parse_declarator(
|
|
1601
|
-
|
|
1701
|
+
decl_specs = self._parse_decl_specs(outer=outer, typed=typed)
|
|
1702
|
+
decl = self._parse_declarator(
|
|
1703
|
+
named=True, param_mode=outer, typed=typed
|
|
1704
|
+
)
|
|
1602
1705
|
else:
|
|
1603
|
-
|
|
1706
|
+
param_mode = 'type'
|
|
1604
1707
|
if outer == 'member':
|
|
1605
1708
|
named = True
|
|
1606
1709
|
elif outer == 'operatorCast':
|
|
1607
|
-
|
|
1710
|
+
param_mode = 'operatorCast'
|
|
1608
1711
|
outer = None
|
|
1609
1712
|
elif outer == 'templateParam':
|
|
1610
1713
|
named = 'single'
|
|
1611
|
-
|
|
1612
|
-
decl = self._parse_declarator(named=named,
|
|
1613
|
-
return ASTType(
|
|
1714
|
+
decl_specs = self._parse_decl_specs(outer=outer)
|
|
1715
|
+
decl = self._parse_declarator(named=named, param_mode=param_mode)
|
|
1716
|
+
return ASTType(decl_specs, decl)
|
|
1614
1717
|
|
|
1615
1718
|
def _parse_type_with_init(
|
|
1616
|
-
|
|
1617
|
-
|
|
1719
|
+
self, named: bool | str, outer: str
|
|
1720
|
+
) -> ASTTypeWithInit | ASTTemplateParamConstrainedTypeWithInit:
|
|
1618
1721
|
if outer:
|
|
1619
|
-
assert outer in
|
|
1722
|
+
assert outer in {'type', 'member', 'function', 'templateParam'}
|
|
1620
1723
|
type = self._parse_type(outer=outer, named=named)
|
|
1621
1724
|
if outer != 'templateParam':
|
|
1622
1725
|
init = self._parse_initializer(outer=outer)
|
|
1623
1726
|
return ASTTypeWithInit(type, init)
|
|
1624
1727
|
# it could also be a constrained type parameter, e.g., C T = int&
|
|
1625
1728
|
pos = self.pos
|
|
1626
|
-
|
|
1729
|
+
e_expr = None
|
|
1627
1730
|
try:
|
|
1628
|
-
init = self._parse_initializer(outer=outer,
|
|
1731
|
+
init = self._parse_initializer(outer=outer, allow_fallback=False)
|
|
1629
1732
|
# note: init may be None if there is no =
|
|
1630
1733
|
if init is None:
|
|
1631
1734
|
return ASTTypeWithInit(type, None)
|
|
1632
1735
|
# we parsed an expression, so we must have a , or a >,
|
|
1633
1736
|
# otherwise the expression didn't get everything
|
|
1634
1737
|
self.skip_ws()
|
|
1635
|
-
if self.current_char
|
|
1738
|
+
if self.current_char not in {',', '>'}:
|
|
1636
1739
|
# pretend it didn't happen
|
|
1637
1740
|
self.pos = pos
|
|
1638
1741
|
init = None
|
|
@@ -1641,21 +1744,22 @@ class DefinitionParser(BaseParser):
|
|
|
1641
1744
|
return ASTTypeWithInit(type, init)
|
|
1642
1745
|
except DefinitionError as e:
|
|
1643
1746
|
self.pos = pos
|
|
1644
|
-
|
|
1645
|
-
if not self.skip_string(
|
|
1747
|
+
e_expr = e
|
|
1748
|
+
if not self.skip_string('='):
|
|
1646
1749
|
return ASTTypeWithInit(type, None)
|
|
1647
1750
|
try:
|
|
1648
|
-
|
|
1649
|
-
return ASTTemplateParamConstrainedTypeWithInit(type,
|
|
1650
|
-
except DefinitionError as
|
|
1651
|
-
if
|
|
1751
|
+
type_init = self._parse_type(named=False, outer=None)
|
|
1752
|
+
return ASTTemplateParamConstrainedTypeWithInit(type, type_init)
|
|
1753
|
+
except DefinitionError as e_type:
|
|
1754
|
+
if e_expr is None:
|
|
1652
1755
|
raise
|
|
1653
|
-
errs = [
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
msg
|
|
1658
|
-
|
|
1756
|
+
errs = [
|
|
1757
|
+
(e_expr, 'If default template argument is an expression'),
|
|
1758
|
+
(e_type, 'If default template argument is a type'),
|
|
1759
|
+
]
|
|
1760
|
+
msg = 'Error in non-type template parameter'
|
|
1761
|
+
msg += ' or constrained template parameter.'
|
|
1762
|
+
raise self._make_multi_error(errs, msg) from e_type
|
|
1659
1763
|
|
|
1660
1764
|
def _parse_type_using(self) -> ASTTypeUsing:
|
|
1661
1765
|
name = self._parse_nested_name()
|
|
@@ -1666,10 +1770,10 @@ class DefinitionParser(BaseParser):
|
|
|
1666
1770
|
return ASTTypeUsing(name, type)
|
|
1667
1771
|
|
|
1668
1772
|
def _parse_concept(self) -> ASTConcept:
|
|
1669
|
-
|
|
1773
|
+
nested_name = self._parse_nested_name()
|
|
1670
1774
|
self.skip_ws()
|
|
1671
1775
|
initializer = self._parse_initializer('member')
|
|
1672
|
-
return ASTConcept(
|
|
1776
|
+
return ASTConcept(nested_name, initializer)
|
|
1673
1777
|
|
|
1674
1778
|
def _parse_class(self) -> ASTClass:
|
|
1675
1779
|
attrs = self._parse_attribute_list()
|
|
@@ -1691,10 +1795,10 @@ class DefinitionParser(BaseParser):
|
|
|
1691
1795
|
self.skip_ws()
|
|
1692
1796
|
if not virtual and self.skip_word_and_ws('virtual'):
|
|
1693
1797
|
virtual = True
|
|
1694
|
-
|
|
1798
|
+
base_name = self._parse_nested_name()
|
|
1695
1799
|
self.skip_ws()
|
|
1696
1800
|
pack = self.skip_string('...')
|
|
1697
|
-
bases.append(ASTBaseClass(
|
|
1801
|
+
bases.append(ASTBaseClass(base_name, visibility, virtual, pack))
|
|
1698
1802
|
self.skip_ws()
|
|
1699
1803
|
if self.skip_string(','):
|
|
1700
1804
|
continue
|
|
@@ -1711,10 +1815,10 @@ class DefinitionParser(BaseParser):
|
|
|
1711
1815
|
attrs = self._parse_attribute_list()
|
|
1712
1816
|
name = self._parse_nested_name()
|
|
1713
1817
|
self.skip_ws()
|
|
1714
|
-
|
|
1818
|
+
underlying_type = None
|
|
1715
1819
|
if self.skip_string(':'):
|
|
1716
|
-
|
|
1717
|
-
return ASTEnum(name, scoped,
|
|
1820
|
+
underlying_type = self._parse_type(named=False)
|
|
1821
|
+
return ASTEnum(name, scoped, underlying_type, attrs)
|
|
1718
1822
|
|
|
1719
1823
|
def _parse_enumerator(self) -> ASTEnumerator:
|
|
1720
1824
|
name = self._parse_nested_name()
|
|
@@ -1725,9 +1829,10 @@ class DefinitionParser(BaseParser):
|
|
|
1725
1829
|
self.skip_ws()
|
|
1726
1830
|
|
|
1727
1831
|
def parser() -> ASTExpression:
|
|
1728
|
-
return self._parse_constant_expression(
|
|
1729
|
-
|
|
1730
|
-
|
|
1832
|
+
return self._parse_constant_expression(in_template=False)
|
|
1833
|
+
|
|
1834
|
+
init_val = self._parse_expression_fallback([], parser)
|
|
1835
|
+
init = ASTInitializer(init_val)
|
|
1731
1836
|
return ASTEnumerator(name, init, attrs)
|
|
1732
1837
|
|
|
1733
1838
|
# ==========================================================================
|
|
@@ -1736,9 +1841,9 @@ class DefinitionParser(BaseParser):
|
|
|
1736
1841
|
self.skip_ws()
|
|
1737
1842
|
if self.skip_word('template'):
|
|
1738
1843
|
# declare a template template parameter
|
|
1739
|
-
|
|
1844
|
+
nested_params = self._parse_template_parameter_list()
|
|
1740
1845
|
else:
|
|
1741
|
-
|
|
1846
|
+
nested_params = None
|
|
1742
1847
|
|
|
1743
1848
|
pos = self.pos
|
|
1744
1849
|
try:
|
|
@@ -1749,83 +1854,93 @@ class DefinitionParser(BaseParser):
|
|
|
1749
1854
|
key = 'typename'
|
|
1750
1855
|
elif self.skip_word_and_ws('class'):
|
|
1751
1856
|
key = 'class'
|
|
1752
|
-
elif
|
|
1753
|
-
self.fail(
|
|
1754
|
-
|
|
1857
|
+
elif nested_params:
|
|
1858
|
+
self.fail(
|
|
1859
|
+
"Expected 'typename' or 'class' after "
|
|
1860
|
+
'template template parameter list.'
|
|
1861
|
+
)
|
|
1755
1862
|
else:
|
|
1756
|
-
self.fail(
|
|
1757
|
-
|
|
1863
|
+
self.fail(
|
|
1864
|
+
"Expected 'typename' or 'class' in the "
|
|
1865
|
+
'beginning of template type parameter.'
|
|
1866
|
+
)
|
|
1758
1867
|
self.skip_ws()
|
|
1759
|
-
|
|
1868
|
+
parameter_pack = self.skip_string('...')
|
|
1760
1869
|
self.skip_ws()
|
|
1761
1870
|
if self.match(identifier_re):
|
|
1762
1871
|
identifier = ASTIdentifier(self.matched_text)
|
|
1763
1872
|
else:
|
|
1764
1873
|
identifier = None
|
|
1765
1874
|
self.skip_ws()
|
|
1766
|
-
if not
|
|
1875
|
+
if not parameter_pack and self.skip_string('='):
|
|
1767
1876
|
default = self._parse_type(named=False, outer=None)
|
|
1768
1877
|
else:
|
|
1769
1878
|
default = None
|
|
1770
1879
|
if self.current_char not in ',>':
|
|
1771
1880
|
self.fail('Expected "," or ">" after (template) type parameter.')
|
|
1772
|
-
data = ASTTemplateKeyParamPackIdDefault(
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1881
|
+
data = ASTTemplateKeyParamPackIdDefault(
|
|
1882
|
+
key, identifier, parameter_pack, default
|
|
1883
|
+
)
|
|
1884
|
+
if nested_params:
|
|
1885
|
+
return ASTTemplateParamTemplateType(nested_params, data)
|
|
1776
1886
|
else:
|
|
1777
1887
|
return ASTTemplateParamType(data)
|
|
1778
|
-
except DefinitionError as
|
|
1779
|
-
if
|
|
1888
|
+
except DefinitionError as e_type:
|
|
1889
|
+
if nested_params:
|
|
1780
1890
|
raise
|
|
1781
1891
|
try:
|
|
1782
1892
|
# non-type parameter or constrained type parameter
|
|
1783
1893
|
self.pos = pos
|
|
1784
1894
|
param = self._parse_type_with_init('maybe', 'templateParam')
|
|
1785
1895
|
self.skip_ws()
|
|
1786
|
-
|
|
1787
|
-
return ASTTemplateParamNonType(param,
|
|
1788
|
-
except DefinitionError as
|
|
1896
|
+
parameter_pack = self.skip_string('...')
|
|
1897
|
+
return ASTTemplateParamNonType(param, parameter_pack)
|
|
1898
|
+
except DefinitionError as e_non_type:
|
|
1789
1899
|
self.pos = pos
|
|
1790
|
-
header =
|
|
1791
|
-
errs = [
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1900
|
+
header = 'Error when parsing template parameter.'
|
|
1901
|
+
errs = [
|
|
1902
|
+
(
|
|
1903
|
+
e_type,
|
|
1904
|
+
'If unconstrained type parameter or template type parameter',
|
|
1905
|
+
),
|
|
1906
|
+
(
|
|
1907
|
+
e_non_type,
|
|
1908
|
+
'If constrained type parameter or non-type parameter',
|
|
1909
|
+
),
|
|
1910
|
+
]
|
|
1796
1911
|
raise self._make_multi_error(errs, header) from None
|
|
1797
1912
|
|
|
1798
1913
|
def _parse_template_parameter_list(self) -> ASTTemplateParams:
|
|
1799
1914
|
# only: '<' parameter-list '>'
|
|
1800
1915
|
# we assume that 'template' has just been parsed
|
|
1801
|
-
|
|
1916
|
+
template_params: list[ASTTemplateParam] = []
|
|
1802
1917
|
self.skip_ws()
|
|
1803
|
-
if not self.skip_string(
|
|
1918
|
+
if not self.skip_string('<'):
|
|
1804
1919
|
self.fail("Expected '<' after 'template'")
|
|
1805
|
-
while
|
|
1920
|
+
while True:
|
|
1806
1921
|
pos = self.pos
|
|
1807
1922
|
err = None
|
|
1808
1923
|
try:
|
|
1809
1924
|
param = self._parse_template_parameter()
|
|
1810
|
-
|
|
1811
|
-
except DefinitionError as
|
|
1925
|
+
template_params.append(param)
|
|
1926
|
+
except DefinitionError as e_param:
|
|
1812
1927
|
self.pos = pos
|
|
1813
|
-
err =
|
|
1928
|
+
err = e_param
|
|
1814
1929
|
self.skip_ws()
|
|
1815
1930
|
if self.skip_string('>'):
|
|
1816
|
-
|
|
1817
|
-
return ASTTemplateParams(
|
|
1931
|
+
requires_clause = self._parse_requires_clause()
|
|
1932
|
+
return ASTTemplateParams(template_params, requires_clause)
|
|
1818
1933
|
elif self.skip_string(','):
|
|
1819
1934
|
continue
|
|
1820
1935
|
else:
|
|
1821
|
-
header =
|
|
1936
|
+
header = 'Error in template parameter list.'
|
|
1822
1937
|
errs = []
|
|
1823
1938
|
if err:
|
|
1824
|
-
errs.append((err,
|
|
1939
|
+
errs.append((err, 'If parameter'))
|
|
1825
1940
|
try:
|
|
1826
1941
|
self.fail('Expected "," or ">".')
|
|
1827
1942
|
except DefinitionError as e:
|
|
1828
|
-
errs.append((e,
|
|
1943
|
+
errs.append((e, 'If no parameter'))
|
|
1829
1944
|
logger.debug(errs)
|
|
1830
1945
|
raise self._make_multi_error(errs, header)
|
|
1831
1946
|
|
|
@@ -1845,17 +1960,19 @@ class DefinitionParser(BaseParser):
|
|
|
1845
1960
|
params = []
|
|
1846
1961
|
while 1:
|
|
1847
1962
|
self.skip_ws()
|
|
1848
|
-
|
|
1963
|
+
parameter_pack = self.skip_string('...')
|
|
1849
1964
|
self.skip_ws()
|
|
1850
1965
|
if not self.match(identifier_re):
|
|
1851
|
-
self.fail(
|
|
1966
|
+
self.fail('Expected identifier in template introduction list.')
|
|
1852
1967
|
txt_identifier = self.matched_text
|
|
1853
1968
|
# make sure there isn't a keyword
|
|
1854
1969
|
if txt_identifier in _keywords:
|
|
1855
|
-
self.fail(
|
|
1856
|
-
|
|
1970
|
+
self.fail(
|
|
1971
|
+
'Expected identifier in template introduction list, '
|
|
1972
|
+
'got keyword: %s' % txt_identifier
|
|
1973
|
+
)
|
|
1857
1974
|
identifier = ASTIdentifier(txt_identifier)
|
|
1858
|
-
params.append(ASTTemplateIntroductionParameter(identifier,
|
|
1975
|
+
params.append(ASTTemplateIntroductionParameter(identifier, parameter_pack))
|
|
1859
1976
|
|
|
1860
1977
|
self.skip_ws()
|
|
1861
1978
|
if self.skip_string('}'):
|
|
@@ -1878,148 +1995,176 @@ class DefinitionParser(BaseParser):
|
|
|
1878
1995
|
return None
|
|
1879
1996
|
|
|
1880
1997
|
def parse_and_expr(self: DefinitionParser) -> ASTExpression:
|
|
1881
|
-
|
|
1998
|
+
and_exprs = []
|
|
1882
1999
|
ops = []
|
|
1883
|
-
|
|
2000
|
+
and_exprs.append(self._parse_primary_expression())
|
|
1884
2001
|
while True:
|
|
1885
2002
|
self.skip_ws()
|
|
1886
|
-
|
|
2003
|
+
one_more = False
|
|
1887
2004
|
if self.skip_string('&&'):
|
|
1888
|
-
|
|
2005
|
+
one_more = True
|
|
1889
2006
|
ops.append('&&')
|
|
1890
2007
|
elif self.skip_word('and'):
|
|
1891
|
-
|
|
2008
|
+
one_more = True
|
|
1892
2009
|
ops.append('and')
|
|
1893
|
-
if not
|
|
2010
|
+
if not one_more:
|
|
1894
2011
|
break
|
|
1895
|
-
|
|
1896
|
-
if len(
|
|
1897
|
-
return
|
|
2012
|
+
and_exprs.append(self._parse_primary_expression())
|
|
2013
|
+
if len(and_exprs) == 1:
|
|
2014
|
+
return and_exprs[0]
|
|
1898
2015
|
else:
|
|
1899
|
-
return ASTBinOpExpr(
|
|
2016
|
+
return ASTBinOpExpr(and_exprs, ops)
|
|
1900
2017
|
|
|
1901
|
-
|
|
2018
|
+
or_exprs = []
|
|
1902
2019
|
ops = []
|
|
1903
|
-
|
|
2020
|
+
or_exprs.append(parse_and_expr(self))
|
|
1904
2021
|
while True:
|
|
1905
2022
|
self.skip_ws()
|
|
1906
|
-
|
|
2023
|
+
one_more = False
|
|
1907
2024
|
if self.skip_string('||'):
|
|
1908
|
-
|
|
2025
|
+
one_more = True
|
|
1909
2026
|
ops.append('||')
|
|
1910
2027
|
elif self.skip_word('or'):
|
|
1911
|
-
|
|
2028
|
+
one_more = True
|
|
1912
2029
|
ops.append('or')
|
|
1913
|
-
if not
|
|
2030
|
+
if not one_more:
|
|
1914
2031
|
break
|
|
1915
|
-
|
|
1916
|
-
if len(
|
|
1917
|
-
return ASTRequiresClause(
|
|
2032
|
+
or_exprs.append(parse_and_expr(self))
|
|
2033
|
+
if len(or_exprs) == 1:
|
|
2034
|
+
return ASTRequiresClause(or_exprs[0])
|
|
1918
2035
|
else:
|
|
1919
|
-
return ASTRequiresClause(ASTBinOpExpr(
|
|
2036
|
+
return ASTRequiresClause(ASTBinOpExpr(or_exprs, ops))
|
|
1920
2037
|
|
|
1921
|
-
def _parse_template_declaration_prefix(
|
|
1922
|
-
|
|
2038
|
+
def _parse_template_declaration_prefix(
|
|
2039
|
+
self, object_type: str
|
|
2040
|
+
) -> ASTTemplateDeclarationPrefix | None:
|
|
1923
2041
|
templates: list[ASTTemplateParams | ASTTemplateIntroduction] = []
|
|
1924
2042
|
while 1:
|
|
1925
2043
|
self.skip_ws()
|
|
1926
2044
|
# the saved position is only used to provide a better error message
|
|
1927
2045
|
params: ASTTemplateParams | ASTTemplateIntroduction | None = None
|
|
1928
2046
|
pos = self.pos
|
|
1929
|
-
if self.skip_word(
|
|
2047
|
+
if self.skip_word('template'):
|
|
1930
2048
|
try:
|
|
1931
2049
|
params = self._parse_template_parameter_list()
|
|
1932
2050
|
except DefinitionError as e:
|
|
1933
|
-
if
|
|
2051
|
+
if object_type == 'member' and len(templates) == 0:
|
|
1934
2052
|
return ASTTemplateDeclarationPrefix(None)
|
|
1935
2053
|
else:
|
|
1936
|
-
raise
|
|
1937
|
-
if
|
|
2054
|
+
raise
|
|
2055
|
+
if object_type == 'concept' and params.requiresClause is not None:
|
|
1938
2056
|
self.fail('requires-clause not allowed for concept')
|
|
1939
2057
|
else:
|
|
1940
2058
|
params = self._parse_template_introduction()
|
|
1941
2059
|
if not params:
|
|
1942
2060
|
break
|
|
1943
|
-
if
|
|
2061
|
+
if object_type == 'concept' and len(templates) > 0:
|
|
1944
2062
|
self.pos = pos
|
|
1945
|
-
self.fail(
|
|
2063
|
+
self.fail('More than 1 template parameter list for concept.')
|
|
1946
2064
|
templates.append(params)
|
|
1947
|
-
if len(templates) == 0 and
|
|
2065
|
+
if len(templates) == 0 and object_type == 'concept':
|
|
1948
2066
|
self.fail('Missing template parameter list for concept.')
|
|
1949
2067
|
if len(templates) == 0:
|
|
1950
2068
|
return None
|
|
1951
2069
|
else:
|
|
1952
2070
|
return ASTTemplateDeclarationPrefix(templates)
|
|
1953
2071
|
|
|
1954
|
-
def _check_template_consistency(
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
2072
|
+
def _check_template_consistency(
|
|
2073
|
+
self,
|
|
2074
|
+
nested_name: ASTNestedName,
|
|
2075
|
+
template_prefix: ASTTemplateDeclarationPrefix,
|
|
2076
|
+
full_spec_shorthand: bool,
|
|
2077
|
+
is_member: bool = False,
|
|
2078
|
+
) -> ASTTemplateDeclarationPrefix:
|
|
2079
|
+
num_args = nested_name.num_templates()
|
|
2080
|
+
is_member_instantiation = False
|
|
2081
|
+
if not template_prefix:
|
|
2082
|
+
num_params = 0
|
|
1962
2083
|
else:
|
|
1963
|
-
if
|
|
1964
|
-
|
|
1965
|
-
|
|
2084
|
+
if is_member and template_prefix.templates is None:
|
|
2085
|
+
num_params = 0
|
|
2086
|
+
is_member_instantiation = True
|
|
1966
2087
|
else:
|
|
1967
|
-
|
|
1968
|
-
if
|
|
1969
|
-
self.fail(
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
2088
|
+
num_params = len(template_prefix.templates)
|
|
2089
|
+
if num_args + 1 < num_params:
|
|
2090
|
+
self.fail(
|
|
2091
|
+
'Too few template argument lists compared to parameter'
|
|
2092
|
+
' lists. Argument lists: %d, Parameter lists: %d.'
|
|
2093
|
+
% (num_args, num_params)
|
|
2094
|
+
)
|
|
2095
|
+
if num_args > num_params:
|
|
2096
|
+
num_extra = num_args - num_params
|
|
2097
|
+
if not full_spec_shorthand and not is_member_instantiation:
|
|
1975
2098
|
msg = (
|
|
1976
2099
|
f'Too many template argument lists compared to parameter lists. '
|
|
1977
|
-
f'Argument lists: {
|
|
1978
|
-
f'Extra empty parameters lists prepended: {
|
|
2100
|
+
f'Argument lists: {num_args:d}, Parameter lists: {num_params:d}, '
|
|
2101
|
+
f'Extra empty parameters lists prepended: {num_extra:d}. '
|
|
1979
2102
|
'Declaration:\n\t'
|
|
1980
2103
|
)
|
|
1981
|
-
if
|
|
1982
|
-
msg += f
|
|
1983
|
-
msg += str(
|
|
2104
|
+
if template_prefix:
|
|
2105
|
+
msg += f'{template_prefix}\n\t'
|
|
2106
|
+
msg += str(nested_name)
|
|
1984
2107
|
self.warn(msg)
|
|
1985
2108
|
|
|
1986
|
-
|
|
1987
|
-
ASTTemplateParams([], requiresClause=None)
|
|
1988
|
-
for _i in range(numExtra)
|
|
2109
|
+
new_templates: list[ASTTemplateParams | ASTTemplateIntroduction] = [
|
|
2110
|
+
ASTTemplateParams([], requiresClause=None) for _i in range(num_extra)
|
|
1989
2111
|
]
|
|
1990
|
-
if
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
return
|
|
2112
|
+
if template_prefix and not is_member_instantiation:
|
|
2113
|
+
new_templates.extend(template_prefix.templates)
|
|
2114
|
+
template_prefix = ASTTemplateDeclarationPrefix(new_templates)
|
|
2115
|
+
return template_prefix
|
|
1994
2116
|
|
|
1995
2117
|
def parse_declaration(self, objectType: str, directiveType: str) -> ASTDeclaration:
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2118
|
+
object_type = objectType
|
|
2119
|
+
directive_type = directiveType
|
|
2120
|
+
if object_type not in {
|
|
2121
|
+
'class',
|
|
2122
|
+
'union',
|
|
2123
|
+
'function',
|
|
2124
|
+
'member',
|
|
2125
|
+
'type',
|
|
2126
|
+
'concept',
|
|
2127
|
+
'enum',
|
|
2128
|
+
'enumerator',
|
|
2129
|
+
}:
|
|
2130
|
+
raise Exception('Internal error, unknown objectType "%s".' % object_type)
|
|
2131
|
+
if directive_type not in {
|
|
2132
|
+
'class',
|
|
2133
|
+
'struct',
|
|
2134
|
+
'union',
|
|
2135
|
+
'function',
|
|
2136
|
+
'member',
|
|
2137
|
+
'var',
|
|
2138
|
+
'type',
|
|
2139
|
+
'concept',
|
|
2140
|
+
'enum',
|
|
2141
|
+
'enum-struct',
|
|
2142
|
+
'enum-class',
|
|
2143
|
+
'enumerator',
|
|
2144
|
+
}:
|
|
2145
|
+
raise Exception(
|
|
2146
|
+
'Internal error, unknown directiveType "%s".' % directive_type
|
|
2147
|
+
)
|
|
2003
2148
|
visibility = None
|
|
2004
|
-
|
|
2005
|
-
|
|
2149
|
+
template_prefix = None
|
|
2150
|
+
trailing_requires_clause = None
|
|
2006
2151
|
declaration: Any = None
|
|
2007
2152
|
|
|
2008
2153
|
self.skip_ws()
|
|
2009
2154
|
if self.match(_visibility_re):
|
|
2010
2155
|
visibility = self.matched_text
|
|
2011
2156
|
|
|
2012
|
-
if
|
|
2013
|
-
|
|
2157
|
+
if object_type in {'type', 'concept', 'member', 'function', 'class', 'union'}:
|
|
2158
|
+
template_prefix = self._parse_template_declaration_prefix(object_type)
|
|
2014
2159
|
|
|
2015
|
-
if
|
|
2016
|
-
|
|
2160
|
+
if object_type == 'type':
|
|
2161
|
+
prev_errors = []
|
|
2017
2162
|
pos = self.pos
|
|
2018
2163
|
try:
|
|
2019
|
-
if not
|
|
2164
|
+
if not template_prefix:
|
|
2020
2165
|
declaration = self._parse_type(named=True, outer='type')
|
|
2021
2166
|
except DefinitionError as e:
|
|
2022
|
-
|
|
2167
|
+
prev_errors.append((e, 'If typedef-like declaration'))
|
|
2023
2168
|
self.pos = pos
|
|
2024
2169
|
pos = self.pos
|
|
2025
2170
|
try:
|
|
@@ -2027,57 +2172,71 @@ class DefinitionParser(BaseParser):
|
|
|
2027
2172
|
declaration = self._parse_type_using()
|
|
2028
2173
|
except DefinitionError as e:
|
|
2029
2174
|
self.pos = pos
|
|
2030
|
-
|
|
2031
|
-
header =
|
|
2032
|
-
raise self._make_multi_error(
|
|
2033
|
-
elif
|
|
2175
|
+
prev_errors.append((e, 'If type alias or template alias'))
|
|
2176
|
+
header = 'Error in type declaration.'
|
|
2177
|
+
raise self._make_multi_error(prev_errors, header) from e
|
|
2178
|
+
elif object_type == 'concept':
|
|
2034
2179
|
declaration = self._parse_concept()
|
|
2035
|
-
elif
|
|
2180
|
+
elif object_type == 'member':
|
|
2036
2181
|
declaration = self._parse_type_with_init(named=True, outer='member')
|
|
2037
|
-
elif
|
|
2182
|
+
elif object_type == 'function':
|
|
2038
2183
|
declaration = self._parse_type(named=True, outer='function')
|
|
2039
|
-
|
|
2040
|
-
elif
|
|
2184
|
+
trailing_requires_clause = self._parse_requires_clause()
|
|
2185
|
+
elif object_type == 'class':
|
|
2041
2186
|
declaration = self._parse_class()
|
|
2042
|
-
elif
|
|
2187
|
+
elif object_type == 'union':
|
|
2043
2188
|
declaration = self._parse_union()
|
|
2044
|
-
elif
|
|
2189
|
+
elif object_type == 'enum':
|
|
2045
2190
|
declaration = self._parse_enum()
|
|
2046
|
-
elif
|
|
2191
|
+
elif object_type == 'enumerator':
|
|
2047
2192
|
declaration = self._parse_enumerator()
|
|
2048
2193
|
else:
|
|
2049
2194
|
raise AssertionError
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2195
|
+
template_prefix = self._check_template_consistency(
|
|
2196
|
+
declaration.name,
|
|
2197
|
+
template_prefix,
|
|
2198
|
+
full_spec_shorthand=False,
|
|
2199
|
+
is_member=object_type == 'member',
|
|
2200
|
+
)
|
|
2054
2201
|
self.skip_ws()
|
|
2055
2202
|
semicolon = self.skip_string(';')
|
|
2056
|
-
return ASTDeclaration(
|
|
2057
|
-
|
|
2058
|
-
|
|
2203
|
+
return ASTDeclaration(
|
|
2204
|
+
object_type,
|
|
2205
|
+
directive_type,
|
|
2206
|
+
visibility,
|
|
2207
|
+
template_prefix,
|
|
2208
|
+
declaration,
|
|
2209
|
+
trailing_requires_clause,
|
|
2210
|
+
semicolon,
|
|
2211
|
+
)
|
|
2059
2212
|
|
|
2060
2213
|
def parse_namespace_object(self) -> ASTNamespace:
|
|
2061
|
-
|
|
2214
|
+
template_prefix = self._parse_template_declaration_prefix(
|
|
2215
|
+
object_type='namespace'
|
|
2216
|
+
)
|
|
2062
2217
|
name = self._parse_nested_name()
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2218
|
+
template_prefix = self._check_template_consistency(
|
|
2219
|
+
name, template_prefix, full_spec_shorthand=False
|
|
2220
|
+
)
|
|
2221
|
+
res = ASTNamespace(name, template_prefix)
|
|
2066
2222
|
res.objectType = 'namespace' # type: ignore[attr-defined]
|
|
2067
2223
|
return res
|
|
2068
2224
|
|
|
2069
2225
|
def parse_xref_object(self) -> tuple[ASTNamespace | ASTDeclaration, bool]:
|
|
2070
2226
|
pos = self.pos
|
|
2071
2227
|
try:
|
|
2072
|
-
|
|
2228
|
+
template_prefix = self._parse_template_declaration_prefix(
|
|
2229
|
+
object_type='xref'
|
|
2230
|
+
)
|
|
2073
2231
|
name = self._parse_nested_name()
|
|
2074
2232
|
# if there are '()' left, just skip them
|
|
2075
2233
|
self.skip_ws()
|
|
2076
2234
|
self.skip_string('()')
|
|
2077
2235
|
self.assert_end()
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2236
|
+
template_prefix = self._check_template_consistency(
|
|
2237
|
+
name, template_prefix, full_spec_shorthand=True
|
|
2238
|
+
)
|
|
2239
|
+
res1 = ASTNamespace(name, template_prefix)
|
|
2081
2240
|
res1.objectType = 'xref' # type: ignore[attr-defined]
|
|
2082
2241
|
return res1, True
|
|
2083
2242
|
except DefinitionError as e1:
|
|
@@ -2090,10 +2249,11 @@ class DefinitionParser(BaseParser):
|
|
|
2090
2249
|
self.assert_end()
|
|
2091
2250
|
return res2, False
|
|
2092
2251
|
except DefinitionError as e2:
|
|
2093
|
-
errs = [
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2252
|
+
errs = [
|
|
2253
|
+
(e1, 'If shorthand ref'),
|
|
2254
|
+
(e2, 'If full function ref'),
|
|
2255
|
+
]
|
|
2256
|
+
msg = 'Error in cross-reference.'
|
|
2097
2257
|
raise self._make_multi_error(errs, msg) from e2
|
|
2098
2258
|
|
|
2099
2259
|
def parse_expression(self) -> ASTExpression | ASTType:
|
|
@@ -2103,16 +2263,14 @@ class DefinitionParser(BaseParser):
|
|
|
2103
2263
|
self.skip_ws()
|
|
2104
2264
|
self.assert_end()
|
|
2105
2265
|
return expr
|
|
2106
|
-
except DefinitionError as
|
|
2266
|
+
except DefinitionError as ex_expr:
|
|
2107
2267
|
self.pos = pos
|
|
2108
2268
|
try:
|
|
2109
2269
|
typ = self._parse_type(False)
|
|
2110
2270
|
self.skip_ws()
|
|
2111
2271
|
self.assert_end()
|
|
2112
2272
|
return typ
|
|
2113
|
-
except DefinitionError as
|
|
2114
|
-
header =
|
|
2115
|
-
errs = []
|
|
2116
|
-
|
|
2117
|
-
errs.append((exType, "If type"))
|
|
2118
|
-
raise self._make_multi_error(errs, header) from exType
|
|
2273
|
+
except DefinitionError as ex_type:
|
|
2274
|
+
header = 'Error when parsing (type) expression.'
|
|
2275
|
+
errs = [(ex_expr, 'If expression'), (ex_type, 'If type')]
|
|
2276
|
+
raise self._make_multi_error(errs, header) from ex_type
|