mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Add support for defineproxy if directive parsing
This commit is contained in:
parent
887d14df54
commit
c65c57ce72
@ -317,8 +317,9 @@ public:
|
|||||||
{
|
{
|
||||||
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
|
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
|
||||||
const auto& firstToken = m_token_cache.front();
|
const auto& firstToken = m_token_cache.front();
|
||||||
while (m_line_cache.front().m_line_number != firstToken.GetPos().m_line
|
while (!m_line_cache.empty()
|
||||||
|| *m_line_cache.front().m_filename != firstToken.GetPos().m_filename.get())
|
&& (m_line_cache.front().m_line_number != firstToken.GetPos().m_line
|
||||||
|
|| *m_line_cache.front().m_filename != firstToken.GetPos().m_filename.get()))
|
||||||
{
|
{
|
||||||
m_line_cache.pop_front();
|
m_line_cache.pop_front();
|
||||||
m_line_index--;
|
m_line_index--;
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
#include "DefinesIfDirectiveExpressionSequence.h"
|
||||||
|
|
||||||
|
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||||
|
#include "DefinesIfExpressionMatchers.h"
|
||||||
|
|
||||||
|
DefinesIfDirectiveExpressionSequence::DefinesIfDirectiveExpressionSequence()
|
||||||
|
{
|
||||||
|
const SimpleMatcherFactory create(this);
|
||||||
|
AddLabeledMatchers(DefinesIfExpressionMatchers().Expression(this), SimpleExpressionMatchers::LABEL_EXPRESSION);
|
||||||
|
AddMatchers(create.Label(SimpleExpressionMatchers::LABEL_EXPRESSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefinesIfDirectiveExpressionSequence::ProcessMatch(DefinesIfDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const
|
||||||
|
{
|
||||||
|
state->m_expression = DefinesIfExpressionMatchers(state).ProcessExpression(result);
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DefinesIfDirectiveParser.h"
|
||||||
|
#include "DefinesIfDirectiveParsingState.h"
|
||||||
|
|
||||||
|
class DefinesIfDirectiveExpressionSequence final : public DefinesIfDirectiveParser::sequence_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DefinesIfDirectiveExpressionSequence();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessMatch(DefinesIfDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const override;
|
||||||
|
};
|
22
src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.cpp
Normal file
22
src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "DefinesIfDirectiveParser.h"
|
||||||
|
|
||||||
|
#include "DefinesIfDirectiveExpressionSequence.h"
|
||||||
|
|
||||||
|
DefinesIfDirectiveParser::DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer, const std::map<std::string, DefinesStreamProxy::Define>& defines)
|
||||||
|
: AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>(lexer, std::make_unique<DefinesIfDirectiveParsingState>(defines))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>::sequence_t*>& DefinesIfDirectiveParser::GetTestsForState()
|
||||||
|
{
|
||||||
|
static std::vector<sequence_t*> sequences
|
||||||
|
{
|
||||||
|
new DefinesIfDirectiveExpressionSequence()
|
||||||
|
};
|
||||||
|
return sequences;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ISimpleExpression> DefinesIfDirectiveParser::GetParsedExpression() const
|
||||||
|
{
|
||||||
|
return std::move(m_state->m_expression);
|
||||||
|
}
|
17
src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.h
Normal file
17
src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DefinesIfDirectiveParsingState.h"
|
||||||
|
#include "Parsing/Impl/AbstractParser.h"
|
||||||
|
#include "Parsing/Simple/SimpleParserValue.h"
|
||||||
|
|
||||||
|
class DefinesIfDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer, const std::map<std::string, DefinesStreamProxy::Define>& defines);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const std::vector<sequence_t*>& GetTestsForState() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
_NODISCARD std::unique_ptr<ISimpleExpression> GetParsedExpression() const;
|
||||||
|
};
|
@ -0,0 +1,6 @@
|
|||||||
|
#include "DefinesIfDirectiveParsingState.h"
|
||||||
|
|
||||||
|
DefinesIfDirectiveParsingState::DefinesIfDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines)
|
||||||
|
: m_defines(defines)
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||||
|
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||||
|
|
||||||
|
class DefinesIfDirectiveParsingState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::map<std::string, DefinesStreamProxy::Define>& m_defines;
|
||||||
|
std::unique_ptr<ISimpleExpression> m_expression;
|
||||||
|
|
||||||
|
explicit DefinesIfDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines);
|
||||||
|
};
|
@ -0,0 +1,37 @@
|
|||||||
|
#include "DefinesIfExpressionMatchers.h"
|
||||||
|
|
||||||
|
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||||
|
|
||||||
|
DefinesIfExpressionMatchers::DefinesIfExpressionMatchers()
|
||||||
|
: DefinesIfExpressionMatchers(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DefinesIfExpressionMatchers::DefinesIfExpressionMatchers(const DefinesIfDirectiveParsingState* state)
|
||||||
|
: SimpleExpressionMatchers(false, false, true, true),
|
||||||
|
m_state(state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SimpleExpressionMatchers::matcher_t> DefinesIfExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const
|
||||||
|
{
|
||||||
|
const SimpleMatcherFactory create(labelSupplier);
|
||||||
|
|
||||||
|
return create.And({
|
||||||
|
create.Keyword("defined"),
|
||||||
|
create.Char('('),
|
||||||
|
create.Identifier().Capture(CAPTURE_DEFINE_NAME),
|
||||||
|
create.Char(')'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ISimpleExpression> DefinesIfExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
||||||
|
{
|
||||||
|
const auto& defineCapture = result.NextCapture(CAPTURE_DEFINE_NAME);
|
||||||
|
|
||||||
|
assert(m_state);
|
||||||
|
if(m_state && m_state->m_defines.find(defineCapture.IdentifierValue()) != m_state->m_defines.end())
|
||||||
|
return std::make_unique<SimpleExpressionValue>(1);
|
||||||
|
|
||||||
|
return std::make_unique<SimpleExpressionValue>(0);
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "DefinesIfDirectiveParsingState.h"
|
||||||
|
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||||
|
|
||||||
|
class DefinesIfExpressionMatchers final : public SimpleExpressionMatchers
|
||||||
|
{
|
||||||
|
static constexpr auto CAPTURE_DEFINE_NAME = CAPTURE_OFFSET_EXPRESSION_EXT + 1;
|
||||||
|
|
||||||
|
const DefinesIfDirectiveParsingState* m_state;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
|
||||||
|
std::unique_ptr<ISimpleExpression> ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DefinesIfExpressionMatchers();
|
||||||
|
explicit DefinesIfExpressionMatchers(const DefinesIfDirectiveParsingState* state);
|
||||||
|
};
|
@ -3,52 +3,15 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
#include "AbstractParser.h"
|
#include "AbstractParser.h"
|
||||||
#include "ParserSingleInputStream.h"
|
#include "ParserSingleInputStream.h"
|
||||||
|
#include "Defines/DefinesIfDirectiveParser.h"
|
||||||
#include "Parsing/ParsingException.h"
|
#include "Parsing/ParsingException.h"
|
||||||
#include "Parsing/Simple/SimpleLexer.h"
|
#include "Parsing/Simple/SimpleLexer.h"
|
||||||
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||||
|
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||||
class DefinesIfDirectiveParsingState
|
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::unique_ptr<ISimpleExpression> m_expression;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DefinesIfDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
explicit DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer)
|
|
||||||
: AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>(lexer, std::make_unique<DefinesIfDirectiveParsingState>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<sequence_t*>& GetTestsForState() override
|
|
||||||
{
|
|
||||||
static std::vector<sequence_t*> sequences
|
|
||||||
{
|
|
||||||
};
|
|
||||||
return sequences;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static bool EvaluateIfDirective(std::map<std::string, DefinesStreamProxy::Define>& defines, const std::string& value)
|
|
||||||
{
|
|
||||||
std::istringstream ss(value);
|
|
||||||
ParserSingleInputStream inputStream(ss, "");
|
|
||||||
SimpleLexer::Config config{};
|
|
||||||
config.m_emit_new_line_tokens = false;
|
|
||||||
config.m_read_numbers = true;
|
|
||||||
config.m_read_strings = false;
|
|
||||||
SimpleLexer lexer(&inputStream, std::move(config));
|
|
||||||
DefinesIfDirectiveParser parser(&lexer);
|
|
||||||
if (!parser.Parse())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto& expression = parser.m_state->m_expression;
|
|
||||||
return expression->IsStatic() && expression->Evaluate().IsTruthy();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DefinesStreamProxy::DefineParameterPosition::DefineParameterPosition()
|
DefinesStreamProxy::DefineParameterPosition::DefineParameterPosition()
|
||||||
: m_parameter_index(0u),
|
: m_parameter_index(0u),
|
||||||
@ -315,6 +278,101 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ISimpleExpression> DefinesStreamProxy::ParseIfExpression(const std::string& expressionString) const
|
||||||
|
{
|
||||||
|
std::istringstream ss(expressionString);
|
||||||
|
ParserSingleInputStream inputStream(ss, "#if expression");
|
||||||
|
|
||||||
|
SimpleLexer::Config lexerConfig;
|
||||||
|
lexerConfig.m_emit_new_line_tokens = false;
|
||||||
|
lexerConfig.m_read_numbers = true;
|
||||||
|
lexerConfig.m_read_strings = false;
|
||||||
|
SimpleExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig);
|
||||||
|
|
||||||
|
SimpleLexer lexer(&inputStream, std::move(lexerConfig));
|
||||||
|
DefinesIfDirectiveParser parser(&lexer, m_defines);
|
||||||
|
|
||||||
|
if (!parser.Parse())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return parser.GetParsedExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DefinesStreamProxy::MatchIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
|
||||||
|
{
|
||||||
|
auto currentPos = directiveStartPosition;
|
||||||
|
|
||||||
|
if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(IF_DIRECTIVE)
|
||||||
|
|| !MatchString(line, currentPos, IF_DIRECTIVE, std::char_traits<char>::length(IF_DIRECTIVE)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK)
|
||||||
|
{
|
||||||
|
m_ignore_depth++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SkipWhitespace(line, currentPos))
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Cannot if without an expression.");
|
||||||
|
|
||||||
|
const auto expressionString = line.m_line.substr(currentPos, line.m_line.size() - currentPos);
|
||||||
|
|
||||||
|
if (expressionString.empty())
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Cannot if without an expression.");
|
||||||
|
|
||||||
|
const auto expression = ParseIfExpression(expressionString);
|
||||||
|
if (!expression)
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Failed to parse if expression");
|
||||||
|
|
||||||
|
m_modes.push(expression->Evaluate().IsTruthy() ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DefinesStreamProxy::MatchElIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
|
||||||
|
{
|
||||||
|
auto currentPos = directiveStartPosition;
|
||||||
|
|
||||||
|
if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(ELIF_DIRECTIVE)
|
||||||
|
|| !MatchString(line, currentPos, ELIF_DIRECTIVE, std::char_traits<char>::length(ELIF_DIRECTIVE)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ignore_depth > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (m_modes.empty())
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Cannot use elif without if");
|
||||||
|
|
||||||
|
if (m_modes.top() == BlockMode::BLOCK_BLOCKED)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(m_modes.top() == BlockMode::IN_BLOCK)
|
||||||
|
{
|
||||||
|
m_modes.top() = BlockMode::BLOCK_BLOCKED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SkipWhitespace(line, currentPos))
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Cannot elif without an expression.");
|
||||||
|
|
||||||
|
const auto expressionString = line.m_line.substr(currentPos, line.m_line.size() - currentPos);
|
||||||
|
|
||||||
|
if (expressionString.empty())
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Cannot elif without an expression.");
|
||||||
|
|
||||||
|
const auto expression = ParseIfExpression(expressionString);
|
||||||
|
if (!expression)
|
||||||
|
throw ParsingException(CreatePos(line, currentPos), "Failed to parse elif expression");
|
||||||
|
|
||||||
|
m_modes.top() = expression->Evaluate().IsTruthy() ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
|
bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
|
||||||
{
|
{
|
||||||
auto currentPos = directiveStartPosition;
|
auto currentPos = directiveStartPosition;
|
||||||
@ -332,7 +390,7 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig
|
|||||||
reverse = true;
|
reverse = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_modes.empty() && !m_modes.top())
|
if (!m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK)
|
||||||
{
|
{
|
||||||
m_ignore_depth++;
|
m_ignore_depth++;
|
||||||
return true;
|
return true;
|
||||||
@ -349,9 +407,9 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig
|
|||||||
const auto entry = m_defines.find(name);
|
const auto entry = m_defines.find(name);
|
||||||
|
|
||||||
if (entry != m_defines.end())
|
if (entry != m_defines.end())
|
||||||
m_modes.push(!reverse);
|
m_modes.push(!reverse ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK);
|
||||||
else
|
else
|
||||||
m_modes.push(reverse);
|
m_modes.push(reverse ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -369,11 +427,11 @@ bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, const unsign
|
|||||||
if (m_ignore_depth > 0)
|
if (m_ignore_depth > 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!m_modes.empty())
|
if (m_modes.empty())
|
||||||
m_modes.top() = !m_modes.top();
|
|
||||||
else
|
|
||||||
throw ParsingException(CreatePos(line, currentPos), "Cannot use else without ifdef");
|
throw ParsingException(CreatePos(line, currentPos), "Cannot use else without ifdef");
|
||||||
|
|
||||||
|
m_modes.top() = m_modes.top() == BlockMode::NOT_IN_BLOCK ? BlockMode::IN_BLOCK : BlockMode::BLOCK_BLOCKED;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +469,7 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line)
|
|||||||
|
|
||||||
directiveStartPos++;
|
directiveStartPos++;
|
||||||
|
|
||||||
if (m_modes.empty() || m_modes.top() == true)
|
if (m_modes.empty() || m_modes.top() == BlockMode::IN_BLOCK)
|
||||||
{
|
{
|
||||||
if (MatchDefineDirective(line, directiveStartPos, directiveEndPos)
|
if (MatchDefineDirective(line, directiveStartPos, directiveEndPos)
|
||||||
|| MatchUndefDirective(line, directiveStartPos, directiveEndPos))
|
|| MatchUndefDirective(line, directiveStartPos, directiveEndPos))
|
||||||
@ -419,6 +477,8 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return MatchIfdefDirective(line, directiveStartPos, directiveEndPos)
|
return MatchIfdefDirective(line, directiveStartPos, directiveEndPos)
|
||||||
|
|| MatchIfDirective(line, directiveStartPos, directiveEndPos)
|
||||||
|
|| MatchElIfDirective(line, directiveStartPos, directiveEndPos)
|
||||||
|| MatchElseDirective(line, directiveStartPos, directiveEndPos)
|
|| MatchElseDirective(line, directiveStartPos, directiveEndPos)
|
||||||
|| MatchEndifDirective(line, directiveStartPos, directiveEndPos);
|
|| MatchEndifDirective(line, directiveStartPos, directiveEndPos);
|
||||||
}
|
}
|
||||||
@ -583,7 +643,7 @@ ParserLine DefinesStreamProxy::NextLine()
|
|||||||
ContinueDefine(line);
|
ContinueDefine(line);
|
||||||
line.m_line.clear();
|
line.m_line.clear();
|
||||||
}
|
}
|
||||||
else if (MatchDirectives(line) || !m_modes.empty() && !m_modes.top())
|
else if (MatchDirectives(line) || !m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK)
|
||||||
{
|
{
|
||||||
line.m_line.clear();
|
line.m_line.clear();
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
|
|
||||||
#include "AbstractDirectiveStreamProxy.h"
|
#include "AbstractDirectiveStreamProxy.h"
|
||||||
#include "Parsing/IParserLineStream.h"
|
#include "Parsing/IParserLineStream.h"
|
||||||
|
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||||
|
|
||||||
class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
|
class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
|
||||||
{
|
{
|
||||||
static constexpr const char* DEFINE_DIRECTIVE = "define";
|
static constexpr const char* DEFINE_DIRECTIVE = "define";
|
||||||
static constexpr const char* UNDEF_DIRECTIVE = "undef";
|
static constexpr const char* UNDEF_DIRECTIVE = "undef";
|
||||||
|
static constexpr const char* IF_DIRECTIVE = "if";
|
||||||
|
static constexpr const char* ELIF_DIRECTIVE = "elif";
|
||||||
static constexpr const char* IFDEF_DIRECTIVE = "ifdef";
|
static constexpr const char* IFDEF_DIRECTIVE = "ifdef";
|
||||||
static constexpr const char* IFNDEF_DIRECTIVE = "ifndef";
|
static constexpr const char* IFNDEF_DIRECTIVE = "ifndef";
|
||||||
static constexpr const char* ELSE_DIRECTIVE = "else";
|
static constexpr const char* ELSE_DIRECTIVE = "else";
|
||||||
@ -43,9 +46,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class BlockMode
|
||||||
|
{
|
||||||
|
NOT_IN_BLOCK,
|
||||||
|
IN_BLOCK,
|
||||||
|
BLOCK_BLOCKED
|
||||||
|
};
|
||||||
|
|
||||||
IParserLineStream* const m_stream;
|
IParserLineStream* const m_stream;
|
||||||
std::map<std::string, Define> m_defines;
|
std::map<std::string, Define> m_defines;
|
||||||
std::stack<bool> m_modes;
|
std::stack<BlockMode> m_modes;
|
||||||
unsigned m_ignore_depth;
|
unsigned m_ignore_depth;
|
||||||
|
|
||||||
bool m_in_define;
|
bool m_in_define;
|
||||||
@ -56,8 +66,11 @@ private:
|
|||||||
static int GetLineEndEscapePos(const ParserLine& line);
|
static int GetLineEndEscapePos(const ParserLine& line);
|
||||||
static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition);
|
static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition);
|
||||||
void ContinueDefine(const ParserLine& line);
|
void ContinueDefine(const ParserLine& line);
|
||||||
|
_NODISCARD std::unique_ptr<ISimpleExpression> ParseIfExpression(const std::string& expressionString) const;
|
||||||
_NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
|
_NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
|
||||||
_NODISCARD bool MatchUndefDirective(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 MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
|
||||||
_NODISCARD bool MatchElseDirective(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 MatchEndifDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
|
||||||
|
@ -470,4 +470,115 @@ namespace test::parsing::impl::defines_stream_proxy
|
|||||||
|
|
||||||
REQUIRE(proxy.Eof());
|
REQUIRE(proxy.Eof());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DefinesStreamProxy: Ensure simple if is working with truthy value", "[parsing][parsingstream]")
|
||||||
|
{
|
||||||
|
const std::vector<std::string> lines
|
||||||
|
{
|
||||||
|
"#if 1",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
};
|
||||||
|
|
||||||
|
MockParserLineStream mockStream(lines);
|
||||||
|
DefinesStreamProxy proxy(&mockStream);
|
||||||
|
|
||||||
|
ExpectLine(&proxy, 1, "");
|
||||||
|
ExpectLine(&proxy, 2, "Hello World");
|
||||||
|
ExpectLine(&proxy, 3, "");
|
||||||
|
|
||||||
|
REQUIRE(proxy.Eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DefinesStreamProxy: Ensure simple if is working with non-truthy value", "[parsing][parsingstream]")
|
||||||
|
{
|
||||||
|
const std::vector<std::string> lines
|
||||||
|
{
|
||||||
|
"#if 0",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
};
|
||||||
|
|
||||||
|
MockParserLineStream mockStream(lines);
|
||||||
|
DefinesStreamProxy proxy(&mockStream);
|
||||||
|
|
||||||
|
ExpectLine(&proxy, 1, "");
|
||||||
|
ExpectLine(&proxy, 2, "");
|
||||||
|
ExpectLine(&proxy, 3, "");
|
||||||
|
|
||||||
|
REQUIRE(proxy.Eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DefinesStreamProxy: Ensure simple if is working with calculated values", "[parsing][parsingstream]")
|
||||||
|
{
|
||||||
|
const std::vector<std::string> lines
|
||||||
|
{
|
||||||
|
"#if 0 || 1",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
"#if 0 && 1",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
};
|
||||||
|
|
||||||
|
MockParserLineStream mockStream(lines);
|
||||||
|
DefinesStreamProxy proxy(&mockStream);
|
||||||
|
|
||||||
|
ExpectLine(&proxy, 1, "");
|
||||||
|
ExpectLine(&proxy, 2, "Hello World");
|
||||||
|
ExpectLine(&proxy, 3, "");
|
||||||
|
ExpectLine(&proxy, 4, "");
|
||||||
|
ExpectLine(&proxy, 5, "");
|
||||||
|
ExpectLine(&proxy, 6, "");
|
||||||
|
|
||||||
|
REQUIRE(proxy.Eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DefinesStreamProxy: Ensure can handle defined operator with defined definition", "[parsing][parsingstream]")
|
||||||
|
{
|
||||||
|
const std::vector<std::string> lines
|
||||||
|
{
|
||||||
|
"#define someStuff 1",
|
||||||
|
"#if defined(someStuff)",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
};
|
||||||
|
|
||||||
|
MockParserLineStream mockStream(lines);
|
||||||
|
DefinesStreamProxy proxy(&mockStream);
|
||||||
|
|
||||||
|
ExpectLine(&proxy, 1, "");
|
||||||
|
ExpectLine(&proxy, 2, "");
|
||||||
|
ExpectLine(&proxy, 3, "Hello World");
|
||||||
|
ExpectLine(&proxy, 4, "");
|
||||||
|
|
||||||
|
REQUIRE(proxy.Eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DefinesStreamProxy: Ensure can handle defined operator with undefined definition", "[parsing][parsingstream]")
|
||||||
|
{
|
||||||
|
const std::vector<std::string> lines
|
||||||
|
{
|
||||||
|
"#define someStuff 1",
|
||||||
|
"#if defined(someStuff) && defined(thisIsNotDefined)",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
"#if defined(thisIsNotDefined)",
|
||||||
|
"Hello World",
|
||||||
|
"#endif",
|
||||||
|
};
|
||||||
|
|
||||||
|
MockParserLineStream mockStream(lines);
|
||||||
|
DefinesStreamProxy proxy(&mockStream);
|
||||||
|
|
||||||
|
ExpectLine(&proxy, 1, "");
|
||||||
|
ExpectLine(&proxy, 2, "");
|
||||||
|
ExpectLine(&proxy, 3, "");
|
||||||
|
ExpectLine(&proxy, 4, "");
|
||||||
|
ExpectLine(&proxy, 5, "");
|
||||||
|
ExpectLine(&proxy, 6, "");
|
||||||
|
ExpectLine(&proxy, 7, "");
|
||||||
|
|
||||||
|
REQUIRE(proxy.Eof());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user