178 lines
3.9 KiB
C++
178 lines
3.9 KiB
C++
|
// Copyright 2023 xensik. All rights reserved.
|
||
|
//
|
||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||
|
// that can be found in the LICENSE file.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
namespace xsk::gsc
|
||
|
{
|
||
|
|
||
|
class position
|
||
|
{
|
||
|
public:
|
||
|
typedef const std::string filename_type;
|
||
|
typedef int counter_type;
|
||
|
|
||
|
filename_type *filename;
|
||
|
counter_type line;
|
||
|
counter_type column;
|
||
|
|
||
|
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
|
||
|
: filename(f), line(l), column(c) {}
|
||
|
|
||
|
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
|
||
|
{
|
||
|
filename = fn;
|
||
|
line = l;
|
||
|
column = c;
|
||
|
}
|
||
|
|
||
|
void lines(counter_type count = 1)
|
||
|
{
|
||
|
if (count)
|
||
|
{
|
||
|
column = 1;
|
||
|
line = add_(line, count, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void columns(counter_type count = 1)
|
||
|
{
|
||
|
column = add_(column, count, 1);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
|
||
|
{
|
||
|
return lhs + rhs < min ? min : lhs + rhs;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline position& operator+=(position &res, position::counter_type width)
|
||
|
{
|
||
|
res.columns(width);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
inline position operator+(position res, position::counter_type width)
|
||
|
{
|
||
|
return res += width;
|
||
|
}
|
||
|
|
||
|
inline position& operator-=(position &res, position::counter_type width)
|
||
|
{
|
||
|
return res += -width;
|
||
|
}
|
||
|
|
||
|
inline position operator-(position res, position::counter_type width)
|
||
|
{
|
||
|
return res -= width;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
|
||
|
{
|
||
|
if (pos.filename)
|
||
|
ostr << *pos.filename << ':';
|
||
|
return ostr << pos.line << '.' << pos.column;
|
||
|
}
|
||
|
|
||
|
class location
|
||
|
{
|
||
|
public:
|
||
|
typedef position::filename_type filename_type;
|
||
|
typedef position::counter_type counter_type;
|
||
|
|
||
|
position begin;
|
||
|
position end;
|
||
|
|
||
|
location(const position &b, const position &e)
|
||
|
: begin(b), end(e) {}
|
||
|
|
||
|
explicit location(const position &p = position())
|
||
|
: begin(p), end(p) {}
|
||
|
|
||
|
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
|
||
|
: begin(f, l, c), end(f, l, c) {}
|
||
|
|
||
|
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
|
||
|
{
|
||
|
begin.initialize(f, l, c);
|
||
|
end = begin;
|
||
|
}
|
||
|
|
||
|
void step()
|
||
|
{
|
||
|
begin = end;
|
||
|
}
|
||
|
|
||
|
void columns(counter_type count = 1)
|
||
|
{
|
||
|
end += count;
|
||
|
}
|
||
|
|
||
|
void lines(counter_type count = 1)
|
||
|
{
|
||
|
end.lines(count);
|
||
|
}
|
||
|
|
||
|
auto print() const -> std::string
|
||
|
{
|
||
|
return fmt::format("{}:{}:{}", *begin.filename, begin.line, begin.column);
|
||
|
}
|
||
|
|
||
|
auto label() const -> std::string
|
||
|
{
|
||
|
return fmt::format("loc_{:X}", begin.line);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline location& operator+=(location &res, const location &end)
|
||
|
{
|
||
|
res.end = end.end;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
inline location operator+(location res, const location &end)
|
||
|
{
|
||
|
return res += end;
|
||
|
}
|
||
|
|
||
|
inline location& operator+=(location &res, location::counter_type width)
|
||
|
{
|
||
|
res.columns(width);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
inline location operator+(location res, location::counter_type width)
|
||
|
{
|
||
|
return res += width;
|
||
|
}
|
||
|
|
||
|
inline location& operator-=(location &res, location::counter_type width)
|
||
|
{
|
||
|
return res += -width;
|
||
|
}
|
||
|
|
||
|
inline location operator-(location res, location::counter_type width)
|
||
|
{
|
||
|
return res -= width;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
|
||
|
{
|
||
|
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
|
||
|
ostr << loc.begin;
|
||
|
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
|
||
|
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
|
||
|
else if (loc.begin.line < loc.end.line)
|
||
|
ostr << '-' << loc.end.line << '.' << end_col;
|
||
|
else if (loc.begin.column < end_col)
|
||
|
ostr << '-' << end_col;
|
||
|
return ostr;
|
||
|
}
|
||
|
|
||
|
} // namespace xsk::gsc
|