Skip to content

Commit

Permalink
Fix macro parameters not being able to be specified over multiple lin…
Browse files Browse the repository at this point in the history
…es when defining
  • Loading branch information
Laupetin committed Dec 14, 2023
1 parent 9095e58 commit aa5731e
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 42 deletions.
98 changes: 60 additions & 38 deletions src/Parser/Parsing/Impl/DefinesStreamProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ DefinesStreamProxy::DefinesStreamProxy(IParserLineStream* stream, const bool ski
: m_stream(stream),
m_skip_directive_lines(skipDirectiveLines),
m_ignore_depth(0),
m_in_define(false)
m_in_define(false),
m_parameter_state(ParameterState::NOT_IN_PARAMETERS)
{
}

Expand All @@ -142,12 +143,16 @@ int DefinesStreamProxy::GetLineEndEscapePos(const ParserLine& line)
return -1;
}

void DefinesStreamProxy::ContinueDefine(const ParserLine& line)
void DefinesStreamProxy::ContinueDefine(const ParserLine& line, const unsigned currentPos)
{
const auto lineEndEscapePos = GetLineEndEscapePos(line);
if (lineEndEscapePos < 0)
{
m_current_define_value << line.m_line;
if (currentPos <= 0)
m_current_define_value << line.m_line;
else
m_current_define_value << line.m_line.substr(currentPos);

m_current_define.m_value = m_current_define_value.str();
m_current_define.IdentifyParameters(m_current_define_parameters);
AddDefine(std::move(m_current_define));
Expand All @@ -159,49 +164,58 @@ void DefinesStreamProxy::ContinueDefine(const ParserLine& line)
}
else
{
if (line.m_line.size() > static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(0, static_cast<unsigned>(lineEndEscapePos));
if (line.m_line.size() > static_cast<unsigned>(lineEndEscapePos) && currentPos < static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(currentPos, static_cast<unsigned>(lineEndEscapePos) - currentPos);
}
}

std::vector<std::string> DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition)
void DefinesStreamProxy::ContinueParameters(const ParserLine& line, unsigned& currentPos)
{
if (line.m_line[parameterPosition] != '(')
return std::vector<std::string>();

parameterPosition++;
std::vector<std::string> parameters;

const auto lineEndEscapePos = GetLineEndEscapePos(line);
while (true)
{
if (!SkipWhitespace(line, parameterPosition) || parameterPosition >= line.m_line.size())
throw ParsingException(CreatePos(line, parameterPosition), "Invalid define parameter list");
if (!SkipWhitespace(line, currentPos))
throw ParsingException(CreatePos(line, currentPos), "Invalid define parameter list");

const auto nameStartPos = parameterPosition;
if (!ExtractIdentifier(line, parameterPosition))
throw ParsingException(CreatePos(line, parameterPosition), "Cannot extract name of parameter of define");
if (lineEndEscapePos >= 0 && currentPos >= static_cast<unsigned>(lineEndEscapePos))
return;

parameters.emplace_back(std::string(line.m_line, nameStartPos, parameterPosition - nameStartPos));
if (currentPos >= line.m_line.size())
throw ParsingException(CreatePos(line, currentPos), "Invalid define parameter list");

if (!SkipWhitespace(line, parameterPosition))
throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters");

if (parameterPosition >= line.m_line.size())
throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters");
if ((m_parameter_state == ParameterState::AFTER_OPEN || m_parameter_state == ParameterState::AFTER_PARAM) && line.m_line[currentPos] == ')')
{
currentPos++;
m_parameter_state = ParameterState::NOT_IN_PARAMETERS;
return;
}

if (line.m_line[parameterPosition] == ')')
if (m_parameter_state == ParameterState::AFTER_PARAM && line.m_line[currentPos] == ',')
{
parameterPosition++;
break;
currentPos++;
m_parameter_state = ParameterState::AFTER_COMMA;
continue;
}

if (line.m_line[parameterPosition] != ',')
throw ParsingException(CreatePos(line, parameterPosition), "Unknown symbol in define parameter list");
const auto nameStartPos = currentPos;
if (!ExtractIdentifier(line, currentPos))
throw ParsingException(CreatePos(line, currentPos), "Cannot extract name of parameter of define");

parameterPosition++;
m_current_define_parameters.emplace_back(line.m_line, nameStartPos, currentPos - nameStartPos);
m_parameter_state = ParameterState::AFTER_PARAM;
}
}

void DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& currentPos)
{
m_current_define_parameters = std::vector<std::string>();
if (line.m_line[currentPos] != '(')
return;

m_parameter_state = ParameterState::AFTER_OPEN;
currentPos++;

return parameters;
ContinueParameters(line, currentPos);
}

bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
Expand All @@ -223,28 +237,28 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsi

const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos);

auto parameters = MatchDefineParameters(line, currentPos);
MatchDefineParameters(line, currentPos);
SkipWhitespace(line, currentPos);

const auto lineEndEscapePos = GetLineEndEscapePos(line);
if (lineEndEscapePos < 0)
{
std::string value;
if (currentPos < line.m_line.size())
value = line.m_line.substr(currentPos + 1);
value = line.m_line.substr(currentPos);

Define define(name, value);
define.IdentifyParameters(parameters);
define.IdentifyParameters(m_current_define_parameters);
AddDefine(std::move(define));
}
else
{
m_in_define = true;
m_current_define = Define(name, std::string());
m_current_define_value.str(std::string());
m_current_define_parameters = std::move(parameters);

if (currentPos < line.m_line.size() && (currentPos + 1) < static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(currentPos + 1, static_cast<unsigned>(lineEndEscapePos) - (currentPos + 1));
if (currentPos < line.m_line.size() && (currentPos) < static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(currentPos, static_cast<unsigned>(lineEndEscapePos) - (currentPos));
}

return true;
Expand Down Expand Up @@ -451,7 +465,7 @@ bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsig
return true;
}

bool DefinesStreamProxy::MatchDirectives(const ParserLine& line)
bool DefinesStreamProxy::MatchDirectives(ParserLine& line)
{
unsigned directiveStartPos;
unsigned directiveEndPos;
Expand Down Expand Up @@ -709,7 +723,15 @@ ParserLine DefinesStreamProxy::NextLine()
{
if (m_in_define)
{
ContinueDefine(line);
unsigned currentPos = 0u;

if (m_parameter_state != ParameterState::NOT_IN_PARAMETERS)
{
ContinueParameters(line, currentPos);
SkipWhitespace(line, currentPos);
}

ContinueDefine(line, currentPos);
if (!m_skip_directive_lines)
{
line.m_line = std::string();
Expand Down
18 changes: 14 additions & 4 deletions src/Parser/Parsing/Impl/DefinesStreamProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,45 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
};

private:
enum class BlockMode
enum class BlockMode : uint8_t
{
NOT_IN_BLOCK,
IN_BLOCK,
BLOCK_BLOCKED
};

enum class ParameterState : uint8_t
{
NOT_IN_PARAMETERS,
AFTER_OPEN,
AFTER_PARAM,
AFTER_COMMA
};

IParserLineStream* const m_stream;
const bool m_skip_directive_lines;
std::map<std::string, Define> m_defines;
std::stack<BlockMode> m_modes;
unsigned m_ignore_depth;

bool m_in_define;
ParameterState m_parameter_state;
Define m_current_define;
std::ostringstream m_current_define_value;
std::vector<std::string> m_current_define_parameters;

static int GetLineEndEscapePos(const ParserLine& line);
static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition);
void ContinueDefine(const ParserLine& line);
void MatchDefineParameters(const ParserLine& line, unsigned& currentPos);
void ContinueDefine(const ParserLine& line, unsigned currentPos);
void ContinueParameters(const ParserLine& line, unsigned& currentPos);
_NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchIfDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchElIfDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchElseDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchEndifDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchDirectives(const ParserLine& line);
_NODISCARD bool MatchDirectives(ParserLine& line);

static void
ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues);
Expand Down

0 comments on commit aa5731e

Please sign in to comment.