Skip to content

Commit

Permalink
C, fix parsing of fundamental types
Browse files Browse the repository at this point in the history
When multiple simple type specifiers are part of the type,
then they may appear in any order.
  • Loading branch information
jakobandersen committed Nov 30, 2021
1 parent 67d6734 commit c09643c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Features added
Bugs fixed
----------

* #9917: C++, parse fundamental types no matter the order of simple type
* #9917: C and C++, parse fundamental types no matter the order of simple type
specifiers.

Testing
Expand Down
51 changes: 27 additions & 24 deletions sphinx/domains/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,28 +95,18 @@
_simple_type_specifiers_re = re.compile(r"""(?x)
\b(
void|_Bool|bool
# Integer
# -------
|((signed|unsigned)\s+)?(char|(
((long\s+long|long|short)\s+)?int
))
|signed|unsigned
|short|long
|char
|int
|__uint128|__int128
# extensions
|((signed|unsigned)\s+)?__int(8|16|32|64|128)
# Floating-point
# --------------
|(float|double|long\s+double)(\s+(_Complex|complex|_Imaginary|imaginary))?
|(_Complex|complex|_Imaginary|imaginary)\s+(float|double|long\s+double)
|__int(8|16|32|64|128) # extension
|float|double
|_Decimal(32|64|128)
# extensions
|__float80|_Float64x|__float128|_Float128|__ibm128
|__fp16
# Fixed-point, extension
|(_Sat\s+)?((signed|unsigned)\s+)?((short|long|long\s+long)\s+)?(_Fract|fract|_Accum|accum)
# Integer types that could be prefixes of the previous ones
# ---------------------------------------------------------
|((signed|unsigned)\s+)?(long\s+long|long|short)
|signed|unsigned
|_Complex|complex|_Imaginary|imaginary
|__float80|_Float64x|__float128|_Float128|__ibm128 # extension
|__fp16 # extension
|_Sat|_Fract|fract|_Accum|accum # extension
)\b
""")

Expand Down Expand Up @@ -636,8 +626,9 @@ class ASTTrailingTypeSpec(ASTBase):


class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
def __init__(self, name: str) -> None:
self.names = name.split()
def __init__(self, names: List[str]) -> None:
assert len(names) != 0
self.names = names

def _stringify(self, transform: StringifyTransform) -> str:
return ' '.join(self.names)
Expand Down Expand Up @@ -2580,12 +2571,24 @@ def _parse_nested_name(self) -> ASTNestedName:
break
return ASTNestedName(names, rooted)

def _parse_simple_type_specifiers(self) -> ASTTrailingTypeSpecFundamental:
names: List[str] = []

self.skip_ws()
while self.match(_simple_type_specifiers_re):
names.append(self.matched_text)
self.skip_ws()
if len(names) == 0:
return None
return ASTTrailingTypeSpecFundamental(names)

def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
# fundamental types, https://en.cppreference.com/w/c/language/type
# and extensions
self.skip_ws()
if self.match(_simple_type_specifiers_re):
return ASTTrailingTypeSpecFundamental(self.matched_text)
res = self._parse_simple_type_specifiers()
if res is not None:
return res

# prefixed
prefix = None
Expand Down
8 changes: 8 additions & 0 deletions tests/test_domain_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:license: BSD, see LICENSE for details.
"""

import itertools
import zlib
from xml.etree import ElementTree

Expand Down Expand Up @@ -329,6 +330,13 @@ def signed(t):
input = "{key}%s foo" % t
output = ' '.join(input.split())
check('type', input, {1: 'foo'}, key='typedef', output=output)
if ' ' in t:
# try permutations of all components
tcs = t.split()
for p in itertools.permutations(tcs):
input = "{key}%s foo" % ' '.join(p)
output = ' '.join(input.split())
check("type", input, {1: 'foo'}, key='typedef', output=output)


def test_domain_c_ast_type_definitions():
Expand Down
2 changes: 1 addition & 1 deletion tests/test_domain_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def makeIdV2():
output = "void f(%s arg)" % t
check("function", input, {1: id1, 2: id2}, output=output)
if ' ' in t:
# try permutations of all commponents
# try permutations of all components
tcs = t.split()
for p in itertools.permutations(tcs):
input = "void f(%s arg)" % ' '.join(p)
Expand Down

0 comments on commit c09643c

Please sign in to comment.