// AUTOGENERATED COPYRIGHT HEADER START // Copyright (C) 2017-2025 Michael Fabian 'Xaymar' Dirks // AUTOGENERATED COPYRIGHT HEADER END #include "ast.hpp" #include #include #include blitz::ast::variable::~variable() { /* 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 lexer) { return lexer->current().type == blitz::token::variant::TEXT; } std::shared_ptr blitz::ast::variable::try_parse(std::shared_ptr 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(); 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 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::value::try_parse(std::shared_ptr lexer) { auto tk = lexer->current(); auto utk = lexer->peek(); auto node = std::make_shared(); 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; } } } }