summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/fileUtils.h35
-rw-r--r--libadhocutil/lexer-regex.h9
-rw-r--r--libadhocutil/lexer.cpp25
-rw-r--r--libadhocutil/lexer.h42
-rw-r--r--libadhocutil/unittests/testLexer.cpp6
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());