Skip to content

Commit

Permalink
bind type specifiers of basic types (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
ltcmelo authored Sep 22, 2024
1 parent f5903f4 commit 8236d34
Show file tree
Hide file tree
Showing 9 changed files with 936 additions and 151 deletions.
1 change: 1 addition & 0 deletions C/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ set(CFE_SOURCES
${PROJECT_SOURCE_DIR}/tests/BinderTester_1000_1999.cpp
${PROJECT_SOURCE_DIR}/tests/BinderTester_2000_2999.cpp
${PROJECT_SOURCE_DIR}/tests/BinderTester_3000_3999.cpp
${PROJECT_SOURCE_DIR}/tests/BinderTester_4000_4999.cpp
${PROJECT_SOURCE_DIR}/tests/ParserTester.h
${PROJECT_SOURCE_DIR}/tests/ParserTester.cpp
${PROJECT_SOURCE_DIR}/tests/ParserTester_0000_0999.cpp
Expand Down
2 changes: 2 additions & 0 deletions C/binder/Binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Binder::Binder(SemanticModel* semaModel, const SyntaxTree* tree)
, semaModel_(semaModel)
, stashedScope_(nullptr)
, decltorIsOfTydef_(false)
, tySpecHasImplicit_int(false)
, tySpecHasImplicit_double(false)
, diagReporter_(this)
{}

Expand Down
6 changes: 4 additions & 2 deletions C/binder/Binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class PSY_C_INTERNAL_API Binder final : protected SyntaxVisitor
template <class TyT, class... TyTArgs> TyT* makeType(TyTArgs... args);

bool decltorIsOfTydef_;
bool tySpecHasImplicit_int;
bool tySpecHasImplicit_double;

struct DiagnosticsReporter
{
Expand All @@ -114,9 +116,9 @@ class PSY_C_INTERNAL_API Binder final : protected SyntaxVisitor

/* Type specifiers */
void TypeSpecifierMissingDefaultsToInt(SyntaxToken declTk);
void TwoOrMoreDataTypesInDeclarationSpecifiers(SyntaxToken tySpecTk);
void InvalidType(SyntaxToken tySpecTk);
static const std::string ID_TypeSpecifierMissingDefaultsToInt;
static const std::string ID_TwoOrMoreDataTypesInDeclarationSpecifiers;
static const std::string ID_InvalidType;

/* Type qualifiers */
void InvalidUseOfRestrict(SyntaxToken tyQualTk);
Expand Down
238 changes: 172 additions & 66 deletions C/binder/Binder_Specifiers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ SyntaxVisitor::Action Binder::visitDeclaration_AtSpecifiers_COMMON(
const DeclT* node,
Action (Binder::*visit_AtDeclarators)(const DeclT*))
{
tySpecHasImplicit_int = false;
tySpecHasImplicit_double = false;
for (auto specIt = node->specifiers(); specIt; specIt = specIt->next)
visitIfNotTypeQualifier(specIt->value);

Expand Down Expand Up @@ -169,7 +171,6 @@ SyntaxVisitor::Action Binder::visitIfTypeQualifier(const SpecifierSyntax* spec)
SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSyntax* node)
{
auto tySpecTk = node->specifierToken();

if (tys_.empty()) {
BasicTypeKind basicTyK;
switch (tySpecTk.kind()) {
Expand All @@ -178,12 +179,14 @@ SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSy
break;
case SyntaxKind::Keyword_short:
basicTyK = BasicTypeKind::Short;
tySpecHasImplicit_int = true;
break;
case SyntaxKind::Keyword_int:
basicTyK = BasicTypeKind::Int;
break;
case SyntaxKind::Keyword_long:
basicTyK = BasicTypeKind::Long;
tySpecHasImplicit_int = true;
break;
case SyntaxKind::Keyword_float:
basicTyK = BasicTypeKind::Float;
Expand All @@ -195,12 +198,15 @@ SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSy
basicTyK = BasicTypeKind::Bool;
break;
case SyntaxKind::Keyword__Complex:
tySpecHasImplicit_double = true;
basicTyK = BasicTypeKind::DoubleComplex;
break;
case SyntaxKind::Keyword_signed:
tySpecHasImplicit_int = true;
basicTyK = BasicTypeKind::Int_S;
break;
case SyntaxKind::Keyword_unsigned:
tySpecHasImplicit_int = true;
basicTyK = BasicTypeKind::Int_U;
break;
default:
Expand All @@ -211,103 +217,203 @@ SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSy
}

TY_AT_TOP(ty);
if (ty->kind() != TypeKind::Basic) {
//diagReporter_.
return Action::Skip;
}

BasicType* builtinTy = ty->asBasicType();
auto curBasicTyK = builtinTy->kind();
BasicTypeKind extraBasicTyK;
switch (curBasicTyK) {
case BasicTypeKind::Char:
switch (tySpecTk.kind()) {
case SyntaxKind::Keyword_signed:
extraBasicTyK = BasicTypeKind::Char_S;
PSY_ASSERT_2(ty->kind() == TypeKind::Basic, return Action::Skip);
BasicType* curBasicTy = ty->asBasicType();
auto curBasicTyK = ty->asBasicType()->kind();
switch (tySpecTk.kind()) {
case SyntaxKind::Keyword_char:
switch (curBasicTyK) {
case BasicTypeKind::Int_S:
if (tySpecHasImplicit_int) {
curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S);
return Action::Skip;
}
break;
case SyntaxKind::Keyword_unsigned:
extraBasicTyK = BasicTypeKind::Char_U;
case BasicTypeKind::Int_U:
if (tySpecHasImplicit_int) {
curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U);
return Action::Skip;
}
break;
default:
// report
return Action::Skip;
break;
}
break;

case BasicTypeKind::Char_S:
case BasicTypeKind::Char_U:
// report
return Action::Skip;

case BasicTypeKind::Short:
switch (tySpecTk.kind()) {
case SyntaxKind::Keyword_signed:
extraBasicTyK = BasicTypeKind::Short_S;
case SyntaxKind::Keyword_short:
switch (curBasicTyK) {
case BasicTypeKind::Int:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Short);
return Action::Skip;
case BasicTypeKind::Int_S:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S);
return Action::Skip;
case BasicTypeKind::Int_U:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U);
return Action::Skip;
default:
break;
case SyntaxKind::Keyword_unsigned:
extraBasicTyK = BasicTypeKind::Short_U;
}
break;

case SyntaxKind::Keyword_int: {
auto allowIdentity = tySpecHasImplicit_int;
tySpecHasImplicit_int = false;
switch (curBasicTyK) {
case BasicTypeKind::Short:
case BasicTypeKind::Short_S:
case BasicTypeKind::Short_U:
case BasicTypeKind::Int_S:
case BasicTypeKind::Int_U:
case BasicTypeKind::Long_S:
case BasicTypeKind::Long_U:
case BasicTypeKind::Long:
case BasicTypeKind::LongLong:
case BasicTypeKind::LongLong_S:
case BasicTypeKind::LongLong_U:
if (allowIdentity)
return Action::Skip;
break;
default:
// report
return Action::Skip;
break;
}
break;
}

case BasicTypeKind::Short_S:
case BasicTypeKind::Short_U:
// report
return Action::Skip;
case SyntaxKind::Keyword_long:
switch (curBasicTyK) {
case BasicTypeKind::Int:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Long);
return Action::Skip;
case BasicTypeKind::Int_S:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S);
return Action::Skip;
case BasicTypeKind::Int_U:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U);
return Action::Skip;
case BasicTypeKind::Long:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong);
return Action::Skip;
case BasicTypeKind::Long_S:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S);
return Action::Skip;
case BasicTypeKind::Long_U:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U);
return Action::Skip;
case BasicTypeKind::Double:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDouble);
return Action::Skip;
case BasicTypeKind::DoubleComplex:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex);
return Action::Skip;
default:
break;
}
break;

case BasicTypeKind::Int:
switch (tySpecTk.kind()) {
case SyntaxKind::Keyword_long:
extraBasicTyK = BasicTypeKind::Long;
case SyntaxKind::Keyword_float:
switch (curBasicTyK) {
case BasicTypeKind::DoubleComplex:
if (tySpecHasImplicit_double) {
curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex);
return Action::Skip;
}
break;
default:
break;
case SyntaxKind::Keyword_signed:
extraBasicTyK = BasicTypeKind::Int_S;
}
break;

case SyntaxKind::Keyword_double: {
bool allowIdentity = tySpecHasImplicit_double;
tySpecHasImplicit_double = false;
switch (curBasicTyK) {
case BasicTypeKind::Long:
if (tySpecHasImplicit_int) {
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDouble);
return Action::Skip;
}
break;
case SyntaxKind::Keyword_unsigned:
extraBasicTyK = BasicTypeKind::Int_U;
case BasicTypeKind::DoubleComplex:
case BasicTypeKind::LongDoubleComplex:
if (allowIdentity)
return Action::Skip;
break;
default:
diagReporter_.TwoOrMoreDataTypesInDeclarationSpecifiers(tySpecTk);
return Action::Skip;
break;
}
break;
}

case BasicTypeKind::Int_S:
case BasicTypeKind::Int_U:
// report
return Action::Skip;
case SyntaxKind::Keyword__Bool:
break;

case BasicTypeKind::Long:
switch (tySpecTk.kind()) {
case SyntaxKind::Keyword_int:
case SyntaxKind::Keyword__Complex:
switch (curBasicTyK) {
case BasicTypeKind::Long:
case BasicTypeKind::LongDouble:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex);
return Action::Skip;
case BasicTypeKind::Float:
curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex);
return Action::Skip;
case BasicTypeKind::Double:
curBasicTy->resetBasicTypeKind(BasicTypeKind::DoubleComplex);
return Action::Skip;
case SyntaxKind::Keyword_signed:
extraBasicTyK = BasicTypeKind::Long_S;
break;
case SyntaxKind::Keyword_unsigned:
extraBasicTyK = BasicTypeKind::Long_U;
break;
default:
diagReporter_.TwoOrMoreDataTypesInDeclarationSpecifiers(tySpecTk);
break;
}
break;

case SyntaxKind::Keyword_signed:
switch (curBasicTyK) {
case BasicTypeKind::Char:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S);
return Action::Skip;
case BasicTypeKind::Short:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S);
return Action::Skip;
case BasicTypeKind::Int:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_S);
return Action::Skip;
case BasicTypeKind::Long:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S);
return Action::Skip;
case BasicTypeKind::LongLong:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S);
return Action::Skip;
default:
break;
}
break;

case BasicTypeKind::Long_S:
case BasicTypeKind::Long_U:
// report
return Action::Skip;
case SyntaxKind::Keyword_unsigned:
switch (curBasicTyK) {
case BasicTypeKind::Char:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U);
return Action::Skip;
case BasicTypeKind::Short:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U);
return Action::Skip;
case BasicTypeKind::Int:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_U);
return Action::Skip;
case BasicTypeKind::Long:
curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U);
return Action::Skip;
case BasicTypeKind::LongLong:
curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U);
return Action::Skip;
default:
break;
}
break;

default:
PSY_ASSERT_FAIL_1(return Action::Quit);
}

if (extraBasicTyK != curBasicTyK)
builtinTy->resetBasicTypeKind(extraBasicTyK);

diagReporter_.InvalidType(tySpecTk);
return Action::Skip;
}

Expand Down
10 changes: 5 additions & 5 deletions C/binder/DiagnosticsReporter_Binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const std::string Binder::DiagnosticsReporter::ID_FunctionReturningArray = "Bind

/* Type specifiers */
const std::string Binder::DiagnosticsReporter::ID_TypeSpecifierMissingDefaultsToInt = "Binder-100-6.7.2-2-A";
const std::string Binder::DiagnosticsReporter::ID_TwoOrMoreDataTypesInDeclarationSpecifiers = "Binder-100-6.7.2-2-B";
const std::string Binder::DiagnosticsReporter::ID_InvalidType = "Binder-100-6.7.2-2-B";

/* Type qualifiers */
const std::string Binder::DiagnosticsReporter::ID_InvalidUseOfRestrict = "Binder-300-6.7.3-2";
Expand Down Expand Up @@ -96,12 +96,12 @@ void Binder::DiagnosticsReporter::TypeSpecifierMissingDefaultsToInt(SyntaxToken
declTk);
}

void Binder::DiagnosticsReporter::TwoOrMoreDataTypesInDeclarationSpecifiers(SyntaxToken tySpecTk)
void Binder::DiagnosticsReporter::InvalidType(SyntaxToken tySpecTk)
{
diagnose(DiagnosticDescriptor(
ID_TwoOrMoreDataTypesInDeclarationSpecifiers,
"[[two or more data types in declaration specifiers]]",
"two or more data types in declaration specifiers",
ID_InvalidType,
"[[invaid type]]",
"invalid type",
DiagnosticSeverity::Error,
DiagnosticCategory::Binding),
tySpecTk);
Expand Down
Loading

0 comments on commit 8236d34

Please sign in to comment.