Rewrite type specifier parsing.

Type specifiers and type qualifiers can now appear in any order, as specified by the C standards. However, storage class specifiers and function specifiers still cannot be freely mixed with them.
This commit is contained in:
Stephen Heumann 2019-10-01 22:21:47 -05:00
parent 06a027b237
commit 428c991895
2 changed files with 241 additions and 291 deletions

View File

@ -2545,7 +2545,7 @@ procedure DeclarationSpecifiers (isConstant: boolean);
{ declarator }
{ typespec - type specifier }
label 1,2;
label 1,2,3;
var
done: boolean; {for loop termination}
@ -2561,6 +2561,9 @@ var
lUseGlobalPool: boolean; {local copy of useGlobalPool}
globalStruct: boolean; {did we force global pool use?}
typeSpecifiers: tokenSet; {set of tokens specifying the type}
typeDone: boolean; {no more type specifiers can be accepted}
procedure FieldList (tp: typePtr; kind: typeKind);
@ -2731,161 +2734,99 @@ var
end; {CheckConst}
procedure ResolveType;
{ Resolve a set of type specifier keywords to a type }
begin {ResolveType}
{See C17 6.7.2}
if typeSpecifiers = [voidsy] then
typeSpec := voidPtr
else if typeSpecifiers = [charsy] then
typeSpec := uBytePtr
else if typeSpecifiers = [signedsy,charsy] then
typeSpec := bytePtr
else if typeSpecifiers = [unsignedsy,charsy] then
typeSpec := uBytePtr
else if (typeSpecifiers = [shortsy])
or (typeSpecifiers = [signedsy,shortsy])
or (typeSpecifiers = [shortsy,intsy])
or (typeSpecifiers = [signedsy,shortsy,intsy]) then
typeSpec := wordPtr
else if (typeSpecifiers = [unsignedsy,shortsy])
or (typeSpecifiers = [unsignedsy,shortsy,intsy]) then
typeSpec := uWordPtr
else if (typeSpecifiers = [intsy])
or (typeSpecifiers = [signedsy])
or (typeSpecifiers = [signedsy,intsy]) then begin
if unix_1 then
typeSpec := longPtr
else
typeSpec := wordPtr;
end {else if}
else if (typeSpecifiers = [unsignedsy])
or (typeSpecifiers = [unsignedsy,intsy]) then begin
if unix_1 then
typeSpec := uLongPtr
else
typeSpec := uWordPtr;
end {else if}
else if (typeSpecifiers = [longsy])
or (typeSpecifiers = [signedsy,longsy])
or (typeSpecifiers = [longsy,intsy])
or (typeSpecifiers = [signedsy,longsy,intsy]) then
typeSpec := longPtr
else if (typeSpecifiers = [unsignedsy,longsy])
or (typeSpecifiers = [unsignedsy,longsy,intsy]) then
typeSpec := uLongPtr
else if typeSpecifiers = [floatsy] then
typeSpec := realPtr
else if typeSpecifiers = [doublesy] then
typeSpec := doublePtr
else if typeSpecifiers = [longsy,doublesy] then
typeSpec := extendedPtr
else if typeSpecifiers = [compsy] then
typeSpec := compPtr
else if typeSpecifiers = [extendedsy] then
typeSpec := extendedPtr
else
Error(9);
end; {ResolveType}
begin {DeclarationSpecifiers}
isForwardDeclared := false; {not doing a forward reference (yet)}
skipDeclarator := false; {declarations are required (so far)}
CheckConst;
case token.kind of
unsignedsy: begin {unsigned}
NextToken;
typeSpecifiers := [];
typeDone := false;
while token.kind in [unsignedsy,signedsy,intsy,longsy,charsy,shortsy,floatsy,
doublesy,voidsy,compsy,extendedsy,enumsy,structsy,unionsy,typedef,
constsy,volatilesy] do begin
case token.kind of
constsy,volatilesy:
CheckConst;
if token.kind = shortsy then begin
NextToken;
CheckConst;
if token.kind = intsy then begin
NextToken;
CheckConst;
end; {if}
typeSpec := uWordPtr;
end {if}
else if token.kind = longsy then begin
NextToken;
CheckConst;
if token.kind = intsy then begin
NextToken;
CheckConst;
end; {if}
typeSpec := uLongPtr;
end {else if}
else if token.kind = charsy then begin
NextToken;
CheckConst;
typeSpec := uBytePtr;
end {else if}
else if token.kind = intsy then begin
NextToken;
CheckConst;
if unix_1 then
typeSpec := uLongPtr
unsignedsy,signedsy,intsy,longsy,charsy,shortsy,floatsy,doublesy,voidsy,
compsy,extendedsy: begin
if typeDone then
Error(9)
else if token.kind in typeSpecifiers then begin
if (token.kind = longsy)
and (typeSpecifiers <= [signedsy,unsignedsy,longsy,intsy]) then
Error(134)
else
typeSpec := uWordPtr;
end {else if}
Error(9);
end {if}
else begin
CheckConst;
if unix_1 then
typeSpec := uLongPtr
else
typeSpec := uWordPtr;
end; {else if}
end;
signedsy: begin {signed}
typeSpecifiers := typeSpecifiers + [token.kind];
ResolveType;
end; {else}
NextToken;
CheckConst;
if token.kind = shortsy then begin
NextToken;
CheckConst;
if token.kind = intsy then begin
NextToken;
CheckConst;
end; {if}
typeSpec := wordPtr;
end {if}
else if token.kind = longsy then begin
NextToken;
CheckConst;
if token.kind = intsy then begin
NextToken;
CheckConst;
end; {if}
typeSpec := longPtr;
end {else if}
else if token.kind = intsy then begin
NextToken;
CheckConst;
if unix_1 then
typeSpec := longPtr
else
typeSpec := wordPtr;
end {else if}
else if token.kind = charsy then begin
NextToken;
CheckConst;
typeSpec := bytePtr;
end; {else if}
end;
intsy: begin {int}
NextToken;
CheckConst;
if unix_1 then
typeSpec := longPtr
else
typeSpec := wordPtr;
end;
longsy: begin {long}
NextToken;
CheckConst;
typeSpec := longPtr;
if token.kind = intsy then begin
NextToken;
CheckConst;
end {if}
else if token.kind = doublesy then begin
typeSpec := extendedPtr;
NextToken;
CheckConst;
end; {else if}
end;
charsy: begin {char}
NextToken;
CheckConst;
typeSpec := uBytePtr;
end;
shortsy: begin {short}
NextToken;
CheckConst;
if token.kind = intsy then begin
NextToken;
CheckConst;
end; {if}
typeSpec := wordPtr;
end;
floatsy: begin {float}
NextToken;
CheckConst;
typeSpec := realPtr;
end;
doublesy: begin {double}
NextToken;
CheckConst;
typeSpec := doublePtr;
end;
compsy: begin {comp}
NextToken;
CheckConst;
typeSpec := compPtr;
end;
extendedsy: begin {extended}
NextToken;
CheckConst;
typeSpec := extendedPtr;
end;
voidsy: begin {void}
NextToken;
CheckConst;
typeSpec := voidPtr;
end;
enumsy: begin {enum}
if typeDone or (typeSpecifiers <> []) then
Error(9);
NextToken; {skip the 'enum' token}
if token.kind = ident then begin {handle a type definition}
variable := FindSymbol(token, tagSpace, true, true);
@ -2950,10 +2891,13 @@ case token.kind of
end; {else}
end; {if}
1: skipDeclarator := token.kind = semicolonch;
typeDone := true;
end;
structsy, {struct}
unionsy: begin {union}
if typeDone or (typeSpecifiers <> []) then
Error(9);
globalStruct := false; {we didn't make it global}
if token.kind = structsy then {set the type kind to use}
tKind := structType
@ -3035,16 +2979,21 @@ case token.kind of
useGlobalPool := lUseGlobalPool;
typeSpec := structTypePtr;
skipDeclarator := token.kind = semicolonch;
typeDone := true;
end;
typedef: begin {named type definition}
if (typeSpecifiers = []) and not typeDone then begin
typeSpec := token.symbolPtr^.itype;
NextToken;
typeDone := true;
end {if}
else {interpret as declarator, not type specifier}
goto 3;
end;
otherwise: ;
end; {case}
end; {while}
3:
if isconstant then begin {handle a constant type}
new(tPtr);
if typeSpec^.kind in [structType,unionType] then begin

View File

@ -648,6 +648,7 @@ if list or (numErr <> 0) then begin
131: msg := @'numeric constant is too long';
132: msg := @'static assertion failed';
133: msg := @'incomplete or function types may not be used here';
134: msg := @'''long long'' types are not supported by ORCA/C';
otherwise: Error(57);
end; {case}
writeln(msg^);