#pragma once #include #include "utils.hpp" #include "tree_sitter/api.h" extern "C" const TSLanguage *tree_sitter_lang(); namespace parser { class ParseTree { public: class Node { public: Node(const TSNode &node, const std::string *source) : node_(node), source_(source) {} std::string get_type() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_type)"); } return ts_node_type(node_); } std::pair get_start_point() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_start_point)"); } TSPoint point = ts_node_start_point(node_); return {point.row, point.column}; } std::pair get_end_point() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_end_point)"); } TSPoint point = ts_node_end_point(node_); return {point.row, point.column}; } std::string get_as_sexpression() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_as_sexpression)"); } return ts_node_string(node_); } std::string get_value() const { // from source if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_value)"); } size_t start = ts_node_start_byte(node_); size_t end = ts_node_end_byte(node_); return source_->substr(start, end - start); } size_t get_value_length() const { // from source if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (get_value_length)"); } size_t start = ts_node_start_byte(node_); size_t end = ts_node_end_byte(node_); return end - start; } bool is_null() const { return ts_node_is_null(node_); } bool is_named() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (is_named)"); } return ts_node_is_named(node_); } bool is_missing() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (is_missing)"); } return ts_node_is_missing(node_); } bool is_extra() const { // comments, etc. if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (is_extra)"); } return ts_node_is_extra(node_); } bool has_error() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (has_error)"); } return ts_node_has_error(node_); } Node nth_child(size_t n) const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (nth_child)"); } return Node(ts_node_child(node_, n), source_); } size_t child_count() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (child_count)"); } return ts_node_child_count(node_); } Node nth_named_child(size_t n) const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (nth_named_child)"); } return Node(ts_node_named_child(node_, n), source_); } size_t named_child_count() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (named_child_count)"); } return ts_node_named_child_count(node_); } Node child_by_field_name(const std::string &name) const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (child_by_field_name)"); } return Node(ts_node_child_by_field_name(node_, name.c_str(), name.size()), source_); } Node previous_sibling() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (previous_sibling)"); } return Node(ts_node_prev_sibling(node_), source_); } Node previous_named_sibling() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (previous_named_sibling)"); } return Node(ts_node_prev_named_sibling(node_), source_); } Node next_sibling() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (next_sibling)"); } return Node(ts_node_next_sibling(node_), source_); } Node next_named_sibling() const { if (is_null()) { error_handling::handle_general_error( "Null parsing node method called (next_named_sibling)"); } return Node(ts_node_next_named_sibling(node_), source_); } private: TSNode node_; const std::string *source_; }; ParseTree(const std::string &source) : source_(source) { TSParser *parser = ts_parser_new(); ts_parser_set_language(parser, tree_sitter_lang()); tree_ = ts_parser_parse_string(parser, nullptr, source_.c_str(), source_.size()); ts_parser_delete(parser); } ParseTree(const ParseTree &parse_tree) : tree_(ts_tree_copy(parse_tree.tree_)), source_(parse_tree.source_) {} Node get_root() const { return Node(ts_tree_root_node(tree_), &source_); } ~ParseTree() { ts_tree_delete(tree_); } bool is_properly_parsed() { // TODO: find place return !get_root().has_error(); } private: TSTree *tree_; std::string source_; // for token value extraction }; } // namespace parser