More work on getting parsing to be functional
This commit is contained in:
@@ -1,14 +1,222 @@
|
||||
// AUTOGENERATED COPYRIGHT HEADER START
|
||||
// Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// Copyright (C) 2017-2025 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// AUTOGENERATED COPYRIGHT HEADER END
|
||||
#include "ast.hpp"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
|
||||
blitz::ast::variable::~variable() {}
|
||||
|
||||
blitz::ast::variable::variable(blitz::token token) : _token(token), _value(nullptr) {}
|
||||
|
||||
void blitz::ast::variable::set_value(std::shared_ptr<blitz::ast::expression> value)
|
||||
blitz::ast::variable::~variable()
|
||||
{
|
||||
_value = value;
|
||||
/* Variable Parsing
|
||||
*
|
||||
* Declaration:
|
||||
* - 8bit Signed Integer Variable
|
||||
* Variable:Byte
|
||||
* Variable:Int8
|
||||
* - 8bit Unsigned Integer Variable
|
||||
* Variable:UByte
|
||||
* Variable:UInt8
|
||||
* - 16bit Signed Integer Variable
|
||||
* Variable:Short
|
||||
* Variable:Int16
|
||||
* - 16bit Unsigned Integer Variable
|
||||
* Variable:UShort
|
||||
* Variable:UInt16
|
||||
* - 32bit Signed Integer Variable
|
||||
* Variable
|
||||
* Variable%
|
||||
* Variable:Int
|
||||
* Variable:Int32
|
||||
* - 32bit Unsigned Integer Variable
|
||||
* Variable:UInt
|
||||
* Variable:UInt32
|
||||
* - 64bit Signed Integer Variable
|
||||
* Variable%%
|
||||
* Variable:Long
|
||||
* Variable:Int64
|
||||
* - 64bit Unsigned Integer Variable
|
||||
* Variable:ULong
|
||||
* Variable:UInt64
|
||||
* - 32bit Real Variable
|
||||
* Variable#
|
||||
* Variable:Float
|
||||
* Variable:Float32
|
||||
* Variable:Real
|
||||
* Variable:Real32
|
||||
* - 64bit Real Variable
|
||||
* Variable##
|
||||
* Variable:Double
|
||||
* Variable:Float64
|
||||
* Variable:Real64
|
||||
* - UTF-8 String Variable
|
||||
* Variable$
|
||||
* Variable:String
|
||||
* - Struct Variable
|
||||
* Variable.StructName
|
||||
* Variable:StructName
|
||||
*
|
||||
* Access:
|
||||
* - Struct Access:
|
||||
* Variable\Key
|
||||
* - Array Access:
|
||||
* Variable[IntegerIndex]
|
||||
* - Dynamic Array Access:
|
||||
* Variable(IntegerIndex)
|
||||
* - Direct Access:
|
||||
* Variable
|
||||
*/
|
||||
}
|
||||
|
||||
bool blitz::ast::variable::can_parse(std::shared_ptr<blitz::lexer> lexer)
|
||||
{
|
||||
return lexer->current().type == blitz::token::variant::TEXT;
|
||||
}
|
||||
|
||||
std::shared_ptr<blitz::ast::node> blitz::ast::variable::try_parse(std::shared_ptr<blitz::lexer> lexer)
|
||||
{
|
||||
auto file = lexer->file();
|
||||
|
||||
auto name_tk = lexer->current();
|
||||
if (name_tk.type != blitz::token::variant::TEXT) {
|
||||
throw blitz::error(file, name_tk.location, name_tk.location, blitz::format("Unexpected %s, expected text.", name_tk.to_string().c_str()));
|
||||
}
|
||||
|
||||
auto node = std::make_shared<blitz::ast::variable>();
|
||||
node->tokens.push_back(name_tk);
|
||||
node->type = blitz::types::type::UNKNOWN;
|
||||
node->name = name_tk.text;
|
||||
|
||||
// Check if this has a type definition
|
||||
auto symbol_tk = lexer->peek();
|
||||
if (symbol_tk.type != blitz::token::variant::SYMBOL) {
|
||||
return node;
|
||||
}
|
||||
if (symbol_tk.text == ":") {
|
||||
// :Type
|
||||
node->tokens.push_back(lexer->next()); // Advance to next token.
|
||||
auto type_tk = lexer->next();
|
||||
if (type_tk != blitz::token::variant::TEXT) {
|
||||
throw blitz::error(file, name_tk.location, type_tk.location, blitz::format("Unexpected %s, expected text.", type_tk.to_string().c_str()));
|
||||
}
|
||||
|
||||
auto type = blitz::types::from_string(type_tk.text);
|
||||
if (type == blitz::types::type::UNKNOWN) {
|
||||
throw blitz::error(file, name_tk.location, type_tk.location, blitz::format("Unexpected %s, expected built-in type name.", type_tk.text.c_str()));
|
||||
}
|
||||
node->tokens.push_back(type_tk);
|
||||
|
||||
node->type = type;
|
||||
} else if (symbol_tk.text == ".") {
|
||||
// .Struct
|
||||
node->tokens.push_back(lexer->next()); // Advance to next token.
|
||||
auto type_tk = lexer->next();
|
||||
if (type_tk != blitz::token::variant::TEXT) {
|
||||
throw blitz::error(file, name_tk.location, type_tk.location, blitz::format("Unexpected %s, expected text.", type_tk.to_string().c_str()));
|
||||
}
|
||||
node->tokens.push_back(type_tk);
|
||||
|
||||
node->type = blitz::types::type::STRUCT;
|
||||
node->struct_name = type_tk.text;
|
||||
} else if (symbol_tk.text == "%") {
|
||||
// Int32
|
||||
node->tokens.push_back(lexer->next()); // Advance to next token.
|
||||
node->type = blitz::types::type::INT32;
|
||||
} else if (symbol_tk.text == "#") {
|
||||
// Float
|
||||
node->tokens.push_back(lexer->next()); // Advance to next token.
|
||||
node->type = blitz::types::type::FLOAT32;
|
||||
} else if (symbol_tk.text == "$") {
|
||||
// String
|
||||
node->tokens.push_back(lexer->next()); // Advance to next token.
|
||||
node->type = blitz::types::type::STRING;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
blitz::ast::value::~value() {}
|
||||
|
||||
bool blitz::ast::value::can_parse(std::shared_ptr<blitz::lexer> lexer)
|
||||
{
|
||||
auto tk = lexer->current();
|
||||
switch (tk.type) {
|
||||
case blitz::token::variant::STRING:
|
||||
case blitz::token::variant::REAL:
|
||||
case blitz::token::variant::INTEGER:
|
||||
return true;
|
||||
case blitz::token::variant::STRING: {
|
||||
// We can only parse True, False, Null
|
||||
std::string text = tk.text;
|
||||
std::transform(text.cbegin(), text.cend(), text.begin(), [](char from) {
|
||||
if (from & 0b10000000) { // Exclude Unicode
|
||||
return from;
|
||||
}
|
||||
return (char)std::tolower(from);
|
||||
});
|
||||
if (tk.text == "false") {
|
||||
return true;
|
||||
} else if (tk.text == "true") {
|
||||
return true;
|
||||
} else if (tk.text == "null") {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<blitz::ast::node> blitz::ast::value::try_parse(std::shared_ptr<blitz::lexer> lexer)
|
||||
{
|
||||
auto tk = lexer->current();
|
||||
auto utk = lexer->peek();
|
||||
|
||||
auto node = std::make_shared<blitz::ast::value>();
|
||||
node->type = variant::UNKNOWN;
|
||||
|
||||
if (tk.type == blitz::token::variant::STRING) {
|
||||
node->type = variant::STRING;
|
||||
node->text = tk.text;
|
||||
return node;
|
||||
} else if (tk.type == blitz::token::variant::INTEGER) {
|
||||
// Figure out which base this integer is in (and where it starts).
|
||||
int base = 10;
|
||||
const char* text = tk.text.c_str();
|
||||
if ((tk.text.length() > 1) && (text[0] == '0')) {
|
||||
if (text[1] == 'x') { // Base 16
|
||||
base = 16;
|
||||
text = text += 2;
|
||||
} else if (text[1] == 'b') { // Base 2
|
||||
base = 2;
|
||||
text = text += 2;
|
||||
} else if (text[1] == '0') {
|
||||
base = 8;
|
||||
text = text += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (utk.type == blitz::token::variant::TEXT && utk.text == "u") {
|
||||
// User specific this is unsigned, so treat it as such.
|
||||
node->type = variant::UNSIGNED_INTEGER;
|
||||
node->number.ui = strtoull(text, nullptr, base);
|
||||
if (errno == ERANGE) {
|
||||
throw blitz::error(file, tk.location, tk.location, blitz::format("Value '%s' is not representable on this system.", tk.text.c_str()));
|
||||
}
|
||||
} else {
|
||||
// Try and figure out if it is unsigned.
|
||||
node->number.i = strtoll(text, nullptr, base);
|
||||
if (errno == ERANGE) {
|
||||
node->type = variant::UNSIGNED_INTEGER;
|
||||
node->number.ui = strtoull(text, nullptr, base);
|
||||
if (errno == ERANGE) {
|
||||
throw blitz::error(file, tk.location, tk.location, blitz::format("Value '%s' is not representable on this system.", tk.text.c_str()));
|
||||
}
|
||||
} else {
|
||||
node->type = variant::INTEGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// AUTOGENERATED COPYRIGHT HEADER START
|
||||
// Copyright (C) 2017-2024 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// Copyright (C) 2017-2025 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
||||
// AUTOGENERATED COPYRIGHT HEADER END
|
||||
#pragma once
|
||||
#include <list>
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include "../lexer.hpp"
|
||||
#include "../types.hpp"
|
||||
|
||||
// BlitzBasic Built-Ins
|
||||
// - Include: Followed by a String, which is the file to include at this location.
|
||||
@@ -30,34 +31,48 @@
|
||||
|
||||
namespace blitz {
|
||||
namespace ast {
|
||||
class node {
|
||||
public:
|
||||
struct node {
|
||||
std::vector<blitz::token> tokens;
|
||||
|
||||
virtual ~node() = default;
|
||||
};
|
||||
|
||||
class expression : public node {};
|
||||
struct variable : public node {
|
||||
std::string name;
|
||||
blitz::types::type type;
|
||||
std::string struct_name;
|
||||
|
||||
class variable : public node {
|
||||
blitz::token _token;
|
||||
std::shared_ptr<blitz::ast::expression> _value;
|
||||
|
||||
public:
|
||||
virtual ~variable();
|
||||
variable(blitz::token token);
|
||||
|
||||
void set_value(std::shared_ptr<blitz::ast::expression> value);
|
||||
static bool can_parse(std::shared_ptr<blitz::lexer> lexer);
|
||||
static std::shared_ptr<blitz::ast::node> try_parse(std::shared_ptr<blitz::lexer> lexer);
|
||||
};
|
||||
|
||||
class call : public node {};
|
||||
struct value : public node {
|
||||
enum class variant {
|
||||
UNKNOWN,
|
||||
NULL,
|
||||
BOOL,
|
||||
INTEGER,
|
||||
UNSIGNED_INTEGER,
|
||||
REAL,
|
||||
STRING,
|
||||
} type;
|
||||
union {
|
||||
bool b;
|
||||
intmax_t i;
|
||||
uintmax_t ui;
|
||||
double f;
|
||||
} number;
|
||||
std::string text;
|
||||
|
||||
class local : public node {
|
||||
public:
|
||||
~local();
|
||||
local();
|
||||
virtual ~value();
|
||||
|
||||
static bool can_parse(std::shared_ptr<blitz::lexer> lexer);
|
||||
static std::shared_ptr<blitz::ast::node> try_parse(std::shared_ptr<blitz::lexer> lexer);
|
||||
};
|
||||
|
||||
class global : public node {};
|
||||
|
||||
struct expression : public node {};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace blitz
|
||||
|
||||
Reference in New Issue
Block a user