diff --git a/CMakeLists.txt b/CMakeLists.txt index 76993bd..5f2efb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,24 @@ add_executable( src/Arguments.h src/Normalizer.cpp src/Normalizer.h - src/ASTNode.cpp - src/ASTNode.h + src/AST/ASTNode.cpp + src/AST/ASTNode.h + src/AST/BinaryOpNode.cpp + src/AST/BinaryOpNode.h + src/AST/ExprNode.cpp + src/AST/ExprNode.h + src/AST/MulNode.cpp + src/AST/MulNode.h + src/AST/NumberNode.cpp + src/AST/NumberNode.h + src/AST/StatementNode.cpp + src/AST/StatementNode.h + src/AST/SumNode.cpp + src/AST/SumNode.h src/replace.cpp src/replace.h + src/Parser.cpp + src/Parser.h ) target_include_directories(sapphirec PUBLIC src) diff --git a/core/__internal/allocate/linux.sp b/core/__internal/allocate/linux.sp new file mode 100644 index 0000000..84388d3 --- /dev/null +++ b/core/__internal/allocate/linux.sp @@ -0,0 +1,11 @@ +namespace allocate { + + @memalloc (void*) (u64 size) { + + } + + @memfree (void* ptr) { + + } + +} \ No newline at end of file diff --git a/core/__internal/linux/x64.sp b/core/__internal/linux/x64.sp index bfca0fb..9e70534 100644 --- a/core/__internal/linux/x64.sp +++ b/core/__internal/linux/x64.sp @@ -19,5 +19,4 @@ namespace linux { @sys_exit (i32 code) { syscall1(60,code); } - } \ No newline at end of file diff --git a/core/allocate.sp b/core/allocate.sp new file mode 100644 index 0000000..76423c1 --- /dev/null +++ b/core/allocate.sp @@ -0,0 +1 @@ +import core/__internal/allocate/linux; \ No newline at end of file diff --git a/core/string.sp b/core/string.sp index 9fda0c9..66d07e9 100644 --- a/core/string.sp +++ b/core/string.sp @@ -1,3 +1,5 @@ +import core/allocate; + namespace string { @len (u64) (str string) { @@ -14,7 +16,7 @@ namespace string { u64 len_a = len(a); u64 len_b = len(b); u64 final_size = len_a + len_b; - i8* chars = i8*(final_size + 1); // TODO: work on allocation + i8* chars = (i8*)allocate.memalloc(final_size + 1); clone(a,chars,len_a); clone(b,chars + len_a,len_b); chars[final_size] = 0; @@ -24,7 +26,7 @@ namespace string { @clone (str string, i8* buffer, u64 max_copy_size) { u64 chars_cloned = 0; i8* ptr = (i8*)string; - while(chars_cloned <= max_copy_size && ptr[chars_cloned] != 0) + while(chars_cloned <= max_copy_size and ptr[chars_cloned] != 0) { buffer[chars_cloned] = ptr[chars_cloned]; chars_cloned += 1; diff --git a/examples/float128.sp b/examples/float128.sp new file mode 100644 index 0000000..23482db --- /dev/null +++ b/examples/float128.sp @@ -0,0 +1,8 @@ +import core/io; +import core/string; + +@main { + f128 float1 = 234.6; + f128 float2 = 2934748348291930404.5; + io.outln(string.concat('Result is: ',(str)(float1 + float2))); +} \ No newline at end of file diff --git a/src/AST/ASTNode.cpp b/src/AST/ASTNode.cpp new file mode 100644 index 0000000..066dfd2 --- /dev/null +++ b/src/AST/ASTNode.cpp @@ -0,0 +1,9 @@ +#include "ASTNode.h" + +ASTNode::ASTNode() +{ +} + +ASTNode::~ASTNode() +{ +} \ No newline at end of file diff --git a/src/AST/ASTNode.h b/src/AST/ASTNode.h new file mode 100644 index 0000000..b891d1b --- /dev/null +++ b/src/AST/ASTNode.h @@ -0,0 +1,9 @@ +#pragma once +#include + +class ASTNode +{ +public: + ASTNode(); + ~ASTNode(); +}; diff --git a/src/AST/BinaryOpNode.cpp b/src/AST/BinaryOpNode.cpp new file mode 100644 index 0000000..bf5d62f --- /dev/null +++ b/src/AST/BinaryOpNode.cpp @@ -0,0 +1,10 @@ +#include "BinaryOpNode.h" + +BinaryOpNode::BinaryOpNode(std::shared_ptr left,std::shared_ptr right) + : left(left), right(right), ExprNode() +{ +} + +BinaryOpNode::~BinaryOpNode() +{ +} \ No newline at end of file diff --git a/src/AST/BinaryOpNode.h b/src/AST/BinaryOpNode.h new file mode 100644 index 0000000..a476dd9 --- /dev/null +++ b/src/AST/BinaryOpNode.h @@ -0,0 +1,12 @@ +#pragma once +#include "ExprNode.h" + +class BinaryOpNode : public ExprNode +{ +protected: + std::shared_ptr left; + std::shared_ptr right; +public: + BinaryOpNode(std::shared_ptr left,std::shared_ptr right); + ~BinaryOpNode(); +}; \ No newline at end of file diff --git a/src/AST/ExprNode.cpp b/src/AST/ExprNode.cpp new file mode 100644 index 0000000..27533d2 --- /dev/null +++ b/src/AST/ExprNode.cpp @@ -0,0 +1,16 @@ +#include "ExprNode.h" + +ExprNode::ExprNode(std::shared_ptr child): child(child), ASTNode() +{ + +} + +ExprNode::ExprNode(): ASTNode() +{ + +} + +ExprNode::~ExprNode() +{ + +} \ No newline at end of file diff --git a/src/AST/ExprNode.h b/src/AST/ExprNode.h new file mode 100644 index 0000000..7695727 --- /dev/null +++ b/src/AST/ExprNode.h @@ -0,0 +1,11 @@ +#pragma once +#include "ASTNode.h" + +class ExprNode : public ASTNode +{ + std::shared_ptr child; +public: + ExprNode(std::shared_ptr child); + ExprNode(); + ~ExprNode(); +}; \ No newline at end of file diff --git a/src/AST/MulNode.cpp b/src/AST/MulNode.cpp new file mode 100644 index 0000000..73025f9 --- /dev/null +++ b/src/AST/MulNode.cpp @@ -0,0 +1,10 @@ +#include "MulNode.h" + +MulNode::MulNode(std::shared_ptr left,std::shared_ptr right, char op) + : BinaryOpNode(left,right), op(op) +{ +} + +MulNode::~MulNode() +{ +} \ No newline at end of file diff --git a/src/AST/MulNode.h b/src/AST/MulNode.h new file mode 100644 index 0000000..a195304 --- /dev/null +++ b/src/AST/MulNode.h @@ -0,0 +1,10 @@ +#pragma once +#include "BinaryOpNode.h" + +class MulNode final : public BinaryOpNode +{ + char op; +public: + MulNode(std::shared_ptr left,std::shared_ptr right, char op); + ~MulNode(); +}; \ No newline at end of file diff --git a/src/AST/NumberNode.cpp b/src/AST/NumberNode.cpp new file mode 100644 index 0000000..e30f840 --- /dev/null +++ b/src/AST/NumberNode.cpp @@ -0,0 +1,2 @@ +#include "NumberNode.h" + diff --git a/src/AST/NumberNode.h b/src/AST/NumberNode.h new file mode 100644 index 0000000..b7f9509 --- /dev/null +++ b/src/AST/NumberNode.h @@ -0,0 +1,10 @@ +#pragma once +#include "ExprNode.h" +#include + +class NumberNode : public ExprNode +{ +public: + NumberNode(); + ~NumberNode(); +}; \ No newline at end of file diff --git a/src/AST/StatementNode.cpp b/src/AST/StatementNode.cpp new file mode 100644 index 0000000..0f059b9 --- /dev/null +++ b/src/AST/StatementNode.cpp @@ -0,0 +1,11 @@ +#include "StatementNode.h" + +StatementNode::StatementNode(std::shared_ptr child): child(child), ASTNode() +{ + +} + +StatementNode::~StatementNode() +{ + +} \ No newline at end of file diff --git a/src/AST/StatementNode.h b/src/AST/StatementNode.h new file mode 100644 index 0000000..e28763d --- /dev/null +++ b/src/AST/StatementNode.h @@ -0,0 +1,10 @@ +#pragma once +#include "ExprNode.h" + +class StatementNode : public ASTNode +{ + std::shared_ptr child; +public: + StatementNode(std::shared_ptr child); + ~StatementNode(); +}; \ No newline at end of file diff --git a/src/AST/SumNode.cpp b/src/AST/SumNode.cpp new file mode 100644 index 0000000..ef10b62 --- /dev/null +++ b/src/AST/SumNode.cpp @@ -0,0 +1,10 @@ +#include "SumNode.h" + +SumNode::SumNode(std::shared_ptr left,std::shared_ptr right, char op) + : BinaryOpNode(left,right), op(op) +{ +} + +SumNode::~SumNode() +{ +} \ No newline at end of file diff --git a/src/AST/SumNode.h b/src/AST/SumNode.h new file mode 100644 index 0000000..ccc3844 --- /dev/null +++ b/src/AST/SumNode.h @@ -0,0 +1,10 @@ +#pragma once +#include "BinaryOpNode.h" + +class SumNode final : public BinaryOpNode +{ + char op; +public: + SumNode(std::shared_ptr left,std::shared_ptr right, char op); + ~SumNode(); +}; \ No newline at end of file diff --git a/src/ASTNode.cpp b/src/ASTNode.cpp deleted file mode 100644 index 118d745..0000000 --- a/src/ASTNode.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "ASTNode.h" - -ASTNode::ASTNode() -{ -} - -ASTNode::~ASTNode() -{ -} - -BinaryOpNode::BinaryOpNode(std::shared_ptr left,std::shared_ptr right) - : left(left), right(right) -{ -} - -BinaryOpNode::~BinaryOpNode() -{ -} - -PlusNode::PlusNode(std::shared_ptr left,std::shared_ptr right) - : BinaryOpNode(left,right) -{ -} - -PlusNode::~PlusNode() -{ -} \ No newline at end of file diff --git a/src/ASTNode.h b/src/ASTNode.h deleted file mode 100644 index a999c9f..0000000 --- a/src/ASTNode.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include - -class ASTNode -{ -public: - ASTNode(); - ~ASTNode(); -}; - -class BinaryOpNode : public ASTNode -{ -protected: - std::shared_ptr left; - std::shared_ptr right; -public: - BinaryOpNode(std::shared_ptr left,std::shared_ptr right); - ~BinaryOpNode(); -}; - -class PlusNode final : public BinaryOpNode -{ -public: - PlusNode(std::shared_ptr left,std::shared_ptr right); - ~PlusNode(); -}; diff --git a/src/FileIO.cpp b/src/FileIO.cpp index 085b778..314931a 100644 --- a/src/FileIO.cpp +++ b/src/FileIO.cpp @@ -1,14 +1,29 @@ #include "FileIO.h" +#include "Error.h" #include #include +#include +#include +#include std::string FileIO::read_all(const std::string& filename) { - std::ifstream file(filename); - if(!file.is_open()) return ""; + std::ifstream file; + file.exceptions(std::ios::badbit | std::ios::failbit); + try + { + file.open(filename); + } + catch(const std::exception& e) + { + Error::throw_error_without_location("unable to open file "+ filename + ": " + strerror(errno)); + return ""; + } + if(std::filesystem::is_directory(std::filesystem::status(filename))) Error::throw_error_without_location("unable to open file "+ filename + ": Is a directory"); + file.exceptions(std::ios::goodbit); std::vector file_chars; char fchar; - while (file) { + while (file.good()) { fchar = file.get(); if(fchar != -1 ) file_chars.push_back(fchar); } diff --git a/src/Importer.cpp b/src/Importer.cpp index 5b8f639..410a880 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -22,7 +22,7 @@ TokenStream Importer::evaluate(const TokenStream& original) { Token current_token = original[i]; - if(current_token.tk_type == TT_Keyword && current_token.string_value == Lexer::keywords[1]) + if(current_token.tk_type == TT_Import) { Token next_token = original[i+1]; if(next_token.tk_type == TT_EOF) diff --git a/src/Lexer.cpp b/src/Lexer.cpp index 4592474..ac47d2d 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -7,7 +7,7 @@ #define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_0123456789" #define DIGITS "0123456789" -const std::array Lexer::keywords = {"var","import","out"}; +const std::array Lexer::types = {"void","bool","str","i8","i16","i32","i64","u8","u16","u32","u64","f32","f64","f128"}; Lexer::Lexer(const std::string& fname) : loc(1,0,fname), index(-1), prev_loc(1,0,fname) @@ -163,6 +163,12 @@ TokenStream Lexer::lex(const std::string& text) case '!': result.push_back(Token::make_with_line({TT_Exclamation,loc},current_line_text)); break; + case '[': + result.push_back(Token::make_with_line({TT_Exclamation,loc},current_line_text)); + break; + case ']': + result.push_back(Token::make_with_line({TT_Exclamation,loc},current_line_text)); + break; default: Error::throw_error(loc,current_line_text,"unknown character"); } @@ -215,21 +221,36 @@ Token Lexer::create_identifier() this->rewind(); std::string identifier(characters.begin(), characters.end()); if(is_path) return Token::make_with_line({TT_Path,identifier,{prev_line,prev_column,loc.fname}},current_line_text); - auto location = std::find(keywords.begin(),keywords.end(),identifier); - if(location != keywords.end()) + auto location = std::find(types.begin(),types.end(),identifier); + if(location != types.end()) { - return Token::make_with_line({TT_Keyword,identifier,{prev_line,prev_column,loc.fname}},current_line_text); + return Token::make_with_line({TT_Type,identifier,{prev_line,prev_column,loc.fname}},current_line_text); } + if (identifier == "import") return Token::make_with_line({TT_Import,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall0") return Token::make_with_line({TT_Syscall0,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall1") return Token::make_with_line({TT_Syscall1,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall2") return Token::make_with_line({TT_Syscall2,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall3") return Token::make_with_line({TT_Syscall3,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall4") return Token::make_with_line({TT_Syscall4,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall5") return Token::make_with_line({TT_Syscall5,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Identifier,identifier,{prev_line,prev_column,loc.fname}},current_line_text); } } std::string identifier(characters.begin(), characters.end()); - auto location = std::find(keywords.begin(),keywords.end(),identifier); - if(location != keywords.end()) + if(is_path) return Token::make_with_line({TT_Path,identifier,{prev_line,prev_column,loc.fname}},current_line_text); + auto location = std::find(types.begin(),types.end(),identifier); + if(location != types.end()) { - return Token::make_with_line({TT_Keyword,identifier,{prev_line,prev_column,loc.fname}},current_line_text); + return Token::make_with_line({TT_Type,identifier,{prev_line,prev_column,loc.fname}},current_line_text); } + if (identifier == "import") return Token::make_with_line({TT_Import,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall0") return Token::make_with_line({TT_Syscall0,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall1") return Token::make_with_line({TT_Syscall1,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall2") return Token::make_with_line({TT_Syscall2,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall3") return Token::make_with_line({TT_Syscall3,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall4") return Token::make_with_line({TT_Syscall4,{prev_line,prev_column,loc.fname}},current_line_text); + if (identifier == "syscall5") return Token::make_with_line({TT_Syscall5,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Identifier,identifier,{prev_line,prev_column,loc.fname}},current_line_text); } diff --git a/src/Lexer.h b/src/Lexer.h index ccdc014..2323b95 100644 --- a/src/Lexer.h +++ b/src/Lexer.h @@ -6,7 +6,7 @@ #include typedef std::vector TokenStream; -#define KEYWORD_COUNT 3 +#define TYPE_COUNT 14 class Lexer { @@ -34,7 +34,7 @@ private: bool is_in_string(const std::string& string, const char& character); public: - static const std::array keywords; + static const std::array types; ~Lexer(); TokenStream lex(const std::string& text); diff --git a/src/Parser.cpp b/src/Parser.cpp new file mode 100644 index 0000000..83dae01 --- /dev/null +++ b/src/Parser.cpp @@ -0,0 +1,9 @@ +#include "Parser.h" + +Parser::Parser(/* args */) +{ +} + +Parser::~Parser() +{ +} \ No newline at end of file diff --git a/src/Parser.h b/src/Parser.h new file mode 100644 index 0000000..595b8b7 --- /dev/null +++ b/src/Parser.h @@ -0,0 +1,10 @@ +#pragma once + +class Parser +{ +private: + /* data */ +public: + Parser(/* args */); + ~Parser(); +}; diff --git a/src/Token.cpp b/src/Token.cpp index f499e72..ae9171a 100644 --- a/src/Token.cpp +++ b/src/Token.cpp @@ -32,7 +32,17 @@ const std::string token_strings[] = { "TT_COMMA", "TT_PATH", "TT_EXCLAMATION", - "TT_NEQUAL" + "TT_NEQUAL", + "TT_LSQB", + "TT_RSQB", + "TT_TYPE", + "TT_IMPORT", + "TT_SYSCALL0", + "TT_SYSCALL1", + "TT_SYSCALL2", + "TT_SYSCALL3", + "TT_SYSCALL4", + "TT_SYSCALL5" }; Token::Token(const TokenType& type) @@ -100,7 +110,11 @@ std::string Token::to_string() const else if (tk_type == TT_Keyword) { return format_string("KEYWORD:%s %s",string_value,details); - } + } + else if (tk_type == TT_Type) + { + return format_string("TYPE:%s %s",string_value,details); + } else if (tk_type == TT_String) { replace(const_cast(string_value),"\n","\\n"); @@ -154,6 +168,24 @@ std::string Token::to_string() const return "EXCLAMATION " + details; case TT_NEqual: return "NEQUAL " + details; + case TT_LSQB: + return "LEFTSQB " + details; + case TT_RSQB: + return "RIGHTSQB " + details; + case TT_Import: + return "IMPORT " + details; + case TT_Syscall0: + return "SYSCALL0 " + details; + case TT_Syscall1: + return "SYSCALL1 " + details; + case TT_Syscall2: + return "SYSCALL2 " + details; + case TT_Syscall3: + return "SYSCALL3 " + details; + case TT_Syscall4: + return "SYSCALL4 " + details; + case TT_Syscall5: + return "SYSCALL5 " + details; } return ""; } diff --git a/src/Token.h b/src/Token.h index 2bbb679..4b6a1e2 100644 --- a/src/Token.h +++ b/src/Token.h @@ -33,7 +33,17 @@ enum TokenType TT_Comma, TT_Path, TT_Exclamation, - TT_NEqual + TT_NEqual, + TT_LSQB, + TT_RSQB, + TT_Type, + TT_Import, + TT_Syscall0, + TT_Syscall1, + TT_Syscall2, + TT_Syscall3, + TT_Syscall4, + TT_Syscall5 }; extern const std::string token_strings[]; diff --git a/src/TopLevelParser.cpp b/src/TopLevelParser.cpp deleted file mode 100644 index 6cc1dae..0000000 --- a/src/TopLevelParser.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "TopLevelParser.h" -#include "Error.h" - -TopLevelParseNode::TopLevelParseNode(const ParseContext& ctx, const TokenStream& tk_stream) - : context(ctx), tokens(tk_stream) -{ -} - -TopLevelParseNode::~TopLevelParseNode() -{ -} - -TopLevelParser::TopLevelParser() -{ -} - -TopLevelParser::~TopLevelParser() -{ -} - -std::vector TopLevelParser::ParseTokenStream(const TokenStream& stream) -{ - current = stream; - index = -1; - std::vector result; - - while(index < current.size()) - { - ++index; - if(current[index].tk_type == TT_Keyword) - { - if(current[index].string_value == "var") - { - result.push_back(ParseGlobalVariable()); - } else { - Error::throw_error(current[index].loc,current[index].line(),"global sections must start with var or @"); - } - } - else if (current[index].tk_type == TT_At) - { - result.push_back(ParseFunctionDefinition()); - } else { - Error::throw_error(current[index].loc,current[index].line(),"global sections must start with var or @"); - } - } - - return result; -} - -TopLevelParseNode TopLevelParser::ParseGlobalVariable() -{ - int prev_index = index; - if(!Token::match_token_types(current,{ - {TT_Keyword}, - {TT_Identifier}, - {TT_LParen}, - {TT_Identifier}, - {TT_RParen} - },index)) - { - Error::throw_error(current[index].loc,current[index].line(),"invalid syntax"); - } - index += 5; - -} \ No newline at end of file diff --git a/src/TopLevelParser.h b/src/TopLevelParser.h deleted file mode 100644 index 72c6ff5..0000000 --- a/src/TopLevelParser.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "Token.h" -#include "Lexer.h" //for TokenStream - -enum ParseContext { - ParseContext_GlobalVariable, - ParseContext_FunctionDefinition -}; - -struct TopLevelParseNode { - ParseContext context; - TokenStream tokens; - TopLevelParseNode(const ParseContext& ctx, const TokenStream& tk_stream); - ~TopLevelParseNode(); -}; - -class TopLevelParser -{ -private: - TokenStream current; - int index; - TopLevelParseNode ParseGlobalVariable(); - TopLevelParseNode ParseFunctionDefinition(); -public: - std::vector ParseTokenStream(const TokenStream& stream); - TopLevelParser(); - ~TopLevelParser(); -}; \ No newline at end of file