used clang-format :)
This commit is contained in:
parent
8fe5297933
commit
4f6a1235a0
@ -10,6 +10,6 @@ SpaceAfterTemplateKeyword: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
TabWidth: '4'
|
||||
UseTab: ForIndentation
|
||||
UseTab: Never
|
||||
|
||||
...
|
||||
|
@ -6,6 +6,7 @@ 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();
|
||||
|
@ -2,15 +2,12 @@
|
||||
|
||||
ExprNode::ExprNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ExprNode::ExprNode() : ASTNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ExprNode::~ExprNode()
|
||||
{
|
||||
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
class ExprNode : public ASTNode
|
||||
{
|
||||
std::shared_ptr<ExprNode> child;
|
||||
|
||||
public:
|
||||
ExprNode(std::shared_ptr<ExprNode> child);
|
||||
ExprNode();
|
||||
|
@ -4,6 +4,7 @@
|
||||
class MulNode final : public BinaryOpNode
|
||||
{
|
||||
char op;
|
||||
|
||||
public:
|
||||
MulNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op);
|
||||
~MulNode();
|
||||
|
@ -1,2 +1 @@
|
||||
#include "NumberNode.h"
|
||||
|
||||
|
@ -2,10 +2,8 @@
|
||||
|
||||
StatementNode::StatementNode(std::shared_ptr<ExprNode> child) : child(child), ASTNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StatementNode::~StatementNode()
|
||||
{
|
||||
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
class StatementNode : public ASTNode
|
||||
{
|
||||
std::shared_ptr<ExprNode> child;
|
||||
|
||||
public:
|
||||
StatementNode(std::shared_ptr<ExprNode> child);
|
||||
~StatementNode();
|
||||
|
@ -4,6 +4,7 @@
|
||||
class SumNode final : public BinaryOpNode
|
||||
{
|
||||
char op;
|
||||
|
||||
public:
|
||||
SumNode(std::shared_ptr<ExprNode> left, std::shared_ptr<ExprNode> right, char op);
|
||||
~SumNode();
|
||||
|
@ -11,7 +11,8 @@ std::string Arguments::cpu;
|
||||
|
||||
void Arguments::parse(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
TCLAP::CmdLine command_line("The Sapphire compiler.", ' ', "0.1");
|
||||
|
||||
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> 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> 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.");
|
||||
|
||||
@ -41,8 +43,9 @@ void Arguments::parse(int argc, char **argv)
|
||||
cpu = mcpu_arg.getValue();
|
||||
|
||||
setTriple(march_arg.getValue(), msystem_arg.getValue());
|
||||
|
||||
} catch (TCLAP::ArgException &e) {
|
||||
}
|
||||
catch (TCLAP::ArgException& e)
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::string triple = llvm::sys::getDefaultTargetTriple();
|
||||
llvm::Triple tgTriple(triple);
|
||||
llvm::Triple targetTriple(triple);
|
||||
|
||||
if (arch != "native")
|
||||
{
|
||||
tgTriple.setArchName(arch);
|
||||
targetTriple.setArchName(arch);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <llvm/ADT/Triple.h>
|
||||
#include <string>
|
||||
|
||||
struct Arguments
|
||||
{
|
||||
@ -14,6 +14,7 @@ struct Arguments
|
||||
static std::string cpu;
|
||||
|
||||
static llvm::Triple TargetTriple;
|
||||
|
||||
private:
|
||||
static void setTriple(const std::string& arch, const std::string& system);
|
||||
};
|
||||
|
@ -1,13 +1,16 @@
|
||||
#include "Error.h"
|
||||
#include "StringConversion.h"
|
||||
#include "Importer.h"
|
||||
#include <iostream>
|
||||
#include "StringConversion.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
std::string Error::get_spaces(const int& num)
|
||||
{
|
||||
std::string output;
|
||||
for(int i = 0; i < num; i++) { output += " "; }
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
output += " ";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -25,7 +28,8 @@ void Error::show_import_line(const Location& loc, std::ostream& output_stream)
|
||||
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;
|
||||
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;
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
void Error::throw_warning(const Location& loc, const std::string line_text, const std::string& details)
|
||||
|
@ -11,7 +11,8 @@ namespace Error
|
||||
|
||||
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);
|
||||
}
|
||||
} // namespace Error
|
||||
|
@ -1,14 +1,15 @@
|
||||
#include "FileIO.h"
|
||||
#include "Error.h"
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
|
||||
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;
|
||||
file.exceptions(std::ios::badbit | std::ios::failbit);
|
||||
try
|
||||
@ -23,7 +24,8 @@ std::string FileIO::read_all(const std::string& filename)
|
||||
file.exceptions(std::ios::goodbit);
|
||||
std::vector<char> file_chars;
|
||||
char fchar;
|
||||
while (file.good()) {
|
||||
while (file.good())
|
||||
{
|
||||
fchar = file.get();
|
||||
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.close();
|
||||
}
|
||||
|
||||
std::string FileIO::remove_file_extension(const std::string& filename)
|
||||
{
|
||||
return filename.substr(0, filename.find_last_of('.'));
|
||||
}
|
@ -8,4 +8,6 @@ namespace FileIO
|
||||
std::string read_all(const std::string& filename);
|
||||
/* Helper function to write a string to a file. */
|
||||
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
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Importer.h"
|
||||
#include "Arguments.h"
|
||||
#include "Error.h"
|
||||
#include "FileIO.h"
|
||||
#include "Arguments.h"
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@ -26,7 +26,8 @@ TokenStream Importer::evaluate(const TokenStream& original)
|
||||
{
|
||||
Token next_token = original[i + 1];
|
||||
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
|
||||
{
|
||||
@ -35,7 +36,8 @@ TokenStream Importer::evaluate(const TokenStream& original)
|
||||
if (last_token.tk_type != TT_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)
|
||||
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::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards
|
||||
if(!input_file.good())
|
||||
Error::throw_error(next_token.loc,next_token.line(),"file not found");
|
||||
if (!input_file.good()) Error::throw_error(next_token.loc, next_token.line(), "file not found");
|
||||
input_file.close();
|
||||
|
||||
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;
|
||||
|
||||
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 + 1]);
|
||||
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];
|
||||
|
||||
if (last_token.tk_type != TT_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)
|
||||
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::ifstream input_file(input_file_name); // only used to check if it exists, thus closed afterwards
|
||||
if(!input_file.good())
|
||||
Error::throw_error(next_token.loc,next_token.line(),"file not found");
|
||||
if (!input_file.good()) Error::throw_error(next_token.loc, next_token.line(), "file not found");
|
||||
input_file.close();
|
||||
|
||||
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;
|
||||
|
||||
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 + 1]);
|
||||
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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (new_tokens.size() != 0)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "Token.h"
|
||||
#include "Lexer.h"
|
||||
#include "Token.h"
|
||||
|
||||
namespace Importer
|
||||
{
|
||||
@ -9,4 +9,4 @@ namespace Importer
|
||||
extern std::vector<std::string> imported_files;
|
||||
TokenStream evaluate(const TokenStream& original);
|
||||
void init(std::string init_file);
|
||||
}
|
||||
} // namespace Importer
|
||||
|
@ -7,10 +7,10 @@
|
||||
#define IDENTIFIERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ_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)
|
||||
: loc(1,0,fname), index(-1), prev_loc(1,0,fname)
|
||||
Lexer::Lexer(const std::string& 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());
|
||||
}
|
||||
|
||||
else switch(current_char)
|
||||
else
|
||||
switch (current_char)
|
||||
{
|
||||
case '/':
|
||||
if (index + 1 != current_lexed_text.size())
|
||||
@ -200,13 +201,15 @@ Token Lexer::create_identifier()
|
||||
}
|
||||
else if (current_char == '/')
|
||||
{
|
||||
if(last_was_path) {
|
||||
if (last_was_path)
|
||||
{
|
||||
characters.pop_back();
|
||||
this->loc = saved_loc;
|
||||
this->prev_loc = saved_prev_loc;
|
||||
this->rewind();
|
||||
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;
|
||||
@ -220,39 +223,61 @@ 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);
|
||||
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_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 == "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);
|
||||
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);
|
||||
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);
|
||||
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());
|
||||
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);
|
||||
if (location != types.end())
|
||||
{
|
||||
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);
|
||||
if( identifier == "compmacro" ) return Token::make_with_line({TT_CompilerMacro,{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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -278,11 +303,13 @@ Token Lexer::create_number()
|
||||
characters.push_back(current_char);
|
||||
++dot_count;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
Error::throw_warning(loc, current_line_text, "floats can only have one dot");
|
||||
this->rewind();
|
||||
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
|
||||
@ -291,7 +318,8 @@ Token Lexer::create_number()
|
||||
if (dot_count != 0)
|
||||
{
|
||||
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());
|
||||
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 == '\'')
|
||||
{
|
||||
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 == '\\')
|
||||
{
|
||||
|
10
src/Lexer.h
10
src/Lexer.h
@ -1,16 +1,17 @@
|
||||
#pragma once
|
||||
#include "Token.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/* Let's redefine TokenStream, as if it wasn't already defined in Token.h*/
|
||||
typedef std::vector<Token> TokenStream;
|
||||
/* The number of data types currently in Sapphire. */
|
||||
#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
|
||||
{
|
||||
private:
|
||||
@ -36,6 +37,7 @@ private:
|
||||
Token create_identifier();
|
||||
|
||||
bool is_in_string(const std::string& string, const char& character);
|
||||
|
||||
public:
|
||||
/* An array containing Sapphire's current data types. */
|
||||
static const std::array<std::string, TYPE_COUNT> types;
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include "StringConversion.h"
|
||||
#include <sstream>
|
||||
|
||||
Location::Location(int ln, int col, std::string file)
|
||||
: line(ln), column(col), fname(file)
|
||||
Location::Location(int ln, int col, std::string file) : line(ln), column(col), fname(file)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
/* Struct to represent a location in a file. */
|
||||
struct Location
|
||||
|
@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
#include "Token.h"
|
||||
#include "Lexer.h" // for TokenStream
|
||||
#include "Token.h"
|
||||
|
||||
/* Namespace to normalize a TokenStream. */
|
||||
namespace Normalizer
|
||||
{
|
||||
/* 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...
|
||||
For example: = + = : ==, < + = : <=...
|
||||
Anyways, this function transforms > and = tokens next to each other into a single >=, which has a different meaning,
|
||||
etc... For example: = + = : ==, < + = : <=...
|
||||
|
||||
It also takes blank tokens and removes them. */
|
||||
TokenStream normalize(const TokenStream& input);
|
||||
}
|
||||
} // namespace Normalizer
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "Parser.h"
|
||||
|
||||
Parser::Parser(const TokenStream& tokens)
|
||||
: tokens(tokens)
|
||||
Parser::Parser(const TokenStream& tokens) : tokens(tokens)
|
||||
{
|
||||
}
|
||||
|
||||
@ -11,7 +10,8 @@ Parser::~Parser()
|
||||
|
||||
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()
|
||||
@ -28,7 +28,8 @@ std::shared_ptr<ASTNode> Parser::parse()
|
||||
|
||||
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()
|
||||
|
29
src/Parser.h
29
src/Parser.h
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "Lexer.h"
|
||||
#include "AST/NumberNode.h"
|
||||
#include "Error.h"
|
||||
#include "Lexer.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
/* Parser class for the Sapphire compiler. */
|
||||
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. */
|
||||
template<typename T>
|
||||
struct ErrorOr
|
||||
/* 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. */
|
||||
template<typename T> struct ErrorOr
|
||||
{
|
||||
/* Return the stored pointer. */
|
||||
std::shared_ptr<T> get()
|
||||
@ -19,7 +19,8 @@ class Parser
|
||||
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()
|
||||
{
|
||||
assert(m_is_error);
|
||||
@ -27,12 +28,20 @@ class Parser
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
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? */
|
||||
bool is_error() { return m_is_error; }
|
||||
bool is_error()
|
||||
{
|
||||
return m_is_error;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_is_error;
|
||||
@ -40,6 +49,7 @@ class Parser
|
||||
std::shared_ptr<Token> error_tok;
|
||||
std::shared_ptr<T> m_ptr;
|
||||
};
|
||||
|
||||
private:
|
||||
Parser(const TokenStream& tokens);
|
||||
TokenStream tokens;
|
||||
@ -52,6 +62,7 @@ private:
|
||||
|
||||
void save_current_position();
|
||||
void restore_current_position();
|
||||
|
||||
public:
|
||||
~Parser();
|
||||
|
||||
|
@ -1,63 +1,26 @@
|
||||
#include "Token.h"
|
||||
#include "StringConversion.h"
|
||||
#include "FormatString/FormatString.hpp"
|
||||
#include "StringConversion.h"
|
||||
#include "replace.h"
|
||||
|
||||
const std::string token_strings[] = {
|
||||
"TT_IDENTIFIER",
|
||||
"TT_NUMBER",
|
||||
"TT_FLOAT",
|
||||
"TT_KEYWORD",
|
||||
"TT_STRING",
|
||||
"TT_PLUS",
|
||||
"TT_MINUS",
|
||||
"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"
|
||||
};
|
||||
"TT_IDENTIFIER", "TT_NUMBER", "TT_FLOAT", "TT_KEYWORD", "TT_STRING", "TT_PLUS",
|
||||
"TT_MINUS", "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)
|
||||
: tk_type(type), loc(0,0,"")
|
||||
Token::Token(const TokenType& type) : tk_type(type), loc(0, 0, "")
|
||||
{
|
||||
}
|
||||
|
||||
Token::Token(const TokenType& type, const Location& location)
|
||||
: tk_type(type), loc(location)
|
||||
Token::Token(const TokenType& type, const Location& location) : tk_type(type), loc(location)
|
||||
{
|
||||
}
|
||||
|
||||
Token::Token(const TokenType& type, const std::string& val)
|
||||
: tk_type(type), loc(0,0,""), string_value(val)
|
||||
Token::Token(const TokenType& type, const std::string& val) : tk_type(type), loc(0, 0, ""), string_value(val)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,8 +94,8 @@ struct Token
|
||||
/* Return a copy of this Token, but with its TokenType changed. */
|
||||
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.
|
||||
If at any point they don't, return false. Else, return true. */
|
||||
/* 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. 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);
|
||||
|
||||
private:
|
||||
|
@ -1,9 +1,9 @@
|
||||
#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);
|
||||
if(start_pos == std::string::npos)
|
||||
return false;
|
||||
if (start_pos == std::string::npos) return false;
|
||||
str.replace(start_pos, from.length(), to);
|
||||
return true;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include "Lexer.h"
|
||||
#include "Arguments.h"
|
||||
#include "FileIO.h"
|
||||
#include "Importer.h"
|
||||
#include "Arguments.h"
|
||||
#include "Lexer.h"
|
||||
#include "Normalizer.h"
|
||||
#include <iostream>
|
||||
|
||||
@ -11,14 +11,16 @@ int main(int argc, char** argv)
|
||||
std::string fname = Arguments::input_fname;
|
||||
std::string contents = FileIO::read_all(fname);
|
||||
|
||||
TokenStream res = Lexer::make_lexer(fname)->lex(contents);
|
||||
Importer::init(fname.substr(0,fname.find_last_of('.')));
|
||||
res = Importer::evaluate(res);
|
||||
res = Normalizer::normalize(res);
|
||||
TokenStream result = Lexer::make_lexer(fname)->lex(contents);
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user