forked from OSchip/llvm-project
[flang] Begin work on character provenances.
Original-commit: flang-compiler/f18@ea3c05af5a Reviewed-on: https://github.com/flang-compiler/f18/pull/9 Tree-same-pre-rewrite: false
This commit is contained in:
parent
fb7dc91efd
commit
ea69370e52
|
@ -0,0 +1,95 @@
|
|||
#ifndef FORTRAN_PROVENANCE_H_
|
||||
#define FORTRAN_PROVENANCE_H_
|
||||
#include "source.h"
|
||||
#include <string>
|
||||
#include <variant>
|
||||
namespace Fortran {
|
||||
|
||||
class SourceContexts;
|
||||
|
||||
using Provenance = size_t;
|
||||
|
||||
struct ProvenanceRange {
|
||||
Provenance begin;
|
||||
size_t bytes;
|
||||
};
|
||||
|
||||
class Sources {
|
||||
public:
|
||||
Sources() {}
|
||||
Sources(Sources &&) = default;
|
||||
Sources &operator(Sources &&) = default;
|
||||
size_t size() const { return bytes_; }
|
||||
char &operator[size_t at] const;
|
||||
private:
|
||||
struct Context {
|
||||
struct Inclusion {
|
||||
const SourceFile &source;
|
||||
};
|
||||
struct MacroUse {
|
||||
ProvenanceRange definition;
|
||||
};
|
||||
|
||||
int myIndex; // *contexts[myIndex] == this;
|
||||
ProvenanceRange replaces;
|
||||
std::variant<SourceFile, Inclusion, MacroUse> v;
|
||||
};
|
||||
std::vector<std::unique_ptr<Context>> contexts_;
|
||||
size_t bytes_;
|
||||
};
|
||||
|
||||
class ProvenancedChar {
|
||||
public:
|
||||
using type = char;
|
||||
char character() const { return static_cast<char>(packed_); }
|
||||
Provenance provenance() const { return packed_ >> 8; }
|
||||
private:
|
||||
size_t packed_;
|
||||
};
|
||||
|
||||
class ProvenancedString {
|
||||
private:
|
||||
class iterator {
|
||||
public:
|
||||
iterator(const Sources &sources, Provenance at)
|
||||
: sources_{&sources}, at_{at} {}
|
||||
iterator(const iterator &that)
|
||||
: sources_{that.sources_}, at_{that.at_} {}
|
||||
iterator &operator(const iterator &that) {
|
||||
sources_ = that.sources_;
|
||||
at_ = that.at_;
|
||||
return *this;
|
||||
}
|
||||
const char &operator*() const;
|
||||
iterator &operator++() {
|
||||
++at_;
|
||||
return *this;
|
||||
}
|
||||
iterator &operator++(int) {
|
||||
iterator result{*this};
|
||||
++at_;
|
||||
return result;
|
||||
}
|
||||
bool operator<(const iterator &that) { return at_ < that.at_; }
|
||||
bool operator<=(const iterator &that) { return at_ <= that.at_; }
|
||||
bool operator==(const iterator &that) { return at_ == that.at_; }
|
||||
bool operator!=(const iterator &that) { return at_ != that.at_; }
|
||||
private:
|
||||
const Sources *sources_;
|
||||
size_t at_;
|
||||
};
|
||||
|
||||
iterator begin(const Sources &sources) const {
|
||||
return iterator(sources, start_);
|
||||
}
|
||||
iterator end(const Sources &sources) const {
|
||||
return iterator(sources, start_ + bytes_);
|
||||
}
|
||||
public:
|
||||
size_t size() const { return bytes_; }
|
||||
private:
|
||||
Provenance start_;
|
||||
size_t bytes_;
|
||||
};
|
||||
} // namespace Fortran
|
||||
#endif // FORTRAN_PROVENANCE_H_
|
|
@ -18,6 +18,24 @@ namespace parser {
|
|||
|
||||
SourceFile::~SourceFile() { Close(); }
|
||||
|
||||
static std::vector<size_t> FindLineStarts(const char *source, size_t bytes) {
|
||||
if (bytes == 0) {
|
||||
return {};
|
||||
}
|
||||
CHECK(source[bytes - 1] == '\n' && "missing ultimate newline");
|
||||
std::vector<size_t> result;
|
||||
size_t at{0};
|
||||
do {
|
||||
result.push_back(at);
|
||||
const void *vp{static_cast<const void *>(&source[at])};
|
||||
const void *vnl{std::memchr(vp, '\n', bytes - at)};
|
||||
const char *nl{static_cast<const char *>(vnl)};
|
||||
at = nl + 1 - source;
|
||||
} while (at < bytes);
|
||||
result.shrink_to_fit();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SourceFile::Open(std::string path, std::stringstream *error) {
|
||||
Close();
|
||||
path_ = path;
|
||||
|
@ -51,12 +69,13 @@ bool SourceFile::Open(std::string path, std::stringstream *error) {
|
|||
if (S_ISREG(statbuf.st_mode)) {
|
||||
bytes_ = static_cast<size_t>(statbuf.st_size);
|
||||
if (bytes_ > 0) {
|
||||
auto vp = mmap(0, bytes_, PROT_READ, MAP_SHARED, fileDescriptor_, 0);
|
||||
void *vp = mmap(0, bytes_, PROT_READ, MAP_SHARED, fileDescriptor_, 0);
|
||||
if (vp != MAP_FAILED) {
|
||||
content_ = reinterpret_cast<const char *>(vp);
|
||||
content_ = static_cast<const char *>(const_cast<const void *>(vp));
|
||||
if (content_[bytes_ - 1] == '\n' &&
|
||||
std::memchr(vp, '\r', bytes_) == nullptr) {
|
||||
isMemoryMapped_ = true;
|
||||
lineStart_ = FindLineStarts(content_, bytes_);
|
||||
return true;
|
||||
}
|
||||
// The file needs normalizing.
|
||||
|
@ -105,6 +124,7 @@ bool SourceFile::Open(std::string path, std::stringstream *error) {
|
|||
*to++ = '\n'; // supply a missing terminal newline
|
||||
}
|
||||
bytes_ = to - contig;
|
||||
lineStart_ = FindLineStarts(content_, bytes_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -123,5 +143,27 @@ void SourceFile::Close() {
|
|||
}
|
||||
path_.clear();
|
||||
}
|
||||
|
||||
Position SourceFile::FindOffsetPosition(size_t at) const {
|
||||
CHECK(at < bytes_);
|
||||
size_t lo{0}, hi{lineStart_.size()};
|
||||
while (lo < hi) {
|
||||
size_t mid{(lo + hi) >> 1};
|
||||
if (lineStart_[mid] > at) {
|
||||
hi = mid;
|
||||
} else {
|
||||
lo = mid;
|
||||
}
|
||||
}
|
||||
return {static_cast<int>(lo + 1), static_cast<int>(at - lineStart_[lo] + 1)};
|
||||
}
|
||||
|
||||
size_t SourceFile::FindPositionOffset(int lineNumber, int column) const {
|
||||
return lineStart_.at(lineNumber - 1) + column - 1;
|
||||
}
|
||||
|
||||
size_t SourceFile::FindPositionOffset(Position pos) const {
|
||||
return FindPositionOffset(pos.lineNumber(), pos.column());
|
||||
}
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
// - Line ending markers are converted to single newline characters
|
||||
// - A newline character is added to the last line of the file if one is needed
|
||||
|
||||
#include "position.h"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Fortran {
|
||||
namespace parser {
|
||||
|
@ -20,6 +22,10 @@ public:
|
|||
std::string path() const { return path_; }
|
||||
const char *content() const { return content_; }
|
||||
size_t bytes() const { return bytes_; }
|
||||
size_t lines() const { return lineStart_.size(); }
|
||||
Position FindOffsetPosition(size_t) const;
|
||||
size_t FindPositionOffset(int lineNumber, int column) const;
|
||||
size_t FindPositionOffset(Position) const;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
|
@ -27,6 +33,7 @@ private:
|
|||
bool isMemoryMapped_{false};
|
||||
const char *content_{nullptr};
|
||||
size_t bytes_{0};
|
||||
std::vector<size_t> lineStart_;
|
||||
};
|
||||
} // namespace parser
|
||||
} // namespace Fortran
|
||||
|
|
Loading…
Reference in New Issue