scriptlang: some work on parser

This commit is contained in:
SimonFJ20 2023-01-10 02:40:17 +01:00
parent e187da0d8d
commit 9737d9e56f
4 changed files with 209 additions and 48 deletions

View File

@ -7,11 +7,13 @@ namespace scriptlang {
auto constexpr Lexer::next() noexcept -> Result<Token, void>
{
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<Token, void>
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<Token, void>
{
auto begin = index;
@ -41,37 +42,52 @@ auto constexpr Lexer::make_id() noexcept -> Result<Token, void>
}
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<Token, void>
{
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<Token, void>
@ -84,10 +100,10 @@ auto constexpr Lexer::make_static() noexcept -> Result<Token, void>
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
auto constexpr Lexer::static_token_type() noexcept -> Result<TokenTypes, void>
auto constexpr Lexer::static_token_type() noexcept -> Result<Tokens, void>
{
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<TokenTypes, void>
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<TokenTypes, void>
return {};
}
auto constexpr Lexer::skip_multiline_comment() noexcept
-> Result<TokenTypes, void>
auto constexpr Lexer::skip_multiline_comment() noexcept -> Result<Tokens, void>
{
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<TokenTypes, void>
auto constexpr Lexer::skip_singleline_comment() noexcept -> Result<Tokens, void>
{
step();
while (!done() and current() != '\n')
step();
if (current() == '\n')
step();
return TokenTypes::SinglelineComment;
return Tokens::SinglelineComment;
}
}

View File

@ -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<Token, void>;
auto constexpr make_id() noexcept -> Result<Token, void>;
auto constexpr id_or_keyword_type(std::string_view substring) noexcept
-> TokenTypes;
-> Tokens;
auto constexpr make_string() noexcept -> Result<Token, void>;
auto constexpr make_static() noexcept -> Result<Token, void>;
auto constexpr static_token_type() noexcept -> Result<TokenTypes, void>;
auto constexpr skip_multiline_comment() noexcept
-> Result<TokenTypes, void>;
auto constexpr skip_singleline_comment() noexcept
-> Result<TokenTypes, void>;
auto constexpr static_token_type() noexcept -> Result<Tokens, void>;
auto constexpr skip_multiline_comment() noexcept -> Result<Tokens, void>;
auto constexpr skip_singleline_comment() noexcept -> Result<Tokens, void>;
[[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;
}

View File

@ -1,3 +1,14 @@
#include "parser.hpp"
namespace scriptlang { }
namespace scriptlang {
auto Parser::parse_value() noexcept -> Result<std::unique_ptr<Expression>, void>
{
switch (lexer.peek()->type) {
case Tokens::Id:
default:
return {};
}
}
}

View File

@ -1,7 +1,139 @@
#pragma once
#include "lexer.hpp"
#include "utils/all.hpp"
#include "utils/result.hpp"
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
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<std::unique_ptr<Expression>, void>;
auto parse_value() noexcept -> Result<std::unique_ptr<Expression>, void>;
private:
std::string_view text;
Lexer lexer;
};
}