herb 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +5 -5
  2. data/{LICENSE → LICENSE.txt} +4 -3
  3. data/Makefile +121 -0
  4. data/README.md +102 -107
  5. data/Rakefile +184 -0
  6. data/exe/herb +5 -0
  7. data/ext/herb/error_helpers.c +302 -0
  8. data/ext/herb/error_helpers.h +15 -0
  9. data/ext/herb/extconf.rb +75 -0
  10. data/ext/herb/extension.c +110 -0
  11. data/ext/herb/extension.h +6 -0
  12. data/ext/herb/extension_helpers.c +117 -0
  13. data/ext/herb/extension_helpers.h +24 -0
  14. data/ext/herb/nodes.c +936 -0
  15. data/ext/herb/nodes.h +12 -0
  16. data/herb.gemspec +49 -0
  17. data/lib/herb/ast/node.rb +61 -0
  18. data/lib/herb/ast/nodes.rb +1542 -0
  19. data/lib/herb/ast.rb +6 -0
  20. data/lib/herb/cli.rb +164 -0
  21. data/lib/herb/errors.rb +352 -0
  22. data/lib/herb/lex_result.rb +20 -0
  23. data/lib/herb/libherb/array.rb +48 -0
  24. data/lib/herb/libherb/ast_node.rb +47 -0
  25. data/lib/herb/libherb/buffer.rb +53 -0
  26. data/lib/herb/libherb/extract_result.rb +17 -0
  27. data/lib/herb/libherb/lex_result.rb +29 -0
  28. data/lib/herb/libherb/libherb.rb +49 -0
  29. data/lib/herb/libherb/parse_result.rb +17 -0
  30. data/lib/herb/libherb/token.rb +43 -0
  31. data/lib/herb/libherb.rb +32 -0
  32. data/lib/herb/location.rb +42 -0
  33. data/lib/herb/parse_result.rb +26 -0
  34. data/lib/herb/position.rb +36 -0
  35. data/lib/herb/project.rb +361 -0
  36. data/lib/herb/range.rb +40 -0
  37. data/lib/herb/result.rb +21 -0
  38. data/lib/herb/token.rb +43 -0
  39. data/lib/herb/token_list.rb +11 -0
  40. data/lib/herb/version.rb +5 -0
  41. data/lib/herb.rb +21 -68
  42. data/src/analyze.c +989 -0
  43. data/src/analyze_helpers.c +241 -0
  44. data/src/analyzed_ruby.c +35 -0
  45. data/src/array.c +137 -0
  46. data/src/ast_node.c +81 -0
  47. data/src/ast_nodes.c +866 -0
  48. data/src/ast_pretty_print.c +588 -0
  49. data/src/buffer.c +199 -0
  50. data/src/errors.c +740 -0
  51. data/src/extract.c +110 -0
  52. data/src/herb.c +103 -0
  53. data/src/html_util.c +143 -0
  54. data/src/include/analyze.h +36 -0
  55. data/src/include/analyze_helpers.h +43 -0
  56. data/src/include/analyzed_ruby.h +33 -0
  57. data/src/include/array.h +33 -0
  58. data/src/include/ast_node.h +35 -0
  59. data/src/include/ast_nodes.h +303 -0
  60. data/src/include/ast_pretty_print.h +17 -0
  61. data/src/include/buffer.h +36 -0
  62. data/src/include/errors.h +125 -0
  63. data/src/include/extract.h +20 -0
  64. data/src/include/herb.h +32 -0
  65. data/src/include/html_util.h +13 -0
  66. data/src/include/io.h +9 -0
  67. data/src/include/json.h +28 -0
  68. data/src/include/lexer.h +13 -0
  69. data/src/include/lexer_peek_helpers.h +23 -0
  70. data/src/include/lexer_struct.h +32 -0
  71. data/src/include/location.h +25 -0
  72. data/src/include/macros.h +10 -0
  73. data/src/include/memory.h +12 -0
  74. data/src/include/parser.h +22 -0
  75. data/src/include/parser_helpers.h +33 -0
  76. data/src/include/position.h +22 -0
  77. data/src/include/pretty_print.h +53 -0
  78. data/src/include/prism_helpers.h +18 -0
  79. data/src/include/range.h +23 -0
  80. data/src/include/ruby_parser.h +6 -0
  81. data/src/include/token.h +25 -0
  82. data/src/include/token_matchers.h +21 -0
  83. data/src/include/token_struct.h +51 -0
  84. data/src/include/util.h +25 -0
  85. data/src/include/version.h +6 -0
  86. data/src/include/visitor.h +11 -0
  87. data/src/io.c +30 -0
  88. data/src/json.c +205 -0
  89. data/src/lexer.c +284 -0
  90. data/src/lexer_peek_helpers.c +59 -0
  91. data/src/location.c +41 -0
  92. data/src/main.c +162 -0
  93. data/src/memory.c +53 -0
  94. data/src/parser.c +704 -0
  95. data/src/parser_helpers.c +161 -0
  96. data/src/position.c +33 -0
  97. data/src/pretty_print.c +242 -0
  98. data/src/prism_helpers.c +50 -0
  99. data/src/range.c +38 -0
  100. data/src/ruby_parser.c +47 -0
  101. data/src/token.c +194 -0
  102. data/src/token_matchers.c +32 -0
  103. data/src/util.c +128 -0
  104. data/src/visitor.c +321 -0
  105. metadata +126 -82
  106. data/test/helper.rb +0 -7
  107. data/test/helpers_test.rb +0 -25
  108. data/test/parsing_test.rb +0 -110
data/src/buffer.c ADDED
@@ -0,0 +1,199 @@
1
+ #include <stdint.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+
5
+ #include "include/buffer.h"
6
+ #include "include/macros.h"
7
+ #include "include/memory.h"
8
+ #include "include/util.h"
9
+
10
+ bool buffer_init(buffer_T* buffer) {
11
+ buffer->capacity = 1024;
12
+ buffer->length = 0;
13
+ buffer->value = nullable_safe_malloc(buffer->capacity * sizeof(char));
14
+
15
+ if (!buffer->value) {
16
+ fprintf(stderr, "Error: Failed to initialize buffer with capacity of %zu.\n", buffer->capacity);
17
+ return false;
18
+ }
19
+
20
+ buffer->value[0] = '\0';
21
+
22
+ return true;
23
+ }
24
+
25
+ buffer_T buffer_new(void) {
26
+ buffer_T buffer;
27
+ buffer_init(&buffer);
28
+ return buffer;
29
+ }
30
+
31
+ char* buffer_value(const buffer_T* buffer) {
32
+ return buffer->value;
33
+ }
34
+
35
+ size_t buffer_length(const buffer_T* buffer) {
36
+ return buffer->length;
37
+ }
38
+
39
+ size_t buffer_capacity(const buffer_T* buffer) {
40
+ return buffer->capacity;
41
+ }
42
+
43
+ size_t buffer_sizeof(void) {
44
+ return sizeof(buffer_T);
45
+ }
46
+
47
+ /**
48
+ * Increases the capacity of the buffer if needed to accommodate additional content.
49
+ * This function only handles memory allocation and does not modify the buffer content
50
+ * or null termination.
51
+ *
52
+ * @param buffer The buffer to increase capacity for
53
+ * @param required_length The additional length needed beyond current buffer length
54
+ * @return true if capacity is sufficient (either already or after reallocation),
55
+ * false if reallocation failed
56
+ */
57
+ bool buffer_increase_capacity(buffer_T* buffer, const size_t required_length) {
58
+ if (SIZE_MAX - buffer->length < required_length) {
59
+ fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
60
+ return false;
61
+ }
62
+
63
+ const size_t required_capacity = buffer->length + required_length;
64
+
65
+ if (buffer->capacity >= required_capacity) { return true; }
66
+
67
+ size_t new_capacity;
68
+ if (required_capacity > SIZE_MAX / 2) {
69
+ new_capacity = required_capacity + 1024;
70
+
71
+ if (new_capacity < required_capacity) { new_capacity = SIZE_MAX; }
72
+ } else {
73
+ new_capacity = required_capacity * 2;
74
+ }
75
+
76
+ char* new_value = safe_realloc(buffer->value, new_capacity);
77
+
78
+ if (unlikely(new_value == NULL)) { return false; }
79
+
80
+ buffer->value = new_value;
81
+ buffer->capacity = new_capacity;
82
+
83
+ return true;
84
+ }
85
+
86
+ /**
87
+ * Appends a null-terminated string to the buffer.
88
+ * @note This function requires that 'text' is a properly null-terminated string.
89
+ * When reading data from files or other non-string sources, ensure the data is
90
+ * null-terminated before calling this function, or use buffer_append_with_length instead.
91
+ *
92
+ * @param buffer The buffer to append to
93
+ * @param text A null-terminated string to append
94
+ * @return void
95
+ */
96
+ void buffer_append(buffer_T* buffer, const char* text) {
97
+ if (!buffer || !text) { return; }
98
+ if (text[0] == '\0') { return; }
99
+
100
+ size_t text_length = strlen(text);
101
+
102
+ if (!buffer_increase_capacity(buffer, text_length)) { return; }
103
+
104
+ memcpy(buffer->value + buffer->length, text, text_length);
105
+ buffer->length += text_length;
106
+ buffer->value[buffer->length] = '\0';
107
+ }
108
+
109
+ /**
110
+ * Appends a string of specified length to the buffer.
111
+ * Unlike buffer_append(), this function does not require the text to be
112
+ * null-terminated as it uses the provided length instead of strlen().
113
+ * This is particularly useful when working with data from files, network
114
+ * buffers, or other non-null-terminated sources.
115
+ *
116
+ * @param buffer The buffer to append to
117
+ * @param text The text to append (doesn't need to be null-terminated)
118
+ * @param length The number of bytes to append from text
119
+ * @return void
120
+ */
121
+ void buffer_append_with_length(buffer_T* buffer, const char* text, const size_t length) {
122
+ if (!buffer || !text || length == 0) { return; }
123
+ if (!buffer_increase_capacity(buffer, length)) { return; }
124
+
125
+ memcpy(buffer->value + buffer->length, text, length);
126
+
127
+ buffer->length += length;
128
+ buffer->value[buffer->length] = '\0';
129
+ }
130
+
131
+ void buffer_append_char(buffer_T* buffer, const char character) {
132
+ static char string[2];
133
+
134
+ string[0] = character;
135
+ string[1] = '\0';
136
+
137
+ buffer_append(buffer, string);
138
+ }
139
+
140
+ void buffer_append_repeated(buffer_T* buffer, const char character, size_t length) {
141
+ if (length == 0) { return; }
142
+
143
+ char* spaces = malloc(length + 1);
144
+ if (!spaces) { return; }
145
+
146
+ memset(spaces, character, length);
147
+ spaces[length] = '\0';
148
+
149
+ buffer_append(buffer, spaces);
150
+
151
+ free(spaces);
152
+ }
153
+
154
+ void buffer_append_whitespace(buffer_T* buffer, const size_t length) {
155
+ buffer_append_repeated(buffer, ' ', length);
156
+ }
157
+
158
+ void buffer_prepend(buffer_T* buffer, const char* text) {
159
+ if (!buffer || !text) { return; }
160
+ if (text[0] == '\0') { return; }
161
+
162
+ size_t text_length = strlen(text);
163
+
164
+ if (!buffer_increase_capacity(buffer, text_length)) { return; }
165
+
166
+ memmove(buffer->value + text_length, buffer->value, buffer->length + 1);
167
+ memcpy(buffer->value, text, text_length);
168
+
169
+ buffer->length += text_length;
170
+ }
171
+
172
+ void buffer_concat(buffer_T* destination, buffer_T* source) {
173
+ if (source->length == 0) { return; }
174
+ if (!buffer_increase_capacity(destination, source->length)) { return; }
175
+
176
+ memcpy(destination->value + destination->length, source->value, source->length);
177
+ destination->length += source->length;
178
+ destination->value[destination->length] = '\0';
179
+ }
180
+
181
+ bool buffer_reserve(buffer_T* buffer, const size_t min_capacity) {
182
+ const size_t required_length = min_capacity - buffer->length;
183
+
184
+ return buffer_increase_capacity(buffer, required_length);
185
+ }
186
+
187
+ void buffer_clear(buffer_T* buffer) {
188
+ buffer->length = 0;
189
+ buffer->value[0] = '\0';
190
+ }
191
+
192
+ void buffer_free(buffer_T* buffer) {
193
+ if (!buffer) { return; }
194
+
195
+ free(buffer->value);
196
+
197
+ buffer->value = NULL;
198
+ buffer->length = buffer->capacity = 0;
199
+ }