ast stuff

This commit is contained in:
apio 2022-06-02 18:25:01 +02:00
parent f1668853dd
commit 60059e1091
32 changed files with 293 additions and 167 deletions

View File

@ -25,10 +25,24 @@ add_executable(
src/Arguments.h src/Arguments.h
src/Normalizer.cpp src/Normalizer.cpp
src/Normalizer.h src/Normalizer.h
src/ASTNode.cpp src/AST/ASTNode.cpp
src/ASTNode.h 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.cpp
src/replace.h src/replace.h
src/Parser.cpp
src/Parser.h
) )
target_include_directories(sapphirec PUBLIC src) target_include_directories(sapphirec PUBLIC src)

View File

@ -0,0 +1,11 @@
namespace allocate {
@memalloc (void*) (u64 size) {
}
@memfree (void* ptr) {
}
}

View File

@ -19,5 +19,4 @@ namespace linux {
@sys_exit (i32 code) { @sys_exit (i32 code) {
syscall1(60,code); syscall1(60,code);
} }
} }

1
core/allocate.sp Normal file
View File

@ -0,0 +1 @@
import core/__internal/allocate/linux;

View File

@ -1,3 +1,5 @@
import core/allocate;
namespace string { namespace string {
@len (u64) (str string) { @len (u64) (str string) {
@ -14,7 +16,7 @@ namespace string {
u64 len_a = len(a); u64 len_a = len(a);
u64 len_b = len(b); u64 len_b = len(b);
u64 final_size = len_a + 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(a,chars,len_a);
clone(b,chars + len_a,len_b); clone(b,chars + len_a,len_b);
chars[final_size] = 0; chars[final_size] = 0;
@ -24,7 +26,7 @@ namespace string {
@clone (str string, i8* buffer, u64 max_copy_size) { @clone (str string, i8* buffer, u64 max_copy_size) {
u64 chars_cloned = 0; u64 chars_cloned = 0;
i8* ptr = (i8*)string; 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]; buffer[chars_cloned] = ptr[chars_cloned];
chars_cloned += 1; chars_cloned += 1;

8
examples/float128.sp Normal file
View File

@ -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)));
}

9
src/AST/ASTNode.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "ASTNode.h"
ASTNode::ASTNode()
{
}
ASTNode::~ASTNode()
{
}

9
src/AST/ASTNode.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <memory>
class ASTNode
{
public:
ASTNode();
~ASTNode();
};

10
src/AST/BinaryOpNode.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "BinaryOpNode.h"
BinaryOpNode::BinaryOpNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right)
: left(left), right(right), ExprNode()
{
}
BinaryOpNode::~BinaryOpNode()
{
}

12
src/AST/BinaryOpNode.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include "ExprNode.h"
class BinaryOpNode : public ExprNode
{
protected:
std::shared_ptr<ExprNode> left;
std::shared_ptr<ExprNode> right;
public:
BinaryOpNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right);
~BinaryOpNode();
};

16
src/AST/ExprNode.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "ExprNode.h"
ExprNode::ExprNode(std::shared_ptr<ExprNode> child): child(child), ASTNode()
{
}
ExprNode::ExprNode(): ASTNode()
{
}
ExprNode::~ExprNode()
{
}

11
src/AST/ExprNode.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "ASTNode.h"
class ExprNode : public ASTNode
{
std::shared_ptr<ExprNode> child;
public:
ExprNode(std::shared_ptr<ExprNode> child);
ExprNode();
~ExprNode();
};

10
src/AST/MulNode.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "MulNode.h"
MulNode::MulNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right, char op)
: BinaryOpNode(left,right), op(op)
{
}
MulNode::~MulNode()
{
}

10
src/AST/MulNode.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "BinaryOpNode.h"
class MulNode final : public BinaryOpNode
{
char op;
public:
MulNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right, char op);
~MulNode();
};

2
src/AST/NumberNode.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "NumberNode.h"

10
src/AST/NumberNode.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "ExprNode.h"
#include <string>
class NumberNode : public ExprNode
{
public:
NumberNode();
~NumberNode();
};

11
src/AST/StatementNode.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "StatementNode.h"
StatementNode::StatementNode(std::shared_ptr<ExprNode> child): child(child), ASTNode()
{
}
StatementNode::~StatementNode()
{
}

10
src/AST/StatementNode.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "ExprNode.h"
class StatementNode : public ASTNode
{
std::shared_ptr<ExprNode> child;
public:
StatementNode(std::shared_ptr<ExprNode> child);
~StatementNode();
};

10
src/AST/SumNode.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "SumNode.h"
SumNode::SumNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right, char op)
: BinaryOpNode(left,right), op(op)
{
}
SumNode::~SumNode()
{
}

10
src/AST/SumNode.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "BinaryOpNode.h"
class SumNode final : public BinaryOpNode
{
char op;
public:
SumNode(std::shared_ptr<ExprNode> left,std::shared_ptr<ExprNode> right, char op);
~SumNode();
};

View File

@ -1,27 +0,0 @@
#include "ASTNode.h"
ASTNode::ASTNode()
{
}
ASTNode::~ASTNode()
{
}
BinaryOpNode::BinaryOpNode(std::shared_ptr<ASTNode> left,std::shared_ptr<ASTNode> right)
: left(left), right(right)
{
}
BinaryOpNode::~BinaryOpNode()
{
}
PlusNode::PlusNode(std::shared_ptr<ASTNode> left,std::shared_ptr<ASTNode> right)
: BinaryOpNode(left,right)
{
}
PlusNode::~PlusNode()
{
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <memory>
class ASTNode
{
public:
ASTNode();
~ASTNode();
};
class BinaryOpNode : public ASTNode
{
protected:
std::shared_ptr<ASTNode> left;
std::shared_ptr<ASTNode> right;
public:
BinaryOpNode(std::shared_ptr<ASTNode> left,std::shared_ptr<ASTNode> right);
~BinaryOpNode();
};
class PlusNode final : public BinaryOpNode
{
public:
PlusNode(std::shared_ptr<ASTNode> left,std::shared_ptr<ASTNode> right);
~PlusNode();
};

View File

@ -1,14 +1,29 @@
#include "FileIO.h" #include "FileIO.h"
#include "Error.h"
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <errno.h>
#include <cstring>
#include <filesystem>
std::string FileIO::read_all(const std::string& filename) std::string FileIO::read_all(const std::string& filename)
{ {
std::ifstream file(filename); std::ifstream file;
if(!file.is_open()) return ""; 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<char> file_chars; std::vector<char> file_chars;
char fchar; char fchar;
while (file) { while (file.good()) {
fchar = file.get(); fchar = file.get();
if(fchar != -1 ) file_chars.push_back(fchar); if(fchar != -1 ) file_chars.push_back(fchar);
} }

View File

@ -22,7 +22,7 @@ TokenStream Importer::evaluate(const TokenStream& original)
{ {
Token current_token = original[i]; 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]; Token next_token = original[i+1];
if(next_token.tk_type == TT_EOF) if(next_token.tk_type == TT_EOF)

View File

@ -7,7 +7,7 @@
#define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_0123456789" #define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_0123456789"
#define DIGITS "0123456789" #define DIGITS "0123456789"
const std::array<std::string,KEYWORD_COUNT> Lexer::keywords = {"var","import","out"}; const std::array<std::string,TYPE_COUNT> Lexer::types = {"void","bool","str","i8","i16","i32","i64","u8","u16","u32","u64","f32","f64","f128"};
Lexer::Lexer(const std::string& fname) Lexer::Lexer(const std::string& fname)
: loc(1,0,fname), index(-1), prev_loc(1,0,fname) : loc(1,0,fname), index(-1), prev_loc(1,0,fname)
@ -163,6 +163,12 @@ TokenStream Lexer::lex(const std::string& text)
case '!': case '!':
result.push_back(Token::make_with_line({TT_Exclamation,loc},current_line_text)); result.push_back(Token::make_with_line({TT_Exclamation,loc},current_line_text));
break; 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: default:
Error::throw_error(loc,current_line_text,"unknown character"); Error::throw_error(loc,current_line_text,"unknown character");
} }
@ -215,21 +221,36 @@ Token Lexer::create_identifier()
this->rewind(); this->rewind();
std::string identifier(characters.begin(), characters.end()); 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); 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); auto location = std::find(types.begin(),types.end(),identifier);
if(location != keywords.end()) 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); return Token::make_with_line({TT_Identifier,identifier,{prev_line,prev_column,loc.fname}},current_line_text);
} }
} }
std::string identifier(characters.begin(), characters.end()); std::string identifier(characters.begin(), characters.end());
auto location = std::find(keywords.begin(),keywords.end(),identifier); if(is_path) return Token::make_with_line({TT_Path,identifier,{prev_line,prev_column,loc.fname}},current_line_text);
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); return Token::make_with_line({TT_Identifier,identifier,{prev_line,prev_column,loc.fname}},current_line_text);
} }

View File

@ -6,7 +6,7 @@
#include <array> #include <array>
typedef std::vector<Token> TokenStream; typedef std::vector<Token> TokenStream;
#define KEYWORD_COUNT 3 #define TYPE_COUNT 14
class Lexer class Lexer
{ {
@ -34,7 +34,7 @@ private:
bool is_in_string(const std::string& string, const char& character); bool is_in_string(const std::string& string, const char& character);
public: public:
static const std::array<std::string,KEYWORD_COUNT> keywords; static const std::array<std::string,TYPE_COUNT> types;
~Lexer(); ~Lexer();
TokenStream lex(const std::string& text); TokenStream lex(const std::string& text);

9
src/Parser.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "Parser.h"
Parser::Parser(/* args */)
{
}
Parser::~Parser()
{
}

10
src/Parser.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
class Parser
{
private:
/* data */
public:
Parser(/* args */);
~Parser();
};

View File

@ -32,7 +32,17 @@ const std::string token_strings[] = {
"TT_COMMA", "TT_COMMA",
"TT_PATH", "TT_PATH",
"TT_EXCLAMATION", "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) Token::Token(const TokenType& type)
@ -101,6 +111,10 @@ std::string Token::to_string() const
{ {
return format_string("KEYWORD:%s %s",string_value,details); 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) else if (tk_type == TT_String)
{ {
replace(const_cast<std::string&>(string_value),"\n","\\n"); replace(const_cast<std::string&>(string_value),"\n","\\n");
@ -154,6 +168,24 @@ std::string Token::to_string() const
return "EXCLAMATION " + details; return "EXCLAMATION " + details;
case TT_NEqual: case TT_NEqual:
return "NEQUAL " + details; 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 ""; return "";
} }

View File

@ -33,7 +33,17 @@ enum TokenType
TT_Comma, TT_Comma,
TT_Path, TT_Path,
TT_Exclamation, 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[]; extern const std::string token_strings[];

View File

@ -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<TopLevelParseNode> TopLevelParser::ParseTokenStream(const TokenStream& stream)
{
current = stream;
index = -1;
std::vector<TopLevelParseNode> 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;
}

View File

@ -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<TopLevelParseNode> ParseTokenStream(const TokenStream& stream);
TopLevelParser();
~TopLevelParser();
};