diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-06 16:40:42 +0100 |
---|---|---|
committer | Andreas Stöckel <andreas@somweyr.de> | 2015-02-06 16:40:42 +0100 |
commit | b211c02c53f3ed38c7d124d6a74f22ee17df7063 (patch) | |
tree | 0fcea811a809f45cdf72d1c12fa00899c431a9be | |
parent | ae6ce2bc21cedf56f9fb445c3f1f7bc62b78de5f (diff) |
Removed childHandler, added "*" notation
-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-- | 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<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/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<std::string, const ParserState *> 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); |