diff --git a/examples/parser-test.sp b/examples/parser-test.sp index 4e1e45e..13da2ef 100644 --- a/examples/parser-test.sp +++ b/examples/parser-test.sp @@ -1 +1 @@ -1+2+3*5 \ No newline at end of file +2+2*6+ diff --git a/src/Lexer.cpp b/src/Lexer.cpp index c75150f..817d39a 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -170,6 +170,9 @@ TokenStream Lexer::lex(const std::string& text) case ']': result.push_back(Token::make_with_line({TT_Exclamation, loc}, current_line_text)); break; + case '\377': + result.push_back(Token(TT_EOF,loc)); + return result; default: Error::throw_error(loc, current_line_text, "unknown character"); } diff --git a/src/Parser.cpp b/src/Parser.cpp index e129dea..dcefa17 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -15,7 +15,9 @@ std::shared_ptr Parser::new_parser(const TokenStream& tokens) std::shared_ptr Parser::parse() { advance(); - return expr(); + auto result = expr(); + if(result.is_error()) result.ethrow(); + return result.get(); } int Parser::advance() @@ -28,45 +30,51 @@ int Parser::advance() return 1; } -std::shared_ptr Parser::factor() +Result Parser::factor() { - Token token = *current_token; + Token& token = *current_token; if (token.tk_type == TT_Number) { advance(); - return std::make_shared(token.int_value); + return Ok(new IntegerNode(token.int_value),&token); } if (token.tk_type == TT_Float) { advance(); - return std::make_shared(token.float_value); + return Ok(new FloatNode(token.float_value),&token); } + + return Err("expected a number",&token); } -std::shared_ptr Parser::term() +Result Parser::term() { - std::shared_ptr left = factor(); + Result left = factor(); + if(left.is_error()) return left; while (current_token->tk_type == TT_Mul || current_token->tk_type == TT_Div) { - Token op = *current_token; + Token& op = *current_token; advance(); - std::shared_ptr right = factor(); - left = std::make_shared(left, right, op.tk_type == TT_Mul ? '*' : '/'); + Result right = factor(); + if(right.is_error()) return right; + left = Ok(new MulNode(left.get(), right.get(), op.tk_type == TT_Mul ? '*' : '/'), &op); } return left; } -std::shared_ptr Parser::expr() +Result Parser::expr() { - std::shared_ptr left = term(); + Result left = term(); + if(left.is_error()) return left; while (current_token->tk_type == TT_Plus || current_token->tk_type == TT_Minus) { - Token op = *current_token; + Token& op = *current_token; advance(); - std::shared_ptr right = term(); - left = std::make_shared(left, right, op.tk_type == TT_Plus ? '+' : '-'); + Result right = term(); + if(right.is_error()) return right; + left = Ok(new SumNode(left.get(), right.get(), op.tk_type == TT_Plus ? '+' : '-'),&op); } return left; } diff --git a/src/Parser.h b/src/Parser.h index 4028add..f4f79e8 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -3,6 +3,7 @@ #include "AST/SumNode.h" #include "Error.h" #include "Lexer.h" +#include "Result.h" #include "sapphirepch.h" /* Parser class for the Sapphire compiler. */ @@ -15,9 +16,9 @@ class Parser int advance(); Token* current_token; - std::shared_ptr factor(); - std::shared_ptr expr(); - std::shared_ptr term(); + Result factor(); + Result expr(); + Result term(); public: /* Construct a new Parser with the given TokenStream. */ diff --git a/src/Result.h b/src/Result.h index 21f4204..5aa8c1e 100644 --- a/src/Result.h +++ b/src/Result.h @@ -9,27 +9,30 @@ class Result public: Result() = default; bool is_error() const { return m_is_error; } - void ethrow(); - std::shared_ptr get() { return m_result; } + void ethrow() { std::exit(1); } + std::shared_ptr get() + { + return m_result; + } protected: - std::shared_ptr m_token; + Token* m_token; std::shared_ptr m_result; bool m_is_error; std::string m_error; - Result(T* result, Token* token) : m_result(result), m_token(token) {} - Result(const std::string& error, Token* token) : m_error(std::move(error)), m_token(token) {} + Result(T* result, Token* token) : m_result(result), m_token(token), m_is_error(false) {} + Result(const std::string& error, Token* token) : m_error(std::move(error)), m_token(token), m_is_error(true) {} }; template -class Ok : public Result +class Ok final : public Result { public: Ok(T* result, Token* token) : Result(result,token) {} }; template -class Err : public Result +class Err final : public Result { public: Err(const std::string& error, Token* token) : Result(std::move(error),token) {}