Get rid of the raw pointers in the parser
This commit is contained in:
@ -1,18 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "elna/parser.hpp"
|
||||
#include "elna/source/parser.hpp"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
class TransformVisitor final : public ParserVisitor
|
||||
class TransformVisitor final : public source::ParserVisitor
|
||||
{
|
||||
void visit(Node *node) override;
|
||||
void visit(Definition *definition) override;
|
||||
void visit(BangStatement *statement) override;
|
||||
void visit(Block *block) override;
|
||||
void visit(Expression *expression) override;
|
||||
void visit(Number *number) override;
|
||||
void visit(Variable *variable) override;
|
||||
void visit(BinaryExpression *binaryExpression) override;
|
||||
void visit(source::definition *definition) override;
|
||||
void visit(source::bang_statement *statement) override;
|
||||
void visit(source::block *block) override;
|
||||
void visit(source::integer_literal *number) override;
|
||||
void visit(source::variable *variable) override;
|
||||
void visit(source::binary_expression *binaryExpression) override;
|
||||
};
|
||||
}
|
||||
|
@ -1,115 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace lex
|
||||
{
|
||||
/**
|
||||
* Range over the source text that keeps track of the current position.
|
||||
*/
|
||||
struct source
|
||||
{
|
||||
class const_iterator
|
||||
{
|
||||
std::string::const_iterator m_buffer;
|
||||
elna::source::position m_position;
|
||||
|
||||
const_iterator(std::string::const_iterator buffer,
|
||||
const elna::source::position start_position = elna::source::position());
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = char;
|
||||
using pointer = const value_type *;
|
||||
using reference = const value_type&;
|
||||
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
reference operator*() const noexcept;
|
||||
pointer operator->() const noexcept;
|
||||
const_iterator& operator++();
|
||||
const_iterator& operator++(int);
|
||||
bool operator==(const const_iterator& that) const noexcept;
|
||||
bool operator!=(const const_iterator& that) const noexcept;
|
||||
|
||||
friend source;
|
||||
};
|
||||
|
||||
source(const std::string& buffer);
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
private:
|
||||
const std::string m_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Union type representing a single token.
|
||||
*/
|
||||
struct Token
|
||||
{
|
||||
/**
|
||||
* Token type.
|
||||
*/
|
||||
enum class type : std::uint16_t
|
||||
{
|
||||
number = 0,
|
||||
term_operator = 1,
|
||||
let = 2,
|
||||
identifier = 3,
|
||||
equals = 4,
|
||||
var = 5,
|
||||
semicolon = 6,
|
||||
left_paren = 7,
|
||||
right_paren = 8,
|
||||
bang = 9,
|
||||
dot = 10,
|
||||
comma = 11,
|
||||
factor_operator = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of the token value.
|
||||
*/
|
||||
union Value
|
||||
{
|
||||
std::int32_t number;
|
||||
const char *identifier;
|
||||
};
|
||||
|
||||
Token(type of, elna::source::position position);
|
||||
Token(type of, std::int32_t value, elna::source::position position);
|
||||
Token(type of, const char *value, elna::source::position position);
|
||||
Token(const Token& that);
|
||||
Token(Token&& that);
|
||||
~Token();
|
||||
|
||||
Token& operator=(const Token& that);
|
||||
Token& operator=(Token&& that);
|
||||
|
||||
type of() const noexcept;
|
||||
const char *identifier() const noexcept;
|
||||
std::int32_t number() const noexcept;
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
private:
|
||||
type m_type;
|
||||
Value m_value;
|
||||
elna::source::position m_position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split the source into tokens.
|
||||
*
|
||||
* \param buffer Source text.
|
||||
* \return Tokens or error.
|
||||
*/
|
||||
elna::source::result<std::vector<Token>> lex(const char *buffer);
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <elna/lexer.hpp>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
enum class BinaryOperator
|
||||
{
|
||||
sum,
|
||||
subtraction,
|
||||
multiplication,
|
||||
division
|
||||
};
|
||||
|
||||
class Node;
|
||||
class Definition;
|
||||
class BangStatement;
|
||||
class Block;
|
||||
class Expression;
|
||||
class BinaryExpression;
|
||||
class Variable;
|
||||
class Number;
|
||||
|
||||
struct ParserVisitor
|
||||
{
|
||||
virtual void visit(Node *) = 0;
|
||||
virtual void visit(Definition *) = 0;
|
||||
virtual void visit(BangStatement *) = 0;
|
||||
virtual void visit(Block *) = 0;
|
||||
virtual void visit(Expression *) = 0;
|
||||
virtual void visit(BinaryExpression *) = 0;
|
||||
virtual void visit(Variable *) = 0;
|
||||
virtual void visit(Number *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* AST node.
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
virtual void accept(ParserVisitor *) = 0;
|
||||
};
|
||||
|
||||
class Statement : public Node
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant definition.
|
||||
*/
|
||||
class Definition : public Node
|
||||
{
|
||||
public:
|
||||
Number *number;
|
||||
const char *identifier;
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class BangStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *expression;
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Block.
|
||||
*/
|
||||
class Block : public Node
|
||||
{
|
||||
public:
|
||||
Definition** definitions{ nullptr };
|
||||
size_t definitionsLength{ 0 };
|
||||
Statement *statement{ nullptr };
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Expression : public Node
|
||||
{
|
||||
public:
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Number : public Expression
|
||||
{
|
||||
public:
|
||||
std::int32_t value;
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Variable : public Expression
|
||||
{
|
||||
public:
|
||||
const char *identifier;
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class BinaryExpression : public Expression
|
||||
{
|
||||
public:
|
||||
Expression *lhs, *rhs;
|
||||
BinaryOperator _operator;
|
||||
|
||||
BinaryExpression(Expression *lhs, Expression *rhs, unsigned char);
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
};
|
||||
|
||||
Expression *parseFactor(lex::Token **tokens, std::size_t *length);
|
||||
Expression *parseTerm(lex::Token **tokens, std::size_t *length);
|
||||
Expression *parseExpression(lex::Token **tokens, std::size_t *length);
|
||||
Definition *parseDefinition(lex::Token **tokens, std::size_t *length);
|
||||
Statement *parseStatement(lex::Token **tokens, std::size_t *length);
|
||||
Definition **parseDefinitions(lex::Token **tokens, std::size_t *length, std::size_t *resultLength);
|
||||
Block *parseBlock(lex::Token **tokens, std::size_t *length);
|
||||
Block *parse(lex::Token *tokenStream, std::size_t length);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "elna/parser.hpp"
|
||||
#include <unordered_map>
|
||||
#include "elna/source/parser.hpp"
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
@ -141,7 +142,7 @@ namespace elna
|
||||
std::uint32_t instruction{ 0 };
|
||||
};
|
||||
|
||||
class RiscVVisitor : public ParserVisitor
|
||||
class RiscVVisitor : public source::ParserVisitor
|
||||
{
|
||||
public:
|
||||
Instruction *instructions;
|
||||
@ -149,19 +150,15 @@ namespace elna
|
||||
bool registerInUse{ true };
|
||||
std::uint32_t variableCounter = 1;
|
||||
Reference references[3];
|
||||
std::int32_t *constValues{ nullptr };
|
||||
const char **constNames{ nullptr };
|
||||
std::size_t constCount{ 0 };
|
||||
std::unordered_map<std::string, std::int32_t> constants;
|
||||
|
||||
virtual void visit(Node *) override;
|
||||
virtual void visit(Definition *definition) override;
|
||||
virtual void visit(BangStatement *statement) override;
|
||||
virtual void visit(Block *block) override;
|
||||
virtual void visit(Expression *operand) override;
|
||||
virtual void visit(Variable *variable) override;
|
||||
virtual void visit(Number *number) override;
|
||||
virtual void visit(BinaryExpression *expression) override;
|
||||
virtual void visit(source::definition *definition) override;
|
||||
virtual void visit(source::bang_statement *statement) override;
|
||||
virtual void visit(source::block *block) override;
|
||||
virtual void visit(source::variable *variable) override;
|
||||
virtual void visit(source::integer_literal *number) override;
|
||||
virtual void visit(source::binary_expression *expression) override;
|
||||
};
|
||||
|
||||
Symbol writeNext(Block *ast);
|
||||
Symbol writeNext(source::block *ast);
|
||||
}
|
||||
|
116
include/elna/source/lexer.hpp
Normal file
116
include/elna/source/lexer.hpp
Normal file
@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
/**
|
||||
* Range over the source text that keeps track of the current position.
|
||||
*/
|
||||
class text_iterator
|
||||
{
|
||||
std::string::const_iterator m_buffer;
|
||||
elna::source::position m_position;
|
||||
|
||||
text_iterator(std::string::const_iterator buffer,
|
||||
const elna::source::position start_position = elna::source::position());
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = char;
|
||||
using pointer = const value_type *;
|
||||
using reference = const value_type&;
|
||||
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
reference operator*() const noexcept;
|
||||
pointer operator->() const noexcept;
|
||||
text_iterator& operator++();
|
||||
text_iterator& operator++(int);
|
||||
bool operator==(const text_iterator& that) const noexcept;
|
||||
bool operator!=(const text_iterator& that) const noexcept;
|
||||
|
||||
friend std::pair<text_iterator, text_iterator> text_iterators(const std::string& buffer);
|
||||
};
|
||||
|
||||
std::pair<text_iterator, text_iterator>
|
||||
text_iterators(const std::string &buffer);
|
||||
|
||||
/**
|
||||
* Union type representing a single token.
|
||||
*/
|
||||
struct token
|
||||
{
|
||||
/**
|
||||
* Token type.
|
||||
*/
|
||||
enum class type : std::uint16_t
|
||||
{
|
||||
number = 0,
|
||||
term_operator = 1,
|
||||
let = 2,
|
||||
identifier = 3,
|
||||
equals = 4,
|
||||
var = 5,
|
||||
semicolon = 6,
|
||||
left_paren = 7,
|
||||
right_paren = 8,
|
||||
bang = 9,
|
||||
dot = 10,
|
||||
comma = 11,
|
||||
factor_operator = 12,
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of the token value.
|
||||
*/
|
||||
union value
|
||||
{
|
||||
value();
|
||||
value(std::int32_t value);
|
||||
value(const std::string& value);
|
||||
~value();
|
||||
|
||||
std::nullptr_t nil;
|
||||
std::int32_t number;
|
||||
std::string identifier;
|
||||
};
|
||||
|
||||
token(type of, elna::source::position position);
|
||||
token(type of, std::int32_t value, const elna::source::position position);
|
||||
token(type of, const std::string& value, const elna::source::position position);
|
||||
token(const token& that);
|
||||
token(token&& that);
|
||||
~token();
|
||||
|
||||
token& operator=(const token& that);
|
||||
token& operator=(token&& that);
|
||||
|
||||
type of() const noexcept;
|
||||
const std::string& identifier() const;
|
||||
std::int32_t number() const;
|
||||
const elna::source::position& position() const noexcept;
|
||||
|
||||
private:
|
||||
type m_type;
|
||||
value m_value;
|
||||
elna::source::position m_position;
|
||||
|
||||
bool has_identifier() const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split the source into tokens.
|
||||
*
|
||||
* \param buffer Source text.
|
||||
* \return Tokens or error.
|
||||
*/
|
||||
elna::source::result<std::vector<token>> lex(const std::string& buffer);
|
||||
}
|
||||
}
|
153
include/elna/source/parser.hpp
Normal file
153
include/elna/source/parser.hpp
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <elna/source/lexer.hpp>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
enum class binary_operator
|
||||
{
|
||||
sum,
|
||||
subtraction,
|
||||
multiplication,
|
||||
division
|
||||
};
|
||||
|
||||
class definition;
|
||||
class bang_statement;
|
||||
class block;
|
||||
class binary_expression;
|
||||
class variable;
|
||||
class integer_literal;
|
||||
|
||||
struct ParserVisitor
|
||||
{
|
||||
virtual void visit(definition *) = 0;
|
||||
virtual void visit(bang_statement *) = 0;
|
||||
virtual void visit(block *) = 0;
|
||||
virtual void visit(binary_expression *) = 0;
|
||||
virtual void visit(variable *) = 0;
|
||||
virtual void visit(integer_literal *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* AST node.
|
||||
*/
|
||||
class node
|
||||
{
|
||||
public:
|
||||
virtual void accept(ParserVisitor *) = 0;
|
||||
};
|
||||
|
||||
class statement : public node
|
||||
{
|
||||
};
|
||||
|
||||
class expression : public node
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant definition.
|
||||
*/
|
||||
class definition : public node
|
||||
{
|
||||
std::string m_identifier;
|
||||
std::unique_ptr<integer_literal> m_body;
|
||||
|
||||
public:
|
||||
definition(std::string&& identifier, std::unique_ptr<integer_literal>&& body);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
std::string& identifier() noexcept;
|
||||
integer_literal& body();
|
||||
};
|
||||
|
||||
class bang_statement : public statement
|
||||
{
|
||||
std::unique_ptr<expression> m_body;
|
||||
|
||||
public:
|
||||
bang_statement(std::unique_ptr<expression>&& body);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
expression& body();
|
||||
};
|
||||
|
||||
/**
|
||||
* Block.
|
||||
*/
|
||||
class block : public node
|
||||
{
|
||||
std::unique_ptr<statement> m_body;
|
||||
std::vector<std::unique_ptr<definition>> m_definitions;
|
||||
|
||||
public:
|
||||
block(std::vector<std::unique_ptr<definition>>&& definitions, std::unique_ptr<statement>&& body);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
statement& body();
|
||||
std::vector<std::unique_ptr<definition>>& definitions() noexcept;
|
||||
};
|
||||
|
||||
class integer_literal : public expression
|
||||
{
|
||||
std::int32_t m_number;
|
||||
|
||||
public:
|
||||
integer_literal(const std::int32_t value);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
std::int32_t number() const noexcept;
|
||||
};
|
||||
|
||||
class variable : public expression
|
||||
{
|
||||
std::string m_name;
|
||||
|
||||
public:
|
||||
variable(const std::string& name);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
const std::string& name() const noexcept;
|
||||
};
|
||||
|
||||
class binary_expression : public expression
|
||||
{
|
||||
std::unique_ptr<expression> m_lhs;
|
||||
std::unique_ptr<expression> m_rhs;
|
||||
binary_operator m_operator;
|
||||
|
||||
public:
|
||||
binary_expression(std::unique_ptr<expression>&& lhs,
|
||||
std::unique_ptr<expression>&& rhs, const unsigned char operation);
|
||||
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
expression& lhs();
|
||||
expression& rhs();
|
||||
binary_operator operation() const noexcept;
|
||||
};
|
||||
|
||||
struct parser
|
||||
{
|
||||
parser(const std::vector<token>& tokens);
|
||||
|
||||
std::unique_ptr<block> parse();
|
||||
|
||||
private:
|
||||
std::unique_ptr<expression> parse_factor();
|
||||
std::unique_ptr<expression> parse_term();
|
||||
std::unique_ptr<expression> parse_expression();
|
||||
std::unique_ptr<definition> parse_definition();
|
||||
std::unique_ptr<statement> parse_bang_statement();
|
||||
std::vector<std::unique_ptr<definition>> parse_definitions();
|
||||
std::unique_ptr<block> parse_block();
|
||||
|
||||
std::vector<token>::const_iterator tokens;
|
||||
std::vector<token>::const_iterator end;
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user