roza/lib/Lexer.cpp

164 lines
3.8 KiB
C++
Raw Normal View History

2023-08-30 18:06:26 +00:00
#include "Lexer.hpp"
#include "lib/Node.hpp"
namespace roza
{
/*explicit*/ Lexer::Lexer(StatusLog& log, SrcLoc loc)
: m_log { log }
, m_loc { loc }
{
m_scanners.push_back(std::bind(&Lexer::scan_int, this));
2023-08-30 22:31:19 +00:00
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "+", NODE_ADD, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "-", NODE_SUB, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "*", NODE_MUL, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "/", NODE_DIV, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "%", NODE_MOD, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "^", NODE_POW, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, "(", NODE_OPAR, false));
m_scanners.push_back(std::bind(&Lexer::scan_text, this, ")", NODE_CPAR, false));
2023-08-30 18:06:26 +00:00
}
/*virtual*/ Lexer::~Lexer()
{
}
2023-08-30 22:31:19 +00:00
bool Lexer::is_at_end() const
{
return m_cursor >= size();
}
2023-08-30 18:06:26 +00:00
void Lexer::scan(std::string const& source)
{
m_source = source;
m_cursor = 0;
skip_blanks();
while (m_cursor < source.size())
{
while (m_cursor < source.size()
&& source[m_cursor] == '#')
{
while (m_cursor < source.size()
&& source[m_cursor] != '\n')
{
m_cursor++;
}
2023-08-30 22:31:19 +00:00
m_loc.set_line(m_loc.line() + 1);
2023-08-30 18:06:26 +00:00
m_cursor++;
}
skip_blanks();
ScanInfo info;
std::shared_ptr<Node> node;
size_t cursor = m_cursor;
for (auto& scanner: m_scanners)
{
ScanInfo info = scanner();
if (info.node && info.cursor > cursor)
{
node = info.node;
cursor = info.cursor;
}
}
m_nodes.push_back(node);
m_cursor = cursor;
skip_blanks();
if (!node)
{
std::string symb;
while (m_cursor < m_source.size()
&& !std::isblank(m_source[m_cursor]))
{
symb += m_source[m_cursor];
m_cursor++;
}
m_log.fatal(m_loc
, std::string()
+ "unexpected symbol '"
+ symb + "'");
}
}
}
void Lexer::skip_blanks()
{
while (m_cursor < m_source.size()
&& std::isspace(m_source.at(m_cursor)))
{
if (m_source.at(m_cursor) == '\n')
{
m_loc.set_line(m_loc.line() + 1);
auto root = std::make_shared<Node>(NODE_EOI, "", m_loc);
m_nodes.push_back(root);
}
m_cursor++;
}
}
std::shared_ptr<Node> Lexer::get_or_nullptr(size_t index) const
{
if (index >= m_nodes.size())
{
return nullptr;
}
return m_nodes.at(index);
}
ScanInfo Lexer::scan_int() const
{
size_t cursor = m_cursor;
std::string repr;
while (cursor < m_source.size()
&& std::isdigit(m_source[cursor]))
{
repr += m_source[cursor];
cursor++;
}
if (!repr.empty())
{
return ScanInfo {
std::make_shared<Node>(NodeType::NODE_INT, repr, m_loc),
cursor
};
}
return ScanInfo {};
}
2023-08-30 22:31:19 +00:00
ScanInfo Lexer::scan_text(std::string const& text
, NodeType type
, bool value) const
{
for (size_t i=0; i<text.size(); i++)
{
if (m_cursor + i >= m_source.size()
|| m_source[m_cursor + i] != text[i])
{
return ScanInfo {
};
}
}
return ScanInfo {
std::make_shared<Node>(type, value ? text : "", m_loc),
m_cursor + text.size()
};
}
2023-08-30 18:06:26 +00:00
}