scriptlang: some work on parser
This commit is contained in:
parent
e187da0d8d
commit
9737d9e56f
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user