@herb-tools/node 0.1.0 → 0.2.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.
- package/CHANGELOG.md +8 -0
- package/dist/herb-node.esm.js +1 -1
- package/extension/extension_helpers.cpp +2 -3
- package/extension/herb.cpp +9 -0
- package/extension/libherb/analyze.c +138 -43
- package/extension/libherb/analyze.h +39 -0
- package/extension/libherb/analyze_helpers.c +44 -1
- package/extension/libherb/analyze_helpers.h +49 -0
- package/extension/libherb/analyzed_ruby.c +10 -1
- package/extension/libherb/analyzed_ruby.h +36 -0
- package/extension/libherb/array.h +33 -0
- package/extension/libherb/ast_node.h +35 -0
- package/extension/libherb/ast_nodes.c +103 -1
- package/extension/libherb/ast_nodes.h +335 -0
- package/extension/libherb/ast_pretty_print.c +60 -0
- package/extension/libherb/ast_pretty_print.h +17 -0
- package/extension/libherb/buffer.c +60 -27
- package/extension/libherb/buffer.h +39 -0
- package/extension/libherb/errors.h +125 -0
- package/extension/libherb/extract.c +57 -20
- package/extension/libherb/extract.h +20 -0
- package/extension/libherb/herb.h +32 -0
- package/extension/libherb/html_util.h +13 -0
- package/extension/libherb/include/analyze.h +3 -0
- package/extension/libherb/include/analyze_helpers.h +6 -0
- package/extension/libherb/include/analyzed_ruby.h +3 -0
- package/extension/libherb/include/ast_nodes.h +32 -0
- package/extension/libherb/include/buffer.h +5 -2
- package/extension/libherb/include/lexer_peek_helpers.h +2 -2
- package/extension/libherb/include/macros.h +2 -2
- package/extension/libherb/include/version.h +1 -1
- package/extension/libherb/io.h +9 -0
- package/extension/libherb/json.h +28 -0
- package/extension/libherb/lexer.c +1 -1
- package/extension/libherb/lexer.h +13 -0
- package/extension/libherb/lexer_peek_helpers.h +23 -0
- package/extension/libherb/lexer_struct.h +32 -0
- package/extension/libherb/location.h +25 -0
- package/extension/libherb/macros.h +10 -0
- package/extension/libherb/main.c +1 -1
- package/extension/libherb/memory.h +12 -0
- package/extension/libherb/parser.c +17 -7
- package/extension/libherb/parser.h +22 -0
- package/extension/libherb/parser_helpers.h +33 -0
- package/extension/libherb/position.h +22 -0
- package/extension/libherb/pretty_print.h +53 -0
- package/extension/libherb/prism_helpers.h +18 -0
- package/extension/libherb/range.h +23 -0
- package/extension/libherb/ruby_parser.h +6 -0
- package/extension/libherb/token.c +1 -1
- package/extension/libherb/token.h +25 -0
- package/extension/libherb/token_matchers.h +21 -0
- package/extension/libherb/token_struct.h +51 -0
- package/extension/libherb/util.c +3 -1
- package/extension/libherb/util.h +25 -0
- package/extension/libherb/version.h +6 -0
- package/extension/libherb/visitor.c +36 -0
- package/extension/libherb/visitor.h +11 -0
- package/extension/nodes.cpp +117 -0
- package/extension/nodes.h +3 -0
- package/package.json +11 -20
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release/templates/src/include/ast_pretty_print.h.erb
|
|
3
|
+
|
|
4
|
+
#ifndef HERB_AST_PRETTY_PRINT_H
|
|
5
|
+
#define HERB_AST_PRETTY_PRINT_H
|
|
6
|
+
|
|
7
|
+
#include "ast_nodes.h"
|
|
8
|
+
#include "buffer.h"
|
|
9
|
+
|
|
10
|
+
void ast_pretty_print_node(
|
|
11
|
+
AST_NODE_T* node,
|
|
12
|
+
size_t indent,
|
|
13
|
+
size_t relative_indent,
|
|
14
|
+
buffer_T* buffer
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
#endif
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
bool buffer_init(buffer_T* buffer) {
|
|
11
11
|
buffer->capacity = 1024;
|
|
12
12
|
buffer->length = 0;
|
|
13
|
-
buffer->value = nullable_safe_malloc(buffer->capacity * sizeof(char));
|
|
13
|
+
buffer->value = nullable_safe_malloc((buffer->capacity + 1) * sizeof(char));
|
|
14
14
|
|
|
15
15
|
if (!buffer->value) {
|
|
16
16
|
fprintf(stderr, "Error: Failed to initialize buffer with capacity of %zu.\n", buffer->capacity);
|
|
@@ -50,32 +50,39 @@ size_t buffer_sizeof(void) {
|
|
|
50
50
|
* or null termination.
|
|
51
51
|
*
|
|
52
52
|
* @param buffer The buffer to increase capacity for
|
|
53
|
-
* @param
|
|
54
|
-
* @return true if capacity
|
|
55
|
-
* false if reallocation failed
|
|
53
|
+
* @param additional_capacity The additional length needed beyond current buffer capacity
|
|
54
|
+
* @return true if capacity was increased, false if reallocation failed
|
|
56
55
|
*/
|
|
57
|
-
bool buffer_increase_capacity(buffer_T* buffer, const size_t
|
|
58
|
-
if (
|
|
56
|
+
bool buffer_increase_capacity(buffer_T* buffer, const size_t additional_capacity) {
|
|
57
|
+
if (additional_capacity + 1 >= SIZE_MAX) {
|
|
59
58
|
fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
|
|
60
|
-
|
|
59
|
+
exit(1);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
const size_t
|
|
64
|
-
|
|
65
|
-
if (buffer->capacity >= required_capacity) { return true; }
|
|
62
|
+
const size_t new_capacity = buffer->capacity + additional_capacity;
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
new_capacity = required_capacity + 1024;
|
|
64
|
+
return buffer_resize(buffer, new_capacity);
|
|
65
|
+
}
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Resizes the capacity of the buffer to the specified new capacity.
|
|
69
|
+
*
|
|
70
|
+
* @param buffer The buffer to resize
|
|
71
|
+
* @param new_capacity The new capacity to resize the buffer to
|
|
72
|
+
* @return true if capacity was resized, false if reallocation failed
|
|
73
|
+
*/
|
|
74
|
+
bool buffer_resize(buffer_T* buffer, const size_t new_capacity) {
|
|
75
|
+
if (new_capacity + 1 >= SIZE_MAX) {
|
|
76
|
+
fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
|
|
77
|
+
exit(1);
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
char* new_value =
|
|
80
|
+
char* new_value = nullable_safe_realloc(buffer->value, new_capacity + 1);
|
|
77
81
|
|
|
78
|
-
if (unlikely(new_value == NULL)) {
|
|
82
|
+
if (unlikely(new_value == NULL)) {
|
|
83
|
+
fprintf(stderr, "Error: Failed to resize buffer to %zu.\n", new_capacity);
|
|
84
|
+
exit(1);
|
|
85
|
+
}
|
|
79
86
|
|
|
80
87
|
buffer->value = new_value;
|
|
81
88
|
buffer->capacity = new_capacity;
|
|
@@ -83,6 +90,33 @@ bool buffer_increase_capacity(buffer_T* buffer, const size_t required_length) {
|
|
|
83
90
|
return true;
|
|
84
91
|
}
|
|
85
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Expands the capacity of the buffer by doubling its current capacity.
|
|
95
|
+
* This function is a convenience function that calls buffer_increase_capacity
|
|
96
|
+
* with a factor of 2.
|
|
97
|
+
*
|
|
98
|
+
* @param buffer The buffer to expand capacity for
|
|
99
|
+
* @return true if capacity was increased, false if reallocation failed
|
|
100
|
+
*/
|
|
101
|
+
bool buffer_expand_capacity(buffer_T* buffer) {
|
|
102
|
+
return buffer_resize(buffer, buffer->capacity * 2);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Expands the capacity of the buffer if needed to accommodate additional content.
|
|
107
|
+
* This function is a convenience function that calls buffer_has_capacity and
|
|
108
|
+
* buffer_expand_capacity.
|
|
109
|
+
*
|
|
110
|
+
* @param buffer The buffer to expand capacity for
|
|
111
|
+
* @param required_length The additional length needed beyond current buffer capacity
|
|
112
|
+
* @return true if capacity was increased, false if reallocation failed
|
|
113
|
+
*/
|
|
114
|
+
bool buffer_expand_if_needed(buffer_T* buffer, const size_t required_length) {
|
|
115
|
+
if (buffer_has_capacity(buffer, required_length)) { return true; }
|
|
116
|
+
|
|
117
|
+
return buffer_resize(buffer, buffer->capacity + (required_length * 2));
|
|
118
|
+
}
|
|
119
|
+
|
|
86
120
|
/**
|
|
87
121
|
* Appends a null-terminated string to the buffer.
|
|
88
122
|
* @note This function requires that 'text' is a properly null-terminated string.
|
|
@@ -99,7 +133,7 @@ void buffer_append(buffer_T* buffer, const char* text) {
|
|
|
99
133
|
|
|
100
134
|
size_t text_length = strlen(text);
|
|
101
135
|
|
|
102
|
-
if (!
|
|
136
|
+
if (!buffer_expand_if_needed(buffer, text_length)) { return; }
|
|
103
137
|
|
|
104
138
|
memcpy(buffer->value + buffer->length, text, text_length);
|
|
105
139
|
buffer->length += text_length;
|
|
@@ -120,7 +154,7 @@ void buffer_append(buffer_T* buffer, const char* text) {
|
|
|
120
154
|
*/
|
|
121
155
|
void buffer_append_with_length(buffer_T* buffer, const char* text, const size_t length) {
|
|
122
156
|
if (!buffer || !text || length == 0) { return; }
|
|
123
|
-
if (!
|
|
157
|
+
if (!buffer_expand_if_needed(buffer, length)) { return; }
|
|
124
158
|
|
|
125
159
|
memcpy(buffer->value + buffer->length, text, length);
|
|
126
160
|
|
|
@@ -161,7 +195,7 @@ void buffer_prepend(buffer_T* buffer, const char* text) {
|
|
|
161
195
|
|
|
162
196
|
size_t text_length = strlen(text);
|
|
163
197
|
|
|
164
|
-
if (!
|
|
198
|
+
if (!buffer_expand_if_needed(buffer, text_length)) { return; }
|
|
165
199
|
|
|
166
200
|
memmove(buffer->value + text_length, buffer->value, buffer->length + 1);
|
|
167
201
|
memcpy(buffer->value, text, text_length);
|
|
@@ -171,17 +205,16 @@ void buffer_prepend(buffer_T* buffer, const char* text) {
|
|
|
171
205
|
|
|
172
206
|
void buffer_concat(buffer_T* destination, buffer_T* source) {
|
|
173
207
|
if (source->length == 0) { return; }
|
|
174
|
-
if (!
|
|
208
|
+
if (!buffer_expand_if_needed(destination, source->length)) { return; }
|
|
175
209
|
|
|
176
210
|
memcpy(destination->value + destination->length, source->value, source->length);
|
|
211
|
+
|
|
177
212
|
destination->length += source->length;
|
|
178
213
|
destination->value[destination->length] = '\0';
|
|
179
214
|
}
|
|
180
215
|
|
|
181
|
-
bool
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return buffer_increase_capacity(buffer, required_length);
|
|
216
|
+
bool buffer_has_capacity(buffer_T* buffer, const size_t required_length) {
|
|
217
|
+
return (buffer->length + required_length <= buffer->capacity);
|
|
185
218
|
}
|
|
186
219
|
|
|
187
220
|
void buffer_clear(buffer_T* buffer) {
|
|
@@ -192,7 +225,7 @@ void buffer_clear(buffer_T* buffer) {
|
|
|
192
225
|
void buffer_free(buffer_T* buffer) {
|
|
193
226
|
if (!buffer) { return; }
|
|
194
227
|
|
|
195
|
-
free(buffer->value);
|
|
228
|
+
if (buffer->value != NULL) { free(buffer->value); }
|
|
196
229
|
|
|
197
230
|
buffer->value = NULL;
|
|
198
231
|
buffer->length = buffer->capacity = 0;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#ifndef HERB_BUFFER_H
|
|
2
|
+
#define HERB_BUFFER_H
|
|
3
|
+
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
|
|
7
|
+
typedef struct BUFFER_STRUCT {
|
|
8
|
+
char* value;
|
|
9
|
+
size_t length;
|
|
10
|
+
size_t capacity;
|
|
11
|
+
} buffer_T;
|
|
12
|
+
|
|
13
|
+
bool buffer_init(buffer_T* buffer);
|
|
14
|
+
buffer_T buffer_new(void);
|
|
15
|
+
|
|
16
|
+
bool buffer_increase_capacity(buffer_T* buffer, size_t additional_capacity);
|
|
17
|
+
bool buffer_has_capacity(buffer_T* buffer, size_t required_length);
|
|
18
|
+
bool buffer_expand_capacity(buffer_T* buffer);
|
|
19
|
+
bool buffer_expand_if_needed(buffer_T* buffer, size_t required_length);
|
|
20
|
+
bool buffer_resize(buffer_T* buffer, size_t new_capacity);
|
|
21
|
+
|
|
22
|
+
void buffer_append(buffer_T* buffer, const char* text);
|
|
23
|
+
void buffer_append_with_length(buffer_T* buffer, const char* text, size_t length);
|
|
24
|
+
void buffer_append_char(buffer_T* buffer, char character);
|
|
25
|
+
void buffer_append_repeated(buffer_T* buffer, char character, size_t length);
|
|
26
|
+
void buffer_append_whitespace(buffer_T* buffer, size_t length);
|
|
27
|
+
void buffer_prepend(buffer_T* buffer, const char* text);
|
|
28
|
+
void buffer_concat(buffer_T* destination, buffer_T* source);
|
|
29
|
+
|
|
30
|
+
char* buffer_value(const buffer_T* buffer);
|
|
31
|
+
|
|
32
|
+
size_t buffer_length(const buffer_T* buffer);
|
|
33
|
+
size_t buffer_capacity(const buffer_T* buffer);
|
|
34
|
+
size_t buffer_sizeof(void);
|
|
35
|
+
|
|
36
|
+
void buffer_clear(buffer_T* buffer);
|
|
37
|
+
void buffer_free(buffer_T* buffer);
|
|
38
|
+
|
|
39
|
+
#endif
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release/templates/src/include/errors.h.erb
|
|
3
|
+
|
|
4
|
+
#ifndef HERB_ERRORS_H
|
|
5
|
+
#define HERB_ERRORS_H
|
|
6
|
+
|
|
7
|
+
#include "array.h"
|
|
8
|
+
#include "buffer.h"
|
|
9
|
+
#include "errors.h"
|
|
10
|
+
#include "location.h"
|
|
11
|
+
#include "position.h"
|
|
12
|
+
#include "token.h"
|
|
13
|
+
|
|
14
|
+
typedef enum {
|
|
15
|
+
UNEXPECTED_ERROR,
|
|
16
|
+
UNEXPECTED_TOKEN_ERROR,
|
|
17
|
+
MISSING_OPENING_TAG_ERROR,
|
|
18
|
+
MISSING_CLOSING_TAG_ERROR,
|
|
19
|
+
TAG_NAMES_MISMATCH_ERROR,
|
|
20
|
+
QUOTES_MISMATCH_ERROR,
|
|
21
|
+
VOID_ELEMENT_CLOSING_TAG_ERROR,
|
|
22
|
+
UNCLOSED_ELEMENT_ERROR,
|
|
23
|
+
RUBY_PARSE_ERROR,
|
|
24
|
+
} error_type_T;
|
|
25
|
+
|
|
26
|
+
typedef struct ERROR_STRUCT {
|
|
27
|
+
error_type_T type;
|
|
28
|
+
location_T* location;
|
|
29
|
+
char* message;
|
|
30
|
+
} ERROR_T;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
typedef struct {
|
|
34
|
+
ERROR_T base;
|
|
35
|
+
const char* description;
|
|
36
|
+
const char* expected;
|
|
37
|
+
const char* found;
|
|
38
|
+
} UNEXPECTED_ERROR_T;
|
|
39
|
+
|
|
40
|
+
typedef struct {
|
|
41
|
+
ERROR_T base;
|
|
42
|
+
token_type_T expected_type;
|
|
43
|
+
token_T* found;
|
|
44
|
+
} UNEXPECTED_TOKEN_ERROR_T;
|
|
45
|
+
|
|
46
|
+
typedef struct {
|
|
47
|
+
ERROR_T base;
|
|
48
|
+
token_T* closing_tag;
|
|
49
|
+
} MISSING_OPENING_TAG_ERROR_T;
|
|
50
|
+
|
|
51
|
+
typedef struct {
|
|
52
|
+
ERROR_T base;
|
|
53
|
+
token_T* opening_tag;
|
|
54
|
+
} MISSING_CLOSING_TAG_ERROR_T;
|
|
55
|
+
|
|
56
|
+
typedef struct {
|
|
57
|
+
ERROR_T base;
|
|
58
|
+
token_T* opening_tag;
|
|
59
|
+
token_T* closing_tag;
|
|
60
|
+
} TAG_NAMES_MISMATCH_ERROR_T;
|
|
61
|
+
|
|
62
|
+
typedef struct {
|
|
63
|
+
ERROR_T base;
|
|
64
|
+
token_T* opening_quote;
|
|
65
|
+
token_T* closing_quote;
|
|
66
|
+
} QUOTES_MISMATCH_ERROR_T;
|
|
67
|
+
|
|
68
|
+
typedef struct {
|
|
69
|
+
ERROR_T base;
|
|
70
|
+
token_T* tag_name;
|
|
71
|
+
const char* expected;
|
|
72
|
+
const char* found;
|
|
73
|
+
} VOID_ELEMENT_CLOSING_TAG_ERROR_T;
|
|
74
|
+
|
|
75
|
+
typedef struct {
|
|
76
|
+
ERROR_T base;
|
|
77
|
+
token_T* opening_tag;
|
|
78
|
+
} UNCLOSED_ELEMENT_ERROR_T;
|
|
79
|
+
|
|
80
|
+
typedef struct {
|
|
81
|
+
ERROR_T base;
|
|
82
|
+
const char* error_message;
|
|
83
|
+
const char* diagnostic_id;
|
|
84
|
+
const char* level;
|
|
85
|
+
} RUBY_PARSE_ERROR_T;
|
|
86
|
+
|
|
87
|
+
UNEXPECTED_ERROR_T* unexpected_error_init(const char* description, const char* expected, const char* found, position_T* start, position_T* end);
|
|
88
|
+
void append_unexpected_error(const char* description, const char* expected, const char* found, position_T* start, position_T* end, array_T* errors);
|
|
89
|
+
UNEXPECTED_TOKEN_ERROR_T* unexpected_token_error_init(token_type_T expected_type, token_T* found, position_T* start, position_T* end);
|
|
90
|
+
void append_unexpected_token_error(token_type_T expected_type, token_T* found, position_T* start, position_T* end, array_T* errors);
|
|
91
|
+
MISSING_OPENING_TAG_ERROR_T* missing_opening_tag_error_init(token_T* closing_tag, position_T* start, position_T* end);
|
|
92
|
+
void append_missing_opening_tag_error(token_T* closing_tag, position_T* start, position_T* end, array_T* errors);
|
|
93
|
+
MISSING_CLOSING_TAG_ERROR_T* missing_closing_tag_error_init(token_T* opening_tag, position_T* start, position_T* end);
|
|
94
|
+
void append_missing_closing_tag_error(token_T* opening_tag, position_T* start, position_T* end, array_T* errors);
|
|
95
|
+
TAG_NAMES_MISMATCH_ERROR_T* tag_names_mismatch_error_init(token_T* opening_tag, token_T* closing_tag, position_T* start, position_T* end);
|
|
96
|
+
void append_tag_names_mismatch_error(token_T* opening_tag, token_T* closing_tag, position_T* start, position_T* end, array_T* errors);
|
|
97
|
+
QUOTES_MISMATCH_ERROR_T* quotes_mismatch_error_init(token_T* opening_quote, token_T* closing_quote, position_T* start, position_T* end);
|
|
98
|
+
void append_quotes_mismatch_error(token_T* opening_quote, token_T* closing_quote, position_T* start, position_T* end, array_T* errors);
|
|
99
|
+
VOID_ELEMENT_CLOSING_TAG_ERROR_T* void_element_closing_tag_error_init(token_T* tag_name, const char* expected, const char* found, position_T* start, position_T* end);
|
|
100
|
+
void append_void_element_closing_tag_error(token_T* tag_name, const char* expected, const char* found, position_T* start, position_T* end, array_T* errors);
|
|
101
|
+
UNCLOSED_ELEMENT_ERROR_T* unclosed_element_error_init(token_T* opening_tag, position_T* start, position_T* end);
|
|
102
|
+
void append_unclosed_element_error(token_T* opening_tag, position_T* start, position_T* end, array_T* errors);
|
|
103
|
+
RUBY_PARSE_ERROR_T* ruby_parse_error_init(const char* error_message, const char* diagnostic_id, const char* level, position_T* start, position_T* end);
|
|
104
|
+
void append_ruby_parse_error(const char* error_message, const char* diagnostic_id, const char* level, position_T* start, position_T* end, array_T* errors);
|
|
105
|
+
|
|
106
|
+
void error_init(ERROR_T* error, error_type_T type, position_T* start, position_T* end);
|
|
107
|
+
|
|
108
|
+
size_t error_sizeof(void);
|
|
109
|
+
error_type_T error_type(ERROR_T* error);
|
|
110
|
+
|
|
111
|
+
char* error_message(ERROR_T* error);
|
|
112
|
+
|
|
113
|
+
const char* error_type_to_string(ERROR_T* error);
|
|
114
|
+
const char* error_human_type(ERROR_T* error);
|
|
115
|
+
|
|
116
|
+
void error_free(ERROR_T* error);
|
|
117
|
+
|
|
118
|
+
void error_pretty_print(ERROR_T* error, size_t indent, size_t relative_indent, buffer_T* buffer);
|
|
119
|
+
|
|
120
|
+
void error_pretty_print_array(
|
|
121
|
+
const char* name, array_T* array, size_t indent, size_t relative_indent, bool last_property,
|
|
122
|
+
buffer_T* buffer
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
#endif
|
|
@@ -7,25 +7,28 @@
|
|
|
7
7
|
#include <stdlib.h>
|
|
8
8
|
|
|
9
9
|
void herb_extract_ruby_to_buffer_with_semicolons(const char* source, buffer_T* output) {
|
|
10
|
-
|
|
10
|
+
array_T* tokens = herb_lex(source);
|
|
11
|
+
bool skip_erb_content = false;
|
|
11
12
|
|
|
12
13
|
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
13
14
|
const token_T* token = array_get(tokens, i);
|
|
14
15
|
|
|
15
16
|
switch (token->type) {
|
|
16
|
-
case TOKEN_NEWLINE:
|
|
17
|
-
|
|
18
|
-
case TOKEN_ERB_END: {
|
|
19
|
-
buffer_append_char(output, ';');
|
|
20
|
-
buffer_append_whitespace(output, range_length(token->range) - 1);
|
|
17
|
+
case TOKEN_NEWLINE: {
|
|
18
|
+
buffer_append(output, token->value);
|
|
21
19
|
break;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
case TOKEN_ERB_START: {
|
|
25
|
-
if (strcmp(token->value, "<%#") == 0) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (strcmp(token->value, "<%#") == 0) { skip_erb_content = true; }
|
|
24
|
+
|
|
25
|
+
buffer_append_whitespace(output, range_length(token->range));
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
case TOKEN_ERB_CONTENT: {
|
|
30
|
+
if (skip_erb_content == false) {
|
|
31
|
+
buffer_append(output, token->value);
|
|
29
32
|
} else {
|
|
30
33
|
buffer_append_whitespace(output, range_length(token->range));
|
|
31
34
|
}
|
|
@@ -33,25 +36,46 @@ void herb_extract_ruby_to_buffer_with_semicolons(const char* source, buffer_T* o
|
|
|
33
36
|
break;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
case TOKEN_ERB_END: {
|
|
40
|
+
skip_erb_content = false;
|
|
41
|
+
|
|
42
|
+
buffer_append_char(output, ';');
|
|
43
|
+
buffer_append_whitespace(output, range_length(token->range) - 1);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
default: {
|
|
48
|
+
buffer_append_whitespace(output, range_length(token->range));
|
|
49
|
+
}
|
|
37
50
|
}
|
|
38
51
|
}
|
|
52
|
+
|
|
53
|
+
herb_free_tokens(&tokens);
|
|
39
54
|
}
|
|
40
55
|
|
|
41
56
|
void herb_extract_ruby_to_buffer(const char* source, buffer_T* output) {
|
|
42
|
-
|
|
57
|
+
array_T* tokens = herb_lex(source);
|
|
58
|
+
bool skip_erb_content = false;
|
|
43
59
|
|
|
44
60
|
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
45
61
|
const token_T* token = array_get(tokens, i);
|
|
46
62
|
|
|
47
63
|
switch (token->type) {
|
|
48
|
-
case TOKEN_NEWLINE:
|
|
49
|
-
|
|
64
|
+
case TOKEN_NEWLINE: {
|
|
65
|
+
buffer_append(output, token->value);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
case TOKEN_ERB_START: {
|
|
51
|
-
if (strcmp(token->value, "<%#") == 0) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
70
|
+
if (strcmp(token->value, "<%#") == 0) { skip_erb_content = true; }
|
|
71
|
+
|
|
72
|
+
buffer_append_whitespace(output, range_length(token->range));
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case TOKEN_ERB_CONTENT: {
|
|
77
|
+
if (skip_erb_content == false) {
|
|
78
|
+
buffer_append(output, token->value);
|
|
55
79
|
} else {
|
|
56
80
|
buffer_append_whitespace(output, range_length(token->range));
|
|
57
81
|
}
|
|
@@ -59,13 +83,24 @@ void herb_extract_ruby_to_buffer(const char* source, buffer_T* output) {
|
|
|
59
83
|
break;
|
|
60
84
|
}
|
|
61
85
|
|
|
62
|
-
|
|
86
|
+
case TOKEN_ERB_END: {
|
|
87
|
+
skip_erb_content = false;
|
|
88
|
+
|
|
89
|
+
buffer_append_whitespace(output, range_length(token->range));
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
default: {
|
|
94
|
+
buffer_append_whitespace(output, range_length(token->range));
|
|
95
|
+
}
|
|
63
96
|
}
|
|
64
97
|
}
|
|
98
|
+
|
|
99
|
+
herb_free_tokens(&tokens);
|
|
65
100
|
}
|
|
66
101
|
|
|
67
102
|
void herb_extract_html_to_buffer(const char* source, buffer_T* output) {
|
|
68
|
-
|
|
103
|
+
array_T* tokens = herb_lex(source);
|
|
69
104
|
|
|
70
105
|
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
71
106
|
const token_T* token = array_get(tokens, i);
|
|
@@ -77,6 +112,8 @@ void herb_extract_html_to_buffer(const char* source, buffer_T* output) {
|
|
|
77
112
|
default: buffer_append(output, token->value);
|
|
78
113
|
}
|
|
79
114
|
}
|
|
115
|
+
|
|
116
|
+
herb_free_tokens(&tokens);
|
|
80
117
|
}
|
|
81
118
|
|
|
82
119
|
char* herb_extract_ruby_with_semicolons(const char* source) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#ifndef HERB_EXTRACT_H
|
|
2
|
+
#define HERB_EXTRACT_H
|
|
3
|
+
|
|
4
|
+
#include "buffer.h"
|
|
5
|
+
|
|
6
|
+
typedef enum {
|
|
7
|
+
HERB_EXTRACT_LANGUAGE_RUBY,
|
|
8
|
+
HERB_EXTRACT_LANGUAGE_HTML,
|
|
9
|
+
} herb_extract_language_T;
|
|
10
|
+
|
|
11
|
+
void herb_extract_ruby_to_buffer(const char* source, buffer_T* output);
|
|
12
|
+
void herb_extract_html_to_buffer(const char* source, buffer_T* output);
|
|
13
|
+
|
|
14
|
+
char* herb_extract_ruby_with_semicolons(const char* source);
|
|
15
|
+
void herb_extract_ruby_to_buffer_with_semicolons(const char* source, buffer_T* output);
|
|
16
|
+
|
|
17
|
+
char* herb_extract(const char* source, herb_extract_language_T language);
|
|
18
|
+
char* herb_extract_from_file(const char* path, herb_extract_language_T language);
|
|
19
|
+
|
|
20
|
+
#endif
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#ifndef HERB_H
|
|
2
|
+
#define HERB_H
|
|
3
|
+
|
|
4
|
+
#include "array.h"
|
|
5
|
+
#include "ast_node.h"
|
|
6
|
+
#include "buffer.h"
|
|
7
|
+
#include "extract.h"
|
|
8
|
+
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
|
|
11
|
+
#ifdef __cplusplus
|
|
12
|
+
extern "C" {
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
void herb_lex_to_buffer(const char* source, buffer_T* output);
|
|
16
|
+
void herb_lex_json_to_buffer(const char* source, buffer_T* output);
|
|
17
|
+
|
|
18
|
+
array_T* herb_lex(const char* source);
|
|
19
|
+
array_T* herb_lex_file(const char* path);
|
|
20
|
+
|
|
21
|
+
AST_DOCUMENT_NODE_T* herb_parse(const char* source);
|
|
22
|
+
|
|
23
|
+
const char* herb_version(void);
|
|
24
|
+
const char* herb_prism_version(void);
|
|
25
|
+
|
|
26
|
+
void herb_free_tokens(array_T** tokens);
|
|
27
|
+
|
|
28
|
+
#ifdef __cplusplus
|
|
29
|
+
}
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
#endif
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#ifndef HERB_HTML_UTIL_H
|
|
2
|
+
#define HERB_HTML_UTIL_H
|
|
3
|
+
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
|
|
6
|
+
bool is_void_element(const char* tag_name);
|
|
7
|
+
bool is_html4_void_element(const char* tag_name);
|
|
8
|
+
|
|
9
|
+
char* html_opening_tag_string(const char* tag_name);
|
|
10
|
+
char* html_closing_tag_string(const char* tag_name);
|
|
11
|
+
char* html_self_closing_tag_string(const char* tag_name);
|
|
12
|
+
|
|
13
|
+
#endif
|
|
@@ -17,7 +17,9 @@ typedef enum {
|
|
|
17
17
|
CONTROL_TYPE_ELSE,
|
|
18
18
|
CONTROL_TYPE_END,
|
|
19
19
|
CONTROL_TYPE_CASE,
|
|
20
|
+
CONTROL_TYPE_CASE_MATCH,
|
|
20
21
|
CONTROL_TYPE_WHEN,
|
|
22
|
+
CONTROL_TYPE_IN,
|
|
21
23
|
CONTROL_TYPE_BEGIN,
|
|
22
24
|
CONTROL_TYPE_RESCUE,
|
|
23
25
|
CONTROL_TYPE_ENSURE,
|
|
@@ -27,6 +29,7 @@ typedef enum {
|
|
|
27
29
|
CONTROL_TYPE_FOR,
|
|
28
30
|
CONTROL_TYPE_BLOCK,
|
|
29
31
|
CONTROL_TYPE_BLOCK_CLOSE,
|
|
32
|
+
CONTROL_TYPE_YIELD,
|
|
30
33
|
CONTROL_TYPE_UNKNOWN
|
|
31
34
|
} control_type_t;
|
|
32
35
|
|
|
@@ -13,7 +13,9 @@ bool has_end(analyzed_ruby_T* analyzed);
|
|
|
13
13
|
bool has_block_node(analyzed_ruby_T* analyzed);
|
|
14
14
|
bool has_block_closing(analyzed_ruby_T* analyzed);
|
|
15
15
|
bool has_case_node(analyzed_ruby_T* analyzed);
|
|
16
|
+
bool has_case_match_node(analyzed_ruby_T* analyzed);
|
|
16
17
|
bool has_when_node(analyzed_ruby_T* analyzed);
|
|
18
|
+
bool has_in_node(analyzed_ruby_T* analyzed);
|
|
17
19
|
bool has_for_node(analyzed_ruby_T* analyzed);
|
|
18
20
|
bool has_while_node(analyzed_ruby_T* analyzed);
|
|
19
21
|
bool has_until_node(analyzed_ruby_T* analyzed);
|
|
@@ -21,12 +23,14 @@ bool has_begin_node(analyzed_ruby_T* analyzed);
|
|
|
21
23
|
bool has_rescue_node(analyzed_ruby_T* analyzed);
|
|
22
24
|
bool has_ensure_node(analyzed_ruby_T* analyzed);
|
|
23
25
|
bool has_unless_node(analyzed_ruby_T* analyzed);
|
|
26
|
+
bool has_yield_node(analyzed_ruby_T* analyzed);
|
|
24
27
|
|
|
25
28
|
bool has_error_message(analyzed_ruby_T* anlayzed, const char* message);
|
|
26
29
|
|
|
27
30
|
bool search_if_nodes(const pm_node_t* node, void* data);
|
|
28
31
|
bool search_block_nodes(const pm_node_t* node, void* data);
|
|
29
32
|
bool search_case_nodes(const pm_node_t* node, void* data);
|
|
33
|
+
bool search_case_match_nodes(const pm_node_t* node, void* data);
|
|
30
34
|
bool search_while_nodes(const pm_node_t* node, void* data);
|
|
31
35
|
bool search_for_nodes(const pm_node_t* node, void* data);
|
|
32
36
|
bool search_until_nodes(const pm_node_t* node, void* data);
|
|
@@ -37,7 +41,9 @@ bool search_else_nodes(analyzed_ruby_T* analyzed);
|
|
|
37
41
|
bool search_end_nodes(analyzed_ruby_T* analyzed);
|
|
38
42
|
bool search_block_closing_nodes(analyzed_ruby_T* analyzed);
|
|
39
43
|
bool search_when_nodes(analyzed_ruby_T* analyzed);
|
|
44
|
+
bool search_in_nodes(analyzed_ruby_T* analyzed);
|
|
40
45
|
bool search_rescue_nodes(analyzed_ruby_T* analyzed);
|
|
41
46
|
bool search_ensure_nodes(analyzed_ruby_T* analyzed);
|
|
47
|
+
bool search_yield_nodes(analyzed_ruby_T* analyzed);
|
|
42
48
|
|
|
43
49
|
#endif
|
|
@@ -17,7 +17,9 @@ typedef struct ANALYZED_RUBY_STRUCT {
|
|
|
17
17
|
bool has_block_closing;
|
|
18
18
|
bool has_block_node;
|
|
19
19
|
bool has_case_node;
|
|
20
|
+
bool has_case_match_node;
|
|
20
21
|
bool has_when_node;
|
|
22
|
+
bool has_in_node;
|
|
21
23
|
bool has_for_node;
|
|
22
24
|
bool has_while_node;
|
|
23
25
|
bool has_until_node;
|
|
@@ -25,6 +27,7 @@ typedef struct ANALYZED_RUBY_STRUCT {
|
|
|
25
27
|
bool has_rescue_node;
|
|
26
28
|
bool has_ensure_node;
|
|
27
29
|
bool has_unless_node;
|
|
30
|
+
bool has_yield_node;
|
|
28
31
|
} analyzed_ruby_T;
|
|
29
32
|
|
|
30
33
|
analyzed_ruby_T* init_analyzed_ruby(char* source);
|
|
@@ -35,6 +35,7 @@ typedef enum {
|
|
|
35
35
|
AST_ERB_BLOCK_NODE,
|
|
36
36
|
AST_ERB_WHEN_NODE,
|
|
37
37
|
AST_ERB_CASE_NODE,
|
|
38
|
+
AST_ERB_CASE_MATCH_NODE,
|
|
38
39
|
AST_ERB_WHILE_NODE,
|
|
39
40
|
AST_ERB_UNTIL_NODE,
|
|
40
41
|
AST_ERB_FOR_NODE,
|
|
@@ -42,6 +43,8 @@ typedef enum {
|
|
|
42
43
|
AST_ERB_ENSURE_NODE,
|
|
43
44
|
AST_ERB_BEGIN_NODE,
|
|
44
45
|
AST_ERB_UNLESS_NODE,
|
|
46
|
+
AST_ERB_YIELD_NODE,
|
|
47
|
+
AST_ERB_IN_NODE,
|
|
45
48
|
} ast_node_type_T;
|
|
46
49
|
|
|
47
50
|
typedef struct AST_NODE_STRUCT {
|
|
@@ -203,6 +206,17 @@ typedef struct AST_ERB_CASE_NODE_STRUCT {
|
|
|
203
206
|
struct AST_ERB_END_NODE_STRUCT* end_node;
|
|
204
207
|
} AST_ERB_CASE_NODE_T;
|
|
205
208
|
|
|
209
|
+
typedef struct AST_ERB_CASE_MATCH_NODE_STRUCT {
|
|
210
|
+
AST_NODE_T base;
|
|
211
|
+
token_T* tag_opening;
|
|
212
|
+
token_T* content;
|
|
213
|
+
token_T* tag_closing;
|
|
214
|
+
array_T* children;
|
|
215
|
+
array_T* conditions;
|
|
216
|
+
struct AST_ERB_ELSE_NODE_STRUCT* else_clause;
|
|
217
|
+
struct AST_ERB_END_NODE_STRUCT* end_node;
|
|
218
|
+
} AST_ERB_CASE_MATCH_NODE_T;
|
|
219
|
+
|
|
206
220
|
typedef struct AST_ERB_WHILE_NODE_STRUCT {
|
|
207
221
|
AST_NODE_T base;
|
|
208
222
|
token_T* tag_opening;
|
|
@@ -269,6 +283,21 @@ typedef struct AST_ERB_UNLESS_NODE_STRUCT {
|
|
|
269
283
|
struct AST_ERB_END_NODE_STRUCT* end_node;
|
|
270
284
|
} AST_ERB_UNLESS_NODE_T;
|
|
271
285
|
|
|
286
|
+
typedef struct AST_ERB_YIELD_NODE_STRUCT {
|
|
287
|
+
AST_NODE_T base;
|
|
288
|
+
token_T* tag_opening;
|
|
289
|
+
token_T* content;
|
|
290
|
+
token_T* tag_closing;
|
|
291
|
+
} AST_ERB_YIELD_NODE_T;
|
|
292
|
+
|
|
293
|
+
typedef struct AST_ERB_IN_NODE_STRUCT {
|
|
294
|
+
AST_NODE_T base;
|
|
295
|
+
token_T* tag_opening;
|
|
296
|
+
token_T* content;
|
|
297
|
+
token_T* tag_closing;
|
|
298
|
+
array_T* statements;
|
|
299
|
+
} AST_ERB_IN_NODE_T;
|
|
300
|
+
|
|
272
301
|
AST_DOCUMENT_NODE_T* ast_document_node_init(array_T* children, position_T* start_position, position_T* end_position, array_T* errors);
|
|
273
302
|
AST_LITERAL_NODE_T* ast_literal_node_init(const char* content, position_T* start_position, position_T* end_position, array_T* errors);
|
|
274
303
|
AST_HTML_OPEN_TAG_NODE_T* ast_html_open_tag_node_init(token_T* tag_opening, token_T* tag_name, token_T* tag_closing, array_T* children, bool is_void, position_T* start_position, position_T* end_position, array_T* errors);
|
|
@@ -289,6 +318,7 @@ AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content,
|
|
|
289
318
|
AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* body, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
290
319
|
AST_ERB_WHEN_NODE_T* ast_erb_when_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, position_T* start_position, position_T* end_position, array_T* errors);
|
|
291
320
|
AST_ERB_CASE_NODE_T* ast_erb_case_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* children, array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
321
|
+
AST_ERB_CASE_MATCH_NODE_T* ast_erb_case_match_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* children, array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
292
322
|
AST_ERB_WHILE_NODE_T* ast_erb_while_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
293
323
|
AST_ERB_UNTIL_NODE_T* ast_erb_until_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
294
324
|
AST_ERB_FOR_NODE_T* ast_erb_for_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
@@ -296,6 +326,8 @@ AST_ERB_RESCUE_NODE_T* ast_erb_rescue_node_init(token_T* tag_opening, token_T* c
|
|
|
296
326
|
AST_ERB_ENSURE_NODE_T* ast_erb_ensure_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, position_T* start_position, position_T* end_position, array_T* errors);
|
|
297
327
|
AST_ERB_BEGIN_NODE_T* ast_erb_begin_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
298
328
|
AST_ERB_UNLESS_NODE_T* ast_erb_unless_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T* start_position, position_T* end_position, array_T* errors);
|
|
329
|
+
AST_ERB_YIELD_NODE_T* ast_erb_yield_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, position_T* start_position, position_T* end_position, array_T* errors);
|
|
330
|
+
AST_ERB_IN_NODE_T* ast_erb_in_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, array_T* statements, position_T* start_position, position_T* end_position, array_T* errors);
|
|
299
331
|
|
|
300
332
|
const char* ast_node_type_to_string(AST_NODE_T* node);
|
|
301
333
|
const char* ast_node_human_type(AST_NODE_T* node);
|