17 #ifndef COM_BORA_SOFTWARE__BALAU_LANG__SCANNED_TOKENS 18 #define COM_BORA_SOFTWARE__BALAU_LANG__SCANNED_TOKENS 28 #pragma clang diagnostic push 29 #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" 37 ConsumeWhitespaceAndComments
39 , ConsumeBlanksAndComments
41 , ConsumeLineBreaksAndComments
92 public:
ScannedTokens(std::shared_ptr<const Resource::Uri> uri_,
94 std::vector<TokenT> && tokens_,
95 std::vector<unsigned int> && startOffsets_)
96 : uri(
std::move(uri_))
97 , text(
std::move(text_))
99 , startOffsets(startOffsets_) {
100 Assert::assertion(tokens.back() == TokenT::EndOfFile,
"ScannedTokens must end with an EndOfFile token.");
106 public: std::string_view
getText(
unsigned int index) {
107 if (index >= tokens.size()) {
108 return std::string_view(text.data() + text.length(), 0);
109 }
else if (index == tokens.size() - 1) {
110 return std::string_view(
111 text.data() + startOffsets[index], text.length() - startOffsets[index]
114 return std::string_view(
115 text.data() + startOffsets[index]
116 , startOffsets[index + 1] - startOffsets[index]
129 return std::move(text);
137 public: std::shared_ptr<const Resource::Uri>
getUri() {
143 private: std::shared_ptr<const Resource::Uri> uri;
144 private: std::string text;
145 private: std::vector<TokenT> tokens;
146 private: std::vector<unsigned int> startOffsets;
171 : scannedTokens(
std::move(scannedTokens_))
172 , codeSpans(buildCodeSpans(scannedTokens)) {}
180 return scannedTokens;
200 unsigned int index) {
201 return determineCodeSpan(scannedTokens.text, scannedTokens.tokens, scannedTokens.startOffsets, index);
212 const std::vector<TokenT> & tokens,
213 const std::vector<unsigned int> & startOffsets,
214 unsigned int index) {
215 if (tokens.size() <= index) {
218 , std::string(
"scanned token range is 0 to ") + ::
toString(tokens.size()), index
222 std::vector<unsigned int> lineLengthCache;
228 for (
size_t thisIndex = 0; thisIndex < tokens.size() - 1; thisIndex++) {
232 , startOffsets[thisIndex]
233 , startOffsets[thisIndex + 1]
238 startPosition = endPosition;
240 if (index == thisIndex) {
241 return CodeSpan(startPosition, endPosition);
246 tokens[tokens.size() - 1]
248 , startOffsets[tokens.size() - 1]
249 , (
unsigned int) text.length()
254 return CodeSpan(startPosition, endPosition);
265 return std::move(scannedTokens.moveTextOut());
272 const std::vector<TokenT> & tokens = scannedTokens.tokens;
273 const std::vector<unsigned int> & startOffsets = scannedTokens.startOffsets;
275 std::vector<CodeSpan> builtCodeSpans;
277 if (tokens.size() == 0) {
278 return builtCodeSpans;
281 std::vector<unsigned int> lineLengthCache;
287 for (
size_t index = 0; index < tokens.size() - 1; index++) {
291 , startOffsets[index]
292 , startOffsets[index + 1]
297 builtCodeSpans.emplace_back(
CodeSpan(startPosition, endPosition));
299 startPosition = endPosition;
303 tokens[tokens.size() - 1]
305 , startOffsets[tokens.size() - 1]
306 , (
unsigned int) scannedTokens.text.length()
311 builtCodeSpans.emplace_back(
CodeSpan(startPosition, endPosition));
313 return builtCodeSpans;
318 private:
static void determineNewEnd(TokenT token,
319 const std::string & fullText,
320 unsigned int thisOffset,
321 unsigned int nextOffset,
323 std::vector<unsigned int> & lineLengthCache) {
324 static const std::regex endLineBreakRegex = std::regex(
"(\n\r|\r\n|\n|\r)$");
326 if (token == TokenT::LineBreak || token == TokenT::CommentLine || token == TokenT::CommentBlock) {
327 const std::string thisText = fullText.substr(thisOffset, nextOffset - thisOffset);
329 const bool hasCurrentLine = !std::regex_search(thisText, endLineBreakRegex);
335 , [&] () {
return std::string(
336 "A line break token was supplied in the determineNewEnd function" 337 "call but no line end was found in the supplied text. " 339 ) +
toString(thisOffset) +
", end offset = " +
340 toString(nextOffset) +
", token text = " + thisText; }
348 endPosition.
column += lineLengths[0];
350 lineLengthCache.push_back(endPosition.
column - 1);
352 if (hasCurrentLine) {
354 for (
size_t m = 1; m < lineLengths.size() - 1; m++) {
355 lineLengthCache.push_back((
unsigned int) lineLengths[m]);
360 endPosition.
column = 1 + (
unsigned int) lineLengths.back();
363 for (
size_t m = 1; m < lineLengths.size(); m++) {
364 lineLengthCache.push_back((
unsigned int) lineLengths[m]);
372 endPosition.
column += nextOffset - thisOffset;
378 private:
static void determineNewStart(TokenT token,
379 const std::string & fullText,
380 unsigned int thisOffset,
381 unsigned int nextOffset,
383 std::vector<unsigned int> & lineLengthCache) {
384 static const std::regex lineBreakRegex = std::regex(
"\n\r|\r\n|\n|\r");
386 if (token == TokenT::LineBreak || token == TokenT::CommentLine || token == TokenT::CommentBlock) {
387 const unsigned int lineBreaks = (
unsigned int)
Util::Strings::occurrences(fullText.substr(thisOffset, nextOffset - thisOffset), lineBreakRegex);
395 "A line break token was supplied in the determineNewStart function" 396 ,
"call but no line end was found in the supplied text. " 397 ,
"Start offset = ", thisOffset
398 ,
", end offset = ", nextOffset
399 ,
", token text = ", fullText.substr(thisOffset, nextOffset - thisOffset)
404 for (
size_t m = 0; m < lineBreaks; m++) {
405 startPosition.
column = lineLengthCache.back() + 1;
406 lineLengthCache.pop_back();
409 startPosition.
line -= lineBreaks;
411 startPosition.
column -= nextOffset - thisOffset;
418 private: std::vector<CodeSpan> codeSpans;
454 , codeSpan(
std::move(codeSpan_))
468 : scannedTokens(std::move(scannedTokens_))
470 , currentCodeSpan(1, 1, 1, 1) {
471 whitespaceModeStack.push(WhitespaceMode::DoNotConsume);
472 if (scannedTokens.tokens.size() > 1) {
474 scannedTokens.tokens[0]
476 , scannedTokens.startOffsets[0]
477 , scannedTokens.startOffsets[1]
478 , currentCodeSpan.end
488 while (!whitespaceModeStack.empty()) {
489 whitespaceModeStack.pop();
492 whitespaceModeStack.push(WhitespaceMode::DoNotConsume);
494 currentCodeSpan =
CodeSpan(1, 1, 1, 1);
495 lineLengthCache.clear();
503 const std::vector<TokenT> & tokens = scannedTokens.tokens;
505 switch (whitespaceModeStack.top()) {
506 case WhitespaceMode::ConsumeWhitespaceAndComments: {
507 while (tokens[currentIndex] == TokenT::Blank
508 || tokens[currentIndex] == TokenT::LineBreak
509 || tokens[currentIndex] == TokenT::CommentLine) {
510 advanceCurrentIndex();
516 case WhitespaceMode::ConsumeWhitespace: {
517 while (tokens[currentIndex] == TokenT::Blank || tokens[currentIndex] == TokenT::LineBreak) {
518 advanceCurrentIndex();
524 case WhitespaceMode::ConsumeBlanksAndComments: {
525 while (tokens[currentIndex] == TokenT::Blank || tokens[currentIndex] == TokenT::CommentLine) {
526 advanceCurrentIndex();
532 case WhitespaceMode::ConsumeBlanks: {
533 while (tokens[currentIndex] == TokenT::Blank) {
534 advanceCurrentIndex();
540 case WhitespaceMode::ConsumeLineBreaksAndComments: {
541 while (tokens[currentIndex] == TokenT::LineBreak || tokens[currentIndex] == TokenT::CommentLine) {
542 advanceCurrentIndex();
548 case WhitespaceMode::ConsumeLineBreaks: {
549 while (tokens[currentIndex] == TokenT::LineBreak) {
550 advanceCurrentIndex();
556 case WhitespaceMode::ConsumeComments: {
557 while (tokens[currentIndex] == TokenT::CommentLine) {
558 advanceCurrentIndex();
570 tokens[currentIndex], currentCodeSpan, scannedTokens.getText(currentIndex)
580 advanceCurrentIndex();
593 public:
void expect(
const TokenT token, std::string_view errorMessage) {
596 if (scannedTokens.tokens[currentIndex] == token) {
597 if (currentIndex < scannedTokens.tokens.size() - 1) {
598 advanceCurrentIndex();
621 public:
template <
template <
typename ...>
class ContainerT,
typename ... ArgT,
typename ReportT>
623 ContainerT<ReportT, ArgT ...> & container,
624 const size_t maxErrorCount,
625 const std::function<ReportT (
const TokenT &,
const CodeSpan &,
size_t)> & errorReport) {
628 if (scannedTokens.tokens[currentIndex] == token) {
629 if (currentIndex < scannedTokens.tokens.size() - 1) {
630 advanceCurrentIndex();
635 auto error = errorReport(token, getCurrentCodeSpan(), container.size());
637 if (container.size() < maxErrorCount) {
638 container.push_back(errorReport(token, getCurrentCodeSpan(), container.size()));
653 public:
void expect(
const std::vector<TokenT> & tokens, std::string_view errorMessage) {
656 if (std::find(tokens.begin(), tokens.end(), scannedTokens.tokens[currentIndex]) != tokens.end()) {
657 advanceCurrentIndex();
679 public:
template <
template <
typename ...>
class TokenContainerT,
template <
typename ...>
class ContainerT,
typename ... TokenArgT,
typename ... ArgT,
typename ReportT>
680 bool expect(
const TokenContainerT<TokenT, TokenArgT ...> & tokens,
681 ContainerT<ReportT, ArgT ...> & container,
682 const size_t maxErrorCount,
683 const std::function<ReportT (
const TokenContainerT<TokenT, TokenArgT ...> &,
const CodeSpan &,
size_t)> & errorReport) {
686 if (std::find(tokens.begin(), tokens.end(), scannedTokens.tokens[currentIndex]) != tokens.end()) {
687 advanceCurrentIndex();
690 if (container.size() < maxErrorCount) {
691 container.push_back(errorReport(tokens, getCurrentCodeSpan(), container.size()));
702 public:
Marker(
const Marker & rhs) noexcept : index(rhs.index) {}
704 public:
Marker(
Marker && rhs) noexcept : index(rhs.index) {}
706 public:
Marker & operator = (
const Marker & rhs) noexcept {
716 private:
explicit Marker(
size_t index_) : index(index_) {}
718 private:
size_t index;
723 public:
Marker mark()
const {
724 return Marker(currentIndex);
727 public:
void putBack(
const Marker & marker) {
728 if (marker.index > currentIndex) {
731 , ::
toString(
"Marker index (", marker.index,
") is greater than current index (", currentIndex,
")")
736 const auto steps = currentIndex - marker.index;
738 for (
size_t m = 0; m < steps; m++) {
750 const std::vector<TokenT> & tokens = scannedTokens.tokens;
752 retreatCurrentIndex();
754 switch (whitespaceModeStack.top()) {
755 case WhitespaceMode::ConsumeWhitespaceAndComments: {
756 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::Blank || tokens[currentIndex - 1] == TokenT::LineBreak || tokens[currentIndex - 1] == TokenT::CommentLine)) {
757 retreatCurrentIndex();
763 case WhitespaceMode::ConsumeWhitespace: {
764 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::Blank || tokens[currentIndex - 1] == TokenT::LineBreak)) {
765 retreatCurrentIndex();
771 case WhitespaceMode::ConsumeBlanksAndComments: {
772 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::Blank || tokens[currentIndex - 1] == TokenT::CommentLine)) {
773 retreatCurrentIndex();
779 case WhitespaceMode::ConsumeBlanks: {
780 while (currentIndex > 0 && tokens[currentIndex - 1] == TokenT::Blank) {
781 retreatCurrentIndex();
787 case WhitespaceMode::ConsumeLineBreaksAndComments: {
788 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::LineBreak || tokens[currentIndex - 1] == TokenT::CommentLine)) {
789 retreatCurrentIndex();
795 case WhitespaceMode::ConsumeLineBreaks: {
796 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::LineBreak)) {
797 retreatCurrentIndex();
803 case WhitespaceMode::ConsumeComments: {
804 while (currentIndex > 0 && (tokens[currentIndex - 1] == TokenT::CommentLine)) {
805 retreatCurrentIndex();
821 return currentCodeSpan;
828 return currentIndex < scannedTokens.tokens.size() && scannedTokens.tokens[currentIndex] == TokenT::Blank;
835 return currentIndex < scannedTokens.tokens.size() && scannedTokens.tokens[currentIndex] == TokenT::LineBreak;
842 if (currentIndex >= scannedTokens.tokens.size()) {
846 const TokenT token = scannedTokens.tokens[currentIndex];
847 return token == TokenT::Blank || token == TokenT::LineBreak;
853 public:
bool isBlank(
const Marker & marker)
const {
854 return scannedTokens.tokens[marker.index] == TokenT::Blank;
861 return scannedTokens.tokens[marker.index] == TokenT::LineBreak;
868 const TokenT token = scannedTokens.tokens[marker.index];
869 return token == TokenT::Blank || token == TokenT::LineBreak;
876 whitespaceModeStack.push(newMode);
883 whitespaceModeStack.pop();
890 return scannedTokens.tokens.size();
901 return std::move(scannedTokens.moveTextOut());
909 public: std::shared_ptr<const Resource::Uri>
getUri() {
910 return scannedTokens.getUri();
915 private:
void advanceCurrentIndex() {
916 if (currentIndex == scannedTokens.tokens.size() - 1) {
920 currentCodeSpan.start = currentCodeSpan.end;
923 if (currentIndex < scannedTokens.tokens.size() - 1) {
926 scannedTokens.tokens[currentIndex]
928 , scannedTokens.startOffsets[currentIndex]
929 , scannedTokens.startOffsets[currentIndex + 1]
930 , currentCodeSpan.end
936 private:
void retreatCurrentIndex() {
937 if (currentIndex == 0) {
941 currentCodeSpan.end = currentCodeSpan.start;
944 scannedTokens.tokens[currentIndex - 1]
946 , scannedTokens.startOffsets[currentIndex - 1]
947 , scannedTokens.startOffsets[currentIndex]
948 , currentCodeSpan.start
956 private:
unsigned int currentIndex;
958 private: std::stack<WhitespaceMode> whitespaceModeStack;
959 private: std::vector<unsigned int> lineLengthCache;
973 private:
const size_t index;
979 public: TokenT token()
const {
983 public:
unsigned int startOffset()
const {
995 private:
size_t index;
1002 : parent(copy.parent)
1003 , index(copy.index) {}
1006 parent = copy.parent;
1017 return ConstElement(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1021 return ConstElement(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1025 return parent == rhs.parent && index == rhs.index;
1038 private:
const size_t index;
1044 public: TokenT token()
const {
1048 public: TokenT & token() {
1052 public:
unsigned int startOffset()
const {
1056 public:
unsigned int & startOffset() {
1068 private:
size_t index;
1075 : parent(copy.parent)
1076 , index(copy.index) {}
1079 parent = copy.parent;
1084 public:
iterator & operator ++ () {
1090 return ConstElement(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1093 public:
Element operator * () {
1094 return Element(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1098 return ConstElement(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1101 public:
Element operator -> () {
1102 return Element(parent->scannedTokens.tokens[index], parent->scannedTokens.startOffsets[index]);
1106 return parent == rhs.parent && index == rhs.index;
1109 public:
bool operator != (
const iterator & rhs)
const {
1123 : scannedTokens(scannedTokens_) {}
1128 public:
void addToken(TokenT token,
unsigned int startOffset) {
1129 scannedTokens.tokens.emplace_back(token);
1130 scannedTokens.startOffsets.emplace_back(startOffset);
1137 return scannedTokens.tokens.size();
1144 return scannedTokens.tokens[index];
1151 return scannedTokens.tokens[index];
1159 return scannedTokens.startOffsets[index];
1166 return scannedTokens.startOffsets[index];
1173 return scannedTokens.tokens;
1180 return scannedTokens.startOffsets;
1208 return iterator(
this, scannedTokens.tokens.size());
1219 return std::move(scannedTokens.moveTextOut());
1229 #pragma clang diagnostic pop 1231 #endif // COM_BORA_SOFTWARE__BALAU_LANG__SCANNED_TOKENS Thrown when a parser incurs invalid syntax.
Definition: ParsingExceptions.hpp:28
bool operator==(const BalauException &lhs, const BalauException &rhs)
Base class comparison function for Balau exceptions.
Definition: BalauException.hpp:112
bool isWhitespace(const Marker &marker) const
Is the marked token whitespace?
Definition: ScannedTokens.hpp:867
TokenT token
The token type for this scanned token.
Definition: ScannedTokens.hpp:438
bool currentIsLineBreak() const
Is the next token line break?
Definition: ScannedTokens.hpp:834
const std::vector< CodeSpan > & getCodeSpans() const
Get the pre-calculated code spans of each scanned token.
Definition: ScannedTokens.hpp:188
std::shared_ptr< const Resource::Uri > getUri()
Get the input uri.
Definition: ScannedTokens.hpp:137
unsigned int column
The column of the code position (1-indexed).
Definition: CodeSpan.hpp:39
A ScannedTokens adaptor that provides an iteration API.
Definition: ScannedTokens.hpp:50
TokenT getToken(unsigned int index) const
Get the token with the specified index.
Definition: ScannedTokens.hpp:1143
void reset()
Rest the scanner API state to the beginning of the scanned tokens.
Definition: ScannedTokens.hpp:487
void pushWhitespaceMode(WhitespaceMode newMode)
Push the supplied whitespace mode onto the whitespace mode stack.
Definition: ScannedTokens.hpp:875
static CodeSpan determineCodeSpan(const std::string &text, const std::vector< TokenT > &tokens, const std::vector< unsigned int > &startOffsets, unsigned int index)
Utility to determine the overall code span for the specified index.
Definition: ScannedTokens.hpp:211
#define ThrowBalauException(ExceptionClass,...)
Throw a Balau style exception, with implicit file and line number, and optional stacktrace.
Definition: BalauException.hpp:45
A position in a piece of multi-line text.
Definition: CodeSpan.hpp:30
static std::vector< size_t > lineLengths(const StringT< char, T ... > &text, const std::regex &lineBreakRegex, bool includeExtraTextAsLine=true)
Determine the lengths of the lines in bytes, given the line break regular expression.
Definition: Strings.hpp:298
std::shared_ptr< const Resource::Uri > getUri()
Move the input uri to its final destination.
Definition: ScannedTokens.hpp:909
IterativeScannedTokens(ScannedTokens< TokenT > &scannedTokens_)
Create a scanned tokens data structure, specifying the source URI and the source text.
Definition: ScannedTokens.hpp:1122
void expect(const TokenT token, std::string_view errorMessage)
Expect the supplied token.
Definition: ScannedTokens.hpp:593
Scanned tokens const iterator.
Definition: ScannedTokens.hpp:991
bool currentIsBlank() const
Is the next token a blank?
Definition: ScannedTokens.hpp:827
unsigned int line
The line of the code position (1-indexed).
Definition: CodeSpan.hpp:34
Information on the span of some source code text.
Definition: CodeSpan.hpp:91
Balau exceptions for containers.
Balau::U8String< AllocatorT > toString(const BalauException &e)
Base class toString<AllocatorT> function for Balau exceptions.
Definition: BalauException.hpp:122
TokenT & getToken(unsigned int index)
Get a reference to the token with the specified index.
Definition: ScannedTokens.hpp:1150
size_t size() const
Get the number of tokens.
Definition: ScannedTokens.hpp:889
CodeSpan getCurrentCodeSpan() const
Get the code span of the current token.
Definition: ScannedTokens.hpp:820
void consume()
Consume the current token.
Definition: ScannedTokens.hpp:579
Encapsulation of a set of language tokens, source text, and start offsets.
Definition: ScannedTokens.hpp:47
std::string_view getText(unsigned int index)
Get the text of the token with the specified index.
Definition: ScannedTokens.hpp:106
std::string && moveTextOut()
Move the input text string to its final destination.
Definition: ScannedTokens.hpp:128
bool isLineBreak(const Marker &marker) const
Is the marked token line break?
Definition: ScannedTokens.hpp:860
Parsing tools and parser implementations.
Definition: AbstractScanner.hpp:27
void expect(const std::vector< TokenT > &tokens, std::string_view errorMessage)
Expect one of the supplied tokens.
Definition: ScannedTokens.hpp:653
const_iterator end() const
Get a const iterator positioned at the end of the data.
Definition: ScannedTokens.hpp:1200
A position marker that can be obtained at any point during parsing, in order to put back multiple tok...
Definition: ScannedTokens.hpp:701
Immutable, random access wrapper over a ScannedTokens data structure.
Definition: ScannedTokens.hpp:48
Balau::U8String< AllocatorT > toString(const CodeSpan &codeSpan)
Print the supplied code span as a UTF-8 string.
Definition: CodeSpan.hpp:235
A position in a piece of multi-line text.
static CodeSpan determineCodeSpan(const ScannedTokens< TokenT > &scannedTokens, unsigned int index)
Utility to determine the overall code span for the specified index.
Definition: ScannedTokens.hpp:199
Scanned tokens non-const iterator.
Definition: ScannedTokens.hpp:1064
unsigned int getStartOffset(unsigned int index) const
Get the start offset of the token with the specified index.
Definition: ScannedTokens.hpp:1158
Returned by const iterators when accessing elements.
Definition: ScannedTokens.hpp:971
RandomAccessScannedTokens(ScannedTokens< TokenT > &&scannedTokens_)
Instantiate a random access scanned tokens data structure.
Definition: ScannedTokens.hpp:170
std::string && moveTextOut()
Move the input text string to its final destination.
Definition: ScannedTokens.hpp:1218
bool currentIsWhitespace() const
Is the next token whitespace?
Definition: ScannedTokens.hpp:841
A ScannedTokens adaptor that provides a traditional scanner API.
Definition: ScannedTokens.hpp:49
Thrown when a specified index is not in the valid range.
Definition: ContainerExceptions.hpp:27
bool expect(const TokenContainerT< TokenT, TokenArgT ... > &tokens, ContainerT< ReportT, ArgT ... > &container, const size_t maxErrorCount, const std::function< ReportT(const TokenContainerT< TokenT, TokenArgT ... > &, const CodeSpan &, size_t)> &errorReport)
Expect one of the supplied tokens.
Definition: ScannedTokens.hpp:680
const std::vector< TokenT > & getTokens() const
Get the token vector.
Definition: ScannedTokens.hpp:1172
Represents a single scanned token in the data structure.
Definition: ScannedTokens.hpp:434
CodeSpan codeSpan
The start and end positions of the token's text within the multi-line source file.
Definition: ScannedTokens.hpp:443
iterator begin()
Get a non-const iterator positioned at the beginning of the data.
Definition: ScannedTokens.hpp:1193
const std::vector< unsigned int > & getStartOffsets() const
Get the start offsets vector.
Definition: ScannedTokens.hpp:1179
size_t size() const
Get the number of tokens.
Definition: ScannedTokens.hpp:1136
Assertion utilities for development purposes.
void putBack()
Put back the current token.
Definition: ScannedTokens.hpp:749
std::string && moveTextOut()
Move the input text string to its final destination.
Definition: ScannedTokens.hpp:264
WhitespaceMode
Determines the whitespace scanning mode used in the scanning API.
Definition: ScannedTokens.hpp:36
unsigned int & getStartOffset(unsigned int index)
Get a reference to the start offset of the token with the specified index.
Definition: ScannedTokens.hpp:1165
Returned by non-const iterators when accessing elements.
Definition: ScannedTokens.hpp:1036
std::string_view text
UTF-8 formatted string of the token.
Definition: ScannedTokens.hpp:448
void addToken(TokenT token, unsigned int startOffset)
Add a token to the data structure, specifying the token and the start offset into the text...
Definition: ScannedTokens.hpp:1128
const_iterator begin() const
Get a const iterator positioned at the beginning of the data.
Definition: ScannedTokens.hpp:1186
bool isBlank(const Marker &marker) const
Is the marked token a blank?
Definition: ScannedTokens.hpp:853
ScannerApiScannedTokens(ScannedTokens< TokenT > &&scannedTokens_) noexcept
Create a scanner API scanned tokens instance.
Definition: ScannedTokens.hpp:467
std::string && moveTextOut()
Move the input text string to its final destination.
Definition: ScannedTokens.hpp:900
static size_t occurrences(const CharT *str, const SubstrT &substring)
How many non-overlapping occurrences of the second string are found in the first string?
Definition: Strings.hpp:208
Balau exceptions for the parser tools.
const ScannedTokens< TokenT > & getScannedTokens() const
Get the scanned tokens structure that this random access wrapper contains.
Definition: ScannedTokens.hpp:179
static void assertion(bool test, StringFunctionT function)
If the bug test assertion fails, abort after logging the message supplied by the function.
Definition: Assert.hpp:49
bool expect(const TokenT token, ContainerT< ReportT, ArgT ... > &container, const size_t maxErrorCount, const std::function< ReportT(const TokenT &, const CodeSpan &, size_t)> &errorReport)
Expect the supplied token.
Definition: ScannedTokens.hpp:622
void popWhitespaceMode()
Pop the top of the whitespace mode stack.
Definition: ScannedTokens.hpp:882
iterator end()
Get a non-const iterator positioned at the end of the data.
Definition: ScannedTokens.hpp:1207