used clang-format :)

This commit is contained in:
apio 2022-06-14 16:29:51 +02:00
parent 8fe5297933
commit 4f6a1235a0
35 changed files with 820 additions and 794 deletions

View File

@ -10,6 +10,6 @@ SpaceAfterTemplateKeyword: 'false'
SpacesInCStyleCastParentheses: 'false' SpacesInCStyleCastParentheses: 'false'
SpacesInSquareBrackets: 'false' SpacesInSquareBrackets: 'false'
TabWidth: '4' TabWidth: '4'
UseTab: ForIndentation UseTab: Never
... ...

View File

@ -6,6 +6,7 @@ class BinaryOpNode : public ExprNode
protected: protected:
std::shared_ptr<ExprNode> left; std::shared_ptr<ExprNode> left;
std::shared_ptr<ExprNode> right; std::shared_ptr<ExprNode> right;
public: public:
BinaryOpNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right); BinaryOpNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right);
~BinaryOpNode(); ~BinaryOpNode();

View File

@ -2,15 +2,12 @@
ExprNode::ExprNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode() ExprNode::ExprNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode()
{ {
} }
ExprNode::ExprNode() : ASTNode() ExprNode::ExprNode() : ASTNode()
{ {
} }
ExprNode::~ExprNode() ExprNode::~ExprNode()
{ {
} }

View File

@ -4,6 +4,7 @@
class ExprNode : public ASTNode class ExprNode : public ASTNode
{ {
std::shared_ptr<ExprNode> child; std::shared_ptr<ExprNode> child;
public: public:
ExprNode(std::shared_ptr<ExprNode> child); ExprNode(std::shared_ptr<ExprNode> child);
ExprNode(); ExprNode();

View File

@ -4,6 +4,7 @@
class MulNode final : public BinaryOpNode class MulNode final : public BinaryOpNode
{ {
char op; char op;
public: public:
MulNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op); MulNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op);
~MulNode(); ~MulNode();

View File

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

View File

@ -2,10 +2,8 @@
StatementNode::StatementNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode() StatementNode::StatementNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode()
{ {
} }
StatementNode::~StatementNode() StatementNode::~StatementNode()
{ {
} }

View File

@ -4,6 +4,7 @@
class StatementNode : public ASTNode class StatementNode : public ASTNode
{ {
std::shared_ptr<ExprNode> child; std::shared_ptr<ExprNode> child;
public: public:
StatementNode(std::shared_ptr<ExprNode> child); StatementNode(std::shared_ptr<ExprNode> child);
~StatementNode(); ~StatementNode();

View File

@ -4,6 +4,7 @@
class SumNode final : public BinaryOpNode class SumNode final : public BinaryOpNode
{ {
char op; char op;
public: public:
SumNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op); SumNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op);
~SumNode(); ~SumNode();

View File

@ -11,7 +11,8 @@ std::string Arguments::cpu;
void Arguments::parse(int argc, char** argv) void Arguments::parse(int argc, char** argv)
{ {
try { try
{
TCLAP::CmdLine command_line("The Sapphire compiler.", ' ', "0.1"); TCLAP::CmdLine command_line("The Sapphire compiler.", ' ', "0.1");
TCLAP::UnlabeledValueArg<std::string> input_fname_arg("file", "Input file.", true, "test.sp", "string"); TCLAP::UnlabeledValueArg<std::string> input_fname_arg("file", "Input file.", true, "test.sp", "string");
@ -19,7 +20,8 @@ void Arguments::parse(int argc, char **argv)
TCLAP::ValueArg<std::string> output_fname_arg("o", "output", "Output file.", false, "sp-output", "string"); TCLAP::ValueArg<std::string> output_fname_arg("o", "output", "Output file.", false, "sp-output", "string");
TCLAP::ValueArg<std::string> march_arg("", "march", "Architecture to compile for.", false, "native", "string"); TCLAP::ValueArg<std::string> march_arg("", "march", "Architecture to compile for.", false, "native", "string");
TCLAP::ValueArg<std::string> mcpu_arg("", "mcpu", "CPU to compile for.", false, "generic", "string"); TCLAP::ValueArg<std::string> mcpu_arg("", "mcpu", "CPU to compile for.", false, "generic", "string");
TCLAP::ValueArg<std::string> msystem_arg("","msystem","Operating System to compile for.",false,"native","string"); TCLAP::ValueArg<std::string> msystem_arg("", "msystem", "Operating System to compile for.", false, "native",
"string");
TCLAP::SwitchArg wimport_arg("", "wimport", "Show a warning when trying to import an already imported file."); TCLAP::SwitchArg wimport_arg("", "wimport", "Show a warning when trying to import an already imported file.");
@ -41,8 +43,9 @@ void Arguments::parse(int argc, char **argv)
cpu = mcpu_arg.getValue(); cpu = mcpu_arg.getValue();
setTriple(march_arg.getValue(), msystem_arg.getValue()); setTriple(march_arg.getValue(), msystem_arg.getValue());
}
} catch (TCLAP::ArgException &e) { catch (TCLAP::ArgException& e)
{
Error::throw_error_without_location(e.error()); Error::throw_error_without_location(e.error());
} }
} }
@ -50,18 +53,18 @@ void Arguments::parse(int argc, char **argv)
void Arguments::setTriple(const std::string& arch, const std::string& system) void Arguments::setTriple(const std::string& arch, const std::string& system)
{ {
std::string triple = llvm::sys::getDefaultTargetTriple(); std::string triple = llvm::sys::getDefaultTargetTriple();
llvm::Triple tgTriple(triple); llvm::Triple targetTriple(triple);
if (arch != "native") if (arch != "native")
{ {
tgTriple.setArchName(arch); targetTriple.setArchName(arch);
} }
if (system != "native") if (system != "native")
{ {
tgTriple.setOSAndEnvironmentName(system); targetTriple.setOSAndEnvironmentName(system);
} }
tgTriple.setVendor(llvm::Triple::VendorType::UnknownVendor); // let's leave it like that targetTriple.setVendor(llvm::Triple::VendorType::UnknownVendor); // let's leave it like that
TargetTriple = tgTriple; TargetTriple = targetTriple;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <string>
#include <llvm/ADT/Triple.h> #include <llvm/ADT/Triple.h>
#include <string>
struct Arguments struct Arguments
{ {
@ -14,6 +14,7 @@ struct Arguments
static std::string cpu; static std::string cpu;
static llvm::Triple TargetTriple; static llvm::Triple TargetTriple;
private: private:
static void setTriple(const std::string& arch, const std::string& system); static void setTriple(const std::string& arch, const std::string& system);
}; };

View File

@ -1,13 +1,16 @@
#include "Error.h" #include "Error.h"
#include "StringConversion.h"
#include "Importer.h" #include "Importer.h"
#include <iostream> #include "StringConversion.h"
#include <algorithm> #include <algorithm>
#include <iostream>
std::string Error::get_spaces(const int& num) std::string Error::get_spaces(const int& num)
{ {
std::string output; std::string output;
for(int i = 0; i < num; i++) { output += " "; } for (int i = 0; i < num; i++)
{
output += " ";
}
return output; return output;
} }
@ -25,7 +28,8 @@ void Error::show_import_line(const Location& loc, std::ostream& output_stream)
output_stream << std::endl; output_stream << std::endl;
} }
void Error::show_import_lines(const Location& loc, void(*import_line_printer)(const Location&, std::ostream&), std::ostream& stream) void Error::show_import_lines(const Location& loc, void (*import_line_printer)(const Location&, std::ostream&),
std::ostream& stream)
{ {
std::vector<Location> locations; std::vector<Location> locations;
Location scanned_loc = loc; Location scanned_loc = loc;
@ -89,7 +93,6 @@ void Error::show_import_lines(const Location& loc, void(*import_line_printer)(co
std::cerr << std::endl; std::cerr << std::endl;
exit(1); exit(1);
} }
void Error::throw_warning(const Location& loc, const std::string line_text, const std::string& details) void Error::throw_warning(const Location& loc, const std::string line_text, const std::string& details)

View File

@ -11,7 +11,8 @@ namespace Error
void throw_warning(const Location& loc, const std::string line_text, const std::string& details); void throw_warning(const Location& loc, const std::string line_text, const std::string& details);
void show_import_lines(const Location& loc, void(*import_line_printer)(const Location&, std::ostream&), std::ostream& stream); void show_import_lines(const Location& loc, void (*import_line_printer)(const Location&, std::ostream&),
std::ostream& stream);
std::string get_spaces(const int& num); std::string get_spaces(const int& num);
} } // namespace Error

View File

@ -1,14 +1,15 @@
#include "FileIO.h" #include "FileIO.h"
#include "Error.h" #include "Error.h"
#include <cstring>
#include <errno.h>
#include <filesystem>
#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)
{ {
if(std::filesystem::is_directory(std::filesystem::status(filename))) Error::throw_error_without_location("unable to open file "+ filename + ": Is a directory"); if (std::filesystem::is_directory(std::filesystem::status(filename)))
Error::throw_error_without_location("unable to open file " + filename + ": Is a directory");
std::ifstream file; std::ifstream file;
file.exceptions(std::ios::badbit | std::ios::failbit); file.exceptions(std::ios::badbit | std::ios::failbit);
try try
@ -23,7 +24,8 @@ std::string FileIO::read_all(const std::string& filename)
file.exceptions(std::ios::goodbit); file.exceptions(std::ios::goodbit);
std::vector<char> file_chars; std::vector<char> file_chars;
char fchar; char fchar;
while (file.good()) { 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);
} }
@ -37,3 +39,8 @@ void FileIO::write_all(const std::string& filename, const std::string& contents)
file << contents; file << contents;
file.close(); file.close();
} }
std::string FileIO::remove_file_extension(const std::string& filename)
{
return filename.substr(0, filename.find_last_of('.'));
}

View File

@ -8,4 +8,6 @@ namespace FileIO
std::string read_all(const std::string& filename); std::string read_all(const std::string& filename);
/* Helper function to write a string to a file. */ /* Helper function to write a string to a file. */
void write_all(const std::string& filename, const std::string& contents); void write_all(const std::string& filename, const std::string& contents);
} /* Return a filename without its extension. */
std::string remove_file_extension(const std::string& filename);
} // namespace FileIO

View File

@ -1,7 +1,7 @@
#include "Importer.h" #include "Importer.h"
#include "Arguments.h"
#include "Error.h" #include "Error.h"
#include "FileIO.h" #include "FileIO.h"
#include "Arguments.h"
#include <algorithm> #include <algorithm>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -26,7 +26,8 @@ TokenStream Importer::evaluate(const TokenStream& original)
{ {
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)
Error::throw_error(current_token.loc,current_token.line(),"did not expect EOF after import statement"); Error::throw_error(current_token.loc, current_token.line(),
"did not expect EOF after import statement");
if (next_token.tk_type == TT_Identifier) // TODO: add support for strings if (next_token.tk_type == TT_Identifier) // TODO: add support for strings
{ {
@ -35,7 +36,8 @@ TokenStream Importer::evaluate(const TokenStream& original)
if (last_token.tk_type != TT_Semicolon) if (last_token.tk_type != TT_Semicolon)
Error::throw_error(last_token.loc, last_token.line(), "expected a semicolon"); Error::throw_error(last_token.loc, last_token.line(), "expected a semicolon");
if(std::find(imported_files.begin(),imported_files.end(),next_token.string_value) != imported_files.end()) if (std::find(imported_files.begin(), imported_files.end(), next_token.string_value) !=
imported_files.end())
{ {
if (Arguments::wimport) if (Arguments::wimport)
Error::throw_warning(next_token.loc, next_token.line(), "file already imported, skipping"); Error::throw_warning(next_token.loc, next_token.line(), "file already imported, skipping");
@ -52,13 +54,13 @@ TokenStream Importer::evaluate(const TokenStream& original)
std::string input_file_name = next_token.string_value + ".sp"; std::string input_file_name = next_token.string_value + ".sp";
std::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards std::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards
if(!input_file.good()) if (!input_file.good()) Error::throw_error(next_token.loc, next_token.line(), "file not found");
Error::throw_error(next_token.loc,next_token.line(),"file not found");
input_file.close(); input_file.close();
auto file_contents = FileIO::read_all(input_file_name); auto file_contents = FileIO::read_all(input_file_name);
auto top_location = std::make_shared<Location>(current_token.loc.line,current_token.loc.column,current_token.loc.fname); auto top_location = std::make_shared<Location>(current_token.loc.line, current_token.loc.column,
current_token.loc.fname);
top_location.get()->parent = current_token.loc.parent; top_location.get()->parent = current_token.loc.parent;
import_stack.push_back(top_location); // Keep ref_count above 0, just in case import_stack.push_back(top_location); // Keep ref_count above 0, just in case
@ -83,14 +85,16 @@ TokenStream Importer::evaluate(const TokenStream& original)
Token::erase(ret_tk[i]); Token::erase(ret_tk[i]);
Token::erase(ret_tk[i + 1]); Token::erase(ret_tk[i + 1]);
Token::erase(ret_tk[i + 2]); Token::erase(ret_tk[i + 2]);
} else if(next_token.tk_type == TT_Path) }
else if (next_token.tk_type == TT_Path)
{ {
Token last_token = original[i + 2]; Token last_token = original[i + 2];
if (last_token.tk_type != TT_Semicolon) if (last_token.tk_type != TT_Semicolon)
Error::throw_error(last_token.loc, last_token.line(), "expected a semicolon"); Error::throw_error(last_token.loc, last_token.line(), "expected a semicolon");
if(std::find(imported_files.begin(),imported_files.end(),next_token.string_value) != imported_files.end()) if (std::find(imported_files.begin(), imported_files.end(), next_token.string_value) !=
imported_files.end())
{ {
if (Arguments::wimport) if (Arguments::wimport)
Error::throw_warning(next_token.loc, next_token.line(), "file already imported, skipping"); Error::throw_warning(next_token.loc, next_token.line(), "file already imported, skipping");
@ -107,13 +111,13 @@ TokenStream Importer::evaluate(const TokenStream& original)
std::string input_file_name = next_token.string_value + ".sp"; std::string input_file_name = next_token.string_value + ".sp";
std::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards std::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards
if(!input_file.good()) if (!input_file.good()) Error::throw_error(next_token.loc, next_token.line(), "file not found");
Error::throw_error(next_token.loc,next_token.line(),"file not found");
input_file.close(); input_file.close();
auto file_contents = FileIO::read_all(input_file_name); auto file_contents = FileIO::read_all(input_file_name);
auto top_location = std::make_shared<Location>(current_token.loc.line,current_token.loc.column,current_token.loc.fname); auto top_location = std::make_shared<Location>(current_token.loc.line, current_token.loc.column,
current_token.loc.fname);
top_location.get()->parent = current_token.loc.parent; top_location.get()->parent = current_token.loc.parent;
import_stack.push_back(top_location); // Keep ref_count above 0, just in case import_stack.push_back(top_location); // Keep ref_count above 0, just in case
@ -138,14 +142,13 @@ TokenStream Importer::evaluate(const TokenStream& original)
Token::erase(ret_tk[i]); Token::erase(ret_tk[i]);
Token::erase(ret_tk[i + 1]); Token::erase(ret_tk[i + 1]);
Token::erase(ret_tk[i + 2]); Token::erase(ret_tk[i + 2]);
} else }
Error::throw_error(next_token.loc,next_token.line(),"import keyword should be followed by an identifier"); else
Error::throw_error(next_token.loc, next_token.line(),
"import keyword should be followed by an identifier");
} }
++i; ++i;
} }
if (new_tokens.size() != 0) if (new_tokens.size() != 0)

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Token.h"
#include "Lexer.h" #include "Lexer.h"
#include "Token.h"
namespace Importer namespace Importer
{ {
@ -9,4 +9,4 @@ namespace Importer
extern std::vector<std::string> imported_files; extern std::vector<std::string> imported_files;
TokenStream evaluate(const TokenStream& original); TokenStream evaluate(const TokenStream& original);
void init(std::string init_file); void init(std::string init_file);
} } // namespace Importer

View File

@ -7,10 +7,10 @@
#define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_0123456789" #define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_0123456789"
#define DIGITS "0123456789" #define DIGITS "0123456789"
const std::array<std::string,TYPE_COUNT> Lexer::types = {"void","bool","str","i8","i16","i32","i64","u8","u16","u32","u64","f32","f64","f128"}; 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)
{ {
} }
@ -105,7 +105,8 @@ TokenStream Lexer::lex(const std::string& text)
result.push_back(create_string()); result.push_back(create_string());
} }
else switch(current_char) else
switch (current_char)
{ {
case '/': case '/':
if (index + 1 != current_lexed_text.size()) if (index + 1 != current_lexed_text.size())
@ -200,13 +201,15 @@ Token Lexer::create_identifier()
} }
else if (current_char == '/') else if (current_char == '/')
{ {
if(last_was_path) { if (last_was_path)
{
characters.pop_back(); characters.pop_back();
this->loc = saved_loc; this->loc = saved_loc;
this->prev_loc = saved_prev_loc; this->prev_loc = saved_prev_loc;
this->rewind(); this->rewind();
std::string identifier(characters.begin(), characters.end()); std::string identifier(characters.begin(), characters.end());
return Token::make_with_line({TT_Path,identifier,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Path, identifier, {prev_line, prev_column, loc.fname}},
current_line_text);
} }
saved_loc = this->loc; saved_loc = this->loc;
@ -220,39 +223,61 @@ 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(types.begin(), types.end(), identifier); auto location = std::find(types.begin(), types.end(), identifier);
if (location != types.end()) if (location != types.end())
{ {
return Token::make_with_line({TT_Type,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 == "import")
if (identifier == "syscall0") return Token::make_with_line({TT_Syscall0,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Import, {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 == "syscall0")
if (identifier == "syscall2") return Token::make_with_line({TT_Syscall2,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Syscall0, {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 == "syscall1")
if (identifier == "syscall4") return Token::make_with_line({TT_Syscall4,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Syscall1, {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); if (identifier == "syscall2")
if( identifier == "compmacro" ) return Token::make_with_line({TT_CompilerMacro,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Syscall2, {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); 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);
if (identifier == "compmacro")
return Token::make_with_line({TT_CompilerMacro, {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());
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(types.begin(), types.end(), identifier); auto location = std::find(types.begin(), types.end(), identifier);
if (location != types.end()) if (location != types.end())
{ {
return Token::make_with_line({TT_Type, 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 == "import")
if (identifier == "syscall0") return Token::make_with_line({TT_Syscall0,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Import, {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 == "syscall0")
if (identifier == "syscall2") return Token::make_with_line({TT_Syscall2,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Syscall0, {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 == "syscall1")
if (identifier == "syscall4") return Token::make_with_line({TT_Syscall4,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Syscall1, {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); if (identifier == "syscall2")
if( identifier == "compmacro" ) return Token::make_with_line({TT_CompilerMacro,{prev_line,prev_column,loc.fname}},current_line_text); 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);
if (identifier == "compmacro")
return Token::make_with_line({TT_CompilerMacro, {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);
} }
@ -278,11 +303,13 @@ Token Lexer::create_number()
characters.push_back(current_char); characters.push_back(current_char);
++dot_count; ++dot_count;
} }
else { else
{
Error::throw_warning(loc, current_line_text, "floats can only have one dot"); Error::throw_warning(loc, current_line_text, "floats can only have one dot");
this->rewind(); this->rewind();
float tk_value = std::stof(std::string(characters.begin(), characters.end()).c_str()); float tk_value = std::stof(std::string(characters.begin(), characters.end()).c_str());
return Token::make_with_line({TT_Float,tk_value,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Float, tk_value, {prev_line, prev_column, loc.fname}},
current_line_text);
} }
} }
else else
@ -291,7 +318,8 @@ Token Lexer::create_number()
if (dot_count != 0) if (dot_count != 0)
{ {
float tk_value = std::stof(std::string(characters.begin(), characters.end()).c_str()); float tk_value = std::stof(std::string(characters.begin(), characters.end()).c_str());
return Token::make_with_line({TT_Float,tk_value,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_Float, tk_value, {prev_line, prev_column, loc.fname}},
current_line_text);
} }
int tk_value = atoi(std::string(characters.begin(), characters.end()).c_str()); int tk_value = atoi(std::string(characters.begin(), characters.end()).c_str());
return Token::make_with_line({TT_Number, tk_value, {prev_line, prev_column, loc.fname}}, current_line_text); return Token::make_with_line({TT_Number, tk_value, {prev_line, prev_column, loc.fname}}, current_line_text);
@ -323,7 +351,8 @@ Token Lexer::create_string()
if (current_char == '\'') if (current_char == '\'')
{ {
std::string identifier(characters.begin(), characters.end()); std::string identifier(characters.begin(), characters.end());
return Token::make_with_line({TT_String,identifier,{prev_line,prev_column,loc.fname}},current_line_text); return Token::make_with_line({TT_String, identifier, {prev_line, prev_column, loc.fname}},
current_line_text);
} }
if (current_char == '\\') if (current_char == '\\')
{ {

View File

@ -1,16 +1,17 @@
#pragma once #pragma once
#include "Token.h" #include "Token.h"
#include <memory>
#include <vector>
#include <string>
#include <array> #include <array>
#include <memory>
#include <string>
#include <vector>
/* Let's redefine TokenStream, as if it wasn't already defined in Token.h*/ /* Let's redefine TokenStream, as if it wasn't already defined in Token.h*/
typedef std::vector<Token> TokenStream; typedef std::vector<Token> TokenStream;
/* The number of data types currently in Sapphire. */ /* The number of data types currently in Sapphire. */
#define TYPE_COUNT 14 #define TYPE_COUNT 14
/* The Lexer for the Sapphire compiler. A Lexer reads source code from a file, and turns it into a stream of tokens the compiler can understand. */ /* The Lexer for the Sapphire compiler. A Lexer reads source code from a file, and turns it into a stream of tokens the
* compiler can understand. */
class Lexer class Lexer
{ {
private: private:
@ -36,6 +37,7 @@ private:
Token create_identifier(); Token create_identifier();
bool is_in_string(const std::string& string, const char& character); bool is_in_string(const std::string& string, const char& character);
public: public:
/* An array containing Sapphire's current data types. */ /* An array containing Sapphire's current data types. */
static const std::array<std::string, TYPE_COUNT> types; static const std::array<std::string, TYPE_COUNT> types;

View File

@ -2,8 +2,7 @@
#include "StringConversion.h" #include "StringConversion.h"
#include <sstream> #include <sstream>
Location::Location(int ln, int col, std::string file) Location::Location(int ln, int col, std::string file) : line(ln), column(col), fname(file)
: line(ln), column(col), fname(file)
{ {
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <string>
#include <memory> #include <memory>
#include <string>
/* Struct to represent a location in a file. */ /* Struct to represent a location in a file. */
struct Location struct Location

View File

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "Token.h"
#include "Lexer.h" // for TokenStream #include "Lexer.h" // for TokenStream
#include "Token.h"
/* Namespace to normalize a TokenStream. */ /* Namespace to normalize a TokenStream. */
namespace Normalizer namespace Normalizer
{ {
/* Some tokens are difficult for the Lexer to parse right, or maybe I'm just lazy. /* Some tokens are difficult for the Lexer to parse right, or maybe I'm just lazy.
Anyways, this function transforms > and = tokens next to each other into a single >=, which has a different meaning, etc... Anyways, this function transforms > and = tokens next to each other into a single >=, which has a different meaning,
For example: = + = : ==, < + = : <=... etc... For example: = + = : ==, < + = : <=...
It also takes blank tokens and removes them. */ It also takes blank tokens and removes them. */
TokenStream normalize(const TokenStream& input); TokenStream normalize(const TokenStream& input);
} } // namespace Normalizer

View File

@ -1,7 +1,6 @@
#include "Parser.h" #include "Parser.h"
Parser::Parser(const TokenStream& tokens) Parser::Parser(const TokenStream& tokens) : tokens(tokens)
: tokens(tokens)
{ {
} }
@ -11,7 +10,8 @@ Parser::~Parser()
std::shared_ptr<Parser> Parser::new_parser(const TokenStream& tokens) std::shared_ptr<Parser> Parser::new_parser(const TokenStream& tokens)
{ {
return std::shared_ptr<Parser>(new Parser(tokens)); // As always, not using std::make_shared 'cause constructor is private return std::shared_ptr<Parser>(
new Parser(tokens)); // As always, not using std::make_shared 'cause constructor is private
} }
std::shared_ptr<ASTNode> Parser::parse() std::shared_ptr<ASTNode> Parser::parse()
@ -28,7 +28,8 @@ std::shared_ptr<ASTNode> Parser::parse()
Parser::ErrorOr<ExprNode> Parser::walk_expr() Parser::ErrorOr<ExprNode> Parser::walk_expr()
{ {
return ErrorOr<ExprNode>(new ExprNode()); // constructor does not want to accept a shared_ptr<T> in the argument list, thats why im not using make_shared here return ErrorOr<ExprNode>(new ExprNode()); // constructor does not want to accept a shared_ptr<T> in the argument
// list, thats why im not using make_shared here
} }
Parser::ErrorOr<NumberNode> Parser::walk_number() Parser::ErrorOr<NumberNode> Parser::walk_number()

View File

@ -1,16 +1,16 @@
#pragma once #pragma once
#include <memory>
#include "Lexer.h"
#include "AST/NumberNode.h" #include "AST/NumberNode.h"
#include "Error.h" #include "Error.h"
#include "Lexer.h"
#include <cassert> #include <cassert>
#include <memory>
/* Parser class for the Sapphire compiler. */ /* Parser class for the Sapphire compiler. */
class Parser class Parser
{ {
/* Struct to store a parsing result which can be either a parsing error or a success, in which case it contains a pointer to the result. */ /* Struct to store a parsing result which can be either a parsing error or a success, in which case it contains a
template<typename T> * pointer to the result. */
struct ErrorOr template<typename T> struct ErrorOr
{ {
/* Return the stored pointer. */ /* Return the stored pointer. */
std::shared_ptr<T> get() std::shared_ptr<T> get()
@ -19,7 +19,8 @@ class Parser
return m_ptr; return m_ptr;
} }
/* Call Error::throw_error() with the stored error's location, line text, and the error string provided to this struct instance. */ /* Call Error::throw_error() with the stored error's location, line text, and the error string provided to this
* struct instance. */
void ethrow() void ethrow()
{ {
assert(m_is_error); assert(m_is_error);
@ -27,12 +28,20 @@ class Parser
} }
/* Construct a new successful ErrorOr with a heap-allocated pointer to the result class. */ /* Construct a new successful ErrorOr with a heap-allocated pointer to the result class. */
ErrorOr(T* ptr) : m_ptr(ptr), m_is_error(false) {} ErrorOr(T* ptr) : m_ptr(ptr), m_is_error(false)
{
}
/* Construct a new failed ErrorOr with the error details and the token where parsing failed. */ /* Construct a new failed ErrorOr with the error details and the token where parsing failed. */
ErrorOr(const std::string& error, const Token& error_tok) : m_error(error), m_is_error(true), error_tok(error_tok) {} ErrorOr(const std::string& error, const Token& error_tok)
: m_error(error), m_is_error(true), error_tok(error_tok)
{
}
/* Is this ErrorOr instance successful or failed? */ /* Is this ErrorOr instance successful or failed? */
bool is_error() { return m_is_error; } bool is_error()
{
return m_is_error;
}
private: private:
bool m_is_error; bool m_is_error;
@ -40,6 +49,7 @@ class Parser
std::shared_ptr<Token> error_tok; std::shared_ptr<Token> error_tok;
std::shared_ptr<T> m_ptr; std::shared_ptr<T> m_ptr;
}; };
private: private:
Parser(const TokenStream& tokens); Parser(const TokenStream& tokens);
TokenStream tokens; TokenStream tokens;
@ -52,6 +62,7 @@ private:
void save_current_position(); void save_current_position();
void restore_current_position(); void restore_current_position();
public: public:
~Parser(); ~Parser();

View File

@ -1,63 +1,26 @@
#include "Token.h" #include "Token.h"
#include "StringConversion.h"
#include "FormatString/FormatString.hpp" #include "FormatString/FormatString.hpp"
#include "StringConversion.h"
#include "replace.h" #include "replace.h"
const std::string token_strings[] = { const std::string token_strings[] = {
"TT_IDENTIFIER", "TT_IDENTIFIER", "TT_NUMBER", "TT_FLOAT", "TT_KEYWORD", "TT_STRING", "TT_PLUS",
"TT_NUMBER", "TT_MINUS", "TT_MUL", "TT_DIV", "TT_AT", "TT_EQUAL", "TT_LESSTHAN",
"TT_FLOAT", "TT_GREATERTHAN", "TT_LPAREN", "TT_RPAREN", "TT_LBRACKET", "TT_RBRACKET", "TT_SEMICOLON",
"TT_KEYWORD", "TT_LOADEDSTRING", "TT_EOF", "TT_NULL", "TT_EQUALS", "TT_GTE", "TT_LTE",
"TT_STRING", "TT_PERIOD", "TT_COMMA", "TT_PATH", "TT_EXCLAMATION", "TT_NEQUAL", "TT_LSQB",
"TT_PLUS", "TT_RSQB", "TT_TYPE", "TT_IMPORT", "TT_SYSCALL0", "TT_SYSCALL1", "TT_SYSCALL2",
"TT_MINUS", "TT_SYSCALL3", "TT_SYSCALL4", "TT_SYSCALL5", "TT_COMPILERMACRO"};
"TT_MUL",
"TT_DIV",
"TT_AT",
"TT_EQUAL",
"TT_LESSTHAN",
"TT_GREATERTHAN",
"TT_LPAREN",
"TT_RPAREN",
"TT_LBRACKET",
"TT_RBRACKET",
"TT_SEMICOLON",
"TT_LOADEDSTRING",
"TT_EOF",
"TT_NULL",
"TT_EQUALS",
"TT_GTE",
"TT_LTE",
"TT_PERIOD",
"TT_COMMA",
"TT_PATH",
"TT_EXCLAMATION",
"TT_NEQUAL",
"TT_LSQB",
"TT_RSQB",
"TT_TYPE",
"TT_IMPORT",
"TT_SYSCALL0",
"TT_SYSCALL1",
"TT_SYSCALL2",
"TT_SYSCALL3",
"TT_SYSCALL4",
"TT_SYSCALL5",
"TT_COMPILERMACRO"
};
Token::Token(const TokenType& type) Token::Token(const TokenType& type) : tk_type(type), loc(0, 0, "")
: tk_type(type), loc(0,0,"")
{ {
} }
Token::Token(const TokenType& type, const Location& location) Token::Token(const TokenType& type, const Location& location) : tk_type(type), loc(location)
: tk_type(type), loc(location)
{ {
} }
Token::Token(const TokenType& type, const std::string& val) Token::Token(const TokenType& type, const std::string& val) : tk_type(type), loc(0, 0, ""), string_value(val)
: tk_type(type), loc(0,0,""), string_value(val)
{ {
} }

View File

@ -94,8 +94,8 @@ struct Token
/* Return a copy of this Token, but with its TokenType changed. */ /* Return a copy of this Token, but with its TokenType changed. */
Token copy_with_new_type(const TokenType& type); Token copy_with_new_type(const TokenType& type);
/* Iterate over two vectors of Tokens, starting from count for vector A, starting from 0 for vector B, checking if the current Tokens' types match. /* Iterate over two vectors of Tokens, starting from count for vector A, starting from 0 for vector B, checking if
If at any point they don't, return false. Else, return true. */ the current Tokens' types match. If at any point they don't, return false. Else, return true. */
static bool match_token_types(const std::vector<Token>& a, const std::vector<Token>& b, int count); static bool match_token_types(const std::vector<Token>& a, const std::vector<Token>& b, int count);
private: private:

View File

@ -1,9 +1,9 @@
#include "replace.h" #include "replace.h"
bool replace(std::string& str, const std::string& from, const std::string& to) { bool replace(std::string& str, const std::string& from, const std::string& to)
{
size_t start_pos = str.find(from); size_t start_pos = str.find(from);
if(start_pos == std::string::npos) if (start_pos == std::string::npos) return false;
return false;
str.replace(start_pos, from.length(), to); str.replace(start_pos, from.length(), to);
return true; return true;
} }

View File

@ -1,7 +1,7 @@
#include "Lexer.h" #include "Arguments.h"
#include "FileIO.h" #include "FileIO.h"
#include "Importer.h" #include "Importer.h"
#include "Arguments.h" #include "Lexer.h"
#include "Normalizer.h" #include "Normalizer.h"
#include <iostream> #include <iostream>
@ -11,14 +11,16 @@ int main(int argc, char** argv)
std::string fname = Arguments::input_fname; std::string fname = Arguments::input_fname;
std::string contents = FileIO::read_all(fname); std::string contents = FileIO::read_all(fname);
TokenStream res = Lexer::make_lexer(fname)->lex(contents); TokenStream result = Lexer::make_lexer(fname)->lex(contents);
Importer::init(fname.substr(0,fname.find_last_of('.')));
res = Importer::evaluate(res);
res = Normalizer::normalize(res);
for(int i = 0; i < res.size(); i++) Importer::init(FileIO::remove_file_extension(fname));
result = Importer::evaluate(result);
result = Normalizer::normalize(result);
for (int i = 0; i < result.size(); i++)
{ {
std::cout << res[i].to_string() << std::endl; std::cout << result[i].to_string() << std::endl;
} }
std::cout << "Output filename: " << Arguments::output_fname << std::endl; std::cout << "Output filename: " << Arguments::output_fname << std::endl;