diff --git a/scriptlang/lexer.cpp b/scriptlang/lexer.cpp index e5a8e7e..6f77eca 100644 --- a/scriptlang/lexer.cpp +++ b/scriptlang/lexer.cpp @@ -7,11 +7,13 @@ namespace scriptlang { auto constexpr Lexer::next() noexcept -> Result { if (done()) - return token(TokenTypes::Eof, index); + return token(Tokens::Eof, index); if (std::isdigit(current()) != 0) return make_number(); - if (std::isalpha(current()) != 0 || current() == '_') + if (std::isalpha(current()) != 0 or current() == '_') return make_id(); + if (current() == '"') + return make_string(); return make_static(); } @@ -24,12 +26,11 @@ auto constexpr Lexer::make_number() noexcept -> Result step(); while (!done() and std::isdigit(current()) != 0) step(); - return token(TokenTypes::Float, begin); + return token(Tokens::Float, begin); } - return token(TokenTypes::Int, begin); + return token(Tokens::Int, begin); } -// NOLINTNEXTLINE(readability-function-cognitive-complexity) auto constexpr Lexer::make_id() noexcept -> Result { auto begin = index; @@ -41,37 +42,52 @@ auto constexpr Lexer::make_id() noexcept -> Result } auto constexpr Lexer::id_or_keyword_type(std::string_view substring) noexcept - -> TokenTypes + -> Tokens { if (substring.compare("if") == 0) - return TokenTypes::If; + return Tokens::If; if (substring.compare("else") == 0) - return TokenTypes::Else; + return Tokens::Else; if (substring.compare("for") == 0) - return TokenTypes::For; + return Tokens::For; if (substring.compare("loop") == 0) - return TokenTypes::Loop; + return Tokens::Loop; if (substring.compare("while") == 0) - return TokenTypes::While; + return Tokens::While; if (substring.compare("break") == 0) - return TokenTypes::Break; + return Tokens::Break; if (substring.compare("continue") == 0) - return TokenTypes::Continue; + return Tokens::Continue; if (substring.compare("fn") == 0) - return TokenTypes::Fn; + return Tokens::Fn; if (substring.compare("return") == 0) - return TokenTypes::Return; + return Tokens::Return; if (substring.compare("false") == 0) - return TokenTypes::False; + return Tokens::False; if (substring.compare("true") == 0) - return TokenTypes::True; + return Tokens::True; if (substring.compare("and") == 0) - return TokenTypes::And; + return Tokens::And; if (substring.compare("or") == 0) - return TokenTypes::Or; + return Tokens::Or; if (substring.compare("xor") == 0) - return TokenTypes::Xor; - return TokenTypes::Id; + return Tokens::Xor; + return Tokens::Id; +} + +auto constexpr Lexer::make_string() noexcept -> Result +{ + auto begin = index; + step(); + auto escaped = false; + while (!done() and (current() != '"' or escaped)) { + escaped = escaped ? false : current() == '\\'; + step(); + } + if (current() != '"') + return {}; + step(); + return token(Tokens::String, begin); } auto constexpr Lexer::make_static() noexcept -> Result @@ -84,10 +100,10 @@ auto constexpr Lexer::make_static() noexcept -> Result } // NOLINTNEXTLINE(readability-function-cognitive-complexity) -auto constexpr Lexer::static_token_type() noexcept -> Result +auto constexpr Lexer::static_token_type() noexcept -> Result { - using TT = TokenTypes; - auto stepped = [&](TokenTypes v) { + using TT = Tokens; + auto stepped = [&](Tokens v) { step(); return v; }; @@ -171,8 +187,8 @@ auto constexpr Lexer::static_token_type() noexcept -> Result if (current() == '!') { step(); if (current() == '=') - return stepped(TT::ExlamationEqual); - return TT::Exlamation; + return stepped(TT::ExclamationEqual); + return TT::Exclamation; } if (current() == '<') { step(); @@ -189,8 +205,7 @@ auto constexpr Lexer::static_token_type() noexcept -> Result return {}; } -auto constexpr Lexer::skip_multiline_comment() noexcept - -> Result +auto constexpr Lexer::skip_multiline_comment() noexcept -> Result { step(); auto last = current(); @@ -200,18 +215,17 @@ auto constexpr Lexer::skip_multiline_comment() noexcept if (last != '*' or current() != '/') return {}; step(); - return TokenTypes::MultilineComment; + return Tokens::MultilineComment; } -auto constexpr Lexer::skip_singleline_comment() noexcept - -> Result +auto constexpr Lexer::skip_singleline_comment() noexcept -> Result { step(); while (!done() and current() != '\n') step(); if (current() == '\n') step(); - return TokenTypes::SinglelineComment; + return Tokens::SinglelineComment; } } diff --git a/scriptlang/lexer.hpp b/scriptlang/lexer.hpp index 3422cfd..71c134a 100644 --- a/scriptlang/lexer.hpp +++ b/scriptlang/lexer.hpp @@ -4,7 +4,7 @@ namespace scriptlang { -enum class TokenTypes { +enum class Tokens { Eof, MultilineComment, @@ -13,6 +13,7 @@ enum class TokenTypes { Id, Int, Float, + String, If, Else, @@ -65,8 +66,8 @@ enum class TokenTypes { FatArrow, DoubleEqual, - Exlamation, - ExlamationEqual, + Exclamation, + ExclamationEqual, Less, LessEqual, @@ -75,12 +76,16 @@ enum class TokenTypes { GreaterEqual, }; -struct Token { - TokenTypes type; - size_t index, length; +struct Location { int line, column; }; +struct Token { + Tokens type; + size_t index, length; + Location location; +}; + class Lexer { public: Lexer(std::string_view text) @@ -98,18 +103,17 @@ private: auto constexpr make_number() noexcept -> Result; auto constexpr make_id() noexcept -> Result; auto constexpr id_or_keyword_type(std::string_view substring) noexcept - -> TokenTypes; + -> Tokens; + auto constexpr make_string() noexcept -> Result; auto constexpr make_static() noexcept -> Result; - auto constexpr static_token_type() noexcept -> Result; - auto constexpr skip_multiline_comment() noexcept - -> Result; - auto constexpr skip_singleline_comment() noexcept - -> Result; + auto constexpr static_token_type() noexcept -> Result; + auto constexpr skip_multiline_comment() noexcept -> Result; + auto constexpr skip_singleline_comment() noexcept -> Result; [[nodiscard]] auto constexpr inline token( - TokenTypes type, size_t begin) noexcept -> Token + Tokens type, size_t begin) noexcept -> Token { - auto token = Token { type, begin, index - begin, line, column }; + auto token = Token { type, begin, index - begin, { line, column } }; last_token = token; return token; } diff --git a/scriptlang/parser.cpp b/scriptlang/parser.cpp index 89283cb..f3481b0 100644 --- a/scriptlang/parser.cpp +++ b/scriptlang/parser.cpp @@ -1,3 +1,14 @@ #include "parser.hpp" -namespace scriptlang { } +namespace scriptlang { + +auto Parser::parse_value() noexcept -> Result, void> +{ + switch (lexer.peek()->type) { + case Tokens::Id: + default: + return {}; + } +} + +} diff --git a/scriptlang/parser.hpp b/scriptlang/parser.hpp index ed0700f..5d0c47b 100644 --- a/scriptlang/parser.hpp +++ b/scriptlang/parser.hpp @@ -1,7 +1,139 @@ #pragma once +#include "lexer.hpp" +#include "utils/all.hpp" +#include "utils/result.hpp" +#include +#include +#include +#include +#include +#include + namespace scriptlang { -class Parser final { }; +struct Span { + Location from, to; +}; + +enum class Expressions { + Binary, + Negate, + Not, + Index, + Access, + Call, + Operator, + + Id, + Int, + Float, + Bool, + String, +}; + +struct Expression { +public: + Expression() = default; + Expression(const Expression&) = delete; + Expression(Expression&&) = delete; + auto operator=(const Expression&) -> Expression& = delete; + auto operator=(Expression&&) -> Expression& = delete; + virtual ~Expression() = default; + [[nodiscard]] virtual auto expression_type() const noexcept -> Expressions + = 0; + [[nodiscard]] virtual auto span() const noexcept -> Span = 0; + +private: +}; + +class Id final : public Expression { +public: + Id(std::string value) + : m_value { std::move(value) } + { } + [[nodiscard]] auto expression_type() const noexcept -> Expressions override + { + return Expressions::Id; + } + [[nodiscard]] auto value() const noexcept { return m_value; } + +private: + std::string m_value; +}; +class Int final : public Expression { +public: + Int(int64_t value) + : m_value { value } + { } + [[nodiscard]] auto expression_type() const noexcept -> Expressions override + { + return Expressions::Int; + } + [[nodiscard]] auto value() const noexcept { return m_value; } + +private: + int64_t m_value; +}; +class Float final : public Expression { +public: + Float(double value) + : m_value { value } + { } + [[nodiscard]] auto expression_type() const noexcept -> Expressions override + { + return Expressions::Float; + } + [[nodiscard]] auto value() const noexcept { return m_value; } + +private: + double m_value; +}; +class Bool final : public Expression { +public: + Bool(bool value) + : m_value { value } + { } + [[nodiscard]] auto expression_type() const noexcept -> Expressions override + { + return Expressions::Bool; + } + [[nodiscard]] auto value() const noexcept { return m_value; } + +private: + bool m_value; +}; +class String final : public Expression { +public: + String(std::string value) + : m_value { std::move(value) } + { } + [[nodiscard]] auto expression_type() const noexcept -> Expressions override + { + return Expressions::String; + } + [[nodiscard]] auto value() const noexcept -> const std::string& + { + return m_value; + } + +private: + std::string m_value; +}; + +class Parser final { +public: + Parser(std::string_view text) + : text { text } + , lexer(text) + { } + auto parse_expression() noexcept + -> Result, void>; + auto parse_value() noexcept -> Result, void>; + +private: + std::string_view text; + Lexer lexer; +}; }