Extract preprocessing from tokenizer
This commit is contained in:
159
src/preprocessor/preprocessor.cpp
Normal file
159
src/preprocessor/preprocessor.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user