Added Result class for error handling while parsing
This commit is contained in:
parent
582ce26776
commit
77317650f5
@ -1 +1 @@
|
|||||||
1+2+3*5
|
2+2*6+
|
||||||
|
@ -170,6 +170,9 @@ 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 '\377':
|
||||||
|
result.push_back(Token(TT_EOF,loc));
|
||||||
|
return result;
|
||||||
default:
|
default:
|
||||||
Error::throw_error(loc, current_line_text, "unknown character");
|
Error::throw_error(loc, current_line_text, "unknown character");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@ std::shared_ptr<Parser> Parser::new_parser(const TokenStream& tokens)
|
|||||||
std::shared_ptr<ASTNode> Parser::parse()
|
std::shared_ptr<ASTNode> Parser::parse()
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
return expr();
|
auto result = expr();
|
||||||
|
if(result.is_error()) result.ethrow();
|
||||||
|
return result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Parser::advance()
|
int Parser::advance()
|
||||||
@ -28,45 +30,51 @@ int Parser::advance()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<NumberNode> Parser::factor()
|
Result<ExprNode> Parser::factor()
|
||||||
{
|
{
|
||||||
Token token = *current_token;
|
Token& token = *current_token;
|
||||||
|
|
||||||
if (token.tk_type == TT_Number)
|
if (token.tk_type == TT_Number)
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
return std::make_shared<IntegerNode>(token.int_value);
|
return Ok<ExprNode>(new IntegerNode(token.int_value),&token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.tk_type == TT_Float)
|
if (token.tk_type == TT_Float)
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
return std::make_shared<FloatNode>(token.float_value);
|
return Ok<ExprNode>(new FloatNode(token.float_value),&token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Err<ExprNode>("expected a number",&token);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ExprNode> Parser::term()
|
Result<ExprNode> Parser::term()
|
||||||
{
|
{
|
||||||
std::shared_ptr<ExprNode> left = factor();
|
Result<ExprNode> left = factor();
|
||||||
|
if(left.is_error()) return left;
|
||||||
while (current_token->tk_type == TT_Mul || current_token->tk_type == TT_Div)
|
while (current_token->tk_type == TT_Mul || current_token->tk_type == TT_Div)
|
||||||
{
|
{
|
||||||
Token op = *current_token;
|
Token& op = *current_token;
|
||||||
advance();
|
advance();
|
||||||
std::shared_ptr<ExprNode> right = factor();
|
Result<ExprNode> right = factor();
|
||||||
left = std::make_shared<MulNode>(left, right, op.tk_type == TT_Mul ? '*' : '/');
|
if(right.is_error()) return right;
|
||||||
|
left = Ok<ExprNode>(new MulNode(left.get(), right.get(), op.tk_type == TT_Mul ? '*' : '/'), &op);
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ExprNode> Parser::expr()
|
Result<ExprNode> Parser::expr()
|
||||||
{
|
{
|
||||||
std::shared_ptr<ExprNode> left = term();
|
Result<ExprNode> left = term();
|
||||||
|
if(left.is_error()) return left;
|
||||||
while (current_token->tk_type == TT_Plus || current_token->tk_type == TT_Minus)
|
while (current_token->tk_type == TT_Plus || current_token->tk_type == TT_Minus)
|
||||||
{
|
{
|
||||||
Token op = *current_token;
|
Token& op = *current_token;
|
||||||
advance();
|
advance();
|
||||||
std::shared_ptr<ExprNode> right = term();
|
Result<ExprNode> right = term();
|
||||||
left = std::make_shared<SumNode>(left, right, op.tk_type == TT_Plus ? '+' : '-');
|
if(right.is_error()) return right;
|
||||||
|
left = Ok<ExprNode>(new SumNode(left.get(), right.get(), op.tk_type == TT_Plus ? '+' : '-'),&op);
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "AST/SumNode.h"
|
#include "AST/SumNode.h"
|
||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
#include "Lexer.h"
|
#include "Lexer.h"
|
||||||
|
#include "Result.h"
|
||||||
#include "sapphirepch.h"
|
#include "sapphirepch.h"
|
||||||
|
|
||||||
/* Parser class for the Sapphire compiler. */
|
/* Parser class for the Sapphire compiler. */
|
||||||
@ -15,9 +16,9 @@ class Parser
|
|||||||
int advance();
|
int advance();
|
||||||
Token* current_token;
|
Token* current_token;
|
||||||
|
|
||||||
std::shared_ptr<NumberNode> factor();
|
Result<ExprNode> factor();
|
||||||
std::shared_ptr<ExprNode> expr();
|
Result<ExprNode> expr();
|
||||||
std::shared_ptr<ExprNode> term();
|
Result<ExprNode> term();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Construct a new Parser with the given TokenStream. */
|
/* Construct a new Parser with the given TokenStream. */
|
||||||
|
17
src/Result.h
17
src/Result.h
@ -9,27 +9,30 @@ class Result
|
|||||||
public:
|
public:
|
||||||
Result() = default;
|
Result() = default;
|
||||||
bool is_error() const { return m_is_error; }
|
bool is_error() const { return m_is_error; }
|
||||||
void ethrow();
|
void ethrow() { std::exit(1); }
|
||||||
std::shared_ptr<T> get() { return m_result; }
|
std::shared_ptr<T> get()
|
||||||
|
{
|
||||||
|
return m_result;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Token> m_token;
|
Token* m_token;
|
||||||
std::shared_ptr<T> m_result;
|
std::shared_ptr<T> m_result;
|
||||||
bool m_is_error;
|
bool m_is_error;
|
||||||
std::string m_error;
|
std::string m_error;
|
||||||
|
|
||||||
Result(T* result, Token* token) : m_result(result), 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) {}
|
Result(const std::string& error, Token* token) : m_error(std::move(error)), m_token(token), m_is_error(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Ok : public Result<T>
|
class Ok final : public Result<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Ok(T* result, Token* token) : Result<T>(result,token) {}
|
Ok(T* result, Token* token) : Result<T>(result,token) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Err : public Result<T>
|
class Err final : public Result<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Err(const std::string& error, Token* token) : Result<T>(std::move(error),token) {}
|
Err(const std::string& error, Token* token) : Result<T>(std::move(error),token) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user