diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-06 16:52:51 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-02-06 16:52:51 +0100 |
commit | 7fb170a87a4551a048487361b7aaf29963dc7b99 (patch) | |
tree | b2f532ec8e6aa54f475c0e48b3ef5d39b6ee3b6c /src | |
parent | 3ceb415e4f81b50b8e46351e9e586794ebf08644 (diff) | |
parent | b211c02c53f3ed38c7d124d6a74f22ee17df7063 (diff) |
Merge branch 'master' of somweyr.de:ousia
Conflicts:
application/src/plugins/xml/XmlParser.cpp
Diffstat (limited to 'src')
-rw-r--r-- | src/core/parser/ParserStack.cpp | 49 | ||||
-rw-r--r-- | src/core/parser/ParserStack.hpp | 28 | ||||
-rw-r--r-- | src/core/parser/ParserState.cpp | 15 | ||||
-rw-r--r-- | src/core/parser/ParserState.hpp | 27 | ||||
-rw-r--r-- | src/plugins/xml/XmlParser.cpp | 25 |
5 files changed, 65 insertions, 79 deletions
diff --git a/src/core/parser/ParserStack.cpp b/src/core/parser/ParserStack.cpp index 50a97c9..0ab7a8e 100644 --- a/src/core/parser/ParserStack.cpp +++ b/src/core/parser/ParserStack.cpp @@ -113,11 +113,12 @@ bool ParserStack::deduceState() return true; } -std::set<std::string> ParserStack::expectedCommands(const ParserState &state) +std::set<std::string> ParserStack::expectedCommands() { + const ParserState *currentState = &(this->currentState()); std::set<std::string> res; for (const auto &v : states) { - if (v.second->parents.count(&state)) { + if (v.second->parents.count(currentState)) { res.insert(v.first); } } @@ -134,42 +135,46 @@ std::string ParserStack::currentCommandName() return stack.empty() ? std::string{} : stack.top()->name(); } -void ParserStack::start(std::string name, Variant::mapType &args, - const SourceLocation &location) +const ParserState *ParserStack::findTargetState(const std::string &name) { - // Fetch the current handler and the current state - ParserState const *currentState = &(this->currentState()); - - // Fetch the correct Handler descriptor for this - ParserState const *targetState = nullptr; - HandlerConstructor ctor = nullptr; + const ParserState *currentState = &(this->currentState()); auto range = states.equal_range(name); for (auto it = range.first; it != range.second; it++) { const ParserStateSet &parents = it->second->parents; if (parents.count(currentState) || parents.count(&ParserStates::All)) { - targetState = it->second; - ctor = targetState->elementHandler ? targetState->elementHandler - : DefaultHandler::create; - break; + return it->second; } } - // Try to use the child handler if one was given - if (!targetState && currentState->childHandler) { - targetState = currentState; - ctor = targetState->childHandler; + return nullptr; +} + +void ParserStack::start(const std::string &name, Variant::mapType &args, + const SourceLocation &location) +{ + ParserState const *targetState = findTargetState(name); + if (!Utils::isIdentifier(name)) { + throw LoggableException(std::string("Invalid identifier \"") + name + + std::string("\"")); } - // No descriptor found, throw an exception. - if (!targetState || !ctor) { - throw InvalidCommand(name, expectedCommands(*currentState)); + if (targetState == nullptr) { + targetState = findTargetState("*"); } + if (targetState == nullptr) { + throw InvalidCommand(name, expectedCommands()); + } + + // Fetch the associated constructor + HandlerConstructor ctor = targetState->elementHandler + ? targetState->elementHandler + : DefaultHandler::create; // Canonicalize the arguments, allow additional arguments targetState->arguments.validateMap(args, ctx.getLogger(), true); // Instantiate the handler and call its start function - Handler *handler = ctor({ctx, name, *targetState, *currentState, location}); + Handler *handler = ctor({ctx, name, *targetState, currentState(), location}); handler->start(args); stack.emplace(handler); } diff --git a/src/core/parser/ParserStack.hpp b/src/core/parser/ParserStack.hpp index 8561d42..efc4e4a 100644 --- a/src/core/parser/ParserStack.hpp +++ b/src/core/parser/ParserStack.hpp @@ -86,9 +86,8 @@ struct HandlerData { * @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) + HandlerData(ParserContext &ctx, std::string name, const ParserState &state, + const ParserState &parentState, const SourceLocation location) : ctx(ctx), name(std::move(name)), state(state), @@ -250,14 +249,23 @@ private: std::stack<std::shared_ptr<Handler>> stack; /** - * Used internally to get all expected command names for the given state - * (does not work if the current Handler instance allows arbitrary - * children). This function is used to build error messages. + * Used internally to get all expected command names for the current state. + * This function is used to build error messages. * - * @param state is the state for which all expected command names should be - * returned. + * @return a set of strings containing the names of the expected commands. */ - std::set<std::string> expectedCommands(const ParserState &state); + 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: /** @@ -309,7 +317,7 @@ public: * @param location is the location in the source file at which the command * starts. */ - void start(std::string name, Variant::mapType &args, + void start(const std::string &name, Variant::mapType &args, const SourceLocation &location = SourceLocation{}); /** diff --git a/src/core/parser/ParserState.cpp b/src/core/parser/ParserState.cpp index 9d3aa7e..f635d86 100644 --- a/src/core/parser/ParserState.cpp +++ b/src/core/parser/ParserState.cpp @@ -22,17 +22,15 @@ namespace ousia { /* Class ParserState */ -ParserState::ParserState() : elementHandler(nullptr), childHandler(nullptr) {} +ParserState::ParserState() : elementHandler(nullptr) {} ParserState::ParserState(ParserStateSet parents, Arguments arguments, RttiSet createdNodeTypes, - HandlerConstructor elementHandler, - HandlerConstructor childHandler) + HandlerConstructor elementHandler) : parents(parents), arguments(arguments), createdNodeTypes(createdNodeTypes), - elementHandler(elementHandler), - childHandler(childHandler) + elementHandler(elementHandler) { } @@ -86,13 +84,6 @@ ParserStateBuilder &ParserStateBuilder::elementHandler( return *this; } -ParserStateBuilder &ParserStateBuilder::childHandler( - HandlerConstructor childHandler) -{ - state.childHandler = childHandler; - return *this; -} - const ParserState &ParserStateBuilder::build() const { return state; } /* Class ParserStateDeductor */ diff --git a/src/core/parser/ParserState.hpp b/src/core/parser/ParserState.hpp index 43b8035..6487fdd 100644 --- a/src/core/parser/ParserState.hpp +++ b/src/core/parser/ParserState.hpp @@ -79,13 +79,6 @@ struct ParserState { HandlerConstructor elementHandler; /** - * Pointer at a function which creates a new concrete Handler instance for - * all child elements for which no matching state is defined. May be nullptr - * in which case no such elements are allowed. - */ - HandlerConstructor childHandler; - - /** * Default constructor, initializes the handlers with nullptr. */ ParserState(); @@ -104,15 +97,10 @@ struct ParserState { * @param elementHandler is a pointer at a function which creates a new * concrete Handler instance for the elements described by this state. May * be nullptr in which case no handler instance is created. - * @param childHandler is a pointer at a function which creates a new - * concrete Handler instance for all child elements for which no matching - * state is defined. May be nullptr in which case no such elements are - * allowed. */ ParserState(ParserStateSet parents, Arguments arguments = Arguments{}, RttiSet createdNodeTypes = RttiSet{}, - HandlerConstructor elementHandler = nullptr, - HandlerConstructor childHandler = nullptr); + HandlerConstructor elementHandler = nullptr); /** * Creates this ParserState from the given ParserStateBuilder instance. @@ -209,19 +197,6 @@ public: ParserStateBuilder &elementHandler(HandlerConstructor elementHandler); /** - * Sets the constructor for the child handler. The constructor creates a new - * concrete Handler instance for all child elements for which no matching - * state is defined. May be nullptr in which case no such elements are - * allowed. - * - * @param childHandler is the HandlerConstructor that should point at the - * constructor of the Handler instance for child elements. - * @return a reference at this ParserStateBuilder instance for method - * chaining. - */ - ParserStateBuilder &childHandler(HandlerConstructor childHandler); - - /** * Returns a reference at the internal ParserState instance that was built * using the ParserStateBuilder. * diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 6a2b160..7b4b1b3 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -77,8 +77,7 @@ public: class DocumentField : public Node { public: - DocumentField(Manager &mgr, std::string name, Handle<Node> parent, - Handle<FieldDescriptor> descriptor) + DocumentField(Manager &mgr, std::string name, Handle<Node> parent) : Node(mgr, name, parent) { } @@ -93,7 +92,7 @@ class DocumentChildHandler : public Handler { public: using Handler::Handler; - void preamble(Hanlde<Node> parentNode, std::string &fieldName, + void preamble(Handle<Node> parentNode, std::string &fieldName, DocumentEntity *&parent, bool &inField) { // check if the parent in the structure tree was an explicit field @@ -691,8 +690,8 @@ public: // StructuredClass as child to it. scope().resolve<Descriptor>( parentNameNode->getName(), strct, logger(), - [&type, &name, &optional](Handle<Node> parent, Handle<Node> strct, - Logger &logger) { + [type, name, optional](Handle<Node> parent, Handle<Node> strct, + Logger &logger) { if (parent != nullptr) { Rooted<FieldDescriptor> field = parent.cast<Descriptor>()->createFieldDescriptor( @@ -727,9 +726,9 @@ public: // resolve the parent, get the referenced field and add the declared // StructuredClass as child to it. scope().resolve<Descriptor>(parentNameNode->getName(), strct, logger(), - [&name, &loc](Handle<Node> parent, - Handle<Node> strct, - Logger &logger) { + [name, loc](Handle<Node> parent, + Handle<Node> strct, + Logger &logger) { if (parent != nullptr) { auto res = parent.cast<Descriptor>()->resolve( RttiTypes::FieldDescriptor, name); @@ -861,9 +860,16 @@ static const ParserState Document = .parent(&None) .createdNodeType(&RttiTypes::Document) .elementHandler(DocumentHandler::create) - .childHandler(DocumentChildHandler::create) .arguments({Argument::String("name", "")}); +static const ParserState DocumentChild = + ParserStateBuilder() + .parent(&Document) + .createdNodeTypes({&RttiTypes::StructureNode, + &RttiTypes::AnnotationEntity, + &RttiTypes::DocumentField}) + .elementHandler(DocumentChildHandler::create); + /* Domain states */ static const ParserState Domain = ParserStateBuilder() .parents({&None, &Document}) @@ -1017,6 +1023,7 @@ static const ParserState Include = static const std::multimap<std::string, const ParserState *> XmlStates{ {"document", &Document}, + {"*", &DocumentChild}, {"domain", &Domain}, {"struct", &DomainStruct}, {"annotation", &DomainAnnotation}, |