diff options
-rw-r--r-- | libadhocutil/fileUtils.h | 35 | ||||
-rw-r--r-- | libadhocutil/lexer-regex.h | 9 | ||||
-rw-r--r-- | libadhocutil/lexer.cpp | 25 | ||||
-rw-r--r-- | libadhocutil/lexer.h | 42 | ||||
-rw-r--r-- | libadhocutil/unittests/testLexer.cpp | 6 |
5 files changed, 100 insertions, 17 deletions
diff --git a/libadhocutil/fileUtils.h b/libadhocutil/fileUtils.h index 3fa5756..939a8ba 100644 --- a/libadhocutil/fileUtils.h +++ b/libadhocutil/fileUtils.h @@ -8,31 +8,66 @@ namespace AdHoc { namespace FileUtils { + /** + * Extract an element of a path. + * @param p The source path. + * @param n The index of the element to extract. + * @return The path element. + */ DLL_PUBLIC boost::filesystem::path operator/(const boost::filesystem::path & p, unsigned int n); + /** + * File handle wrapper to ensure closure on scope exit + */ class DLL_PUBLIC FileHandle { public: + /** + * Open a new file handle. + * @param path Path of file to open. + * @param flags File handle flags + */ FileHandle(const boost::filesystem::path & path, int flags = O_RDONLY); virtual ~FileHandle(); + /// The file handle. const int fh; }; + /** + * An extension to FileHandle that automatically calls fstat on the opened handle. + */ class DLL_PUBLIC FileHandleStat : public FileHandle { public: + /** + * Open a new file handle (with the default flags). + * @param path Path of file to open. + */ FileHandleStat(const boost::filesystem::path & path); + /** + * Get the stat structure. + * @return The stat structure. + */ const struct stat & getStat() const; protected: + /// The stat structure. struct stat st; }; + /** + * Extension to FileHandle to automatically memmaps the file. + */ class DLL_PUBLIC MemMap : public FileHandleStat { public: + /** + * Open a new file handle (with the default flags). + * @param path Path of file to open. + */ MemMap(const boost::filesystem::path & path); ~MemMap(); + /// The file data. void * const data; }; } diff --git a/libadhocutil/lexer-regex.h b/libadhocutil/lexer-regex.h index 2397071..5a141b9 100644 --- a/libadhocutil/lexer-regex.h +++ b/libadhocutil/lexer-regex.h @@ -5,7 +5,14 @@ namespace AdHoc { namespace LexerMatchers { - DLL_PUBLIC Lexer::PatternPtr regex(const Glib::ustring &, GRegexCompileFlags compile = (GRegexCompileFlags)0, GRegexMatchFlags match = (GRegexMatchFlags)0); + /** + * Create a AdHoc::Lexer pattern matcher using regexen. + * @param regex The regex string. + * @param compile The regex compile flags. + * @param match The regex match flags. + * @return Pointer to the newly created pattern matcher. + */ + DLL_PUBLIC Lexer::PatternPtr regex(const Glib::ustring & regex, GRegexCompileFlags compile = (GRegexCompileFlags)0, GRegexMatchFlags match = (GRegexMatchFlags)0); } }; diff --git a/libadhocutil/lexer.cpp b/libadhocutil/lexer.cpp index 95e079b..83d2666 100644 --- a/libadhocutil/lexer.cpp +++ b/libadhocutil/lexer.cpp @@ -15,7 +15,7 @@ namespace AdHoc { Lexer::extract(const gchar * string, size_t length) const { ExecuteState es; - while (es.position < length) { + while (es.pos < length) { const Rule * selected = nullptr; for (const auto & r : rules) { const auto & s = boost::get<0>(r); @@ -23,24 +23,23 @@ namespace AdHoc { continue; } const auto & p = boost::get<1>(r); - if (p->matches(string, length, es.position)) { + if (p->matches(string, length, es.pos)) { selected = &r; break; } } if (!selected) { - throw std::runtime_error(std::string("Unexpected input in state (" + es.getState() + ") at ") + (string + es.position)); + throw std::runtime_error(std::string("Unexpected input in state (" + es.getState() + ") at ") + (string + es.pos)); } - es.pattern = boost::get<1>(*selected); + es.pat = boost::get<1>(*selected); const auto & h = boost::get<2>(*selected); h(&es); - es.position += es.pattern->matchedLength(); + es.pos += es.pat->matchedLength(); } - } Lexer::ExecuteState::ExecuteState() : - position(0) + pos(0) { stateStack.push_back(InitialState); } @@ -74,5 +73,17 @@ namespace AdHoc { { return stateStack.size(); } + + size_t + Lexer::ExecuteState::position() const + { + return pos; + } + + Lexer::PatternPtr + Lexer::ExecuteState::pattern() const + { + return pat; + } } diff --git a/libadhocutil/lexer.h b/libadhocutil/lexer.h index fdc4507..98cbd3c 100644 --- a/libadhocutil/lexer.h +++ b/libadhocutil/lexer.h @@ -11,48 +11,78 @@ #include "visibility.h" namespace AdHoc { + /// An extensible lexer. class DLL_PUBLIC Lexer { public: + /// Pattern matcher interface. class Pattern { public: virtual ~Pattern() = default; + /// Test the pattern against the given input. virtual bool matches(const gchar *, size_t, size_t) const = 0; + /// Get the total amount of input matched. virtual size_t matchedLength() const = 0; + /// Get an extracted value from the pattern. virtual boost::optional<Glib::ustring> match(int) const = 0; }; + /// Smart pointer to Pattern. typedef boost::shared_ptr<Pattern> PatternPtr; - + /// Lexer state identifiers. typedef std::string State; + /// Collection of States. typedef std::set<State> States; + /// Class representing the runtime execution of the lexer. class ExecuteState { public: + /// Default constructor. ExecuteState(); + /// Push a new state to the stack. void pushState(const State &); + /// Pop the top of the state stack off. void popState(); + /// Replace the current top of the state stack. void setState(const State &); + /// Get the current state. const State & getState() const; + /// Get the state stack depth. size_t depth() const; - - size_t position; - PatternPtr pattern; + /// Get the current position. + size_t position() const; + /// Get the currently matched pattern. + PatternPtr pattern() const; private: + friend class Lexer; + size_t pos; + PatternPtr pat; + std::vector<State> stateStack; }; + /// Callback for handling matched patterns. typedef boost::function<void(ExecuteState *)> Handler; + /** + * Rule definition: + * States: in which states should the rule be considered? + * Pattern: the pattern matcher to test against the input. + * Handler: the callback to execute when a match succeeds. + */ typedef boost::tuple<States, PatternPtr, Handler> Rule; + /// Collection of Rules that make up the lexer configuration. typedef std::vector<Rule> Rules; - + /// The initial state of applied to the lexer. static const State InitialState; + /// Default constructor (empty rule set) Lexer(); + /// Construct with an initial set of rules. Lexer(const Rules &); - + /// The lexer's current rule set. Rules rules; + /// Execute the lexer to extract matches for the current rules. void extract(const gchar * string, size_t length) const; }; } diff --git a/libadhocutil/unittests/testLexer.cpp b/libadhocutil/unittests/testLexer.cpp index c0b973b..a8bc6ce 100644 --- a/libadhocutil/unittests/testLexer.cpp +++ b/libadhocutil/unittests/testLexer.cpp @@ -51,14 +51,14 @@ BOOST_AUTO_TEST_CASE( state ) { { "3" }, regex("a"), [&](auto es) { m += 3; - s += *es->pattern->match(0); + s += *es->pattern()->match(0); BOOST_REQUIRE_EQUAL(3, es->depth()); es->setState("4"); BOOST_REQUIRE_EQUAL(3, es->depth()); BOOST_REQUIRE_EQUAL("4", es->getState()); BOOST_REQUIRE_EQUAL(3, es->depth()); - BOOST_REQUIRE(!es->pattern->match(1)); - BOOST_REQUIRE(!es->pattern->match(2)); + BOOST_REQUIRE(!es->pattern()->match(1)); + BOOST_REQUIRE(!es->pattern()->match(2)); es->popState(); BOOST_REQUIRE_EQUAL(2, es->depth()); BOOST_REQUIRE_EQUAL("2", es->getState()); |