#pragma once
|
|
#include <variant>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <span>
|
|
#include <UserScript.h>
|
|
|
|
namespace scripting {
|
|
namespace ast {
|
|
enum class operator_t : uint8_t {
|
|
logical_not = 0b00000,
|
|
binary_not = 0b00001,
|
|
divide = 0b00010,
|
|
modulo = 0b00100,
|
|
multiply = 0b00101,
|
|
subtract = 0b00110,
|
|
add = 0b01000,
|
|
bitshift_left = 0b01001,
|
|
bitshift_right = 0b01010,
|
|
rotate_left = 0b01100,
|
|
rotate_right = 0b01101,
|
|
less_than = 0b01110,
|
|
greater_than = 0b10000,
|
|
less_or_equal_than = 0b10001,
|
|
greater_or_equal_than = 0b10010,
|
|
equals = 0b10100,
|
|
different = 0b10101,
|
|
binary_and = 0b10110,
|
|
binary_or = 0b11000,
|
|
binary_xor = 0b11001,
|
|
logical_and = 0b11010,
|
|
logical_or = 0b11100,
|
|
};
|
|
|
|
enum class symbol_t {
|
|
l_paren, r_paren,
|
|
logical_not,
|
|
binary_not,
|
|
divide,
|
|
modulo,
|
|
multiply,
|
|
subtract,
|
|
add,
|
|
bitshift_left,
|
|
bitshift_right,
|
|
rotate_left,
|
|
rotate_right,
|
|
less_than,
|
|
greater_than,
|
|
less_or_equal_than,
|
|
greater_or_equal_than,
|
|
equals,
|
|
different,
|
|
binary_and,
|
|
binary_or,
|
|
binary_xor,
|
|
logical_and,
|
|
logical_or,
|
|
new_line
|
|
};
|
|
|
|
struct identifier {
|
|
std::shared_ptr<const code_location> location;
|
|
std::string value;
|
|
};
|
|
|
|
inline auto operator<=>(const identifier& lhs, const identifier& rhs) {
|
|
// TODO: check if the stdlib evolves to support ALL THE HELLA <=> THAT SHOULD BE THERE
|
|
return -1 * (lhs.value < rhs.value) + (lhs.value > rhs.value);
|
|
}
|
|
|
|
inline auto operator==(const identifier& lhs, const identifier& rhs) {
|
|
return lhs.value == rhs.value;
|
|
}
|
|
|
|
struct expression;
|
|
|
|
struct unary_algebraic_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
operator_t op;
|
|
std::unique_ptr<expression> content;
|
|
};
|
|
|
|
struct binary_algebraic_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
std::unique_ptr<expression> lhs;
|
|
operator_t op;
|
|
std::unique_ptr<expression> rhs;
|
|
};
|
|
|
|
struct command_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
identifier name;
|
|
std::vector<std::unique_ptr<expression>> arguments;
|
|
};
|
|
|
|
struct variable_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
identifier name;
|
|
};
|
|
|
|
struct paren_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
std::variant<
|
|
std::unique_ptr<expression>,
|
|
std::unique_ptr<command_expression>
|
|
> content;
|
|
};
|
|
|
|
struct literal_int_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
int32_t value;
|
|
};
|
|
|
|
struct literal_string_expression {
|
|
std::shared_ptr<const code_location> location;
|
|
std::string value;
|
|
};
|
|
|
|
struct expression {
|
|
std::shared_ptr<const code_location> location;
|
|
std::variant<
|
|
std::unique_ptr<unary_algebraic_expression>,
|
|
std::unique_ptr<binary_algebraic_expression>,
|
|
std::unique_ptr<paren_expression>,
|
|
std::unique_ptr<variable_expression>,
|
|
std::unique_ptr<literal_int_expression>,
|
|
std::unique_ptr<literal_string_expression>
|
|
> contents;
|
|
};
|
|
|
|
struct statement;
|
|
|
|
struct block {
|
|
std::shared_ptr<const code_location> location;
|
|
std::vector<statement> contents;
|
|
};
|
|
|
|
struct conditional {
|
|
std::shared_ptr<const code_location> location;
|
|
std::unique_ptr<expression> condition;
|
|
std::unique_ptr<block> on_condition;
|
|
std::unique_ptr<block> otherwise;
|
|
};
|
|
|
|
struct while_loop {
|
|
std::shared_ptr<const code_location> location;
|
|
std::unique_ptr<expression> condition;
|
|
std::unique_ptr<block> on_condition;
|
|
};
|
|
|
|
struct statement {
|
|
std::shared_ptr<const code_location> location;
|
|
std::variant<
|
|
std::unique_ptr<command_expression>,
|
|
std::unique_ptr<conditional>,
|
|
std::unique_ptr<while_loop>
|
|
> contents;
|
|
};
|
|
|
|
struct token {
|
|
std::shared_ptr<const scripting::code_location> location;
|
|
std::variant<scripting::ast::identifier, int32_t, std::string, symbol_t> value;
|
|
};
|
|
|
|
std::vector<token> lex(const std::string& code, std::vector<scripting::script_error>& errors);
|
|
scripting::ast::block parse(std::span<token> code, std::vector<scripting::script_error>& errors);
|
|
}
|
|
}
|