diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-14 23:42:05 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-14 23:42:05 +0100 |
commit | efe60ac3c3a8725ac71329c0bb19fa9d9c58f399 (patch) | |
tree | 97802b0eec92d51be02b94c939c1285feeaf3b4f /src/core/parser/generic/ParserStateStack.hpp | |
parent | c1776468bc3daab431d0e2b51589dd12df595227 (diff) |
Moved specific file format parsers to formats/ folder, moved old tokenizer to css code (this is the only place where it is actually used)
Diffstat (limited to 'src/core/parser/generic/ParserStateStack.hpp')
-rw-r--r-- | src/core/parser/generic/ParserStateStack.hpp | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/src/core/parser/generic/ParserStateStack.hpp b/src/core/parser/generic/ParserStateStack.hpp new file mode 100644 index 0000000..efc4e4a --- /dev/null +++ b/src/core/parser/generic/ParserStateStack.hpp @@ -0,0 +1,361 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file ParserStack.hpp + * + * Helper classes for document or description parsers. Contains the ParserStack + * class, which is an pushdown automaton responsible for accepting commands in + * the correct order and calling specified handlers. + * + * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) + */ + +#ifndef _OUSIA_PARSER_STACK_HPP_ +#define _OUSIA_PARSER_STACK_HPP_ + +#include <cstdint> + +#include <map> +#include <memory> +#include <set> +#include <stack> +#include <vector> + +#include <core/common/Variant.hpp> +#include <core/common/Logger.hpp> +#include <core/common/Argument.hpp> + +#include "Parser.hpp" +#include "ParserContext.hpp" +#include "ParserState.hpp" + +namespace ousia { + +/** + * Struct collecting all the data that is being passed to a Handler instance. + */ +struct HandlerData { + /** + * Reference to the ParserContext instance that should be used to resolve + * references to nodes in the Graph. + */ + ParserContext &ctx; + + /** + * Contains the name of the tag that is being handled. + */ + const std::string name; + + /** + * Contains the current state of the state machine. + */ + const ParserState &state; + + /** + * Contains the state of the state machine when the parent node was handled. + */ + const ParserState &parentState; + + /** + * Current source code location. + */ + const SourceLocation location; + + /** + * Constructor of the HandlerData class. + * + * @param ctx is the parser context the handler should be executed in. + * @param name is the name of the string. + * @param state is the state this handler was called for. + * @param parentState is the state of the parent command. + * @param location is the location at which the handler is created. + */ + HandlerData(ParserContext &ctx, std::string name, const ParserState &state, + const ParserState &parentState, const SourceLocation location) + : ctx(ctx), + name(std::move(name)), + state(state), + parentState(parentState), + location(location){}; +}; + +/** + * The handler class provides a context for handling an XML tag. It has to be + * overridden and registered in the StateStack class to form handlers for + * concrete XML tags. + */ +class Handler { +private: + /** + * Structure containing the internal handler data. + */ + const HandlerData handlerData; + +public: + /** + * Constructor of the Handler class. + * + * @param data is a structure containing all data being passed to the + * handler. + */ + Handler(const HandlerData &handlerData) : handlerData(handlerData){}; + + /** + * Virtual destructor. + */ + virtual ~Handler(){}; + + /** + * Returns a reference at the ParserContext. + * + * @return a reference at the ParserContext. + */ + ParserContext &context() { return handlerData.ctx; } + + /** + * Returns the command name for which the handler was created. + * + * @return a const reference at the command name. + */ + const std::string &name() { return handlerData.name; } + + /** + * Returns a reference at the ParserScope instance. + * + * @return a reference at the ParserScope instance. + */ + ParserScope &scope() { return handlerData.ctx.getScope(); } + + /** + * Returns a reference at the Manager instance which manages all nodes. + * + * @return a referance at the Manager instance. + */ + Manager &manager() { return handlerData.ctx.getManager(); } + + /** + * Returns a reference at the Logger instance used for logging error + * messages. + * + * @return a reference at the Logger instance. + */ + Logger &logger() { return handlerData.ctx.getLogger(); } + + /** + * Returns a reference at the Project Node, representing the project into + * which the file is currently being parsed. + * + * @return a referance at the Project Node. + */ + Rooted<Project> project() { return handlerData.ctx.getProject(); } + + /** + * Reference at the ParserState descriptor for which this Handler was + * created. + * + * @return a const reference at the constructing ParserState descriptor. + */ + const ParserState &state() { return handlerData.state; } + + /** + * Reference at the ParserState descriptor of the parent state of the state + * for which this Handler was created. Set to ParserStates::None if there + * is no parent state. + * + * @return a const reference at the parent state of the constructing + * ParserState descriptor. + */ + const ParserState &parentState() { return handlerData.parentState; } + + /** + * Returns the current location in the source file. + * + * @return the current location in the source file. + */ + SourceLocation location() { return handlerData.location; } + + /** + * Called when the command that was specified in the constructor is + * instanciated. + * + * @param args is a map from strings to variants (argument name and value). + */ + virtual void start(Variant::mapType &args) = 0; + + /** + * Called whenever the command for which this handler is defined ends. + */ + virtual void end() = 0; + + /** + * Called whenever raw data (int the form of a string) is available for the + * Handler instance. In the default handler an exception is raised if the + * received data contains non-whitespace characters. + * + * @param data is a pointer at the character data that is available for the + * Handler instance. + * @param field is the field number (the interpretation of this value + * depends on the format that is being parsed). + */ + virtual void data(const std::string &data, int field); +}; + +/** + * HandlerConstructor is a function pointer type used to create concrete + * instances of the Handler class. + * + * @param handlerData is the data that should be passed to the new handler + * instance. + * @return a newly created handler instance. + */ +using HandlerConstructor = Handler *(*)(const HandlerData &handlerData); + +/** + * The ParserStack class is a pushdown automaton responsible for turning a + * command stream into a tree of Node instances. + */ +class ParserStack { +private: + /** + * Reference at the parser context. + */ + ParserContext &ctx; + + /** + * Map containing all registered command names and the corresponding + * state descriptors. + */ + const std::multimap<std::string, const ParserState *> &states; + + /** + * Internal stack used for managing the currently active Handler instances. + */ + std::stack<std::shared_ptr<Handler>> stack; + + /** + * Used internally to get all expected command names for the current state. + * This function is used to build error messages. + * + * @return a set of strings containing the names of the expected commands. + */ + std::set<std::string> expectedCommands(); + + /** + * Returns the targetState for a command with the given name that can be + * reached from for the current state. + * + * @param name is the name of the requested command. + * @return nullptr if no target state was found, a pointer at the target + *state + * otherwise. + */ + const ParserState *findTargetState(const std::string &name); + +public: + /** + * Creates a new instance of the ParserStack class. + * + * @param ctx is the parser context the parser stack is working on. + * @param states is a map containing the command names and pointers at the + * corresponding ParserState instances. + */ + ParserStack(ParserContext &ctx, + const std::multimap<std::string, const ParserState *> &states); + + /** + * Tries to reconstruct the parser state from the Scope instance of the + * ParserContext given in the constructor. This functionality is needed for + * including files,as the Parser of the included file needs to be brought to + + an equivalent state as the one in the including file. + * + * @param scope is the ParserScope instance from which the ParserState + * should be reconstructed. + * @param logger is the logger instance to which error messages should be + * written. + * @return true if the operation was sucessful, false otherwise. + */ + bool deduceState(); + + /** + * Returns the state the ParserStack instance currently is in. + * + * @return the state of the currently active Handler instance or STATE_NONE + * if no handler is on the stack. + */ + const ParserState ¤tState(); + + /** + * Returns the command name that is currently being handled. + * + * @return the name of the command currently being handled by the active + * Handler instance or an empty string if no handler is currently active. + */ + std::string currentCommandName(); + + /** + * Function that should be called whenever a new command starts. + * + * @param name is the name of the command. + * @param args is a map from strings to variants (argument name and value). + * Note that the passed map will be modified. + * @param location is the location in the source file at which the command + * starts. + */ + void start(const std::string &name, Variant::mapType &args, + const SourceLocation &location = SourceLocation{}); + + /** + * Function that should be called whenever a new command starts. + * + * @param name is the name of the command. + * @param args is a map from strings to variants (argument name and value). + * @param location is the location in the source file at which the command + * starts. + */ + void start(std::string name, + const Variant::mapType &args = Variant::mapType{}, + const SourceLocation &location = SourceLocation{}); + + /** + * Function called whenever a command ends. + */ + void end(); + + /** + * Function that should be called whenever data is available for the + * command. + * + * @param data is the data that should be passed to the handler. + * @param field is the field number (the interpretation of this value + * depends on the format that is being parsed). + */ + void data(const std::string &data, int field = 0); + + /** + * Returns a reference to the parser context the parser stack is currently + * working on. + * + * @return a reference to the parser context. + */ + ParserContext &getContext() { return ctx; } +}; +} + +#endif /* _OUSIA_PARSER_STACK_HPP_ */ + |