[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