1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/**
* @file node.h
*
* Functions related to nodes in the AST.
*/
#ifndef PRISM_NODE_H
#define PRISM_NODE_H
#include "prism/defines.h"
#include "prism/parser.h"
#include "prism/util/pm_buffer.h"
/**
* Loop through each node in the node list, writing each node to the given
* pm_node_t pointer.
*/
#define PM_NODE_LIST_FOREACH(list, index, node) \
for (size_t index = 0; index < (list)->size && ((node) = (list)->nodes[index]); index++)
/**
* Attempts to grow the node list to the next size. If there is already
* capacity in the list, this function does nothing. Otherwise it reallocates
* the list to be twice as large as it was before. If the reallocation fails,
* this function returns false, otherwise it returns true.
*
* @param list The list to grow.
* @return True if the list was successfully grown, false otherwise.
*/
bool pm_node_list_grow(pm_node_list_t *list);
/**
* Append a new node onto the end of the node list.
*
* @param list The list to append to.
* @param node The node to append.
*/
void pm_node_list_append(pm_node_list_t *list, pm_node_t *node);
/**
* Prepend a new node onto the beginning of the node list.
*
* @param list The list to prepend to.
* @param node The node to prepend.
*/
void
pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node);
/**
* Free the internal memory associated with the given node list.
*
* @param list The list to free.
*/
void pm_node_list_free(pm_node_list_t *list);
/**
* Deallocate a node and all of its children.
*
* @param parser The parser that owns the node.
* @param node The node to deallocate.
*/
PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, struct pm_node *node);
/**
* This struct stores the information gathered by the pm_node_memsize function.
* It contains both the memory footprint and additionally metadata about the
* shape of the tree.
*/
typedef struct {
/** The total memory footprint of the node and all of its children. */
size_t memsize;
/** The number of children the node has. */
size_t node_count;
} pm_memsize_t;
/**
* Calculates the memory footprint of a given node.
*
* @param node The node to calculate the memory footprint of.
* @param memsize The memory footprint of the node and all of its children.
*/
PRISM_EXPORTED_FUNCTION void pm_node_memsize(pm_node_t *node, pm_memsize_t *memsize);
/**
* Returns a string representation of the given node type.
*
* @param node_type The node type to convert to a string.
* @return A string representation of the given node type.
*/
PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_type);
/**
* Visit each of the nodes in this subtree using the given visitor callback. The
* callback function will be called for each node in the subtree. If it returns
* false, then that node's children will not be visited. If it returns true,
* then the children will be visited. The data parameter is treated as an opaque
* pointer and is passed to the visitor callback for consumers to use as they
* see fit.
*
* As an example:
*
* ```c
* #include "prism.h"
*
* bool visit(const pm_node_t *node, void *data) {
* size_t *indent = (size_t *) data;
* for (size_t i = 0; i < *indent * 2; i++) putc(' ', stdout);
* printf("%s\n", pm_node_type_to_str(node->type));
*
* size_t next_indent = *indent + 1;
* size_t *next_data = &next_indent;
* pm_visit_child_nodes(node, visit, next_data);
*
* return false;
* }
*
* int main(void) {
* const char *source = "1 + 2; 3 + 4";
* size_t size = strlen(source);
*
* pm_parser_t parser;
* pm_options_t options = { 0 };
* pm_parser_init(&parser, (const uint8_t *) source, size, &options);
*
* size_t indent = 0;
* pm_node_t *node = pm_parse(&parser);
*
* size_t *data = &indent;
* pm_visit_node(node, visit, data);
*
* pm_node_destroy(&parser, node);
* pm_parser_free(&parser);
* return EXIT_SUCCESS;
* }
* ```
*
* @param node The root node to start visiting from.
* @param visitor The callback to call for each node in the subtree.
* @param data An opaque pointer that is passed to the visitor callback.
*/
PRISM_EXPORTED_FUNCTION void pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data);
/**
* Visit the children of the given node with the given callback. This is the
* default behavior for walking the tree that is called from pm_visit_node if
* the callback returns true.
*
* @param node The node to visit the children of.
* @param visitor The callback to call for each child node.
* @param data An opaque pointer that is passed to the visitor callback.
*/
PRISM_EXPORTED_FUNCTION void pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data);
#endif
|