From 67c3618e593f88eb8177404475586735902d693f Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sun, 25 Jan 2015 18:57:19 +0100 Subject: Restructures parser classes a little, removed Registry from ParserContext, gave a ResourceManager instance to the Project, using ResourceRequest when including or linking files, thought through how "including" and "linking" are handled --- CMakeLists.txt | 3 +- src/core/model/Project.cpp | 4 +- src/core/model/Project.hpp | 20 ++- src/core/parser/ParserContext.cpp | 29 +++- src/core/parser/ParserContext.hpp | 114 ++++++++++--- src/core/parser/ParserScope.hpp | 1 - src/core/parser/ParserStack.cpp | 3 +- src/core/parser/ParserStack.hpp | 27 +--- src/core/resource/ResourceManager.cpp | 234 ++++++++++----------------- src/core/resource/ResourceManager.hpp | 173 ++++++++++++-------- src/plugins/css/CSSParser.cpp | 28 ++-- src/plugins/xml/XmlParser.cpp | 19 +-- test/core/RegistryTest.cpp | 2 +- test/core/parser/StandaloneParserContext.hpp | 12 +- test/plugins/css/CSSParserTest.cpp | 4 +- 15 files changed, 361 insertions(+), 312 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58037c0..b2c24fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,7 @@ ADD_LIBRARY(ousia_core src/core/resource/Resource src/core/resource/ResourceLocator src/core/resource/ResourceManager - src/core/resource/ResourceUtils + src/core/resource/ResourceRequest # src/core/script/ScriptEngine ) @@ -241,6 +241,7 @@ IF(TEST) test/core/model/TypesystemTest test/core/parser/ParserStackTest test/core/resource/ResourceLocatorTest + test/core/resource/ResourceRequestTest # test/core/script/FunctionTest # test/core/script/ObjectTest # test/core/script/VariantTest diff --git a/src/core/model/Project.cpp b/src/core/model/Project.cpp index 45a5c69..a298ffc 100644 --- a/src/core/model/Project.cpp +++ b/src/core/model/Project.cpp @@ -25,9 +25,9 @@ namespace ousia { - -Project::Project(Manager &mgr) +Project::Project(Manager &mgr, Registry ®istry) : Node(mgr), + registry(registry), systemTypesystem(acquire(new SystemTypesystem(mgr))), documents(this) { diff --git a/src/core/model/Project.hpp b/src/core/model/Project.hpp index 642059c..2c50f49 100644 --- a/src/core/model/Project.hpp +++ b/src/core/model/Project.hpp @@ -28,6 +28,8 @@ #ifndef _OUSIA_PROJECT_HPP_ #define _OUSIA_PROJECT_HPP_ +#include + #include "Node.hpp" namespace ousia { @@ -35,8 +37,8 @@ namespace ousia { // Forward declarations class Logger; class Rtti; - - +class Registry; +class ParserContext; class SystemTypesystem; class Typesystem; class Document; @@ -49,6 +51,11 @@ class Domain; */ class Project : public Node { private: + /** + * Reference at the internally used Registry instance. + */ + Registry ®istry; + /** * Private instance of the system typesystem which is distributed as a * reference to all child typesystems. @@ -60,6 +67,11 @@ private: */ NodeVector documents; + /** + * ResourceManager used to manage all resources used by the project. + */ + ResourceManager resourceManager; + protected: /** * Validates the project and all parts it consists of. @@ -73,8 +85,10 @@ public: * Constructor of the Project class. * * @param mgr is the manager instance used for managing this Node. + * @param registry is the registry instance that should be used for locating + * files and finding parsers for these files. */ - Project(Manager &mgr); + Project(Manager &mgr, Registry ®istry); /** * Returns a reference to the internal system typesystem. diff --git a/src/core/parser/ParserContext.cpp b/src/core/parser/ParserContext.cpp index fa26c59..0a75fdf 100644 --- a/src/core/parser/ParserContext.cpp +++ b/src/core/parser/ParserContext.cpp @@ -22,15 +22,28 @@ namespace ousia { /* Class ParserContext */ -ParserContext::ParserContext(ParserScope &scope, Registry ®istry, - Logger &logger, Manager &manager, - Handle project) - : scope(scope), - registry(registry), - logger(logger), - manager(manager), - project(project) +ParserContext::ParserContext(Handle project, ParserScope &scope, + SourceId sourceId, Logger &logger) + : project(project), scope(scope), sourceId(sourceId), logger(logger) { } + +ParserContext::ParserContext(Handle project, ParserScope &scope, + Logger &logger) + : project(project), scope(scope), sourceId(InvalidSourceId), logger(logger) +{ +} + +ParserContext ParserContext::clone(ParserScope &scope, SourceId sourceId) const +{ + return ParserContext{project, scope, sourceId, logger}; +} + +ParserContext ParserContext::clone(SourceId sourceId) const +{ + return ParserContext{project, scope, sourceId, logger}; +} + +Manager &ParserContext::getManager() const { return project->getManager(); } } diff --git a/src/core/parser/ParserContext.hpp b/src/core/parser/ParserContext.hpp index bb64600..c44222f 100644 --- a/src/core/parser/ParserContext.hpp +++ b/src/core/parser/ParserContext.hpp @@ -28,64 +28,128 @@ #ifndef _OUSIA_PARSER_CONTEXT_HPP_ #define _OUSIA_PARSER_CONTEXT_HPP_ +#include #include -#include #include +#include "ParserScope.hpp" + namespace ousia { // Forward declaration class Logger; -class ParserScope; -class Registry; /** - * Struct containing the objects that are passed to a parser instance. + * Class containing the objects that are passed to a parser instance. */ -struct ParserContext { +class ParserContext { +private: /** - * Reference to the ParserScope instance that should be used within the parser. + * Project instance into which the new content should be parsed. */ - ParserScope &scope; + Rooted project; /** - * Reference to the Registry instance that should be used within the parser. + * Reference to the ParserScope instance that should be used within the + * parser. */ - Registry ®istry; + ParserScope &scope; /** - * Reference to the Logger the parser should log any messages to. + * SourceId is the ID of the resource that is currently being processed. */ - Logger &logger; + SourceId sourceId; /** - * Reference to the Manager the parser should append nodes to. + * Reference to the Logger the parser should log any messages to. */ - Manager &manager; + Logger &logger; +public: /** - * Project instance into which the new content should be parsed. + * Constructor of the ParserContext class. + * + * @param project is the project into which the content should be parsed. + * @param scope is a reference to the ParserScope instance that should be + * used to lookup names. + * @param sourceId is a SourceId instance specifying the source the parser + * is reading from. + * @param logger is a reference to the Logger instance that should be used + * to log error messages and warnings that occur while parsing the document. */ - Rooted project; + ParserContext(Handle project, ParserScope &scope, + SourceId sourceId, Logger &logger); /** - * Constructor of the ParserContext class. + * Constructor of the ParserContext class with the sourceId being set + * to the InvalidSourceId value. * + * @param project is the project into which the content should be parsed. * @param scope is a reference to the ParserScope instance that should be * used to lookup names. - * @param registry is a reference at the Registry class, which allows to - * obtain references at parsers for other formats or script engine - * implementations. * @param logger is a reference to the Logger instance that should be used * to log error messages and warnings that occur while parsing the document. - * @param manager is a Reference to the Manager the parser should append - * nodes to. - * @param project is the project into which the content should be parsed. */ - ParserContext(ParserScope &scope, Registry ®istry, Logger &logger, - Manager &manager, Handle project); -}; + ParserContext(Handle project, ParserScope &scope, + Logger &logger); + + /** + * Clones the ParserContext instance but exchanges the ParserScope instance + * and the source id. + * + * @param scope is a reference at the new ParserScope instance. + * @param sourceId is the source id the parser is reading from. + * @return a copy of this ParserContext with exchanged scope and source id. + */ + ParserContext clone(ParserScope &scope, SourceId sourceId) const; + /** + * Clones the ParserContext instance but exchanges the source id. + * + * @param sourceId is the source id the parser is reading from. + * @return a copy of this ParserContext with exchanged source id. + */ + ParserContext clone(SourceId sourceId) const; + + /** + * Returns a handle pointing at the Project node. + * + * @return a project node handle. + */ + Rooted getProject() const { return project; } + + /** + * Returns a reference pointing at the current ParserScope instance. + * + * @return a reference at the parser scope object that should be used during + * the parsing process. + */ + ParserScope &getScope() const { return scope; } + + /** + * Returns a reference pointing at the current LoggerInstance. + * + * @return a reference at LoggerInstance to which all error messages should + * be logged. + */ + Logger &getLogger() const { return logger; } + + /** + * Returns a reference pointing at the manager instance that should be used + * when creating new Managed objects. + * + * @return a reference pointing at the underlying Manager instance. + */ + Manager &getManager() const; + + /** + * Returns the SourceId instance which specifies the source file the parser + * is currently reading from. + * + * @return the current source id. + */ + SourceId getSourceId() const { return sourceId; } +}; } #endif /* _OUSIA_PARSER_CONTEXT_HPP_ */ diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp index a759738..c1369dd 100644 --- a/src/core/parser/ParserScope.hpp +++ b/src/core/parser/ParserScope.hpp @@ -41,7 +41,6 @@ namespace ousia { // Forward declaration class CharReader; -class Registry; class Logger; class ParserScope; diff --git a/src/core/parser/ParserStack.cpp b/src/core/parser/ParserStack.cpp index 3792ee8..02b142a 100644 --- a/src/core/parser/ParserStack.cpp +++ b/src/core/parser/ParserStack.cpp @@ -22,6 +22,7 @@ #include #include +#include namespace ousia { @@ -74,7 +75,7 @@ HandlerInstance HandlerDescriptor::create(const ParserContext &ctx, } // Canonicalize the arguments - arguments.validateMap(args, ctx.logger, true); + arguments.validateMap(args, ctx.getLogger(), true); h->start(args); return HandlerInstance(h, this); diff --git a/src/core/parser/ParserStack.hpp b/src/core/parser/ParserStack.hpp index 6296dff..031ce68 100644 --- a/src/core/parser/ParserStack.hpp +++ b/src/core/parser/ParserStack.hpp @@ -139,15 +139,13 @@ public: const std::string &name() { return handlerData.name; } - ParserScope &scope() { return handlerData.ctx.scope; } + ParserScope &scope() { return handlerData.ctx.getScope(); } - Registry ®istry() { return handlerData.ctx.registry; } + Manager &manager() { return handlerData.ctx.getManager(); } - Manager &manager() { return handlerData.ctx.manager; } + Logger &logger() { return handlerData.ctx.getLogger(); } - Logger &logger() { return handlerData.ctx.logger; } - - Rooted project() { return handlerData.ctx.project; } + Rooted project() { return handlerData.ctx.getProject(); } State state() { return handlerData.state; } @@ -321,11 +319,6 @@ private: */ std::stack stack; - /** - * Reference at some user defined data. - */ - void *userData; - /** * Used internally to get all expected command names for the given state * (does not work if the current Handler instance allows arbitrary @@ -345,9 +338,8 @@ public: * corresponding HandlerDescriptor instances. */ ParserStack(ParserContext &ctx, - const std::multimap &handlers, - void *userData = nullptr) - : ctx(ctx), handlers(handlers), userData(userData){}; + const std::multimap &handlers) + : ctx(ctx), handlers(handlers){}; /** * Returns the state the ParserStack instance currently is in. @@ -425,13 +417,6 @@ public: * @return a reference to the parser context. */ ParserContext &getContext() { return ctx; } - - /** - * Returns the user defined data. - * - * @return the userData pointer that was given in the constructor. - */ - void *getUserData() { return userData; } }; } diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp index 184a16d..03fd65b 100644 --- a/src/core/resource/ResourceManager.cpp +++ b/src/core/resource/ResourceManager.cpp @@ -25,33 +25,17 @@ #include #include #include -#include +#include #include +#include +#include #include #include "ResourceManager.hpp" -#include "ResourceUtils.hpp" +#include "ResourceRequest.hpp" namespace ousia { -/* Static helper functions */ - -static void logUnsopportedType(Logger &logger, Resource &resource, - const RttiSet &supportedTypes) -{ - // Build a list containing the expected type names - std::vector expected; - for (const Rtti *supportedType : supportedTypes) { - expected.push_back(supportedType->name); - } - - // Log the actual error message - logger.error( - std::string("Expected the file \"") + resource.getLocation() + - std::string("\" to define one of the following internal types ") + - Utils::join(expected, ", ", "{", "}")); -} - /* Class ResourceManager */ SourceId ResourceManager::allocateSourceId(const Resource &resource) @@ -86,39 +70,14 @@ void ResourceManager::purgeResource(SourceId sourceId) contextReaders.erase(sourceId); } -Rooted ResourceManager::parse(ParserContext &ctx, Resource &resource, - const std::string &mimetype, - const RttiSet &supportedTypes) +Rooted ResourceManager::parse(Registry ®istry, ParserContext &ctx, + const ResourceRequest &req, ParseMode mode) { - // Try to deduce the mimetype of no mimetype was given - std::string mime = mimetype; - if (mime.empty()) { - mime = ctx.registry.getMimetypeForFilename(resource.getLocation()); - if (mime.empty()) { - ctx.logger.error(std::string("Filename \"") + - resource.getLocation() + - std::string( - "\" has an unknown file extension. Explicitly " - "specify a mimetype.")); - return nullptr; - } - } - - // Fetch a parser for the mimetype - const std::pair &parserDescr = - ctx.registry.getParserForMimetype(mime); - Parser *parser = parserDescr.first; - - // Make sure a parser was found - if (!parser) { - ctx.logger.error(std::string("Cannot parse files of type \"") + mime + - std::string("\"")); - return nullptr; - } - - // Make sure the parser returns at least one of the supported types - if (!Rtti::setIsOneOf(parserDescr.second, supportedTypes)) { - logUnsopportedType(ctx.logger, resource, supportedTypes); + // Locate the resource relative to the old resource, abort if this did not + // work + Resource resource; + if (!req.locate(registry, ctx.getLogger(), resource, + getResource(ctx.getSourceId()))) { return nullptr; } @@ -129,16 +88,31 @@ Rooted ResourceManager::parse(ParserContext &ctx, Resource &resource, Rooted node; try { // Set the current source id in the logger instance - GuardedLogger logger(ctx.logger, SourceLocation{sourceId}); - - // Fetch the input stream and create a char reader - std::unique_ptr is = resource.stream(); - CharReader reader(*is, sourceId); - - // Actually parse the input stream - node = parser->parse(reader, ctx); + { + GuardedLogger logger(ctx.getLogger(), SourceLocation{sourceId}); + + // Fetch the input stream and create a char reader + std::unique_ptr is = resource.stream(); + CharReader reader(*is, sourceId); + + // Actually parse the input stream, distinguish the LINK and the + // INCLUDE + // mode + switch (mode) { + case ParseMode::LINK: { + ParserScope scope; // New empty parser scope instance + ParserContext childCtx = ctx.clone(scope, sourceId); + node = req.getParser()->parse(reader, childCtx); + } + case ParseMode::INCLUDE: { + ParserContext childCtx = ctx.clone(sourceId); + node = req.getParser()->parse(reader, childCtx); + } + } + } if (node == nullptr) { - throw LoggableException{"Internal error: Parser returned null."}; + throw LoggableException{"File \"" + resource.getLocation() + + "\" cannot be parsed."}; } } catch (LoggableException ex) { @@ -146,17 +120,66 @@ Rooted ResourceManager::parse(ParserContext &ctx, Resource &resource, purgeResource(sourceId); // Log the exception and return nullptr - ctx.logger.log(ex); + ctx.getLogger().log(ex); return nullptr; } - // Store the parsed node along with the sourceId - storeNode(sourceId, node); + // Store the parsed node along with the sourceId, if we are in the LINK mode + if (mode == ParseMode::LINK) { + storeNode(sourceId, node); + } // Return the parsed node return node; } +Rooted ResourceManager::link(Registry ®istry, ParserContext &ctx, + const std::string &path, + const std::string &mimetype, + const std::string &rel, + const RttiSet &supportedTypes) +{ + ResourceRequest req{path, mimetype, rel, supportedTypes}; + if (req.deduce(registry, ctx.getLogger())) { + return parse(registry, ctx, req, ParseMode::LINK); + } + return nullptr; +} + +Rooted ResourceManager::include(Registry ®istry, ParserContext &ctx, + const std::string &path, + const std::string &mimetype, + const std::string &rel, + const RttiSet &supportedTypes) +{ + ResourceRequest req{path, mimetype, rel, supportedTypes}; + if (req.deduce(registry, ctx.getLogger())) { + return parse(registry, ctx, req, ParseMode::INCLUDE); + } + return nullptr; +} + +SourceContext ResourceManager::readContext(const SourceLocation &location, + size_t maxContextLength) +{ + const Resource &resource = getResource(location.getSourceId()); + if (resource.isValid()) { + // Fetch a char reader for the resource + std::unique_ptr is = resource.stream(); + CharReader reader{*is, location.getSourceId()}; + + // Return the context + return contextReaders[location.getSourceId()].readContext( + reader, location, maxContextLength, resource.getLocation()); + } + return SourceContext{}; +} + +SourceContext ResourceManager::readContext(const SourceLocation &location) +{ + return readContext(location, SourceContextReader::MAX_MAX_CONTEXT_LENGTH); +} + SourceId ResourceManager::getSourceId(const std::string &location) { auto it = locations.find(location); @@ -187,7 +210,7 @@ Rooted ResourceManager::getNode(Manager &mgr, SourceId sourceId) { auto it = nodes.find(sourceId); if (it != nodes.end()) { - Managed *managed = mgr.getManaged(sourceId); + Managed *managed = mgr.getManaged(it->second); if (managed != nullptr) { return dynamic_cast(managed); } else { @@ -206,86 +229,5 @@ Rooted ResourceManager::getNode(Manager &mgr, const Resource &resource) { return getNode(mgr, getSourceId(resource)); } - -Rooted ResourceManager::link(ParserContext &ctx, const std::string &path, - const std::string &mimetype, - const std::string &rel, - const RttiSet &supportedTypes, - const Resource &relativeTo) -{ - // Try to deduce the ResourceType - ResourceType resourceType = - ResourceUtils::deduceResourceType(rel, supportedTypes, ctx.logger); - - // Lookup the resource for given path and resource type - Resource resource; - if (!ctx.registry.locateResource(resource, path, resourceType, - relativeTo)) { - ctx.logger.error("File \"" + path + "\" not found."); - return nullptr; - } - - // Try to shrink the set of supportedTypes - RttiSet types = ResourceUtils::limitRttiTypes(supportedTypes, rel); - - // Check whether the resource has already been parsed - Rooted node = getNode(ctx.manager, resource); - if (node == nullptr) { - // Node has not already been parsed, parse it now - node = parse(ctx, resource, mimetype, supportedTypes); - - // Abort if parsing failed - if (node == nullptr) { - return nullptr; - } - } - - // Make sure the node has one of the supported types - if (!node->type().isOneOf(supportedTypes)) { - logUnsopportedType(ctx.logger, resource, supportedTypes); - return nullptr; - } - - return node; -} - -Rooted ResourceManager::link(ParserContext &ctx, const std::string &path, - const std::string &mimetype, - const std::string &rel, - const RttiSet &supportedTypes, - SourceId relativeTo) -{ - // Fetch the resource corresponding to the source id, make sure it is valid - const Resource &relativeResource = getResource(relativeTo); - if (!relativeResource.isValid()) { - ctx.logger.fatalError("Internal error: Invalid SourceId supplied."); - return nullptr; - } - - // Continue with the usual include routine - return link(ctx, path, mimetype, rel, supportedTypes, relativeResource); -} - -SourceContext ResourceManager::readContext(const SourceLocation &location, - size_t maxContextLength) -{ - const Resource &resource = getResource(location.getSourceId()); - if (resource.isValid()) { - // Fetch a char reader for the resource - std::unique_ptr is = resource.stream(); - CharReader reader{*is, location.getSourceId()}; - - // Return the context - return contextReaders[location.getSourceId()].readContext( - reader, location, maxContextLength, resource.getLocation()); - } - return SourceContext{}; -} - -SourceContext ResourceManager::readContext(const SourceLocation &location) -{ - return readContext(location, SourceContextReader::MAX_MAX_CONTEXT_LENGTH); -} - } diff --git a/src/core/resource/ResourceManager.hpp b/src/core/resource/ResourceManager.hpp index 221e2cc..6cb3249 100644 --- a/src/core/resource/ResourceManager.hpp +++ b/src/core/resource/ResourceManager.hpp @@ -34,6 +34,7 @@ #include #include +#include #include #include "Resource.hpp" @@ -41,8 +42,11 @@ namespace ousia { // Forward declarations +class Registry; class Node; +class Parser; class ParserContext; +class ResourceRequest; extern const Resource NullResource; /** @@ -51,6 +55,12 @@ extern const Resource NullResource; * and returns references for those resources that already have been parsed. */ class ResourceManager { +public: + /** + * Used internally to set the mode of the Parse function. + */ + enum class ParseMode { LINK, INCLUDE }; + private: /** * Next SourceId to be used. @@ -105,25 +115,113 @@ private: void purgeResource(SourceId sourceId); /** - * Used internally to parse the given resource. + * Used internally to parse the given resource. Can either operate in the + * "link" or the "include" mode. In the latter case the ParserScope instance + * inside the ParserContext is exchanged with an empty one. + * + * @param registry is the registry that should be used to locate the + * resource. + * @param ctx is the context that should be passed to the parser. + * @param req is a ResourceRequest instance that contains all information + * about the requested resource. + * @param mode describes whether the file should be included or linked. + * @return the parsed node or nullptr if something goes wrong. + */ + Rooted parse(Registry ®istry, ParserContext &ctx, + const ResourceRequest &req, ParseMode mode); + +public: + /** + * Resolves the reference to the file specified by the given path and -- if + * this has not already happened -- parses the file. The parser that is + * called is provided a new ParserContext instance with an empty ParserScope + * which allows the Node instance returned by the parser to be cached. Logs + * any problem in the logger instance of the given ParserContext. + * + * @param registry is the registry instance that should be used to lookup + * the parser instances and to locate the resources. + * @param ctx is the context from which the Logger instance will be looked + * up. This context instance is not directly passed to the Parser, the + * ParserScope instance is replaced with a new one. The sourceId specified + * in the context instance will be used as relative location for looking up + * the new resource. + * @param mimetype is the mimetype of the resource that should be parsed + * (may be empty, in which case the mimetype is deduced from the file + * extension) + * @param rel is a "relation string" supplied by the user which specifies + * the relationship of the specified resource. + * @param supportedTypes contains the types of the returned Node the caller + * can deal with. Note that only the types the parser claims to return are + * checked, not the actual result. + * @return the parsed node or nullptr if something goes wrong. + */ + Rooted link(Registry ®istry, ParserContext &ctx, + const std::string &path, const std::string &mimetype = "", + const std::string &rel = "", + const RttiSet &supportedTypes = RttiSet{}); + + /** + * Resolves the reference to the file specified by the given path and parses + * the file using the provided context. As the result of the "include" + * function depends on the ParserScope inside the provided ParserContext + * instance, the resource has to be parsed every time this function is + * called. This contasts the behaviour of the "link" function, which creates + * a new ParserScope and thus guarantees reproducible results. Logs any + * problem in the logger instance of the given ParserContext. * - * @param ctx is the context from the Registry and the Logger instance will - * be looked up. - * @param resource is the resource from which the input stream should be - * obtained. + * @param registry is the registry instance that should be used to lookup + * the parser instances and to locate the resources. + * @param ctx is the context from which the Logger instance will be looked + * up. The sourceId specified in the context instance will be used as + * relative location for looking up the new resource. + * @param path is the requested path of the file that should be included. * @param mimetype is the mimetype of the resource that should be parsed * (may be empty, in which case the mimetype is deduced from the file * extension) + * @param rel is a "relation string" supplied by the user which specifies + * the relationship of the specified resource. * @param supportedTypes contains the types of the returned Node the caller * can deal with. Note that only the types the parser claims to return are * checked, not the actual result. * @return the parsed node or nullptr if something goes wrong. */ - Rooted parse(ParserContext &ctx, Resource &resource, - const std::string &mimetype, - const RttiSet &supportedTypes); + Rooted include(Registry ®istry, ParserContext &ctx, + const std::string &path, + const std::string &mimetype = "", + const std::string &rel = "", + const RttiSet &supportedTypes = RttiSet{}); + + /** + * Creates and returns a SourceContext structure containing information + * about the given SourceLocation (such as line and column number). Throws + * a LoggableException if an irrecoverable error occurs while looking up the + * context (such as a no longer existing resource). + * + * @param location is the SourceLocation for which context information + * should be retrieved. This method is used by the Logger class to print + * pretty messages. + * @param maxContextLength is the maximum length in character of context + * that should be extracted. + * @return a valid SourceContext if a valid SourceLocation was given or an + * invalid SourceContext if the location is invalid. + */ + SourceContext readContext(const SourceLocation &location, + size_t maxContextLength); + /** + * Creates and returns a SourceContext structure containing information + * about the given SourceLocation (such as line and column number). Throws + * a LoggableException if an irrecoverable error occurs while looking up the + * context (such as a no longer existing resource). Does not limit the + * context length. + * + * @param location is the SourceLocation for which context information + * should be retrieved. This method is used by the Logger class to print + * pretty messages. + * @return a valid SourceContext if a valid SourceLocation was given or an + * invalid SourceContext if the location is invalid. + */ + SourceContext readContext(const SourceLocation &location); -public: /** * Returns the sourceId for the given location string. * @@ -188,63 +286,6 @@ public: * @return the Node instance corresponding to the given resource. */ Rooted getNode(Manager &mgr, const Resource &resource); - - /** - * Resolves the reference to the file specified by the given path and -- if - * this has not already happened -- parses the file. Logs any problem in - * the logger instance of the given ParserContext. - * - * @param ctx is the context from the Registry and the Logger instance will - * be looked up. - * @param path is the path to the file that should be included. - * @param mimetype is the mimetype the file was included with. If no - * mimetype is given, the path must have an extension that is known by - */ - Rooted link(ParserContext &ctx, const std::string &path, - const std::string &mimetype = "", - const std::string &rel = "", - const RttiSet &supportedTypes = RttiSet{}, - const Resource &relativeTo = NullResource); - - /** - * Resolves the reference to the file specified by the given path and -- if - * this has not already happened -- parses the file. Logs any problem in - * the logger instance of the given ParserContext. - */ - Rooted link(ParserContext &ctx, const std::string &path, - const std::string &mimetype, const std::string &rel, - const RttiSet &supportedTypes, SourceId relativeTo); - - /** - * Creates and returns a SourceContext structure containing information - * about the given SourceLocation (such as line and column number). Throws - * a LoggableException if an irrecoverable error occurs while looking up the - * context (such as a no longer existing resource). - * - * @param location is the SourceLocation for which context information - * should be retrieved. This method is used by the Logger class to print - * pretty messages. - * @param maxContextLength is the maximum length in character of context - * that should be extracted. - * @return a valid SourceContext if a valid SourceLocation was given or an - * invalid SourceContext if the location is invalid. - */ - SourceContext readContext(const SourceLocation &location, - size_t maxContextLength); - /** - * Creates and returns a SourceContext structure containing information - * about the given SourceLocation (such as line and column number). Throws - * a LoggableException if an irrecoverable error occurs while looking up the - * context (such as a no longer existing resource). Does not limit the - * context length. - * - * @param location is the SourceLocation for which context information - * should be retrieved. This method is used by the Logger class to print - * pretty messages. - * @return a valid SourceContext if a valid SourceLocation was given or an - * invalid SourceContext if the location is invalid. - */ - SourceContext readContext(const SourceLocation &location); }; } diff --git a/src/plugins/css/CSSParser.cpp b/src/plugins/css/CSSParser.cpp index 8cb41ea..cf92d32 100644 --- a/src/plugins/css/CSSParser.cpp +++ b/src/plugins/css/CSSParser.cpp @@ -79,7 +79,7 @@ Rooted CSSParser::doParse(CharReader &reader, ParserContext &ctx) CodeTokenizer tokenizer{reader, CSS_ROOT, CSS_DESCRIPTORS}; tokenizer.ignoreComments = true; tokenizer.ignoreLinebreaks = true; - Rooted root = {new SelectorNode{ctx.manager, "root"}}; + Rooted root = {new SelectorNode{ctx.getManager(), "root"}}; parseDocument(root, tokenizer, ctx); return root; } @@ -165,7 +165,7 @@ std::pair, Rooted> CSSParser::parseSelector( auto tuple = parseSelector(tokenizer, ctx); // then we establish the DESCENDANT relationship s->getEdges().push_back( - new SelectorNode::SelectorEdge(ctx.manager, tuple.first)); + new SelectorNode::SelectorEdge(ctx.getManager(), tuple.first)); // and we return this node as well as the leaf. return std::make_pair(s, tuple.second); } @@ -177,7 +177,7 @@ std::pair, Rooted> CSSParser::parseSelector( auto tuple = parseSelector(tokenizer, ctx); // then we establish the DESCENDANT relationship s->getEdges().push_back(new SelectorNode::SelectorEdge( - ctx.manager, tuple.first, + ctx.getManager(), tuple.first, SelectionOperator::DIRECT_DESCENDANT)); // and we return this node as well as the leaf. return std::make_pair(s, tuple.second); @@ -198,7 +198,7 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, const std::string name = t.content; if (!tokenizer.peek(t)) { // if we are at the end, we just return this selector with its name. - Rooted n{new SelectorNode(ctx.manager, name)}; + Rooted n{new SelectorNode(ctx.getManager(), name)}; return n; } @@ -219,7 +219,7 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, if (!expect(PAREN_OPEN, tokenizer, t, false, ctx)) { // if we don't have any, we return here. Rooted n{new SelectorNode( - ctx.manager, name, {pseudo_select_name, isGenerative})}; + ctx.getManager(), name, {pseudo_select_name, isGenerative})}; return n; } // parse the argument list. @@ -227,18 +227,18 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, // we require at least one argument, if parantheses are used // XXX args.push_back(VariantReader::parseGeneric(tokenizer.getInput(), - ctx.logger, + ctx.getLogger(), {',', ')'}).second); while (expect(COMMA, tokenizer, t, false, ctx)) { // as long as we find commas we expect new arguments. args.push_back( VariantReader::parseGeneric( - tokenizer.getInput(), ctx.logger, {',', ')'}).second); + tokenizer.getInput(), ctx.getLogger(), {',', ')'}).second); } expect(PAREN_CLOSE, tokenizer, t, true, ctx); // and we return with the finished Selector. Rooted n{new SelectorNode( - ctx.manager, name, {pseudo_select_name, args, isGenerative})}; + ctx.getManager(), name, {pseudo_select_name, args, isGenerative})}; return n; } case HASH: { @@ -250,7 +250,7 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, Variant::arrayType args{Variant(t.content.c_str())}; // and we return the finished Selector Rooted n{ - new SelectorNode(ctx.manager, name, {"has_id", args, false})}; + new SelectorNode(ctx.getManager(), name, {"has_id", args, false})}; return n; } case BRACKET_OPEN: { @@ -270,7 +270,7 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, expect(BRACKET_CLOSE, tokenizer, t, true, ctx); // and then we can return the result. Rooted n{new SelectorNode( - ctx.manager, name, {"has_attribute", args, false})}; + ctx.getManager(), name, {"has_attribute", args, false})}; return n; } else { // with an equals sign we have a has_value PseudoSelector and @@ -281,14 +281,14 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, expect(BRACKET_CLOSE, tokenizer, t, true, ctx); // and then we can return the result. Rooted n{new SelectorNode( - ctx.manager, name, {"has_value", args, false})}; + ctx.getManager(), name, {"has_value", args, false})}; return n; } } default: // everything else is not part of the Selector anymore. tokenizer.resetPeek(); - Rooted n{new SelectorNode(ctx.manager, name)}; + Rooted n{new SelectorNode(ctx.getManager(), name)}; return n; } } @@ -296,7 +296,7 @@ Rooted CSSParser::parsePrimitiveSelector(CodeTokenizer &tokenizer, Rooted CSSParser::parseRuleSet(CodeTokenizer &tokenizer, ParserContext &ctx) { - Rooted ruleSet{new RuleSet(ctx.manager)}; + Rooted ruleSet{new RuleSet(ctx.getManager())}; // if we have no ruleset content, we return an empty ruleset. Token t; if (!expect(CURLY_OPEN, tokenizer, t, false, ctx)) { @@ -332,7 +332,7 @@ bool CSSParser::parseRule(CodeTokenizer &tokenizer, ParserContext &ctx, expect(COLON, tokenizer, t, true, ctx); // then the value // TODO: Resolve key for appropriate parsing function here. - value = VariantReader::parseGeneric(tokenizer.getInput(), ctx.logger, + value = VariantReader::parseGeneric(tokenizer.getInput(), ctx.getLogger(), {';'}).second; // and a ; expect(SEMICOLON, tokenizer, t, true, ctx); diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 78d9df8..17bc470 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -32,8 +32,6 @@ namespace ousia { -using namespace ousia::model; - /* Document structure */ static const State STATE_DOCUMENT = 0; static const State STATE_HEAD = 1; @@ -235,24 +233,18 @@ public: /* Adapter Expat -> ParserStack */ -struct XMLParserUserData { - SourceId sourceId; -}; - static SourceLocation syncLoggerPosition(XML_Parser p) { // Fetch the parser stack and the associated user data ParserStack *stack = static_cast(XML_GetUserData(p)); - XMLParserUserData *ud = - static_cast(stack->getUserData()); // Fetch the current location in the XML file size_t offs = XML_GetCurrentByteIndex(p); // Build the source location and update the default location of the current // logger instance - SourceLocation loc{ud->sourceId, offs}; - stack->getContext().logger.setDefaultLocation(loc); + SourceLocation loc{stack->getContext().getSourceId(), offs}; + stack->getContext().getLogger().setDefaultLocation(loc); return loc; } @@ -269,7 +261,7 @@ static void xmlStartElementHandler(void *p, const XML_Char *name, while (*attr) { const std::string key{*(attr++)}; std::pair value = VariantReader::parseGenericString( - *(attr++), stack->getContext().logger); + *(attr++), stack->getContext().getLogger()); args.emplace(std::make_pair(key, value.second)); } stack->start(std::string(name), args, loc); @@ -305,10 +297,7 @@ Rooted XmlParser::doParse(CharReader &reader, ParserContext &ctx) // Create the parser stack instance and pass the reference to the state // machine descriptor - XMLParserUserData data; - data.sourceId = reader.getSourceId(); - - ParserStack stack{ctx, XML_HANDLERS, &data}; + ParserStack stack{ctx, XML_HANDLERS}; XML_SetUserData(&p, &stack); XML_UseParserAsHandlerArg(&p); diff --git a/test/core/RegistryTest.cpp b/test/core/RegistryTest.cpp index 21195f2..1a23139 100644 --- a/test/core/RegistryTest.cpp +++ b/test/core/RegistryTest.cpp @@ -33,7 +33,7 @@ class TestParser : public Parser { protected: Rooted doParse(CharReader &reader, ParserContext &ctx) override { - return new Node{ctx.manager}; + return new Node{ctx.getManager()}; } }; } diff --git a/test/core/parser/StandaloneParserContext.hpp b/test/core/parser/StandaloneParserContext.hpp index 51cd1e6..cae843f 100644 --- a/test/core/parser/StandaloneParserContext.hpp +++ b/test/core/parser/StandaloneParserContext.hpp @@ -34,19 +34,21 @@ public: Manager manager; Logger logger; Registry registry; + Rooted project; ParserScope scope; - Rooted project; ParserContext context; StandaloneParserContext() - : project(new model::Project(manager)), - context(scope, registry, logger, manager, project) + : project(new Project(manager, registry)), + context(project, scope, logger) { } StandaloneParserContext(Logger &externalLogger) - : project(new model::Project(manager)), - context(scope, registry, externalLogger, manager, project){}; + : project(new Project(manager, registry)), + context(project, scope, externalLogger) + { + } }; } diff --git a/test/plugins/css/CSSParserTest.cpp b/test/plugins/css/CSSParserTest.cpp index 5132e51..46b4ebb 100644 --- a/test/plugins/css/CSSParserTest.cpp +++ b/test/plugins/css/CSSParserTest.cpp @@ -266,9 +266,7 @@ void assertException(std::string css) CharReader reader(css); TerminalLogger logger(std::cerr, true); { - GuardedLogger sl(logger); - StandaloneParserContext ctx(sl); - + StandaloneParserContext ctx(logger); CSSParser instance; try { instance.parse(reader, ctx.context).cast(); -- cgit v1.2.3