[mathicgb] 306/393: Added option to match on a string to Scanner.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:59:26 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.

commit 418b63723af0faa74da16756503381c51f396e27
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Thu May 2 02:35:26 2013 +0200

    Added option to match on a string to Scanner.
---
 src/mathicgb/Scanner.cpp | 80 ++++++++++++++++++++++++++++++++++--------------
 src/mathicgb/Scanner.hpp | 24 ++++++++++++---
 src/test/Scanner.cpp     | 17 +++++++---
 3 files changed, 88 insertions(+), 33 deletions(-)

diff --git a/src/mathicgb/Scanner.cpp b/src/mathicgb/Scanner.cpp
index 6fc72a9..6fb10dd 100755
--- a/src/mathicgb/Scanner.cpp
+++ b/src/mathicgb/Scanner.cpp
@@ -6,6 +6,15 @@
 #include <sstream>
 #include <cstring>
 
+static const size_t BufferSize =
+#ifdef MATHICGB_DEBUG
+  1;
+#else
+  10 * 1024;
+#endif
+
+
+
 void reportSyntaxError(std::string s) {
   mathic::reportError(s);
 }
@@ -14,7 +23,6 @@ void Scanner::reportError(std::string msg) const {
   reportSyntaxError(msg);
 }
 
-static const size_t BufferSize = 10 * 1024;
 
 Scanner::Scanner(FILE* input):
   mFile(input),
@@ -44,14 +52,45 @@ Scanner::Scanner(const char* const input):
   mLineCount(1),
   mChar(' '),
   mBuffer(input, input + std::strlen(input)),
-  mBufferPos(mBuffer.end())
+  mBufferPos(mBuffer.begin())
 {
   get();
 }
 
-void Scanner::expect(const char* str) {
+Scanner::Scanner(const std::string& input):
+  mFile(0),
+  mStream(0),
+  mLineCount(1),
+  mChar(' '),
+  mBuffer(input.begin(), input.end()),
+  mBufferPos(mBuffer.begin())
+{
+  get();
+}
+
+bool Scanner::match(const char* const str) {
+  eatWhite();
   MATHICGB_ASSERT(str != 0);
+  const auto size = std::strlen(str);
+  if (!ensureBuffer(size - 1))
+    return false;
+  if (size == 0)
+    return true;
+  if (peek() != *str)
+    return false;
+  if (std::strncmp(&*mBufferPos, str + 1, size - 1) != 0)
+    return false;
+  ignore(size);
+  return true;
+}
+
+bool Scanner::ensureBuffer(size_t min) {
+  const auto got = std::distance(mBufferPos, mBuffer.end()) + 1;
+  return got >= min || readBuffer(min - got);
+}
 
+void Scanner::expect(const char* str) {
+  MATHICGB_ASSERT(str != 0);
   eatWhite();
 
   const char* it = str;
@@ -121,27 +160,22 @@ void Scanner::reportErrorUnexpectedToken(
   reportSyntaxError(errorMsg.str());
 }
 
-int Scanner::readBuffer() {
-  size_t read;
+bool Scanner::readBuffer(size_t minRead) {
+  auto saveCount = std::distance(mBufferPos, mBuffer.end());
+  if (mBufferPos != mBuffer.begin() && mBufferPos != mBuffer.end())
+    std::copy(mBufferPos, mBuffer.end(), mBuffer.begin());
+  mBuffer.resize(std::max(saveCount + minRead, mBuffer.capacity()));
+  auto readInto = reinterpret_cast<char*>(mBuffer.data() + saveCount);
+  auto readCount = mBuffer.size() - saveCount;
+
+  size_t didReadCount = 0;
   if (mFile != 0) {
-    if (mBuffer.size() < mBuffer.capacity() && (feof(mFile) || ferror(mFile)))
-      return EOF;
-    mBuffer.resize(mBuffer.capacity());
-    read = fread(&mBuffer[0], 1, mBuffer.capacity(), mFile);
+    didReadCount = fread(readInto, 1, readCount, mFile);
   } else if (mStream != 0) {
-    MATHICGB_ASSERT(mStream != 0);
-    if (mBuffer.size() < mBuffer.capacity() && !mStream->good())
-      return EOF;
-    mBuffer.resize(mBuffer.capacity());
-    mStream->read(reinterpret_cast<char*>(mBuffer.data()), mBuffer.size());
-    read = mStream->gcount();
-  } else
-    return EOF;
-  mBuffer.resize(read);
+    mStream->read(readInto, readCount);
+    didReadCount = mStream->gcount();
+  }
+  mBuffer.resize(didReadCount);
   mBufferPos = mBuffer.begin();
-  if (read == 0)
-    return EOF;
-  const char c = *mBufferPos;
-  ++mBufferPos;
-  return c;
+  return didReadCount >= minRead;
 }
diff --git a/src/mathicgb/Scanner.hpp b/src/mathicgb/Scanner.hpp
index 505a7c5..e3e7c05 100755
--- a/src/mathicgb/Scanner.hpp
+++ b/src/mathicgb/Scanner.hpp
@@ -45,9 +45,15 @@ public:
   /// Construct a Scanner object reading from the input string.
   Scanner(const char* const input);
 
+  /// Construct a Scanner object reading from the input string.
+  Scanner(const std::string& input);
+
   /// Reads a single character from the stream.
   int get();
 
+  /// Takes count characters off the stream.
+  void ignore(size_t count);
+
   /// Return true if the next character is c, and in that case skip
   /// past it.
   bool match(char c);
@@ -55,6 +61,8 @@ public:
   /// Return true if no more input.
   bool matchEOF();
 
+  bool match(const char* const str);
+
   /// Require the next character to be equal to expected. This
   /// character is skipped past.
   void expect(char expected);
@@ -91,6 +99,8 @@ public:
   /// whitespace.
   bool peekDigit() {return std::isdigit(peek());}
 
+  bool peekAlpha() {return std::isalpha(peek());}
+
   /// Returns true if the next character is whitespace. Does not skip
   /// whitespace. Whitespace is defined by std::isspace().
   bool peekWhite() {return isspace(peek());}
@@ -112,7 +122,8 @@ private:
   void reportErrorUnexpectedToken
     (const std::string& expected, const std::string& got);
 
-  int readBuffer();
+  bool ensureBuffer(size_t min);
+  bool readBuffer(size_t minRead);
 
   FILE* mFile;
   std::istream* mStream;
@@ -160,19 +171,22 @@ inline int Scanner::get() {
   if (mChar == '\n')
     ++mLineCount;
   int oldChar = mChar;
-  if (mBufferPos == mBuffer.end())
-    mChar = readBuffer();
+  if (mBufferPos == mBuffer.end() && !readBuffer(1))
+    mChar = EOF;
   else {
     mChar = *mBufferPos;
     ++mBufferPos;
   }
-  std::cout << "read '" << char(oldChar) << "' (" << oldChar << ")\n";
   return oldChar;
 }
 
+inline void Scanner::ignore(size_t count) {
+  for (size_t i = 0; i < count; ++i)
+    get();
+}
+
 template<class T>
 T Scanner::readInteger(const bool negate) {
-  std::cout << "***" << std::endl;
   static_assert(std::numeric_limits<T>::is_integer, "");
 
   eatWhite();
diff --git a/src/test/Scanner.cpp b/src/test/Scanner.cpp
index 428dcba..bca051f 100755
--- a/src/test/Scanner.cpp
+++ b/src/test/Scanner.cpp
@@ -2,7 +2,6 @@
 #include "mathicgb/Scanner.hpp"
 
 #include <gtest/gtest.h>
-#include <iterator>
 
 namespace {
   const char* const alpha = "abcdefghijkl";
@@ -44,8 +43,7 @@ TEST(Scanner, ExpectChar) {
 }
 
 TEST(Scanner, ExpectTwoChars) {
-  std::stringstream s(alphaSpaced);
-  Scanner in(s);
+  Scanner in(alphaSpaced);
   for (size_t i = 0; alpha[i] != '\0'; ++i) {
     if (i % 2 == 0)
       in.expect('!', alpha[i]);
@@ -56,8 +54,7 @@ TEST(Scanner, ExpectTwoChars) {
 }
 
 TEST(Scanner, ExpectString) {
-  std::stringstream s(alphaSpaced);
-  Scanner in(s);
+  Scanner in{std::string(alphaSpaced)};
   const auto size = sizeof(alphas) / sizeof(*alphas);
   for (size_t i = 0; i < size; ++i) {
     if (i % 2 == 0)
@@ -67,6 +64,16 @@ TEST(Scanner, ExpectString) {
   }
 }
 
+TEST(Scanner, MatchString) {
+  Scanner in{std::string(alphaSpaced)};
+  const auto size = sizeof(alphas) / sizeof(*alphas);
+  for (size_t i = 0; i < size; ++i) {
+    ASSERT_FALSE(in.match("ef"));
+    ASSERT_FALSE(in.match("deq"));
+    ASSERT_TRUE(in.match(alphas[i]));
+  }
+}
+
 TEST(Scanner, readInteger) {
   std::stringstream s("0 1 +0 -0 +1 -1 127 -128 128");
   Scanner in(s);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git



More information about the debian-science-commits mailing list