Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include "node.hpp"
- #include "lexer.hpp"
- #include <map>
- #include <vector>
- #include <memory>
- // TODO: If we didn't use token_type in the template, we could most likely remove the #include to the lexer.
- class scope_t {
- std::vector<std::map<std::string const, node* const>> scope;
- public:
- std::map<std::string const, node* const>& add_scope() {
- scope.emplace_back();
- return scope.back();
- }
- inline void pop_scope() {
- scope.pop_back();
- }
- inline void add_symbol(node* const symbol) {
- assert(scope.size() != 0);
- //std::cout << "Adding variable: " << symbol->name() << "\n";
- scope.back().emplace( std::make_pair(symbol->name(), symbol) );
- }
- const std::optional<node * const> find(const std::string& symbol) {
- for (auto i = scope.begin(); i != scope.end(); ++i) {
- if (auto fres = i->find(symbol); fres != i->end()) {
- return fres->second;
- }
- }
- return std::nullopt;
- }
- };
- class branch_node: public node {
- protected:
- std::multimap< std::string, node* const> index; // Symbol Table!
- std::vector<std::unique_ptr<node>> children;
- std::vector<std::string> semantic_errors;
- // --- Symbol Table Functions ---
- inline void insert(std::vector<token> const& input);
- inline node& insert(std::vector<token> const& input, std::string const& symbol_name);
- inline void insert(std::unique_ptr<node>&& input);
- inline node& insert(std::unique_ptr<node>&& input, std::string const& symbol_name);
- // --- Parsing DSL ---
- template<token_type T> // From token_type
- inline void match(lexer& tokens, std::string const& symbol_name) {
- tokens.peek_for(T);
- insert( tokens.advance(), symbol_name );
- }/*
- template<token_type T> // From token_type
- void match(lexer& tokens, std::vector<token>& symbol_ref) {
- tokens.peek_for(T);
- symbol_ref = tokens.advance();
- return;
- }*/
- template<token_type T> // From token_type
- inline void match(lexer& input) {
- input.peek_for(T);
- insert( input.advance() );
- }
- template<typename T> // Consume node using class constructor
- inline void match(lexer& input, std::string const& symbol_name = "") {
- insert( std::make_unique<T>(input) , symbol_name );
- }
- using factory = std::unique_ptr<node>(*)(lexer&, int);
- template<factory F> // TODO: THIS NEEDS VARGS.
- inline void match(lexer& tokens, std::string const& rolename = "", int min_bp = 0) {
- insert(F(tokens, min_bp), rolename);
- }
- // TODO: Create a "Create Error Node" function instead.
- inline void reset() {
- children.clear();
- index.clear();
- }
- public:
- inline void add_error(const std::string& msg) final {
- semantic_errors.push_back(msg);
- }
- // TODO: Code smells?
- std::string value() const override { throw std::runtime_error("Can't get value of a parse node!"); };
- // --- Symbol Table Lookup ---
- std::vector<node*> operator[](std::string const& lookup) const final;
- void check_for_errors(scope_t&) override;
- std::string print() const override;
- int line_number() const override;
- int column() const override;
- int length() const override;
- std::string toTree() const override;
- std::string asHTML() const override;
- };
- class syntax_error_node: public branch_node {
- std::string error_msg;
- int error_offset;
- public:
- syntax_error_node(lexer& input, token_type recovery, std::string const& msg, std::vector<token>::iterator const& saved_pos);
- syntax_error_node(lexer& input, std::vector<token_type> const& recovery, std::string const& msg, std::vector<token>::iterator const& saved_pos);
- std::string print() const final;
- void check_for_errors(scope_t&) final;
- std::string asHTML() const final {
- std::string result = "<span class='syntax_error' title='" + error_msg + "'>";
- for(const auto& c: children) {
- result += c->asHTML();
- }
- result += "</span>";
- return result;
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement