From ae6ce2bc21cedf56f9fb445c3f1f7bc62b78de5f Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Fri, 6 Feb 2015 16:40:15 +0100 Subject: Do not capture references --- src/plugins/xml/XmlParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 2d62c11..c2e89ec 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -547,7 +547,7 @@ public: // StructuredClass as child to it. scope().resolve( dummy->getName(), strct, logger(), - [&type, &name, &optional](Handle parent, Handle strct, + [type, name, optional](Handle parent, Handle strct, Logger &logger) { if (parent != nullptr) { Rooted field = @@ -583,7 +583,7 @@ public: // resolve the parent, get the referenced field and add the declared // StructuredClass as child to it. scope().resolve(dummy->getName(), strct, logger(), - [&name, &loc](Handle parent, + [name, loc](Handle parent, Handle strct, Logger &logger) { if (parent != nullptr) { -- cgit v1.2.3 From b211c02c53f3ed38c7d124d6a74f22ee17df7063 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Fri, 6 Feb 2015 16:40:42 +0100 Subject: Removed childHandler, added "*" notation --- src/core/parser/ParserStack.cpp | 49 ++++++++++++++++++++---------------- src/core/parser/ParserStack.hpp | 28 +++++++++++++-------- src/core/parser/ParserState.cpp | 15 +++-------- src/core/parser/ParserState.hpp | 27 +------------------- test/core/parser/ParserStackTest.cpp | 12 ++++++--- 5 files changed, 57 insertions(+), 74 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 ParserStack::expectedCommands(const ParserState &state) +std::set ParserStack::expectedCommands() { + const ParserState *currentState = &(this->currentState()); std::set 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> 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 expectedCommands(const ParserState &state); + std::set 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 @@ -78,13 +78,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. */ @@ -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. @@ -208,19 +196,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/test/core/parser/ParserStackTest.cpp b/test/core/parser/ParserStackTest.cpp index 7ffcf3a..3a0decb 100644 --- a/test/core/parser/ParserStackTest.cpp +++ b/test/core/parser/ParserStackTest.cpp @@ -52,8 +52,7 @@ static const ParserState Document = ParserStateBuilder().parent(&None).elementHandler(TestHandler::create); static const ParserState Body = ParserStateBuilder() .parent(&Document) - .elementHandler(TestHandler::create) - .childHandler(TestHandler::create); + .elementHandler(TestHandler::create); static const ParserState Empty = ParserStateBuilder().parent(&Document).elementHandler(TestHandler::create); static const ParserState Special = @@ -63,13 +62,18 @@ static const ParserState Arguments = .parent(&None) .elementHandler(TestHandler::create) .arguments({Argument::Int("a"), Argument::String("b")}); +static const ParserState BodyChildren = + ParserStateBuilder() + .parent(&Body) + .elementHandler(TestHandler::create); static const std::multimap TestHandlers{ {"document", &Document}, {"body", &Body}, {"empty", &Empty}, {"special", &Special}, - {"arguments", &Arguments}}; + {"arguments", &Arguments}, + {"*", &BodyChildren}}; } TEST(ParserStack, simpleTest) @@ -101,7 +105,7 @@ TEST(ParserStack, simpleTest) s.start("inner", {}); EXPECT_EQ("inner", s.currentCommandName()); - EXPECT_EQ(&ParserStates::Body, &s.currentState()); + EXPECT_EQ(&ParserStates::BodyChildren, &s.currentState()); s.end(); EXPECT_EQ(3, startCount); EXPECT_EQ(1, endCount); -- cgit v1.2.3