Files
wassembly/src/preprocessor/preprocessor.cpp

159 lines
3.2 KiB
C++

#include <preprocessor/preprocessor.hpp>
#include <utils.hpp>
bool trySubstitute(
std::string & line,
std::size_t const lineColumn,
std::vector<std::string> const & substitutionIdentifiers,
std::vector<std::string> const & substitutionValues)
{
for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i)
{
if (line.compare(lineColumn, substitutionIdentifiers[i].size(), substitutionIdentifiers[i]) != 0)
{
continue;
}
std::string const lineCopy = line;
line = lineCopy.substr(0, lineColumn) + substitutionValues[i];
if (lineCopy.size() > lineColumn + substitutionIdentifiers[i].size())
{
line += lineCopy.substr(lineColumn + substitutionIdentifiers[i].size(), lineCopy.size());
}
return true;
}
return false;
}
void Preprocessor::extractComment(
std::string & line,
std::size_t const lineNumber,
std::size_t const lineColumn)
{
if (line.size() <= lineColumn + 1 ||
line.compare(lineColumn + 1, std::string::npos, "DEFINE") <= 0)
{
// No match or empty DEFINE statement
line = line.substr(0, lineColumn);
}
enum CommentParseState
{
LookForArgumentStart,
LookForArgumentEnd
};
std::string firstArgument, secondArgument;
std::size_t argumentCount = 0, argumentStart = 0;
CommentParseState state = LookForArgumentStart;
for(std::size_t i = lineColumn + 7; i < line.size(); ++i)
{
switch(state)
{
case LookForArgumentStart:
if(!Utils::isWhitespaceCharacter(line[i]))
{
argumentStart = i;
state = CommentParseState::LookForArgumentEnd;
}
break;
case LookForArgumentEnd:
if (Utils::isWhitespaceCharacter(line[i]))
{
switch(argumentCount)
{
case 0:
firstArgument = line.substr(argumentStart, i - argumentStart);
break;
case 1:
secondArgument = line.substr(argumentStart, i - argumentStart);
break;
default:
break;
}
++argumentCount;
state = CommentParseState::LookForArgumentStart;
}
break;
}
}
switch(state)
{
case CommentParseState::LookForArgumentStart:
break;
case CommentParseState::LookForArgumentEnd:
switch(argumentCount)
{
case 0:
firstArgument = line.substr(argumentStart);
break;
case 1:
secondArgument = line.substr(argumentStart);
break;
default:
break;
}
++argumentCount;
break;
}
if (argumentCount > 0)
{
substitutionIdentifiers.push_back(firstArgument);
substitutionValues.push_back(secondArgument);
}
line = line.substr(0, lineColumn);
}
void Preprocessor::processLine(std::string & line, std::size_t const lineNumber)
{
for(std::size_t i = 0; i < line.size(); ++i)
{
if (!Utils::isWhitespaceCharacter(line[i]))
{
if (trySubstitute(line, i, substitutionIdentifiers, substitutionValues))
{
continue;
}
if (line[i] == '#')
{
extractComment(line, lineNumber, i);
return;
}
}
}
}
void Preprocessor::process(std::vector<std::string> & lines)
{
substitutionIdentifiers.clear();
substitutionValues.clear();
for(std::size_t i = 0; i < lines.size(); ++i)
{
processLine(lines[i], i);
}
}
void Preprocessor::printSubstitutions() const
{
for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i)
{
std::printf(
"%s -> %s\n",
substitutionIdentifiers[i].c_str(),
substitutionValues[i].c_str());
}
}