Implement IO nodes
authorLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Sun, 17 Aug 2025 12:03:28 +0000 (14:03 +0200)
committerLukáš Jiřiště <gymnazium.jiriste@gmail.com>
Sun, 17 Aug 2025 12:03:28 +0000 (14:03 +0200)
Now the IO nodes get transformed from the parse tree into members of
their part.

Libft
grammar
parsing_table
src/c_load.c

diff --git a/Libft b/Libft
index addf28c14063c052d44dce1b6bd0ddc532497163..afad394321e07d175dfb1bd25e339a462cae69bf 160000 (submodule)
--- a/Libft
+++ b/Libft
@@ -1 +1 @@
-Subproject commit addf28c14063c052d44dce1b6bd0ddc532497163
+Subproject commit afad394321e07d175dfb1bd25e339a462cae69bf
diff --git a/grammar b/grammar
index f6da7d50209acb70dd8698da24afba1d2177ba47..e1c97711fb18e238dbbd8eb278e3d56616d64ce9 100644 (file)
--- a/grammar
+++ b/grammar
@@ -38,6 +38,6 @@ PinSpec -> PartName DOT PartPinSpec
 PartPinSpec -> PinName
 PartPinSpec -> BusName PinBusAccess
 Name -> STRING
-SubBusAccess -> LEFT_BRACKET Index SEMICOLON Index RIGHT_BRACKET
+SubBusAccess -> LEFT_BRACKET Index COMMA Index RIGHT_BRACKET
 PinBusAccess -> LEFT_BRACKET Index RIGHT_BRACKET
 Index -> NUMBER
index b5b806cabe1e0eff11aea218a4a10d8696ad9076..726b2d4f431b0af0de0bfa013d9f610ccdfbe25a 100644 (file)
@@ -42,8 +42,8 @@ State;STRING;DOT;NUMBER;STATE;WIDENS;NARROWS;EQUAL;HYPHEN;RIGHT_BRACKET;LEFT_BRA
 40;s6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41;;;;;50;51;;;;
 41;;;;;;;;;;s42;r33;;;;r33;;;;;;;;;;;;;;;;;;;;;;;49;;;
 42;;;s43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44
-43;;;;;;;;;;;;;;;r42;;;;;;;;;;;;;;;;;;;;;;;;;;
-44;;;;;;;;;;;;;;;s45;;;;;;;;;;;;;;;;;;;;;;;;;;
+43;;;;;;;;;;;r42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+44;;;;;;;;;;;s45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 45;;;s46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47
 46;;;;;;;;;r42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 47;;;;;;;;;s48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -75,8 +75,8 @@ State;STRING;DOT;NUMBER;STATE;WIDENS;NARROWS;EQUAL;HYPHEN;RIGHT_BRACKET;LEFT_BRA
 73;;;;;r37;;;r37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 74;;;;;;r33;r33;;;s75;;;;;;;;;;;;;;;;;;;;;;;;;;;;82;;83;
 75;;;s76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77
-76;;;;;;;;;r42;;;;;;r42;;;;;;;;;;;;;;;;;;;;;;;;;;
-77;;;;;;;;;s78;;;;;;s79;;;;;;;;;;;;;;;;;;;;;;;;;;
+76;;;;;;;;;r42;;r42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+77;;;;;;;;;s78;;s79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 78;;;;;r41;;;r41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 79;;;s46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80
 80;;;;;;;;;s81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 3d19937899a4cc28fd5589a1c92842c0a87f2326..d12096726d8835c75ae67f5ef73dd4293c0d8368 100644 (file)
@@ -34,9 +34,9 @@ static const t_token g_defined_tokens[] = {
        {.type = "HYPHEN", .str = "-"},
        {.type = "NARROWS", .str = ">"},
        {.type = "WIDENS", .str = "<"},
-       {.type = "IO_HEAD", .str = "Connectors:"},
-       {.type = "USED_PARTS_HEAD", .str = "Parts:"},
-       {.type = "CONNECTIONS_HEAD", .str = "Connections:"},
+       {.type = "IO_HEAD", .str = "connectors:"},
+       {.type = "USED_PARTS_HEAD", .str = "parts:"},
+       {.type = "CONNECTIONS_HEAD", .str = "connections:"},
        {.type = "NUMBER", .str = NULL},
        {.type = "STATE", .str = NULL},
        {.type = "STRING", .str = NULL},
@@ -220,12 +220,14 @@ int       tokenize(t_vec *tokens, int fd)
 
 typedef struct s_part
 {
-       char    *name;
-       t_vec   nodes;
-       t_vec   mosfets;
-       t_dict  used_parts;
-       t_dict  io_to_node;
-}      t_part;
+       int                                             is_graph_built;
+       char                                    *name;
+       const t_parse_tree_node *parsed_node;
+       t_vec                                   nodes;
+       t_vec                                   mosfets;
+       t_dict                                  used_parts;
+       t_dict                                  io_to_node;
+}                                                      t_part;
 
 int    cmp_parts_void(const void *a_v, const void *b_v)
 {
@@ -336,13 +338,10 @@ t_ft_stat insert_into_catalog(t_catalog *part_catalog, t_part *part)
        return (ft_rbtree_insert(part_catalog, part) != success);
 }
 
-// This works because part name is the first member of a part and there can
-// be no padding before the first member of a struct
-//
-// Thinking about it this is an easy way to use rbtrees as dicts...
 t_part *access_catalog(t_catalog *part_catalog, const char *part_name)
 {
-       return (ft_rbtree_search(part_catalog, &part_name));
+       const t_part    part = {.name = (char *)part_name};
+       return (ft_rbtree_search(part_catalog, (t_part *)&part));
 }
 
 void   free_catalog(t_catalog *part_catalog)
@@ -356,16 +355,16 @@ int       extract_used_names(t_catalog *part_catalog, t_parse_tree_node *part_spec_lis
 {
        int                                             res;
        t_part                                  new_part;
-       const t_parse_tree_node *part_specification;
        const t_parse_tree_node *used_parts;
 
        if (init_new_part(&new_part))
                return (1);
-       part_specification = ft_cget_node_child(part_spec_list, part_spec_list->children.size - 1);
-       new_part.name = ft_strdup(ft_cget_child_deep(part_specification, 4, 0, 0, 0, 0)->token.str);
+       new_part.parsed_node = ft_cget_node_child(part_spec_list, part_spec_list->children.size - 1);
+       new_part.name = ft_strdup(ft_cget_child_deep(new_part.parsed_node, 4, 0, 0, 0, 0)->token.str);
+       new_part.is_graph_built = 0;
        if (!new_part.name)
                return (1);
-       used_parts = ft_cget_child_deep(part_specification, 2, 2, 1);
+       used_parts = ft_cget_child_deep(new_part.parsed_node, 2, 2, 1);
        while (used_parts->children.size == 3)
        {
                res = write_used_part(&new_part, ft_cget_node_child(used_parts, 2));
@@ -415,7 +414,7 @@ static const char                   g_p_name[] = "p";
 static const char                      g_n_name[] = "n";
 
 // IO needs to hold node id instead of pointer
-#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_node *))
+#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_id))
 #define G_COMPLETE_SIZE_OF_FET_PART (sizeof(t_part) + 3 * (sizeof(t_node)) + sizeof(t_id) + sizeof(t_mosfet) + 3 * G_SIZE_OF_IO_NODE)
 
 void   init_fet_nodes(t_part *fet, t_node *nodes, t_id *mosfet)
@@ -463,7 +462,7 @@ void        init_fet_single_io(t_part *fet, t_rbtree_node *io_node, t_node *node, t_ter
        io_node->is_black = 1;
        io_node->left = NULL;
        io_node->right = NULL;
-       ft_memcpy((char *)&io_node->data + sizeof(char *), &node, sizeof(t_node  *));
+       ft_memcpy((char *)&io_node->data + sizeof(char *), &node->id, sizeof(t_id));
        if (terminal == source)
        {
                bind_fet_node(&fet->nodes, mosfet, node, source);
@@ -499,7 +498,7 @@ void        init_fet_io(t_part *fet, t_rbtree_node *io_node_source)
        const int                               gate_drain_cmp = cmp_strings_void(&g_gate_str, &g_drain_str);
        const int                               drain_source_cmp = cmp_strings_void(&g_drain_str, &g_source_str);
 
-       ft_dict_init(&fet->io_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void);
+       ft_dict_init(&fet->io_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void);
        init_fet_single_io(fet, io_node_source, ft_vec_access(&fet->nodes, 0), source);
        init_fet_single_io(fet, io_node_gate, ft_vec_access(&fet->nodes, 1), gate);
        init_fet_single_io(fet, io_node_drain, ft_vec_access(&fet->nodes, 2), drain);
@@ -592,6 +591,114 @@ int       rebind_names_to_parts(t_catalog *parts_catalog)
        return (0);
 }
 
+int    add_pin(t_part *part, const char *name)
+{
+       t_node  *node;
+       char    *name_copy;
+
+       node = add_node(&part->nodes, floating);
+       if (!node)
+               return (1);
+       name_copy = ft_strdup(name);
+       if (!name_copy)
+               return (1);
+       if (ft_dict_insert(&part->io_to_node, &name_copy, &node->id) != success)
+       {
+               free(name_copy);
+               return (1);
+       }
+       return (0);
+}
+
+// For simplicity the index is written in reverse order
+void   fill_index(char *buffer, size_t index)
+{
+       while (index > 0)
+       {
+               *buffer = '0' + index % 10;
+               index /= 10;
+               ++buffer;
+       }
+       *buffer = '\0';
+}
+
+static const char      g_bus_index_separator[] = "-";
+
+int    add_bus(t_part *part, const t_parse_tree_node *bus_spec)
+{
+       const char *const       bus_name = ft_cget_child_deep(bus_spec, 3, 0, 0, 0)->token.str;
+       const char *const       bus_size_str = ft_cget_child_deep(bus_spec, 2, 2, 0)->token.str;
+       size_t                          bus_size;
+       char                            *buffer;
+       size_t                          buffer_size;
+       size_t                          base_size;
+
+       bus_size = (size_t)ft_atoi(bus_size_str);
+       buffer = ft_itoa((int)bus_size);
+       if (!buffer || ft_strcmp(buffer, bus_size_str))
+       {
+               free(buffer);
+               return (1);
+       }
+       free(buffer);
+       base_size = ft_strlen(bus_name) + ft_strlen(g_bus_index_separator);
+       buffer_size = base_size + ft_strlen(bus_size_str) + 1;
+       buffer = malloc(buffer_size);
+       if (!buffer)
+               return (1);
+       while (bus_size > 0)
+       {
+               --bus_size;
+               ft_strlcpy(buffer, bus_name, buffer_size);
+               ft_strlcat(buffer, g_bus_index_separator, buffer_size);
+               fill_index(buffer + base_size, bus_size);
+               if (add_pin(part, buffer))
+               {
+                       free(buffer);
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+int    add_io(t_part *part, const t_parse_tree_node *io_spec)
+{
+       if (io_spec->children.size == 1)
+               return (add_pin(part, ft_cget_child_deep(io_spec, 3, 0, 0, 0)->token.str));
+       return (add_bus(part, io_spec));
+}
+
+int    prepare_io(t_part *part)
+{
+       const t_parse_tree_node *io_list;
+
+       io_list = ft_cget_child_deep(part->parsed_node, 2, 1, 1);
+       while (io_list->children.size == 3)
+       {
+               if (add_io(part, ft_cget_node_child(io_list, 2)))
+                       return (1);
+               io_list = ft_cget_node_child(io_list, 0);
+       }
+       return (add_io(part, ft_cget_node_child(io_list, 0)));
+}
+
+int    build_part_graph(t_part *part)
+{
+       if (prepare_io(part))
+               return (1);
+       return (0);
+}
+
+int    build_main_graph(t_catalog *part_catalog)
+{
+       t_part                          *main_part;
+
+       main_part = access_catalog(part_catalog, "main");
+       if (!main_part)
+               return (1);
+       return (build_part_graph(main_part));
+}
+
 int    construct_new_graph(t_parse_tree_node *parse_tree, __attribute__((unused)) t_vec *nodes, __attribute__((unused)) t_vec *mosfets)
 {
        t_catalog       part_catalog;
@@ -599,7 +706,7 @@ int construct_new_graph(t_parse_tree_node *parse_tree, __attribute__((unused)) t
        init_catalog(&part_catalog);
        extract_used_names(&part_catalog, parse_tree);
        rebind_names_to_parts(&part_catalog);
-       //build_graphs(&part_catalog, parse_tree);
+       build_main_graph(&part_catalog);
        //transfer_main(&part_catalog, nodes, mosfets);
        free_catalog(&part_catalog);
        return (0);