llvm/flang/lib/parser/char-block.h
peter klausler 424ec7b35b [flang] Handle empty files gracefully.
Create interval.h.  Use std::size_t instead of bare size_t.  Redefine parser::Name to not be just a bare string.

Break out and rename CharBlock from token-sequence.h for use in the parse tree.

Incremental replacement of name strings with pointers to cooked characters.

Fix case sensitivity problem.

Use new CharBlock encoding to replace strings for real literal constants.

Normalized cooked character stream to lower case.

Simplify parsing now that cooked stream is lower case.  Replace Keyword in parse tree.

Add static_asserts to || and recovery parsers to enforce same result types.

Remove needless TODO comment inserted earlier.

Fix case conversion on prefixed character literals (f90_correct/dc04.f90).

Use CharBlock in user-state.h.

Complete transition from nextChar to nextCh (i.e., always use pointers).

Document extensions.  Begin work on compiler directive lines.

More documentation work.

Reformat prescan.cc.

More work on compiler directive scanning.

Original-commit: flang-compiler/f18@38d0404e16
Reviewed-on: https://github.com/flang-compiler/f18/pull/29
Tree-same-pre-rewrite: false
2018-03-23 13:32:55 -07:00

80 lines
2.6 KiB
C++

#ifndef FORTRAN_PARSER_CHAR_BLOCK_H_
#define FORTRAN_PARSER_CHAR_BLOCK_H_
// Describes a contiguous block of characters; does not own their storage.
#include "interval.h"
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <string>
#include <utility>
namespace Fortran {
namespace parser {
class CharBlock {
public:
CharBlock() {}
CharBlock(const char *x, std::size_t n = 1) : interval_{x, n} {}
CharBlock(const char *b, const char *e)
: interval_{b, static_cast<std::size_t>(e - b)} {}
CharBlock(const std::string &s) : interval_{s.data(), s.size()} {}
CharBlock(const CharBlock &) = default;
CharBlock(CharBlock &&) = default;
CharBlock &operator=(const CharBlock &) = default;
CharBlock &operator=(CharBlock &&) = default;
bool empty() const { return interval_.empty(); }
std::size_t size() const { return interval_.size(); }
const char *begin() const { return interval_.start(); }
const char *end() const { return interval_.start() + interval_.size(); }
const char &operator[](std::size_t j) const { return interval_.start()[j]; }
bool IsBlank() const {
for (char ch : *this) {
if (ch != ' ' && ch != '\t') {
return false;
}
}
return true;
}
std::string ToString() const {
return std::string{interval_.start(), interval_.size()};
}
bool operator<(const CharBlock &that) const { return Compare(that) < 0; }
bool operator<=(const CharBlock &that) const { return Compare(that) <= 0; }
bool operator==(const CharBlock &that) const { return Compare(that) == 0; }
bool operator!=(const CharBlock &that) const { return Compare(that) != 0; }
bool operator>=(const CharBlock &that) const { return Compare(that) >= 0; }
bool operator>(const CharBlock &that) const { return Compare(that) > 0; }
private:
int Compare(const CharBlock &that) const {
std::size_t bytes{std::min(size(), that.size())};
int cmp{std::memcmp(static_cast<const void *>(begin()),
static_cast<const void *>(that.begin()), bytes)};
if (cmp != 0) {
return cmp;
}
return size() < that.size() ? -1 : size() > that.size();
}
Interval<const char *> interval_{nullptr, 0};
};
} // namespace parser
} // namespace Fortran
// Specializations to enable std::unordered_map<CharBlock, ...> &c.
template<> struct std::hash<Fortran::parser::CharBlock> {
std::size_t operator()(const Fortran::parser::CharBlock &x) const {
std::size_t hash{0}, bytes{x.size()};
for (std::size_t j{0}; j < bytes; ++j) {
hash = (hash * 31) ^ x[j];
}
return hash;
}
};
#endif // FORTRAN_PARSER_CHAR_BLOCK_H_