#ifndef SYNTH_HIGHLIGTHED_FILE_HPP_INCLUDED
#define SYNTH_HIGHLIGTHED_FILE_HPP_INCLUDED
#include <boost/filesystem/path.hpp>
#include <cstdint>
#include <iosfwd>
#include <string>
#include <unordered_map>
#include <vector>
namespace synth {
namespace fs = boost::filesystem;
using TokenAttributesUnderlying = std::uint16_t;
enum class TokenAttributes : TokenAttributesUnderlying {
none,
attr,
cmmt,
constant, // Enumerator, non-type template param.
func,
kw,
kwDecl,
lbl,
lit,
litChr,
litKw, // true, false, nullptr
litNum,
litNumFlt,
litNumIntBin,
litNumIntDecLong,
litNumIntHex,
litNumIntOct,
litStr,
namesp,
op,
opWord,
pre,
preIncludeFile,
punct,
ty,
tyBuiltin,
varGlobal,
varLocal,
varNonstaticMember,
varStaticMember,
maskKind = 0x3ff, // 1023 kinds
flagDecl = 1 << 15,
flagDef = 1 << 14
};
#define SYNTH_DEF_TOKATTR_OP(op) \
constexpr TokenAttributes operator op ( \
TokenAttributes lhs, TokenAttributes rhs) \
{ \
return static_cast<TokenAttributes>( \
static_cast<TokenAttributesUnderlying>(lhs) \
op static_cast<TokenAttributesUnderlying>(rhs)); \
}
SYNTH_DEF_TOKATTR_OP(|)
SYNTH_DEF_TOKATTR_OP(&)
SYNTH_DEF_TOKATTR_OP(^)
#define SYNTH_DEF_TOKATTR_ASSIGN_OP(op) \
inline TokenAttributes operator op ( \
TokenAttributes& lhs, TokenAttributes rhs) \
{ \
auto r = static_cast<TokenAttributesUnderlying>(lhs); \
r op static_cast<TokenAttributesUnderlying>(rhs); \
return lhs = static_cast<TokenAttributes>(r); \
}
SYNTH_DEF_TOKATTR_ASSIGN_OP(|=)
SYNTH_DEF_TOKATTR_ASSIGN_OP(&=)
SYNTH_DEF_TOKATTR_ASSIGN_OP(^=)
constexpr TokenAttributes operator~ (TokenAttributes t)
{
return static_cast<TokenAttributes>(
~static_cast<TokenAttributesUnderlying>(t));
}
struct HighlightedFile;
struct SymbolDeclaration {
HighlightedFile const* file;
unsigned lineno; // 0: Whole file referenced. Implies fileUniueName.empty().
std::string fileUniqueName; // Can be empty.
bool valid() const { return file != nullptr; }
};
inline bool operator== (
SymbolDeclaration const& lhs, SymbolDeclaration const& rhs)
{
return lhs.lineno == rhs.lineno
&& lhs.file == rhs.file
&& lhs.fileUniqueName == rhs.fileUniqueName;
}
class MultiTuProcessor;
// return.empty(): No reference.
using CodeRef = std::function<std::string(fs::path const&, MultiTuProcessor&)>;
struct Markup {
unsigned beginOffset;
unsigned endOffset;
TokenAttributes attrs;
std::string const* fileUniqueName;
CodeRef refd;
bool empty() const;
bool isRef() const { return static_cast<bool>(refd); }
};
struct HighlightedFile {
// Relative to inOutDir: first / fname: original, second / fname: dst.
fs::path fname;
std::pair<fs::path, fs::path> const* inOutDir;
std::vector<Markup> markups;
std::vector<std::pair<unsigned, unsigned>> disabledLines;
fs::path dstPath() const;
fs::path srcPath() const { return inOutDir->first / fname; }
void supplementMarkups(std::vector<Markup> const& supplementary);
void writeTo(
std::ostream& out,
MultiTuProcessor& multiTuProcessor,
std::ifstream& selfIn) const;
};
// Must be called before writeTo() or supplementMarkups()
void sortMarkups(std::vector<Markup>& markups);
inline std::string lineId(unsigned lineno)
{
return std::to_string(lineno) + "L";
}
} // namespace synth
#endif