-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#5977: First iteration supporting parsing of known declarations.
- Loading branch information
1 parent
e0a3213
commit 941062e
Showing
9 changed files
with
383 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#pragma once | ||
|
||
#include "ideclmanager.h" | ||
#include <map> | ||
#include <vector> | ||
#include <memory> | ||
#include <thread> | ||
|
||
namespace decl | ||
{ | ||
|
||
class DeclarationParser; | ||
|
||
class DeclarationManager : | ||
public IDeclarationManager | ||
{ | ||
private: | ||
std::map<std::string, IDeclarationParser::Ptr> _parsersByTypename; | ||
|
||
struct RegisteredFolder | ||
{ | ||
std::string folder; | ||
std::string extension; | ||
Type defaultType; | ||
}; | ||
|
||
std::vector<RegisteredFolder> _registeredFolders; | ||
|
||
struct Declarations | ||
{ | ||
// The decl library | ||
NamedDeclarations decls; | ||
|
||
// If not empty, holds the running parser | ||
std::unique_ptr<DeclarationParser> parser; | ||
}; | ||
|
||
// One entry for each decl | ||
std::map<Type, Declarations> _declarationsByType; | ||
std::mutex _declarationLock; | ||
|
||
std::vector<DeclarationBlockSyntax> _unrecognisedBlocks; | ||
std::mutex _unrecognisedBlockLock; | ||
|
||
public: | ||
void registerDeclType(const std::string& typeName, const IDeclarationParser::Ptr& parser) override; | ||
void unregisterDeclType(const std::string& typeName) override; | ||
void registerDeclFolder(Type defaultType, const std::string& inputFolder, const std::string& inputExtension) override; | ||
void foreachDeclaration(Type type, const std::function<void(const IDeclaration&)>& functor) override; | ||
|
||
const std::string& getName() const override; | ||
const StringSet& getDependencies() const override; | ||
void initialiseModule(const IApplicationContext& ctx) override; | ||
|
||
// Invoked once a parser thread has finished. It will move its data over to here. | ||
void onParserFinished(std::map<Type, NamedDeclarations>&& parsedDecls, | ||
std::vector<DeclarationBlockSyntax>&& unrecognisedBlocks); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include "DeclarationParser.h" | ||
|
||
#include "DeclarationManager.h" | ||
|
||
namespace decl | ||
{ | ||
|
||
inline DeclarationBlockSyntax createBlock(const parser::BlockTokeniser::Block& block) | ||
{ | ||
auto spacePos = block.name.find(' '); | ||
|
||
return DeclarationBlockSyntax | ||
{ | ||
spacePos != std::string::npos ? block.name.substr(0, spacePos) : std::string(), // type | ||
spacePos != std::string::npos ? block.name.substr(spacePos + 1) : block.name, // name | ||
block.contents | ||
}; | ||
} | ||
|
||
DeclarationParser::DeclarationParser(DeclarationManager& owner, Type declType, | ||
const std::string& baseDir, const std::string& extension, | ||
const std::map<std::string, IDeclarationParser::Ptr>& parsersByTypename) : | ||
ThreadedDeclParser<void>(declType, baseDir, extension, 1), | ||
_owner(owner), | ||
_parsersByTypename(parsersByTypename) | ||
{ | ||
_defaultTypeParser = getParserByType(declType); | ||
|
||
if (!_defaultTypeParser) throw std::invalid_argument("No parser has been associated to the default type " + getTypeName(declType)); | ||
} | ||
|
||
void DeclarationParser::parse(std::istream& stream, const vfs::FileInfo& fileInfo, const std::string& modDir) | ||
{ | ||
// Cut the incoming stream into declaration blocks | ||
parser::BasicDefBlockTokeniser<std::istream> tokeniser(stream); | ||
|
||
while (tokeniser.hasMoreBlocks()) | ||
{ | ||
auto block = tokeniser.nextBlock(); | ||
|
||
// Convert the incoming block to a DeclarationBlockSyntax | ||
auto blockSyntax = createBlock(block); | ||
|
||
auto spacePos = block.name.find(' '); | ||
|
||
if (spacePos == std::string::npos) | ||
{ | ||
// No type specified, use the default type parser | ||
parseBlock(*_defaultTypeParser, blockSyntax); | ||
continue; | ||
} | ||
|
||
// Locate a parser capable of handling that block | ||
auto parser = _parsersByTypename.find(block.name.substr(0, spacePos)); | ||
|
||
if (parser != _parsersByTypename.end()) | ||
{ | ||
parseBlock(*parser->second, blockSyntax); | ||
continue; | ||
} | ||
|
||
// Unknown block type, move to buffer | ||
_unrecognisedBlocks.emplace_back(std::move(blockSyntax)); | ||
} | ||
} | ||
|
||
void DeclarationParser::onFinishParsing() | ||
{ | ||
// Submit all parsed declarations to the decl manager | ||
_owner.onParserFinished(std::move(_parsedDecls), std::move(_unrecognisedBlocks)); | ||
} | ||
|
||
void DeclarationParser::parseBlock(IDeclarationParser& parser, const DeclarationBlockSyntax& block) | ||
{ | ||
auto declaration = parser.parseFromBlock(block); | ||
|
||
auto& declMap = _parsedDecls.try_emplace(parser.getDeclType(), NamedDeclarations()).first->second; | ||
|
||
// Insert into map, emit a warning on duplicates | ||
auto result = declMap.try_emplace(declaration->getName(), std::move(declaration)); | ||
|
||
if (!result.second) | ||
{ | ||
rWarning() << "[DeclParser]: " << getTypeName(parser.getDeclType()) << " " << | ||
result.first->second->getName() << " has already been declared" << std::endl; | ||
} | ||
} | ||
|
||
IDeclarationParser::Ptr DeclarationParser::getParserByType(Type declType) const | ||
{ | ||
// Get the default type parser | ||
for (const auto& pair : _parsersByTypename) | ||
{ | ||
if (pair.second->getDeclType() == declType) | ||
{ | ||
return pair.second; | ||
} | ||
} | ||
|
||
return {}; | ||
} | ||
|
||
} |
Oops, something went wrong.