diff --git a/src/Parser/Parsing/Impl/ParserInputStream.cpp b/src/Parser/Parsing/Impl/ParserInputStream.cpp new file mode 100644 index 00000000..06a338eb --- /dev/null +++ b/src/Parser/Parsing/Impl/ParserInputStream.cpp @@ -0,0 +1,65 @@ +#include "ParserInputStream.h" + +#include + +ParserInputStream::ParserInputStream(std::istream& stream, std::string fileName) + : m_stream(stream), + m_file_name(std::move(fileName)), + m_line_number(1) +{ +} + +ParserLine ParserInputStream::NextLine() +{ + std::ostringstream str; + auto hasLength = false; + + auto c = m_stream.get(); + while (c != EOF) + { + switch (c) + { + case '\r': + c = m_stream.get(); + if (c == '\n') + return ParserLine(m_file_name, m_line_number++, str.str()); + str << '\r'; + hasLength = true; + continue; + + case '\n': + return ParserLine(m_file_name, m_line_number++, str.str()); + + default: + str << static_cast(c); + hasLength = true; + break; + } + + c = m_stream.get(); + } + + if (hasLength) + return ParserLine(m_file_name, m_line_number, str.str()); + + return ParserLine(); +} + +bool ParserInputStream::IncludeFile(const std::string& filename) +{ + return false; +} + +void ParserInputStream::PopCurrentFile() +{ +} + +bool ParserInputStream::IsOpen() const +{ + return !m_stream.eof(); +} + +bool ParserInputStream::Eof() const +{ + return !m_stream.eof(); +} diff --git a/src/Parser/Parsing/Impl/ParserInputStream.h b/src/Parser/Parsing/Impl/ParserInputStream.h new file mode 100644 index 00000000..87e78398 --- /dev/null +++ b/src/Parser/Parsing/Impl/ParserInputStream.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "Parsing/IParserLineStream.h" + +class ParserInputStream final : public IParserLineStream +{ + std::istream& m_stream; + std::string m_file_name; + int m_line_number; + +public: + ParserInputStream(std::istream& stream, std::string fileName); + + ParserLine NextLine() override; + bool IncludeFile(const std::string& filename) override; + void PopCurrentFile() override; + _NODISCARD bool IsOpen() const override; + _NODISCARD bool Eof() const override; +}; \ No newline at end of file diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.cpp b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.cpp new file mode 100644 index 00000000..19531b30 --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.cpp @@ -0,0 +1,14 @@ +#include "SimpleMatcherCharacter.h" + +SimpleMatcherCharacter::SimpleMatcherCharacter(const char c) + : m_char(c) +{ +} + +MatcherResult SimpleMatcherCharacter::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + const auto& token = lexer->GetToken(tokenOffset); + return token.m_type == SimpleParserValueType::CHARACTER && token.CharacterValue() == m_char + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.h b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.h new file mode 100644 index 00000000..c795061f --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherCharacter.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Simple/SimpleParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class SimpleMatcherCharacter final : public AbstractMatcher +{ + char m_char; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit SimpleMatcherCharacter(char c); +}; diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp new file mode 100644 index 00000000..e8b3692d --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.cpp @@ -0,0 +1,40 @@ +#include "SimpleMatcherFactory.h" + +#include "SimpleMatcherCharacter.h" +#include "SimpleMatcherKeyword.h" +#include "SimpleMatcherValueType.h" + +SimpleMatcherFactory::SimpleMatcherFactory(const IMatcherForLabelSupplier* labelSupplier) + : AbstractMatcherFactory(labelSupplier) +{ +} + +MatcherFactoryWrapper SimpleMatcherFactory::Type(SimpleParserValueType type) const +{ + return MatcherFactoryWrapper(std::make_unique(type)); +} + +MatcherFactoryWrapper SimpleMatcherFactory::Keyword(std::string value) const +{ + return MatcherFactoryWrapper(std::make_unique(std::move(value))); +} + +MatcherFactoryWrapper SimpleMatcherFactory::Identifier() const +{ + return MatcherFactoryWrapper(std::make_unique(SimpleParserValueType::IDENTIFIER)); +} + +MatcherFactoryWrapper SimpleMatcherFactory::Integer() const +{ + return MatcherFactoryWrapper(std::make_unique(SimpleParserValueType::INTEGER)); +} + +MatcherFactoryWrapper SimpleMatcherFactory::FloatingPoint() const +{ + return MatcherFactoryWrapper(std::make_unique(SimpleParserValueType::FLOATING_POINT)); +} + +MatcherFactoryWrapper SimpleMatcherFactory::Char(char c) const +{ + return MatcherFactoryWrapper(std::make_unique(c)); +} diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h new file mode 100644 index 00000000..7c9c26ee --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "Parsing/Simple/SimpleParserValue.h" +#include "Parsing/Matcher/AbstractMatcherFactory.h" + +class SimpleMatcherFactory final : public AbstractMatcherFactory +{ +public: + explicit SimpleMatcherFactory(const IMatcherForLabelSupplier* labelSupplier); + + _NODISCARD MatcherFactoryWrapper Type(SimpleParserValueType type) const; + _NODISCARD MatcherFactoryWrapper Keyword(std::string value) const; + _NODISCARD MatcherFactoryWrapper Identifier() const; + _NODISCARD MatcherFactoryWrapper Integer() const; + _NODISCARD MatcherFactoryWrapper FloatingPoint() const; + _NODISCARD MatcherFactoryWrapper Char(char c) const; +}; diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.cpp b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.cpp new file mode 100644 index 00000000..b29e0021 --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.cpp @@ -0,0 +1,16 @@ +#include "SimpleMatcherKeyword.h" + +SimpleMatcherKeyword::SimpleMatcherKeyword(std::string value) + : m_value(std::move(value)) +{ + const std::hash hash; + m_hash = hash(m_value); +} + +MatcherResult SimpleMatcherKeyword::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + const auto& token = lexer->GetToken(tokenOffset); + return token.m_type == SimpleParserValueType::IDENTIFIER && token.IdentifierHash() == m_hash && token.IdentifierValue() == m_value + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.h b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.h new file mode 100644 index 00000000..40183667 --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherKeyword.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Parsing/Simple/SimpleParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class SimpleMatcherKeyword final : public AbstractMatcher +{ + size_t m_hash; + std::string m_value; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit SimpleMatcherKeyword(std::string value); +}; diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.cpp b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.cpp new file mode 100644 index 00000000..c71a50f2 --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.cpp @@ -0,0 +1,13 @@ +#include "SimpleMatcherValueType.h" + +SimpleMatcherValueType::SimpleMatcherValueType(const SimpleParserValueType type) + : m_type(type) +{ +} + +MatcherResult SimpleMatcherValueType::CanMatch(ILexer* lexer, const unsigned tokenOffset) +{ + return lexer->GetToken(tokenOffset).m_type == m_type + ? MatcherResult::Match(1) + : MatcherResult::NoMatch(); +} diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.h b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.h new file mode 100644 index 00000000..9bb6669c --- /dev/null +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherValueType.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Simple/SimpleParserValue.h" +#include "Parsing/Matcher/AbstractMatcher.h" + +class SimpleMatcherValueType final : public AbstractMatcher +{ + SimpleParserValueType m_type; + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override; + +public: + explicit SimpleMatcherValueType(SimpleParserValueType type); +}; diff --git a/src/Parser/Parsing/Simple/SimpleLexer.cpp b/src/Parser/Parsing/Simple/SimpleLexer.cpp new file mode 100644 index 00000000..f0105785 --- /dev/null +++ b/src/Parser/Parsing/Simple/SimpleLexer.cpp @@ -0,0 +1,44 @@ +#include "SimpleLexer.h" + +SimpleLexer::SimpleLexer(IParserLineStream* stream) + : AbstractLexer(stream) +{ +} + +SimpleParserValue SimpleLexer::GetNextToken() +{ + auto c = NextChar(); + + while (isspace(c)) + c = NextChar(); + + if(c == EOF) + return SimpleParserValue::EndOfFile(TokenPos()); + + if (c == '\"') + return SimpleParserValue::String(GetPreviousCharacterPos(), new std::string(ReadString())); + + const auto pos = GetPreviousCharacterPos(); + if (isdigit(c)) + { + bool isFloatingPointValue; + double doubleValue; + int integerValue; + + ReadNumber(isFloatingPointValue, doubleValue, integerValue); + + if (isFloatingPointValue) + return SimpleParserValue::FloatingPoint(pos, doubleValue); + + return SimpleParserValue::Integer(pos, integerValue); + } + + if (isalpha(c) || c == '_') + { + auto identifier = ReadIdentifier(); + + return SimpleParserValue::Identifier(pos, new std::string(std::move(identifier))); + } + + return SimpleParserValue::Character(pos, static_cast(c)); +} diff --git a/src/Parser/Parsing/Simple/SimpleLexer.h b/src/Parser/Parsing/Simple/SimpleLexer.h new file mode 100644 index 00000000..e0dc3c58 --- /dev/null +++ b/src/Parser/Parsing/Simple/SimpleLexer.h @@ -0,0 +1,13 @@ +#pragma once + +#include "SimpleParserValue.h" +#include "Parsing/Impl/AbstractLexer.h" + +class SimpleLexer final : public AbstractLexer +{ +protected: + SimpleParserValue GetNextToken() override; + +public: + explicit SimpleLexer(IParserLineStream* stream); +}; \ No newline at end of file diff --git a/src/Parser/Parsing/Simple/SimpleParserValue.cpp b/src/Parser/Parsing/Simple/SimpleParserValue.cpp new file mode 100644 index 00000000..e06c7951 --- /dev/null +++ b/src/Parser/Parsing/Simple/SimpleParserValue.cpp @@ -0,0 +1,141 @@ +#include "SimpleParserValue.h" + +#include + +SimpleParserValue SimpleParserValue::Invalid(const TokenPos pos) +{ + SimpleParserValue pv(pos, SimpleParserValueType::INVALID); + return pv; +} + +SimpleParserValue SimpleParserValue::EndOfFile(const TokenPos pos) +{ + SimpleParserValue pv(pos, SimpleParserValueType::END_OF_FILE); + return pv; +} + +SimpleParserValue SimpleParserValue::Character(const TokenPos pos, const char c) +{ + SimpleParserValue pv(pos, SimpleParserValueType::CHARACTER); + pv.m_value.char_value = c; + return pv; +} + +SimpleParserValue SimpleParserValue::Integer(const TokenPos pos, const int value) +{ + SimpleParserValue pv(pos, SimpleParserValueType::INTEGER); + pv.m_value.int_value = value; + return pv; +} + +SimpleParserValue SimpleParserValue::FloatingPoint(const TokenPos pos, const double value) +{ + SimpleParserValue pv(pos, SimpleParserValueType::FLOATING_POINT); + pv.m_value.double_value = value; + return pv; +} + +SimpleParserValue SimpleParserValue::String(const TokenPos pos, std::string* stringValue) +{ + SimpleParserValue pv(pos, SimpleParserValueType::STRING); + pv.m_value.string_value = stringValue; + return pv; +} + +SimpleParserValue SimpleParserValue::Identifier(const TokenPos pos, std::string* identifier) +{ + SimpleParserValue pv(pos, SimpleParserValueType::IDENTIFIER); + pv.m_value.string_value = identifier; + pv.m_hash = std::hash()(*identifier); + return pv; +} + +SimpleParserValue::SimpleParserValue(const TokenPos pos, const SimpleParserValueType type) + : m_pos(pos), + m_type(type), + m_hash(0), + m_value{} +{ +} + +SimpleParserValue::~SimpleParserValue() +{ + switch (m_type) + { + case SimpleParserValueType::STRING: + case SimpleParserValueType::IDENTIFIER: + delete m_value.string_value; + break; + + default: + break; + } + + m_value = ValueType(); +} + +SimpleParserValue::SimpleParserValue(SimpleParserValue&& other) noexcept + : m_pos(other.m_pos), + m_type(other.m_type), + m_hash(other.m_hash), + m_value(other.m_value) +{ + other.m_value = ValueType(); +} + +SimpleParserValue& SimpleParserValue::operator=(SimpleParserValue&& other) noexcept +{ + m_pos = other.m_pos; + m_type = other.m_type; + m_value = other.m_value; + m_hash = other.m_hash; + other.m_value = ValueType(); + + return *this; +} + +bool SimpleParserValue::IsEof() const +{ + return m_type == SimpleParserValueType::END_OF_FILE; +} + +const TokenPos& SimpleParserValue::GetPos() const +{ + return m_pos; +} + +char SimpleParserValue::CharacterValue() const +{ + assert(m_type == SimpleParserValueType::CHARACTER); + return m_value.char_value; +} + +int SimpleParserValue::IntegerValue() const +{ + assert(m_type == SimpleParserValueType::INTEGER); + return m_value.int_value; +} + +double SimpleParserValue::FloatingPointValue() const +{ + assert(m_type == SimpleParserValueType::FLOATING_POINT); + return m_value.double_value; +} + +std::string& SimpleParserValue::StringValue() const +{ + assert(m_type == SimpleParserValueType::STRING); + return *m_value.string_value; +} + +std::string& SimpleParserValue::IdentifierValue() const +{ + assert(m_type == SimpleParserValueType::IDENTIFIER); + return *m_value.string_value; +} + +size_t SimpleParserValue::IdentifierHash() const +{ + assert(m_type == SimpleParserValueType::IDENTIFIER); + return m_hash; +} diff --git a/src/Parser/Parsing/Simple/SimpleParserValue.h b/src/Parser/Parsing/Simple/SimpleParserValue.h new file mode 100644 index 00000000..8a4b3ec6 --- /dev/null +++ b/src/Parser/Parsing/Simple/SimpleParserValue.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "Utils/ClassUtils.h" +#include "Parsing/TokenPos.h" + +enum class SimpleParserValueType +{ + // Meta tokens + INVALID, + END_OF_FILE, + + // Single character + CHARACTER, + + // Generic token types + INTEGER, + FLOATING_POINT, + STRING, + IDENTIFIER, + + // End + MAX +}; + +class SimpleParserValue final : public IParserValue +{ +public: + TokenPos m_pos; + SimpleParserValueType m_type; + size_t m_hash; + union ValueType + { + char char_value; + int int_value; + double double_value; + std::string* string_value; + } m_value; + + static SimpleParserValue Invalid(TokenPos pos); + static SimpleParserValue EndOfFile(TokenPos pos); + static SimpleParserValue Character(TokenPos pos, char c); + static SimpleParserValue Integer(TokenPos pos, int value); + static SimpleParserValue FloatingPoint(TokenPos pos, double value); + static SimpleParserValue String(TokenPos pos, std::string* stringValue); + static SimpleParserValue Identifier(TokenPos pos, std::string* identifier); + +private: + SimpleParserValue(TokenPos pos, SimpleParserValueType type); + +public: + ~SimpleParserValue() override; + SimpleParserValue(const SimpleParserValue& other) = delete; + SimpleParserValue(SimpleParserValue&& other) noexcept; + SimpleParserValue& operator=(const SimpleParserValue& other) = delete; + SimpleParserValue& operator=(SimpleParserValue&& other) noexcept; + + _NODISCARD bool IsEof() const override; + _NODISCARD const TokenPos& GetPos() const override; + + _NODISCARD char CharacterValue() const; + _NODISCARD int IntegerValue() const; + _NODISCARD double FloatingPointValue() const; + _NODISCARD std::string& StringValue() const; + _NODISCARD std::string& IdentifierValue() const; + _NODISCARD size_t IdentifierHash() const; +};