]> gitweb.ps.run Git - toc/blobdiff - antlr4-cpp-runtime-4.9.2-source/runtime/src/UnbufferedCharStream.cpp
add antlr source code and ReadMe
[toc] / antlr4-cpp-runtime-4.9.2-source / runtime / src / UnbufferedCharStream.cpp
diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/UnbufferedCharStream.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/UnbufferedCharStream.cpp
new file mode 100644 (file)
index 0000000..1f18d38
--- /dev/null
@@ -0,0 +1,211 @@
+/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
+ * Use of this file is governed by the BSD 3-clause license that
+ * can be found in the LICENSE.txt file in the project root.
+ */
+
+#include "misc/Interval.h"
+#include "Exceptions.h"
+#include "support/StringUtils.h"
+
+#include "UnbufferedCharStream.h"
+
+using namespace antlrcpp;
+using namespace antlr4;
+using namespace antlr4::misc;
+
+UnbufferedCharStream::UnbufferedCharStream(std::wistream &input) : _input(input) {
+  InitializeInstanceFields();
+
+  // The vector's size is what used to be n in Java code.
+  fill(1); // prime
+}
+
+void UnbufferedCharStream::consume() {
+  if (LA(1) == EOF) {
+    throw IllegalStateException("cannot consume EOF");
+  }
+
+  // buf always has at least data[p==0] in this method due to ctor
+  _lastChar = _data[_p]; // track last char for LA(-1)
+
+  if (_p == _data.size() - 1 && _numMarkers == 0) {
+    size_t capacity = _data.capacity();
+    _data.clear();
+    _data.reserve(capacity);
+
+    _p = 0;
+    _lastCharBufferStart = _lastChar;
+  } else {
+    _p++;
+  }
+
+  _currentCharIndex++;
+  sync(1);
+}
+
+void UnbufferedCharStream::sync(size_t want) {
+  if (_p + want <= _data.size()) // Already enough data loaded?
+    return;
+
+  fill(_p + want - _data.size());
+}
+
+size_t UnbufferedCharStream::fill(size_t n) {
+  for (size_t i = 0; i < n; i++) {
+    if (_data.size() > 0 && _data.back() == 0xFFFF) {
+      return i;
+    }
+
+    try {
+      char32_t c = nextChar();
+      add(c);
+#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
+    } catch (IOException &ioe) {
+      // throw_with_nested is not available before VS 2015.
+      throw ioe;
+#else
+    } catch (IOException & /*ioe*/) {
+      std::throw_with_nested(RuntimeException());
+#endif
+    }
+  }
+
+  return n;
+}
+
+char32_t UnbufferedCharStream::nextChar()  {
+  wchar_t result = 0;
+  _input >> result;
+  return result;
+}
+
+void UnbufferedCharStream::add(char32_t c) {
+  _data += c;
+}
+
+size_t UnbufferedCharStream::LA(ssize_t i) {
+  if (i == -1) { // special case
+    return _lastChar;
+  }
+
+  // We can look back only as many chars as we have buffered.
+  ssize_t index = static_cast<ssize_t>(_p) + i - 1;
+  if (index < 0) {
+    throw IndexOutOfBoundsException();
+  }
+
+  if (i > 0) {
+    sync(static_cast<size_t>(i)); // No need to sync if we look back.
+  }
+  if (static_cast<size_t>(index) >= _data.size()) {
+    return EOF;
+  }
+
+  if (_data[static_cast<size_t>(index)] == 0xFFFF) {
+    return EOF;
+  }
+
+  return _data[static_cast<size_t>(index)];
+}
+
+ssize_t UnbufferedCharStream::mark() {
+  if (_numMarkers == 0) {
+    _lastCharBufferStart = _lastChar;
+  }
+
+  ssize_t mark = -static_cast<ssize_t>(_numMarkers) - 1;
+  _numMarkers++;
+  return mark;
+}
+
+void UnbufferedCharStream::release(ssize_t marker) {
+  ssize_t expectedMark = -static_cast<ssize_t>(_numMarkers);
+  if (marker != expectedMark) {
+    throw IllegalStateException("release() called with an invalid marker.");
+  }
+
+  _numMarkers--;
+  if (_numMarkers == 0 && _p > 0) {
+    _data.erase(0, _p);
+    _p = 0;
+    _lastCharBufferStart = _lastChar;
+  }
+}
+
+size_t UnbufferedCharStream::index() {
+  return _currentCharIndex;
+}
+
+void UnbufferedCharStream::seek(size_t index) {
+  if (index == _currentCharIndex) {
+    return;
+  }
+
+  if (index > _currentCharIndex) {
+    sync(index - _currentCharIndex);
+    index = std::min(index, getBufferStartIndex() + _data.size() - 1);
+  }
+
+  // index == to bufferStartIndex should set p to 0
+  ssize_t i = static_cast<ssize_t>(index) - static_cast<ssize_t>(getBufferStartIndex());
+  if (i < 0) {
+    throw IllegalArgumentException(std::string("cannot seek to negative index ") + std::to_string(index));
+  } else if (i >= static_cast<ssize_t>(_data.size())) {
+    throw UnsupportedOperationException("Seek to index outside buffer: " + std::to_string(index) +
+                                        " not in " + std::to_string(getBufferStartIndex()) + ".." +
+                                        std::to_string(getBufferStartIndex() + _data.size()));
+  }
+
+  _p = static_cast<size_t>(i);
+  _currentCharIndex = index;
+  if (_p == 0) {
+    _lastChar = _lastCharBufferStart;
+  } else {
+    _lastChar = _data[_p - 1];
+  }
+}
+
+size_t UnbufferedCharStream::size() {
+  throw UnsupportedOperationException("Unbuffered stream cannot know its size");
+}
+
+std::string UnbufferedCharStream::getSourceName() const {
+  if (name.empty()) {
+    return UNKNOWN_SOURCE_NAME;
+  }
+
+  return name;
+}
+
+std::string UnbufferedCharStream::getText(const misc::Interval &interval) {
+  if (interval.a < 0 || interval.b >= interval.a - 1) {
+    throw IllegalArgumentException("invalid interval");
+  }
+
+  size_t bufferStartIndex = getBufferStartIndex();
+  if (!_data.empty() && _data.back() == 0xFFFF) {
+    if (interval.a + interval.length() > bufferStartIndex + _data.size()) {
+      throw IllegalArgumentException("the interval extends past the end of the stream");
+    }
+  }
+
+  if (interval.a < static_cast<ssize_t>(bufferStartIndex) || interval.b >= ssize_t(bufferStartIndex + _data.size())) {
+    throw UnsupportedOperationException("interval " + interval.toString() + " outside buffer: " +
+      std::to_string(bufferStartIndex) + ".." + std::to_string(bufferStartIndex + _data.size() - 1));
+  }
+  // convert from absolute to local index
+  size_t i = interval.a - bufferStartIndex;
+  return utf32_to_utf8(_data.substr(i, interval.length()));
+}
+
+size_t UnbufferedCharStream::getBufferStartIndex() const {
+  return _currentCharIndex - _p;
+}
+
+void UnbufferedCharStream::InitializeInstanceFields() {
+  _p = 0;
+  _numMarkers = 0;
+  _lastChar = 0;
+  _lastCharBufferStart = 0;
+  _currentCharIndex = 0;
+}