diff --git a/flamingo/grammar/function_declaration.h b/flamingo/grammar/function_declaration.h index 0763ce9..7b46ecc 100644 --- a/flamingo/grammar/function_declaration.h +++ b/flamingo/grammar/function_declaration.h @@ -4,12 +4,95 @@ #pragma once #include "params.h" +#include "var_decl.h" #include #include #include #include #include +static int find_static_members_in_class(flamingo_t* flamingo, TSNode body) { + assert(strcmp(ts_node_type(body), "block") == 0); + + size_t const n = ts_node_named_child_count(body); + + for (size_t i = 0; i < n; i++) { + TSNode const node = ts_node_named_child(body, i); + char const* const type = ts_node_type(node); + + bool const is_var_decl = strcmp(type, "var_decl") == 0; + bool const is_fn_decl = strcmp(type, "function_declaration") == 0; + bool const is_class_decl = strcmp(type, "class_declaration") == 0; + + if (!is_var_decl && !is_fn_decl && !is_class_decl) { + continue; + } + + // Check for static in qualifier list. + + TSNode const qualifiers = ts_node_child_by_field_name(node, "qualifiers", 10); + bool const has_qualifiers = !ts_node_is_null(qualifiers); + + if (!has_qualifiers) { + continue; + } + + assert(strcmp(ts_node_type(qualifiers), "qualifier_list") == 0); + + size_t const qualifier_count = ts_node_child_count(qualifiers); + bool is_static = false; + + for (size_t j = 0; j < qualifier_count; j++) { + TSNode const qualifier = ts_node_child(qualifiers, j); + + size_t const start = ts_node_start_byte(qualifier); + size_t const end = ts_node_end_byte(qualifier); + + char const* const qualifier_name = flamingo->src + start; + size_t const size = end - start; + + if (strncmp(qualifier_name, "static", size) == 0) { + is_static = true; + break; + } + } + + if (!is_static) { + continue; + } + + // Parse static member. + + if (is_fn_decl) { + if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_FUNCTION) < 0) { + return -1; + } + + return 0; + } + + if (is_var_decl) { + if (parse_var_decl(flamingo, node) < 0) { + return -1; + } + + return 0; + } + + if (is_class_decl) { + if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_CLASS) < 0) { + return -1; + } + + return 0; + } + + assert(false); + } + + return 0; +} + static int parse_function_declaration(flamingo_t* flamingo, TSNode node, flamingo_fn_kind_t kind) { size_t const child_count = ts_node_child_count(node); assert(child_count >= 4 || child_count <= 6); @@ -124,6 +207,14 @@ static int parse_function_declaration(flamingo_t* flamingo, TSNode node, flaming memcpy(var->val->fn.body, &body, sizeof body); } + // If class, look for any static members. + + if (kind == FLAMINGO_FN_KIND_CLASS) { + if (find_static_members_in_class(flamingo, body) < 0) { + return -1; + } + } + // Since I want 'flamingo.h' to be usable without importing all of Tree-sitter, 'var->val->fn.body' can't just be a 'TSNode'. // Thus, since only this file knows about the size of 'TSNode', we must dynamically allocate this on the heap.