herb 0.7.5-arm64-darwin → 0.8.3-arm64-darwin
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.
- checksums.yaml +4 -4
- data/Makefile +8 -5
- data/README.md +6 -1
- data/config.yml +26 -6
- data/ext/herb/error_helpers.c +57 -3
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +2 -1
- data/ext/herb/extension.c +11 -25
- data/ext/herb/extension_helpers.c +3 -3
- data/ext/herb/extension_helpers.h +1 -1
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/3.0/herb.bundle +0 -0
- data/lib/herb/3.1/herb.bundle +0 -0
- data/lib/herb/3.2/herb.bundle +0 -0
- data/lib/herb/3.3/herb.bundle +0 -0
- data/lib/herb/3.4/herb.bundle +0 -0
- data/lib/herb/ast/helpers.rb +11 -0
- data/lib/herb/ast/node.rb +15 -6
- data/lib/herb/ast/nodes.rb +609 -392
- data/lib/herb/cli.rb +31 -0
- data/lib/herb/colors.rb +82 -0
- data/lib/herb/engine/compiler.rb +140 -14
- data/lib/herb/engine/debug_visitor.rb +1 -5
- data/lib/herb/engine/error_formatter.rb +13 -5
- data/lib/herb/engine/parser_error_overlay.rb +1 -1
- data/lib/herb/engine.rb +8 -14
- data/lib/herb/errors.rb +166 -56
- data/lib/herb/location.rb +2 -2
- data/lib/herb/project.rb +86 -21
- data/lib/herb/token.rb +14 -2
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/ast/node.rbs +12 -5
- data/sig/herb/ast/nodes.rbs +124 -62
- data/sig/herb/colors.rbs +35 -0
- data/sig/herb/engine/compiler.rbs +23 -1
- data/sig/herb/errors.rbs +74 -20
- data/sig/herb/token.rbs +8 -0
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/serialized_ast_errors.rbs +8 -0
- data/src/analyze.c +591 -204
- data/src/analyze_helpers.c +17 -4
- data/src/analyze_missing_end.c +147 -0
- data/src/analyze_transform.c +196 -0
- data/src/analyzed_ruby.c +23 -2
- data/src/ast_node.c +34 -5
- data/src/ast_nodes.c +179 -179
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +246 -126
- data/src/extract.c +63 -71
- data/src/herb.c +40 -52
- data/src/html_util.c +34 -96
- data/src/include/analyze.h +10 -2
- data/src/include/analyze_helpers.h +3 -0
- data/src/include/analyzed_ruby.h +4 -2
- data/src/include/ast_node.h +4 -2
- data/src/include/ast_nodes.h +67 -66
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +30 -14
- data/src/include/extract.h +3 -4
- data/src/include/herb.h +10 -10
- data/src/include/html_util.h +4 -5
- data/src/include/lexer.h +1 -3
- data/src/include/lexer_peek_helpers.h +14 -14
- data/src/include/lexer_struct.h +3 -2
- data/src/include/macros.h +12 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +25 -15
- data/src/include/position.h +5 -0
- data/src/include/pretty_print.h +38 -28
- data/src/include/prism_helpers.h +5 -1
- data/src/include/token.h +5 -8
- data/src/include/utf8.h +3 -2
- data/src/include/util/hb_arena.h +31 -0
- data/src/include/util/hb_arena_debug.h +8 -0
- data/src/include/util/hb_array.h +33 -0
- data/src/include/util/hb_buffer.h +36 -0
- data/src/include/util/hb_string.h +29 -0
- data/src/include/util/hb_system.h +9 -0
- data/src/include/util.h +3 -14
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +1 -1
- data/src/io.c +7 -4
- data/src/lexer.c +61 -88
- data/src/lexer_peek_helpers.c +35 -37
- data/src/main.c +19 -23
- data/src/parser.c +280 -201
- data/src/parser_helpers.c +46 -40
- data/src/parser_match_tags.c +316 -0
- data/src/position.c +27 -0
- data/src/pretty_print.c +82 -106
- data/src/prism_helpers.c +14 -15
- data/src/token.c +18 -65
- data/src/utf8.c +4 -4
- data/src/util/hb_arena.c +179 -0
- data/src/util/hb_arena_debug.c +237 -0
- data/src/{array.c → util/hb_array.c} +26 -27
- data/src/util/hb_buffer.c +211 -0
- data/src/util/hb_string.c +85 -0
- data/src/util/hb_system.c +30 -0
- data/src/util.c +29 -99
- data/src/visitor.c +54 -54
- data/templates/ext/herb/error_helpers.c.erb +3 -3
- data/templates/ext/herb/error_helpers.h.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +11 -6
- data/templates/java/error_helpers.c.erb +75 -0
- data/templates/java/error_helpers.h.erb +20 -0
- data/templates/java/nodes.c.erb +97 -0
- data/templates/java/nodes.h.erb +23 -0
- data/templates/java/org/herb/ast/Errors.java.erb +121 -0
- data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
- data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
- data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
- data/templates/lib/herb/ast/nodes.rb.erb +28 -16
- data/templates/lib/herb/errors.rb.erb +17 -12
- data/templates/rust/src/ast/nodes.rs.erb +220 -0
- data/templates/rust/src/errors.rs.erb +216 -0
- data/templates/rust/src/nodes.rs.erb +374 -0
- data/templates/src/analyze_missing_end.c.erb +36 -0
- data/templates/src/analyze_transform.c.erb +24 -0
- data/templates/src/ast_nodes.c.erb +14 -14
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +31 -31
- data/templates/src/include/ast_nodes.h.erb +10 -9
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +6 -6
- data/templates/src/parser_match_tags.c.erb +38 -0
- data/templates/src/visitor.c.erb +4 -4
- data/templates/template.rb +22 -3
- data/templates/wasm/error_helpers.cpp.erb +9 -9
- data/templates/wasm/error_helpers.h.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +9 -9
- data/templates/wasm/nodes.h.erb +1 -1
- data/vendor/prism/Rakefile +4 -1
- data/vendor/prism/config.yml +2 -1
- data/vendor/prism/include/prism/ast.h +31 -1
- data/vendor/prism/include/prism/diagnostic.h +1 -0
- data/vendor/prism/include/prism/version.h +3 -3
- data/vendor/prism/src/diagnostic.c +3 -1
- data/vendor/prism/src/prism.c +130 -71
- data/vendor/prism/src/util/pm_string.c +6 -8
- data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
- metadata +35 -20
- data/lib/herb/libherb/array.rb +0 -51
- data/lib/herb/libherb/ast_node.rb +0 -50
- data/lib/herb/libherb/buffer.rb +0 -56
- data/lib/herb/libherb/extract_result.rb +0 -20
- data/lib/herb/libherb/lex_result.rb +0 -32
- data/lib/herb/libherb/libherb.rb +0 -52
- data/lib/herb/libherb/parse_result.rb +0 -20
- data/lib/herb/libherb/token.rb +0 -46
- data/lib/herb/libherb.rb +0 -35
- data/src/buffer.c +0 -241
- data/src/include/array.h +0 -33
- data/src/include/buffer.h +0 -39
- data/src/include/json.h +0 -28
- data/src/include/memory.h +0 -12
- data/src/json.c +0 -205
- data/src/memory.c +0 -53
data/src/extract.c
CHANGED
|
@@ -1,101 +1,89 @@
|
|
|
1
|
-
#include "include/array.h"
|
|
2
|
-
#include "include/buffer.h"
|
|
3
1
|
#include "include/herb.h"
|
|
4
2
|
#include "include/io.h"
|
|
5
3
|
#include "include/lexer.h"
|
|
4
|
+
#include "include/util/hb_array.h"
|
|
5
|
+
#include "include/util/hb_buffer.h"
|
|
6
6
|
|
|
7
7
|
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
8
9
|
|
|
9
|
-
void
|
|
10
|
-
|
|
10
|
+
void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
|
|
11
|
+
hb_array_T* tokens = herb_lex(source);
|
|
11
12
|
bool skip_erb_content = false;
|
|
13
|
+
bool is_comment_tag = false;
|
|
12
14
|
|
|
13
|
-
for (size_t i = 0; i <
|
|
14
|
-
const token_T* token =
|
|
15
|
+
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
16
|
+
const token_T* token = hb_array_get(tokens, i);
|
|
15
17
|
|
|
16
18
|
switch (token->type) {
|
|
17
19
|
case TOKEN_NEWLINE: {
|
|
18
|
-
|
|
20
|
+
hb_buffer_append(output, token->value);
|
|
19
21
|
break;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
case TOKEN_ERB_START: {
|
|
23
|
-
if (strcmp(token->value, "<%#") == 0
|
|
25
|
+
if (strcmp(token->value, "<%#") == 0) {
|
|
24
26
|
skip_erb_content = true;
|
|
27
|
+
is_comment_tag = true;
|
|
28
|
+
} else if (strcmp(token->value, "<%%") == 0 || strcmp(token->value, "<%%=") == 0) {
|
|
29
|
+
skip_erb_content = true;
|
|
30
|
+
is_comment_tag = false;
|
|
31
|
+
} else {
|
|
32
|
+
skip_erb_content = false;
|
|
33
|
+
is_comment_tag = false;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
28
37
|
break;
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
case TOKEN_ERB_CONTENT: {
|
|
32
41
|
if (skip_erb_content == false) {
|
|
33
|
-
|
|
42
|
+
bool is_inline_comment = false;
|
|
43
|
+
|
|
44
|
+
if (!is_comment_tag && token->value != NULL) {
|
|
45
|
+
const char* content = token->value;
|
|
46
|
+
|
|
47
|
+
while (*content == ' ' || *content == '\t') {
|
|
48
|
+
content++;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (*content == '#' && token->location.start.line == token->location.end.line) {
|
|
52
|
+
is_comment_tag = true;
|
|
53
|
+
is_inline_comment = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (is_inline_comment) {
|
|
58
|
+
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
59
|
+
} else {
|
|
60
|
+
hb_buffer_append(output, token->value);
|
|
61
|
+
}
|
|
34
62
|
} else {
|
|
35
|
-
|
|
63
|
+
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
36
64
|
}
|
|
37
65
|
|
|
38
66
|
break;
|
|
39
67
|
}
|
|
40
68
|
|
|
41
69
|
case TOKEN_ERB_END: {
|
|
70
|
+
bool was_comment = is_comment_tag;
|
|
42
71
|
skip_erb_content = false;
|
|
72
|
+
is_comment_tag = false;
|
|
43
73
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
default: {
|
|
50
|
-
buffer_append_whitespace(output, range_length(token->range));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
herb_free_tokens(&tokens);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
void herb_extract_ruby_to_buffer(const char* source, buffer_T* output) {
|
|
59
|
-
array_T* tokens = herb_lex(source);
|
|
60
|
-
bool skip_erb_content = false;
|
|
61
|
-
|
|
62
|
-
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
63
|
-
const token_T* token = array_get(tokens, i);
|
|
64
|
-
|
|
65
|
-
switch (token->type) {
|
|
66
|
-
case TOKEN_NEWLINE: {
|
|
67
|
-
buffer_append(output, token->value);
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
case TOKEN_ERB_START: {
|
|
72
|
-
if (strcmp(token->value, "<%#") == 0 || strcmp(token->value, "<%%") == 0 || strcmp(token->value, "<%%=") == 0) {
|
|
73
|
-
skip_erb_content = true;
|
|
74
|
+
if (was_comment) {
|
|
75
|
+
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
76
|
+
break;
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
case TOKEN_ERB_CONTENT: {
|
|
81
|
-
if (skip_erb_content == false) {
|
|
82
|
-
buffer_append(output, token->value);
|
|
83
|
-
} else {
|
|
84
|
-
buffer_append_whitespace(output, range_length(token->range));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
case TOKEN_ERB_END: {
|
|
91
|
-
skip_erb_content = false;
|
|
92
|
-
|
|
93
|
-
buffer_append_whitespace(output, range_length(token->range));
|
|
79
|
+
hb_buffer_append_char(output, ' ');
|
|
80
|
+
hb_buffer_append_char(output, ';');
|
|
81
|
+
hb_buffer_append_whitespace(output, range_length(token->range) - 2);
|
|
94
82
|
break;
|
|
95
83
|
}
|
|
96
84
|
|
|
97
85
|
default: {
|
|
98
|
-
|
|
86
|
+
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
99
87
|
}
|
|
100
88
|
}
|
|
101
89
|
}
|
|
@@ -103,17 +91,17 @@ void herb_extract_ruby_to_buffer(const char* source, buffer_T* output) {
|
|
|
103
91
|
herb_free_tokens(&tokens);
|
|
104
92
|
}
|
|
105
93
|
|
|
106
|
-
void herb_extract_html_to_buffer(const char* source,
|
|
107
|
-
|
|
94
|
+
void herb_extract_html_to_buffer(const char* source, hb_buffer_T* output) {
|
|
95
|
+
hb_array_T* tokens = herb_lex(source);
|
|
108
96
|
|
|
109
|
-
for (size_t i = 0; i <
|
|
110
|
-
const token_T* token =
|
|
97
|
+
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
98
|
+
const token_T* token = hb_array_get(tokens, i);
|
|
111
99
|
|
|
112
100
|
switch (token->type) {
|
|
113
101
|
case TOKEN_ERB_START:
|
|
114
102
|
case TOKEN_ERB_CONTENT:
|
|
115
|
-
case TOKEN_ERB_END:
|
|
116
|
-
default:
|
|
103
|
+
case TOKEN_ERB_END: hb_buffer_append_whitespace(output, range_length(token->range)); break;
|
|
104
|
+
default: hb_buffer_append(output, token->value);
|
|
117
105
|
}
|
|
118
106
|
}
|
|
119
107
|
|
|
@@ -121,17 +109,21 @@ void herb_extract_html_to_buffer(const char* source, buffer_T* output) {
|
|
|
121
109
|
}
|
|
122
110
|
|
|
123
111
|
char* herb_extract_ruby_with_semicolons(const char* source) {
|
|
124
|
-
|
|
125
|
-
buffer_init(&output);
|
|
112
|
+
if (!source) { return NULL; }
|
|
126
113
|
|
|
127
|
-
|
|
114
|
+
hb_buffer_T output;
|
|
115
|
+
hb_buffer_init(&output, strlen(source));
|
|
116
|
+
|
|
117
|
+
herb_extract_ruby_to_buffer(source, &output);
|
|
128
118
|
|
|
129
119
|
return output.value;
|
|
130
120
|
}
|
|
131
121
|
|
|
132
122
|
char* herb_extract(const char* source, const herb_extract_language_T language) {
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
if (!source) { return NULL; }
|
|
124
|
+
|
|
125
|
+
hb_buffer_T output;
|
|
126
|
+
hb_buffer_init(&output, strlen(source));
|
|
135
127
|
|
|
136
128
|
switch (language) {
|
|
137
129
|
case HERB_EXTRACT_LANGUAGE_RUBY: herb_extract_ruby_to_buffer(source, &output); break;
|
data/src/herb.c
CHANGED
|
@@ -1,103 +1,91 @@
|
|
|
1
1
|
#include "include/herb.h"
|
|
2
|
-
#include "include/array.h"
|
|
3
|
-
#include "include/buffer.h"
|
|
4
2
|
#include "include/io.h"
|
|
5
|
-
#include "include/json.h"
|
|
6
3
|
#include "include/lexer.h"
|
|
7
4
|
#include "include/parser.h"
|
|
8
5
|
#include "include/token.h"
|
|
6
|
+
#include "include/util/hb_array.h"
|
|
7
|
+
#include "include/util/hb_buffer.h"
|
|
9
8
|
#include "include/version.h"
|
|
10
9
|
|
|
11
10
|
#include <prism.h>
|
|
12
11
|
#include <stdlib.h>
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
lexer_T
|
|
13
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex(const char* source) {
|
|
14
|
+
lexer_T lexer = { 0 };
|
|
15
|
+
lexer_init(&lexer, source);
|
|
16
|
+
|
|
16
17
|
token_T* token = NULL;
|
|
17
|
-
|
|
18
|
+
hb_array_T* tokens = hb_array_init(128);
|
|
18
19
|
|
|
19
|
-
while ((token = lexer_next_token(lexer))->type != TOKEN_EOF) {
|
|
20
|
-
|
|
20
|
+
while ((token = lexer_next_token(&lexer))->type != TOKEN_EOF) {
|
|
21
|
+
hb_array_append(tokens, token);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
lexer_free(lexer);
|
|
24
|
+
hb_array_append(tokens, token);
|
|
26
25
|
|
|
27
26
|
return tokens;
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options) {
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
HERB_EXPORTED_FUNCTION AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options) {
|
|
30
|
+
if (!source) { source = ""; }
|
|
31
|
+
|
|
32
|
+
lexer_T lexer = { 0 };
|
|
33
|
+
lexer_init(&lexer, source);
|
|
34
|
+
parser_T parser = { 0 };
|
|
35
|
+
|
|
36
|
+
parser_options_T parser_options = HERB_DEFAULT_PARSER_OPTIONS;
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
if (options != NULL) { parser_options = *options; }
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
herb_parser_init(&parser, &lexer, parser_options);
|
|
41
|
+
|
|
42
|
+
AST_DOCUMENT_NODE_T* document = herb_parser_parse(&parser);
|
|
43
|
+
|
|
44
|
+
herb_parser_deinit(&parser);
|
|
37
45
|
|
|
38
46
|
return document;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex_file(const char* path) {
|
|
42
50
|
char* source = herb_read_file(path);
|
|
43
|
-
|
|
51
|
+
hb_array_T* tokens = herb_lex(source);
|
|
44
52
|
|
|
45
53
|
free(source);
|
|
46
54
|
|
|
47
55
|
return tokens;
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
void herb_lex_to_buffer(const char* source,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
54
|
-
token_T* token = array_get(tokens, i);
|
|
58
|
+
HERB_EXPORTED_FUNCTION void herb_lex_to_buffer(const char* source, hb_buffer_T* output) {
|
|
59
|
+
hb_array_T* tokens = herb_lex(source);
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
free(type);
|
|
61
|
+
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
62
|
+
token_T* token = hb_array_get(tokens, i);
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
herb_free_tokens(&tokens);
|
|
64
|
-
}
|
|
64
|
+
hb_string_T type = token_to_string(token);
|
|
65
|
+
hb_buffer_append_string(output, type);
|
|
66
|
+
free(type.data);
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
array_T* tokens = herb_lex(source);
|
|
68
|
-
|
|
69
|
-
buffer_T json = buffer_new();
|
|
70
|
-
json_start_root_array(&json);
|
|
71
|
-
|
|
72
|
-
for (size_t i = 0; i < array_size(tokens); i++) {
|
|
73
|
-
token_T* token = array_get(tokens, i);
|
|
74
|
-
char* token_json = token_to_json(token);
|
|
75
|
-
json_add_raw_string(&json, token_json);
|
|
76
|
-
free(token_json);
|
|
68
|
+
hb_buffer_append(output, "\n");
|
|
77
69
|
}
|
|
78
70
|
|
|
79
|
-
json_end_array(&json);
|
|
80
|
-
buffer_concat(output, &json);
|
|
81
|
-
|
|
82
|
-
buffer_free(&json);
|
|
83
71
|
herb_free_tokens(&tokens);
|
|
84
72
|
}
|
|
85
73
|
|
|
86
|
-
void herb_free_tokens(
|
|
74
|
+
HERB_EXPORTED_FUNCTION void herb_free_tokens(hb_array_T** tokens) {
|
|
87
75
|
if (!tokens || !*tokens) { return; }
|
|
88
76
|
|
|
89
|
-
for (size_t i = 0; i <
|
|
90
|
-
token_T* token =
|
|
77
|
+
for (size_t i = 0; i < hb_array_size(*tokens); i++) {
|
|
78
|
+
token_T* token = hb_array_get(*tokens, i);
|
|
91
79
|
if (token) { token_free(token); }
|
|
92
80
|
}
|
|
93
81
|
|
|
94
|
-
|
|
82
|
+
hb_array_free(tokens);
|
|
95
83
|
}
|
|
96
84
|
|
|
97
|
-
const char* herb_version(void) {
|
|
85
|
+
HERB_EXPORTED_FUNCTION const char* herb_version(void) {
|
|
98
86
|
return HERB_VERSION;
|
|
99
87
|
}
|
|
100
88
|
|
|
101
|
-
const char* herb_prism_version(void) {
|
|
89
|
+
HERB_EXPORTED_FUNCTION const char* herb_prism_version(void) {
|
|
102
90
|
return PRISM_VERSION;
|
|
103
91
|
}
|
data/src/html_util.c
CHANGED
|
@@ -1,76 +1,31 @@
|
|
|
1
1
|
#include "include/html_util.h"
|
|
2
2
|
#include "include/util.h"
|
|
3
|
+
#include "include/util/hb_buffer.h"
|
|
4
|
+
#include "include/util/hb_string.h"
|
|
3
5
|
|
|
4
6
|
#include <ctype.h>
|
|
5
7
|
#include <stdbool.h>
|
|
6
8
|
#include <stddef.h>
|
|
7
9
|
#include <stdlib.h>
|
|
8
10
|
#include <string.h>
|
|
9
|
-
#include <strings.h>
|
|
10
11
|
|
|
11
12
|
// https://developer.mozilla.org/en-US/docs/Glossary/Void_element
|
|
12
|
-
bool is_void_element(
|
|
13
|
-
if (tag_name
|
|
13
|
+
bool is_void_element(hb_string_T tag_name) {
|
|
14
|
+
if (hb_string_is_empty(tag_name)) { return false; }
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
"area",
|
|
16
|
+
hb_string_T void_tags[14] = {
|
|
17
|
+
hb_string("area"), hb_string("base"), hb_string("br"), hb_string("col"), hb_string("embed"),
|
|
18
|
+
hb_string("hr"), hb_string("img"), hb_string("input"), hb_string("link"), hb_string("meta"),
|
|
19
|
+
hb_string("param"), hb_string("source"), hb_string("track"), hb_string("wbr"),
|
|
17
20
|
};
|
|
18
21
|
|
|
19
|
-
for (size_t i = 0; i <
|
|
20
|
-
if (
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
bool is_html4_void_element(const char* tag_name) {
|
|
27
|
-
if (tag_name == NULL) { return false; }
|
|
28
|
-
|
|
29
|
-
const char* html4_void_tags[] = {
|
|
30
|
-
"basefont", "bgsound", "command", "frame", "image", "keygen",
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
for (size_t i = 0; i < sizeof(html4_void_tags) / sizeof(char*); i++) {
|
|
34
|
-
if (strcasecmp(tag_name, html4_void_tags[i]) == 0) { return true; }
|
|
22
|
+
for (size_t i = 0; i < 14; i++) {
|
|
23
|
+
if (hb_string_equals_case_insensitive(tag_name, void_tags[i])) { return true; }
|
|
35
24
|
}
|
|
36
25
|
|
|
37
26
|
return false;
|
|
38
27
|
}
|
|
39
28
|
|
|
40
|
-
/**
|
|
41
|
-
* @brief Creates an opening HTML tag string like "<tag_name>"
|
|
42
|
-
*
|
|
43
|
-
* @param tag_name The name of the HTML tag to be enclosed in a opening tag
|
|
44
|
-
* @return A newly allocated string containing the opening tag, or NULL if memory allocation fails
|
|
45
|
-
* @note The caller is responsible for freeing the returned string
|
|
46
|
-
*
|
|
47
|
-
* Example:
|
|
48
|
-
* @code
|
|
49
|
-
* char* tag = html_opening_tag_string("div");
|
|
50
|
-
* if (tag) {
|
|
51
|
-
* printf("%s\n", tag); // Prints: <div>
|
|
52
|
-
* free(tag);
|
|
53
|
-
* }
|
|
54
|
-
* @endcode
|
|
55
|
-
*/
|
|
56
|
-
char* html_opening_tag_string(const char* tag_name) {
|
|
57
|
-
if (tag_name == NULL) { return herb_strdup("<>"); }
|
|
58
|
-
|
|
59
|
-
size_t length = strlen(tag_name);
|
|
60
|
-
char* result = (char*) malloc(length + 3); // +3 for '<', '>', and '\0'
|
|
61
|
-
|
|
62
|
-
if (result == NULL) { return NULL; }
|
|
63
|
-
|
|
64
|
-
result[0] = '<';
|
|
65
|
-
|
|
66
|
-
memcpy(result + 1, tag_name, length);
|
|
67
|
-
|
|
68
|
-
result[length + 1] = '>';
|
|
69
|
-
result[length + 2] = '\0';
|
|
70
|
-
|
|
71
|
-
return result;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
29
|
/**
|
|
75
30
|
* @brief Creates a closing HTML tag string like "</tag_name>"
|
|
76
31
|
*
|
|
@@ -80,30 +35,22 @@ char* html_opening_tag_string(const char* tag_name) {
|
|
|
80
35
|
*
|
|
81
36
|
* Example:
|
|
82
37
|
* @code
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* }
|
|
38
|
+
* hb_string_T tag = html_closing_tag_string(hb_string("div"));
|
|
39
|
+
*
|
|
40
|
+
* printf("%.*s\n", tag.length, tag.data); // Prints: </div>
|
|
41
|
+
* free(tag.data);
|
|
88
42
|
* @endcode
|
|
89
43
|
*/
|
|
90
|
-
|
|
91
|
-
|
|
44
|
+
hb_string_T html_closing_tag_string(hb_string_T tag_name) {
|
|
45
|
+
hb_buffer_T buffer;
|
|
46
|
+
hb_buffer_init(&buffer, tag_name.length + 3);
|
|
92
47
|
|
|
93
|
-
|
|
94
|
-
|
|
48
|
+
hb_buffer_append_char(&buffer, '<');
|
|
49
|
+
hb_buffer_append_char(&buffer, '/');
|
|
50
|
+
hb_buffer_append_string(&buffer, tag_name);
|
|
51
|
+
hb_buffer_append_char(&buffer, '>');
|
|
95
52
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
result[0] = '<';
|
|
99
|
-
result[1] = '/';
|
|
100
|
-
|
|
101
|
-
memcpy(result + 2, tag_name, length);
|
|
102
|
-
|
|
103
|
-
result[length + 2] = '>';
|
|
104
|
-
result[length + 3] = '\0';
|
|
105
|
-
|
|
106
|
-
return result;
|
|
53
|
+
return hb_string(buffer.value);
|
|
107
54
|
}
|
|
108
55
|
|
|
109
56
|
/**
|
|
@@ -115,29 +62,20 @@ char* html_closing_tag_string(const char* tag_name) {
|
|
|
115
62
|
*
|
|
116
63
|
* Example:
|
|
117
64
|
* @code
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* free(tag);
|
|
122
|
-
* }
|
|
65
|
+
* hb_string_T tag = html_self_closing_tag_string(hb_string("br"));
|
|
66
|
+
* printf("%.*s\n", tag.length, tag.data); // Prints: <br />
|
|
67
|
+
* free(tag);
|
|
123
68
|
* @endcode
|
|
124
69
|
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
size_t length = strlen(tag_name);
|
|
129
|
-
char* result = (char*) malloc(length + 5); // +5 for '<', ' ', '/', '>', and '\0'
|
|
130
|
-
|
|
131
|
-
if (result == NULL) { return NULL; }
|
|
132
|
-
|
|
133
|
-
result[0] = '<';
|
|
134
|
-
|
|
135
|
-
memcpy(result + 1, tag_name, length);
|
|
70
|
+
hb_string_T html_self_closing_tag_string(hb_string_T tag_name) {
|
|
71
|
+
hb_buffer_T buffer;
|
|
72
|
+
hb_buffer_init(&buffer, tag_name.length + 4);
|
|
136
73
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
74
|
+
hb_buffer_append_char(&buffer, '<');
|
|
75
|
+
hb_buffer_append_string(&buffer, tag_name);
|
|
76
|
+
hb_buffer_append_char(&buffer, ' ');
|
|
77
|
+
hb_buffer_append_char(&buffer, '/');
|
|
78
|
+
hb_buffer_append_char(&buffer, '>');
|
|
141
79
|
|
|
142
|
-
return
|
|
80
|
+
return hb_string(buffer.value);
|
|
143
81
|
}
|
data/src/include/analyze.h
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
#define HERB_ANALYZE_H
|
|
3
3
|
|
|
4
4
|
#include "analyzed_ruby.h"
|
|
5
|
-
#include "array.h"
|
|
6
5
|
#include "ast_nodes.h"
|
|
6
|
+
#include "util/hb_array.h"
|
|
7
7
|
|
|
8
8
|
typedef struct ANALYZE_RUBY_CONTEXT_STRUCT {
|
|
9
9
|
AST_DOCUMENT_NODE_T* document;
|
|
10
10
|
AST_NODE_T* parent;
|
|
11
|
-
|
|
11
|
+
hb_array_T* ruby_context_stack;
|
|
12
12
|
} analyze_ruby_context_T;
|
|
13
13
|
|
|
14
14
|
typedef enum {
|
|
@@ -33,7 +33,15 @@ typedef enum {
|
|
|
33
33
|
CONTROL_TYPE_UNKNOWN
|
|
34
34
|
} control_type_t;
|
|
35
35
|
|
|
36
|
+
typedef struct {
|
|
37
|
+
int loop_depth;
|
|
38
|
+
int rescue_depth;
|
|
39
|
+
} invalid_erb_context_T;
|
|
40
|
+
|
|
36
41
|
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source);
|
|
37
42
|
void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source);
|
|
38
43
|
|
|
44
|
+
hb_array_T* rewrite_node_array(AST_NODE_T* node, hb_array_T* array, analyze_ruby_context_T* context);
|
|
45
|
+
bool transform_erb_nodes(const AST_NODE_T* node, void* data);
|
|
46
|
+
|
|
39
47
|
#endif
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <stdbool.h>
|
|
6
6
|
|
|
7
7
|
#include "analyzed_ruby.h"
|
|
8
|
+
#include "ast_node.h"
|
|
8
9
|
|
|
9
10
|
bool has_if_node(analyzed_ruby_T* analyzed);
|
|
10
11
|
bool has_elsif_node(analyzed_ruby_T* analyzed);
|
|
@@ -46,4 +47,6 @@ bool search_rescue_nodes(analyzed_ruby_T* analyzed);
|
|
|
46
47
|
bool search_ensure_nodes(analyzed_ruby_T* analyzed);
|
|
47
48
|
bool search_yield_nodes(const pm_node_t* node, void* data);
|
|
48
49
|
|
|
50
|
+
void check_erb_node_for_missing_end(const AST_NODE_T* node);
|
|
51
|
+
|
|
49
52
|
#endif
|
data/src/include/analyzed_ruby.h
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#ifndef HERB_ANALYZED_RUBY_H
|
|
2
2
|
#define HERB_ANALYZED_RUBY_H
|
|
3
3
|
|
|
4
|
-
#include "
|
|
4
|
+
#include "util/hb_array.h"
|
|
5
|
+
#include "util/hb_string.h"
|
|
5
6
|
|
|
6
7
|
#include <prism.h>
|
|
7
8
|
|
|
@@ -30,7 +31,8 @@ typedef struct ANALYZED_RUBY_STRUCT {
|
|
|
30
31
|
bool has_yield_node;
|
|
31
32
|
} analyzed_ruby_T;
|
|
32
33
|
|
|
33
|
-
analyzed_ruby_T* init_analyzed_ruby(
|
|
34
|
+
analyzed_ruby_T* init_analyzed_ruby(hb_string_T source);
|
|
34
35
|
void free_analyzed_ruby(analyzed_ruby_T* analyzed);
|
|
36
|
+
const char* erb_keyword_from_analyzed_ruby(const analyzed_ruby_T* analyzed);
|
|
35
37
|
|
|
36
38
|
#endif
|
data/src/include/ast_node.h
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#include "position.h"
|
|
7
7
|
#include "token_struct.h"
|
|
8
8
|
|
|
9
|
-
void ast_node_init(AST_NODE_T* node, ast_node_type_T type, position_T start, position_T end,
|
|
9
|
+
void ast_node_init(AST_NODE_T* node, ast_node_type_T type, position_T start, position_T end, hb_array_T* errors);
|
|
10
10
|
void ast_node_free(AST_NODE_T* node);
|
|
11
11
|
|
|
12
12
|
AST_LITERAL_NODE_T* ast_literal_node_init_from_token(const token_T* token);
|
|
@@ -22,7 +22,7 @@ void ast_node_set_start(AST_NODE_T* node, position_T position);
|
|
|
22
22
|
void ast_node_set_end(AST_NODE_T* node, position_T position);
|
|
23
23
|
|
|
24
24
|
size_t ast_node_errors_count(const AST_NODE_T* node);
|
|
25
|
-
|
|
25
|
+
hb_array_T* ast_node_errors(const AST_NODE_T* node);
|
|
26
26
|
void ast_node_append_error(const AST_NODE_T* node, ERROR_T* error);
|
|
27
27
|
|
|
28
28
|
void ast_node_set_start_from_token(AST_NODE_T* node, const token_T* token);
|
|
@@ -32,4 +32,6 @@ void ast_node_set_positions_from_token(AST_NODE_T* node, const token_T* token);
|
|
|
32
32
|
|
|
33
33
|
bool ast_node_is(const AST_NODE_T* node, ast_node_type_T type);
|
|
34
34
|
|
|
35
|
+
AST_NODE_T* find_erb_content_at_offset(AST_DOCUMENT_NODE_T* document, const char* source, size_t offset);
|
|
36
|
+
|
|
35
37
|
#endif
|