Skip to content

Commit

Permalink
Basic support for typeAliases
Browse files Browse the repository at this point in the history
  • Loading branch information
Chlumsky committed Mar 28, 2023
1 parent 7c5a5ea commit 546eb13
Show file tree
Hide file tree
Showing 28 changed files with 278 additions and 87 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
/generate-configuration-parser.bat
/cmake-gen.bat
/install.bat
/cmake-gen.sh
/build.sh
30 changes: 27 additions & 3 deletions generated/ConfigurationParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ void ConfigurationParser::parseStdString(std::string &value) {
value.clear();
while (*cur != '"') {
if (*cur == '\\') {
char buffer[8];
unescape(buffer);
value += buffer;
char utfBuffer[8];
unescape(utfBuffer);
value += utfBuffer;
continue;
}
if (!*cur)
Expand Down Expand Up @@ -653,6 +653,24 @@ void ConfigurationParser::parseStdVectorConfigurationStringDef(std::vector<Confi
throw Error::JSON_SYNTAX_ERROR;
}

void ConfigurationParser::parseStdMapStdStringStdString(std::map<std::string, std::string> &value) {
if (!matchSymbol('{'))
throw Error::TYPE_MISMATCH;
value.clear();
int separatorCheck = -1;
while (!matchSymbol('}')) {
if (!separatorCheck)
throw Error::JSON_SYNTAX_ERROR;
parseStdString(buffer);
if (!matchSymbol(':'))
throw Error::JSON_SYNTAX_ERROR;
parseStdString(value[buffer]);
separatorCheck = matchSymbol(',');
}
if (separatorCheck == 1)
throw Error::JSON_SYNTAX_ERROR;
}

void ConfigurationParser::parseConstStringAPI(ConstStringAPI &value) {
if (!matchSymbol('{'))
throw Error::TYPE_MISMATCH;
Expand Down Expand Up @@ -1257,6 +1275,12 @@ void ConfigurationParser::parseConfiguration(Configuration &value) {
continue;
}
break;
case 'y':
if (buffer == "typeAliases") {
parseStdMapStdStringStdString(value.typeAliases);
continue;
}
break;
}
break;
case 16:
Expand Down
1 change: 1 addition & 0 deletions generated/ConfigurationParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ConfigurationParser {
void parseStringAPI(StringAPI &value);
void parseConfigurationStringDef(Configuration::StringDef &value);
void parseStdVectorConfigurationStringDef(std::vector<Configuration::StringDef> &value);
void parseStdMapStdStringStdString(std::map<std::string, std::string> &value);
void parseConstStringAPI(ConstStringAPI &value);
void parseConfigurationConstStringDef(Configuration::ConstStringDef &value);
void parseStdVectorConfigurationConstStringDef(std::vector<Configuration::ConstStringDef> &value);
Expand Down
2 changes: 2 additions & 0 deletions src/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <string>
#include <vector>
#include <map>

struct Settings {
/// Specifies how the JSON data is received / outputted.
Expand Down Expand Up @@ -176,6 +177,7 @@ struct Configuration {
std::vector<GeneratorDef> serializers;

std::string stringType = "std::string";
std::map<std::string, std::string> typeAliases;
std::vector<StringDef> stringTypes;
std::vector<ConstStringDef> constStringTypes;
std::vector<ArrayContainerDef> arrayContainerTypes;
Expand Down
2 changes: 2 additions & 0 deletions src/ContainerTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ template <typename... T>
class ContainerType;

class TemplateInstanceCache;
class ArrayContainerTemplate;

// Represents a container type template such as std::vector, std::unique_ptr, etc.
template <typename... T>
Expand All @@ -22,6 +23,7 @@ class ContainerTemplate {
virtual TypeName instanceName(const Type *elementType, T... templateArgs) const = 0;
int templateArgIndex(char c) const;
virtual std::unique_ptr<ContainerType<T...> > instantiate(TemplateInstanceCache *instanceCache, const Type *elementType, T... templateArgs) const = 0;
inline virtual const ArrayContainerTemplate *arrayContainerTemplate() const { return nullptr; }

protected:
inline explicit ContainerTemplate(const std::string &name) : templateName(name) { }
Expand Down
2 changes: 1 addition & 1 deletion src/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const char *const Generator::signature =

const unsigned Generator::FEATURE_CSTDLIB = 0x01;

Generator::Generator(const std::string &className, const StringType *stringType, const Settings &settings) : mStringType(stringType), mSettings(settings), featureBits(0) {
Generator::Generator(const std::string &className, const StringType *stringType, const Settings &settings) : mStringType(stringType), mSettings(settings) {
std::string namePart;
for (char c : className) {
if (c == ':') {
Expand Down
2 changes: 1 addition & 1 deletion src/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Generator {
std::vector<std::pair<std::string, std::string> > virtualTypedefs;
std::set<std::string> resolvedVirtualTypenames;
std::vector<const Type *> entryTypes;
unsigned featureBits;
unsigned featureBits = 0;

std::string generateVirtualTypedefs(const std::string &indent);
std::string generateFunctionName(const char *prefix, const Type *type);
Expand Down
21 changes: 5 additions & 16 deletions src/HeaderParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,10 @@ Type *HeaderParser::parseStruct() {
fullStructName += structName;
}
if (Type *type = typeSet->find(fullStructName)) {
if (!(structType = dynamic_cast<StructureType *>(type)))
if (!(structType = type->structurePrototype()))
throw Error::TYPE_REDEFINITION;
if (forwardDeclaration)
return type;
if (structType->membersFinalized())
throw Error::TYPE_REDEFINITION;
} else {
std::unique_ptr<StructureType> newType(new StructureType(Generator::safeName(fullStructName)));
structType = newType.get();
Expand All @@ -143,15 +141,8 @@ Type *HeaderParser::parseStruct() {
}
matchKeyword("virtual");
if (const Type *baseType = parseType()) {
if (!nonPublic && !parseNamesOnly && dynamic_cast<const StructureType *>(baseType)) {
// Get non-const pointer to baseType
std::string baseTypeName = baseType->name().body();
if (baseTypeName.size() >= 2 && baseTypeName[0] == ':' && baseTypeName[1] == ':')
baseTypeName = baseTypeName.substr(2);
if (StructureType *baseStructType = dynamic_cast<StructureType *>(typeSet->find(baseTypeName)))
structType->inheritFrom(baseStructType);
// else internal error
}
if (!nonPublic && !parseNamesOnly)
structType->inheritFrom(baseType);
} else {
// Skip unrecognized type name - modified skipExpression()
while (skipWhitespaceAndComments(), cur < end) {
Expand Down Expand Up @@ -205,7 +196,7 @@ Type *HeaderParser::parseStruct() {
if (matchSymbol(';')) {
if (!parseNamesOnly && !staticMember && memberBaseType && memberBaseType->name().substance() == TypeName::VIRTUAL) {
// Special case - non-variable anonymous structure is considered part of parent structure
if (!structType->absorb(dynamic_cast<const StructureType *>(memberBaseType)))
if (!structType->absorb(memberBaseType->structureType()))
throw Error::DUPLICATE_STRUCT_MEMBER;
}
continue;
Expand Down Expand Up @@ -292,12 +283,10 @@ Type *HeaderParser::parseEnum() {
} else
fullEnumName = enumNamespace+enumName;
if (Type *type = typeSet->find(fullEnumName)) {
if (!((enumType = dynamic_cast<EnumType *>(type)) && enumType->isEnumClass() == enumClass))
if (!((enumType = type->enumPrototype()) && enumType->isEnumClass() == enumClass))
throw Error::TYPE_REDEFINITION;
if (forwardDeclaration)
return type;
if (enumType->isFinalized())
throw Error::TYPE_REDEFINITION;
} else {
std::unique_ptr<EnumType> newType(new EnumType(enumClass, enumNamespace, Generator::safeName(fullEnumName)));
enumType = newType.get();
Expand Down
3 changes: 3 additions & 0 deletions src/NameFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ std::string formatName(const std::string &name, NameFormat format) {
break;
case NameFormat::UPPERCASE_UNDERSCORE:
separator = '_';
// fallthrough
case NameFormat::UPERCASE_DASH:
for (char c : name) {
if (!isalnum(c)) {
Expand All @@ -28,6 +29,7 @@ std::string formatName(const std::string &name, NameFormat format) {
break;
case NameFormat::LOWERCASE_UNDERSCORE:
separator = '_';
// fallthrough
case NameFormat::LOWERCASE_DASH:
for (char c : name) {
if (!isalnum(c)) {
Expand All @@ -44,6 +46,7 @@ std::string formatName(const std::string &name, NameFormat format) {
break;
case NameFormat::CAMELCASE_CAPITAL:
prevSpace = true;
// fallthrough
case NameFormat::CAMELCASE:
for (char c : name) {
if (!isalnum(c))
Expand Down
2 changes: 1 addition & 1 deletion src/ParserGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ void ParserGenerator::generateParserFunction(const Type *type) {
}

std::string ParserGenerator::generateParserFunctionCall(const Type *type, const std::string &outputArg) {
if (!type)
if (!(type && (type = type->actualType())))
return std::string();
std::string &functionName = functionNames[type->name().fullName()];
if (functionName.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion src/SerializerGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void SerializerGenerator::generateSerializerFunction(const Type *type) {
}

std::string SerializerGenerator::generateSerializerFunctionCall(const Type *type, const std::string &inputArg) {
if (!type)
if (!(type && (type = type->actualType())))
return std::string();
std::string &functionName = functionNames[type->name().fullName()];
if (functionName.empty()) {
Expand Down
4 changes: 2 additions & 2 deletions src/StringSwitchTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ std::unique_ptr<StringSwitchTree> StringSwitchTree::build(const std::string *lab
}

// Find string position (or length) with most unique values and use it as root switch
int commonPrefixLength = 0;
size_t commonPrefixLength = 0;
int maxVariance = 0;
int maxVariancePos = LEAF_NODE_MARKER;
for (size_t i = 0; i < minLength; ++i) {
Expand All @@ -54,7 +54,7 @@ std::unique_ptr<StringSwitchTree> StringSwitchTree::build(const std::string *lab
if (commonPrefixLength == i && variance == 1)
++commonPrefixLength;
}
if (maxVariance <= maxLength-minLength+1) {
if (maxVariance <= int(maxLength-minLength+1)) {
int lengthVariance = 0;
std::vector<bool> lengthOccurences(maxLength+1, false);
for (const std::string *label = labels, *end = labels+count; label < end; ++label) {
Expand Down
17 changes: 17 additions & 0 deletions src/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,30 @@
class ParserGenerator;
class SerializerGenerator;

class Type;
class StringType;
class StructureType;
class EnumType;
class OptionalContainerType;

class Type {

public:
static constexpr int CHANGE_FLAG = 0x01;
static constexpr int BASE_DEPENDENCY_FLAG = 0x02;

virtual ~Type() = default;
inline const TypeName &name() const { return typeName; }
virtual std::string generateParserFunctionBody(ParserGenerator *generator, const std::string &indent) const = 0;
virtual std::string generateSerializerFunctionBody(SerializerGenerator *generator, const std::string &indent) const = 0;
inline virtual const Type *actualType() const { return this; }
inline virtual const StringType *stringType() const { return nullptr; }
inline virtual const OptionalContainerType *optionalContainerType() const { return nullptr; }
inline virtual const StructureType *structureType() const { return nullptr; }
inline virtual const EnumType *enumType() const { return nullptr; }
inline virtual StructureType *structurePrototype() { return nullptr; }
inline virtual EnumType *enumPrototype() { return nullptr; }
inline virtual int compile() { return 0; }

protected:
inline explicit Type(const TypeName &name) : typeName(name) { }
Expand Down
42 changes: 32 additions & 10 deletions src/TypeSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,26 +123,48 @@ TypeSet::ContainerTemplateMap<> &TypeSet::containerTemplateMap() {
return containerTemplates;
}

template <>
const TypeSet::ContainerTemplateMap<> &TypeSet::containerTemplateMap() const {
return containerTemplates;
}

template <>
TypeSet::ContainerTemplateMap<int> &TypeSet::containerTemplateMap() {
return staticArrayContainerTemplates;
}

template <>
const TypeSet::ContainerTemplateMap<int> &TypeSet::containerTemplateMap() const {
return staticArrayContainerTemplates;
}

template <>
TypeSet::ContainerTemplateMap<const Type *> &TypeSet::containerTemplateMap() {
return objectMapContainerTemplates;
}

const Type *TypeSet::finalizeInheritance() {
for (const std::map<std::string, std::unique_ptr<Type> >::value_type &type : types) {
if (StructureType *structType = dynamic_cast<StructureType *>(type.second.get()))
if (!structType->finalizeInheritance())
return structType;
}
for (const std::unique_ptr<Type> &type : unnamedTypes) {
if (StructureType *structType = dynamic_cast<StructureType *>(type.get()))
if (!structType->finalizeInheritance())
return structType;
template <>
const TypeSet::ContainerTemplateMap<const Type *> &TypeSet::containerTemplateMap() const {
return objectMapContainerTemplates;
}

const Type *TypeSet::compile() {
int resultFlags;
do { // Repeat in case of back and forth dependencies
resultFlags = 0;
for (const std::map<std::string, std::unique_ptr<Type> >::value_type &type : types)
resultFlags |= type.second->compile();
for (const std::unique_ptr<Type> &type : unnamedTypes)
resultFlags |= type->compile();
} while (resultFlags&Type::CHANGE_FLAG);
// Cyclic dependency detected
if (resultFlags&Type::BASE_DEPENDENCY_FLAG) {
for (const std::map<std::string, std::unique_ptr<Type> >::value_type &type : types)
if (type.second->compile()&Type::BASE_DEPENDENCY_FLAG)
return type.second.get();
for (const std::unique_ptr<Type> &type : unnamedTypes)
if (type->compile()&Type::BASE_DEPENDENCY_FLAG)
return type.get();
}
return nullptr;
}
6 changes: 4 additions & 2 deletions src/TypeSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class TypeSet {
const ContainerType<T...> *getContainerType(const ContainerTemplate<T...> *containerTemplate, const Type *elementType, T... templateArgs);

// Returns null on success, otherwise the type that failed
const Type *finalizeInheritance();
const Type *compile();

private:
template <typename... T>
Expand All @@ -52,6 +52,8 @@ class TypeSet {
void addBasicType(const char *name, BasicType::Type type);
template <typename... T>
ContainerTemplateMap<T...> &containerTemplateMap();
template <typename... T>
const ContainerTemplateMap<T...> &containerTemplateMap() const;

};

Expand All @@ -66,7 +68,7 @@ ContainerTemplate<T...> *TypeSet::findContainerTemplate(const std::string &name)

template <typename... T>
const ContainerTemplate<T...> *TypeSet::findContainerTemplate(const std::string &name) const {
ContainerTemplateMap<T...> &map = containerTemplateMap<T...>();
const ContainerTemplateMap<T...> &map = containerTemplateMap<T...>();
typename ContainerTemplateMap<T...>::const_iterator it = map.find(name);
if (it != map.end())
return it->second.get();
Expand Down
1 change: 1 addition & 0 deletions src/container-templates/ArrayContainerTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ArrayContainerTemplate : public ContainerTemplate<> {
virtual TypeName instanceName(const Type *elementType) const override;
virtual std::unique_ptr<ContainerType<> > instantiate(TemplateInstanceCache *, const Type *elementType) const override;
inline const ArrayContainerAPI &api() const { return containerAPI; }
inline virtual const ArrayContainerTemplate *arrayContainerTemplate() const override { return this; }

private:
ArrayContainerAPI containerAPI;
Expand Down
Loading

0 comments on commit 546eb13

Please sign in to comment.