mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
Use SimpleExpressionInterpreter in DefinesStreamProxy and expand defines and defined expressions before parsing
This commit is contained in:
parent
7cce0e387e
commit
a36d1c430a
@ -1,15 +0,0 @@
|
||||
#pragma options TEST(asdf, bla)
|
||||
#pragma switch TEST_SWITCH
|
||||
|
||||
#ifdef TEST_SWITCH
|
||||
#define SVAL "1"
|
||||
#else
|
||||
#define SVAL "0"
|
||||
#endif
|
||||
|
||||
#pragma filename "lemao_" + TEST + SVAL + ".txt"
|
||||
|
||||
HAHA TEST
|
||||
#ifdef TEST_SWITCH
|
||||
kekw
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
#include "DefinesDirectiveExpressionSequence.h"
|
||||
|
||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||
#include "DefinesExpressionMatchers.h"
|
||||
|
||||
DefinesDirectiveExpressionSequence::DefinesDirectiveExpressionSequence()
|
||||
{
|
||||
const SimpleMatcherFactory create(this);
|
||||
AddLabeledMatchers(DefinesExpressionMatchers().Expression(this), SimpleExpressionMatchers::LABEL_EXPRESSION);
|
||||
AddMatchers(create.Label(SimpleExpressionMatchers::LABEL_EXPRESSION));
|
||||
}
|
||||
|
||||
void DefinesDirectiveExpressionSequence::ProcessMatch(DefinesDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const
|
||||
{
|
||||
state->m_expression = DefinesExpressionMatchers(state).ProcessExpression(result);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "DefinesDirectiveParser.h"
|
||||
#include "DefinesDirectiveParsingState.h"
|
||||
|
||||
class DefinesDirectiveExpressionSequence final : public DefinesDirectiveParser::sequence_t
|
||||
{
|
||||
public:
|
||||
DefinesDirectiveExpressionSequence();
|
||||
|
||||
protected:
|
||||
void ProcessMatch(DefinesDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const override;
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
#include "DefinesDirectiveParser.h"
|
||||
|
||||
#include "DefinesDirectiveExpressionSequence.h"
|
||||
|
||||
DefinesDirectiveParser::DefinesDirectiveParser(ILexer<SimpleParserValue>* lexer, const std::map<std::string, DefinesStreamProxy::Define>& defines)
|
||||
: AbstractParser<SimpleParserValue, DefinesDirectiveParsingState>(lexer, std::make_unique<DefinesDirectiveParsingState>(defines))
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<AbstractParser<SimpleParserValue, DefinesDirectiveParsingState>::sequence_t*>& DefinesDirectiveParser::GetTestsForState()
|
||||
{
|
||||
static std::vector<sequence_t*> sequences
|
||||
{
|
||||
new DefinesDirectiveExpressionSequence()
|
||||
};
|
||||
return sequences;
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> DefinesDirectiveParser::GetParsedExpression() const
|
||||
{
|
||||
return std::move(m_state->m_expression);
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "DefinesDirectiveParsingState.h"
|
||||
#include "Parsing/Impl/AbstractParser.h"
|
||||
#include "Parsing/Simple/SimpleParserValue.h"
|
||||
|
||||
class DefinesDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesDirectiveParsingState>
|
||||
{
|
||||
public:
|
||||
DefinesDirectiveParser(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;
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
#include "DefinesDirectiveParsingState.h"
|
||||
|
||||
DefinesDirectiveParsingState::DefinesDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines)
|
||||
: m_defines(defines)
|
||||
{
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "Parsing/Impl/DefinesStreamProxy.h"
|
||||
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||
|
||||
class DefinesDirectiveParsingState
|
||||
{
|
||||
public:
|
||||
const std::map<std::string, DefinesStreamProxy::Define>& m_defines;
|
||||
std::unique_ptr<ISimpleExpression> m_expression;
|
||||
|
||||
explicit DefinesDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines);
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
#include "DefinesExpressionMatchers.h"
|
||||
|
||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||
|
||||
DefinesExpressionMatchers::DefinesExpressionMatchers()
|
||||
: DefinesExpressionMatchers(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DefinesExpressionMatchers::DefinesExpressionMatchers(const DefinesDirectiveParsingState* state)
|
||||
: SimpleExpressionMatchers(true, false, true, true, false),
|
||||
m_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<SimpleExpressionMatchers::matcher_t> DefinesExpressionMatchers::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> DefinesExpressionMatchers::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);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "DefinesDirectiveParsingState.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||
|
||||
class DefinesExpressionMatchers final : public SimpleExpressionMatchers
|
||||
{
|
||||
static constexpr auto CAPTURE_DEFINE_NAME = CAPTURE_OFFSET_EXPRESSION_EXT + 1;
|
||||
|
||||
const DefinesDirectiveParsingState* 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:
|
||||
DefinesExpressionMatchers();
|
||||
explicit DefinesExpressionMatchers(const DefinesDirectiveParsingState* state);
|
||||
};
|
@ -1,13 +1,14 @@
|
||||
#include "DefinesStreamProxy.h"
|
||||
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "AbstractParser.h"
|
||||
#include "ParserSingleInputStream.h"
|
||||
#include "Defines/DefinesDirectiveParser.h"
|
||||
#include "Parsing/ParsingException.h"
|
||||
#include "Parsing/Simple/SimpleExpressionInterpreter.h"
|
||||
#include "Parsing/Simple/SimpleLexer.h"
|
||||
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||
@ -34,7 +35,7 @@ DefinesStreamProxy::Define::Define(std::string name, std::string value)
|
||||
{
|
||||
}
|
||||
|
||||
std::string DefinesStreamProxy::Define::Render(const std::vector<std::string>& parameterValues)
|
||||
std::string DefinesStreamProxy::Define::Render(const std::vector<std::string>& parameterValues) const
|
||||
{
|
||||
if (parameterValues.empty() || m_parameter_positions.empty())
|
||||
return m_value;
|
||||
@ -279,25 +280,17 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ISimpleExpression> DefinesStreamProxy::ParseExpression(const std::string& expressionString) const
|
||||
std::unique_ptr<ISimpleExpression> DefinesStreamProxy::ParseExpression(std::string expressionString) const
|
||||
{
|
||||
std::istringstream ss(expressionString);
|
||||
ParserLine pseudoLine(nullptr, 1, std::move(expressionString));
|
||||
ExpandDefinedExpressions(pseudoLine);
|
||||
ExpandDefines(pseudoLine);
|
||||
|
||||
std::istringstream ss(pseudoLine.m_line);
|
||||
ParserSingleInputStream inputStream(ss, "defines directive expression");
|
||||
|
||||
SimpleLexer::Config lexerConfig;
|
||||
lexerConfig.m_emit_new_line_tokens = false;
|
||||
lexerConfig.m_read_integer_numbers = true;
|
||||
lexerConfig.m_read_floating_point_numbers = true;
|
||||
lexerConfig.m_read_strings = true;
|
||||
SimpleExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig);
|
||||
|
||||
SimpleLexer lexer(&inputStream, std::move(lexerConfig));
|
||||
DefinesDirectiveParser parser(&lexer, m_defines);
|
||||
|
||||
if (!parser.Parse())
|
||||
return nullptr;
|
||||
|
||||
return parser.GetParsedExpression();
|
||||
const SimpleExpressionInterpreter expressionInterpreter(&inputStream);
|
||||
return expressionInterpreter.Evaluate();
|
||||
}
|
||||
|
||||
bool DefinesStreamProxy::MatchIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition)
|
||||
@ -485,7 +478,7 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line)
|
||||
|| MatchEndifDirective(line, directiveStartPos, directiveEndPos);
|
||||
}
|
||||
|
||||
bool DefinesStreamProxy::FindDefineForWord(const ParserLine& line, const unsigned wordStart, const unsigned wordEnd, Define*& value)
|
||||
bool DefinesStreamProxy::FindDefineForWord(const ParserLine& line, const unsigned wordStart, const unsigned wordEnd, const Define*& value) const
|
||||
{
|
||||
const std::string word(line.m_line, wordStart, wordEnd - wordStart);
|
||||
const auto foundEntry = m_defines.find(word);
|
||||
@ -560,7 +553,58 @@ void DefinesStreamProxy::ExtractParametersFromDefineUsage(const ParserLine& line
|
||||
}
|
||||
}
|
||||
|
||||
void DefinesStreamProxy::ExpandDefines(ParserLine& line)
|
||||
bool DefinesStreamProxy::MatchDefinedExpression(const ParserLine& line, unsigned& pos, std::string& definitionName)
|
||||
{
|
||||
unsigned currentPos = pos;
|
||||
|
||||
if (!MatchNextCharacter(line, currentPos, '('))
|
||||
return false;
|
||||
|
||||
const auto nameStartPos = currentPos;
|
||||
if (!ExtractIdentifier(line, currentPos))
|
||||
return false;
|
||||
|
||||
const auto nameEndPos = currentPos;
|
||||
if (!MatchNextCharacter(line, currentPos, ')'))
|
||||
return false;
|
||||
|
||||
pos = currentPos;
|
||||
definitionName = line.m_line.substr(nameStartPos, nameEndPos - nameStartPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DefinesStreamProxy::ExpandDefinedExpressions(ParserLine& line) const
|
||||
{
|
||||
auto currentPos = 0u;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const auto definedPos = line.m_line.find(DEFINED_KEYWORD, currentPos);
|
||||
if (definedPos == std::string::npos)
|
||||
break;
|
||||
|
||||
currentPos = definedPos;
|
||||
|
||||
if (definedPos > 0 && !isspace(line.m_line[definedPos - 1]))
|
||||
{
|
||||
currentPos += std::char_traits<char>::length(DEFINED_KEYWORD);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto definitionEndPos = currentPos + std::char_traits<char>::length(DEFINED_KEYWORD);
|
||||
std::string definitionName;
|
||||
if (!MatchDefinedExpression(line, definitionEndPos, definitionName))
|
||||
{
|
||||
currentPos += std::char_traits<char>::length(DEFINED_KEYWORD);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto entry = m_defines.find(definitionName);
|
||||
line.m_line.replace(currentPos, definitionEndPos - currentPos, entry != m_defines.end() ? "1" : "0");
|
||||
}
|
||||
}
|
||||
|
||||
void DefinesStreamProxy::ExpandDefines(ParserLine& line) const
|
||||
{
|
||||
bool usesDefines;
|
||||
auto defineIterations = 0u;
|
||||
@ -575,7 +619,7 @@ void DefinesStreamProxy::ExpandDefines(ParserLine& line)
|
||||
auto wordStart = 0u;
|
||||
auto lastWordEnd = 0u;
|
||||
auto inWord = false;
|
||||
Define* value;
|
||||
const Define* value;
|
||||
std::ostringstream str;
|
||||
|
||||
for (auto i = 0u; i < line.m_line.size(); i++)
|
||||
|
@ -18,6 +18,7 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
|
||||
static constexpr const char* IFNDEF_DIRECTIVE = "ifndef";
|
||||
static constexpr const char* ELSE_DIRECTIVE = "else";
|
||||
static constexpr const char* ENDIF_DIRECTIVE = "endif";
|
||||
static constexpr const char* DEFINED_KEYWORD = "defined";
|
||||
|
||||
static constexpr auto MAX_DEFINE_ITERATIONS = 128u;
|
||||
|
||||
@ -42,7 +43,7 @@ public:
|
||||
Define();
|
||||
Define(std::string name, std::string value);
|
||||
void IdentifyParameters(const std::vector<std::string>& parameterNames);
|
||||
std::string Render(const std::vector<std::string>& parameterValues);
|
||||
_NODISCARD std::string Render(const std::vector<std::string>& parameterValues) const;
|
||||
};
|
||||
|
||||
private:
|
||||
@ -77,17 +78,20 @@ private:
|
||||
_NODISCARD bool MatchDirectives(const ParserLine& line);
|
||||
|
||||
static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues);
|
||||
bool FindDefineForWord(const ParserLine& line, unsigned wordStart, unsigned wordEnd, Define*& value);
|
||||
bool FindDefineForWord(const ParserLine& line, unsigned wordStart, unsigned wordEnd, const Define*& value) const;
|
||||
|
||||
static bool MatchDefinedExpression(const ParserLine& line, unsigned& pos, std::string& definitionName);
|
||||
void ExpandDefinedExpressions(ParserLine& line) const;
|
||||
|
||||
public:
|
||||
DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false);
|
||||
explicit DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false);
|
||||
|
||||
void AddDefine(Define define);
|
||||
void Undefine(const std::string& name);
|
||||
|
||||
void ExpandDefines(ParserLine& line);
|
||||
void ExpandDefines(ParserLine& line) const;
|
||||
|
||||
_NODISCARD std::unique_ptr<ISimpleExpression> ParseExpression(const std::string& expressionString) const;
|
||||
_NODISCARD std::unique_ptr<ISimpleExpression> ParseExpression(std::string expressionString) const;
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
|
@ -92,9 +92,7 @@ bool TemplatingStreamProxy::MatchOptionsDirective(const ParserLine& line, const
|
||||
if (!ExtractIdentifier(line, currentPosition))
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
|
||||
|
||||
std::ostringstream optionValueBuilder;
|
||||
optionValueBuilder << '"' << line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition) << '"';
|
||||
options.emplace_back(optionValueBuilder.str());
|
||||
options.emplace_back(line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition));
|
||||
|
||||
firstArg = false;
|
||||
}
|
||||
@ -126,10 +124,7 @@ bool TemplatingStreamProxy::MatchFilenameDirective(const ParserLine& line, const
|
||||
if (expressionString.empty())
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Cannot pragma filename without an expression.");
|
||||
|
||||
ParserLine expressionStringAsLine(line.m_filename, line.m_line_number, expressionString);
|
||||
m_defines_proxy->ExpandDefines(expressionStringAsLine);
|
||||
|
||||
const auto expression = m_defines_proxy->ParseExpression(expressionStringAsLine.m_line);
|
||||
const auto expression = m_defines_proxy->ParseExpression(expressionString);
|
||||
if (!expression)
|
||||
throw ParsingException(CreatePos(line, currentPosition), "Failed to parse pragma filename expression");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user