Use SimpleExpressionInterpreter in DefinesStreamProxy and expand defines and defined expressions before parsing

This commit is contained in:
Jan 2022-09-06 20:52:52 +02:00
parent 7cce0e387e
commit a36d1c430a
13 changed files with 77 additions and 197 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -1,6 +0,0 @@
#include "DefinesDirectiveParsingState.h"
DefinesDirectiveParsingState::DefinesDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines)
: m_defines(defines)
{
}

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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);
};

View File

@ -1,13 +1,14 @@
#include "DefinesStreamProxy.h" #include "DefinesStreamProxy.h"
#include <regex>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#include "Utils/ClassUtils.h" #include "Utils/ClassUtils.h"
#include "AbstractParser.h" #include "AbstractParser.h"
#include "ParserSingleInputStream.h" #include "ParserSingleInputStream.h"
#include "Defines/DefinesDirectiveParser.h"
#include "Parsing/ParsingException.h" #include "Parsing/ParsingException.h"
#include "Parsing/Simple/SimpleExpressionInterpreter.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" #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()) if (parameterValues.empty() || m_parameter_positions.empty())
return m_value; return m_value;
@ -279,25 +280,17 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig
return true; 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"); ParserSingleInputStream inputStream(ss, "defines directive expression");
SimpleLexer::Config lexerConfig; const SimpleExpressionInterpreter expressionInterpreter(&inputStream);
lexerConfig.m_emit_new_line_tokens = false; return expressionInterpreter.Evaluate();
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();
} }
bool DefinesStreamProxy::MatchIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) 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); || 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 std::string word(line.m_line, wordStart, wordEnd - wordStart);
const auto foundEntry = m_defines.find(word); 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; bool usesDefines;
auto defineIterations = 0u; auto defineIterations = 0u;
@ -575,7 +619,7 @@ void DefinesStreamProxy::ExpandDefines(ParserLine& line)
auto wordStart = 0u; auto wordStart = 0u;
auto lastWordEnd = 0u; auto lastWordEnd = 0u;
auto inWord = false; auto inWord = false;
Define* value; const Define* value;
std::ostringstream str; std::ostringstream str;
for (auto i = 0u; i < line.m_line.size(); i++) for (auto i = 0u; i < line.m_line.size(); i++)

View File

@ -18,6 +18,7 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
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";
static constexpr const char* ENDIF_DIRECTIVE = "endif"; static constexpr const char* ENDIF_DIRECTIVE = "endif";
static constexpr const char* DEFINED_KEYWORD = "defined";
static constexpr auto MAX_DEFINE_ITERATIONS = 128u; static constexpr auto MAX_DEFINE_ITERATIONS = 128u;
@ -42,7 +43,7 @@ public:
Define(); Define();
Define(std::string name, std::string value); Define(std::string name, std::string value);
void IdentifyParameters(const std::vector<std::string>& parameterNames); 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: private:
@ -77,17 +78,20 @@ private:
_NODISCARD bool MatchDirectives(const ParserLine& line); _NODISCARD bool MatchDirectives(const ParserLine& line);
static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues); 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: public:
DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false); explicit DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false);
void AddDefine(Define define); void AddDefine(Define define);
void Undefine(const std::string& name); 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; ParserLine NextLine() override;
bool IncludeFile(const std::string& filename) override; bool IncludeFile(const std::string& filename) override;

View File

@ -92,9 +92,7 @@ bool TemplatingStreamProxy::MatchOptionsDirective(const ParserLine& line, const
if (!ExtractIdentifier(line, currentPosition)) if (!ExtractIdentifier(line, currentPosition))
throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive."); throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive.");
std::ostringstream optionValueBuilder; options.emplace_back(line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition));
optionValueBuilder << '"' << line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition) << '"';
options.emplace_back(optionValueBuilder.str());
firstArg = false; firstArg = false;
} }
@ -126,10 +124,7 @@ bool TemplatingStreamProxy::MatchFilenameDirective(const ParserLine& line, const
if (expressionString.empty()) if (expressionString.empty())
throw ParsingException(CreatePos(line, currentPosition), "Cannot pragma filename without an expression."); throw ParsingException(CreatePos(line, currentPosition), "Cannot pragma filename without an expression.");
ParserLine expressionStringAsLine(line.m_filename, line.m_line_number, expressionString); const auto expression = m_defines_proxy->ParseExpression(expressionString);
m_defines_proxy->ExpandDefines(expressionStringAsLine);
const auto expression = m_defines_proxy->ParseExpression(expressionStringAsLine.m_line);
if (!expression) if (!expression)
throw ParsingException(CreatePos(line, currentPosition), "Failed to parse pragma filename expression"); throw ParsingException(CreatePos(line, currentPosition), "Failed to parse pragma filename expression");