C, fix parsing of fundamental types

When multiple simple type specifiers are part of the type,
then they may appear in any order.
This commit is contained in:
Jakob Lykke Andersen
2021-11-30 21:57:30 +01:00
parent 67d673406f
commit c09643c21f
4 changed files with 38 additions and 27 deletions

View File

@@ -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

View File

@@ -95,28 +95,18 @@ _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
_simple_type_specifiers_re = re.compile(r"""(?x)
\b(
void|_Bool|bool
# Integer
# -------
|((signed|unsigned)\s+)?(char|(
((long\s+long|long|short)\s+)?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)
|_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
|short|long
|char
|int
|__uint128|__int128
|__int(8|16|32|64|128) # extension
|float|double
|_Decimal(32|64|128)
|_Complex|complex|_Imaginary|imaginary
|__float80|_Float64x|__float128|_Float128|__ibm128 # extension
|__fp16 # extension
|_Sat|_Fract|fract|_Accum|accum # extension
)\b
""")
@@ -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)
@@ -2580,12 +2571,24 @@ class DefinitionParser(BaseParser):
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

View File

@@ -8,6 +8,7 @@
:license: BSD, see LICENSE for details.
"""
import itertools
import zlib
from xml.etree import ElementTree
@@ -329,6 +330,13 @@ def test_domain_c_ast_fundamental_types():
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():

View File

@@ -144,7 +144,7 @@ def test_domain_cpp_ast_fundamental_types():
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)