herb 0.9.2-arm-linux-gnu → 0.9.4-arm-linux-gnu
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/README.md +2 -0
- data/config.yml +125 -0
- data/ext/herb/error_helpers.c +172 -2
- data/ext/herb/extconf.rb +6 -0
- data/ext/herb/extension.c +16 -2
- data/ext/herb/extension_helpers.c +6 -5
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +89 -3
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/ast/erb_content_node.rb +32 -0
- data/lib/herb/ast/nodes.rb +244 -3
- data/lib/herb/cli.rb +12 -2
- data/lib/herb/engine/compiler.rb +166 -75
- data/lib/herb/engine/validators/security_validator.rb +40 -0
- data/lib/herb/engine.rb +3 -0
- data/lib/herb/errors.rb +268 -0
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +58 -17
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +82 -0
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/erb_content_node.rbs +13 -0
- data/sig/herb/ast/nodes.rbs +98 -2
- data/sig/herb/engine/compiler.rbs +31 -2
- data/sig/herb/engine/validators/security_validator.rbs +4 -0
- data/sig/herb/engine.rbs +3 -0
- data/sig/herb/errors.rbs +122 -0
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +12 -0
- data/sig/serialized_ast_errors.rbs +29 -0
- data/sig/serialized_ast_nodes.rbs +19 -0
- data/src/analyze/action_view/attribute_extraction_helpers.c +420 -91
- data/src/analyze/action_view/image_tag.c +87 -0
- data/src/analyze/action_view/javascript_include_tag.c +22 -12
- data/src/analyze/action_view/registry.c +6 -3
- data/src/analyze/action_view/tag.c +19 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +105 -36
- data/src/analyze/action_view/tag_helpers.c +792 -44
- data/src/analyze/analyze.c +167 -13
- data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
- data/src/analyze/analyzed_ruby.c +1 -1
- data/src/analyze/builders.c +11 -8
- data/src/analyze/conditional_elements.c +6 -7
- data/src/analyze/conditional_open_tags.c +6 -7
- data/src/analyze/control_type.c +4 -2
- data/src/analyze/invalid_structures.c +5 -5
- data/src/analyze/missing_end.c +2 -2
- data/src/analyze/parse_errors.c +47 -6
- data/src/analyze/prism_annotate.c +7 -7
- data/src/analyze/render_nodes.c +6 -26
- data/src/analyze/strict_locals.c +651 -0
- data/src/analyze/transform.c +7 -0
- data/src/{ast_node.c → ast/ast_node.c} +8 -8
- data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
- data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
- data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
- data/src/errors.c +398 -8
- data/src/extract.c +5 -5
- data/src/herb.c +15 -5
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
- data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
- data/src/include/analyze/action_view/tag_helpers.h +4 -3
- data/src/include/analyze/analyze.h +12 -5
- data/src/include/analyze/analyzed_ruby.h +2 -2
- data/src/include/analyze/builders.h +4 -4
- data/src/include/analyze/conditional_elements.h +2 -2
- data/src/include/analyze/conditional_open_tags.h +2 -2
- data/src/include/analyze/control_type.h +1 -1
- data/src/include/analyze/helpers.h +2 -2
- data/src/include/analyze/invalid_structures.h +1 -1
- data/src/include/analyze/prism_annotate.h +2 -2
- data/src/include/analyze/render_nodes.h +1 -1
- data/src/include/analyze/strict_locals.h +11 -0
- data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
- data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
- data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
- data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
- data/src/include/errors.h +65 -7
- data/src/include/extract.h +2 -2
- data/src/include/herb.h +5 -5
- data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
- data/src/include/{lexer.h → lexer/lexer.h} +1 -1
- data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
- data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
- data/src/include/{token.h → lexer/token.h} +3 -3
- data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
- data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
- data/src/include/{util → lib}/hb_foreach.h +1 -1
- data/src/include/{util → lib}/hb_string.h +5 -1
- data/src/include/{location.h → location/location.h} +1 -1
- data/src/include/parser/dot_notation.h +12 -0
- data/src/include/{parser.h → parser/parser.h} +11 -4
- data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
- data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
- data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
- data/src/include/{html_util.h → util/html_util.h} +1 -1
- data/src/include/util/ruby_util.h +9 -0
- data/src/include/{utf8.h → util/utf8.h} +1 -1
- data/src/include/{util.h → util/util.h} +1 -1
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +3 -3
- data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
- data/src/{token.c → lexer/token.c} +8 -8
- data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
- data/src/lexer.c +6 -6
- data/src/{util → lib}/hb_allocator.c +2 -2
- data/src/{util → lib}/hb_arena.c +1 -1
- data/src/{util → lib}/hb_arena_debug.c +2 -2
- data/src/{util → lib}/hb_array.c +2 -2
- data/src/{util → lib}/hb_buffer.c +2 -2
- data/src/{util → lib}/hb_narray.c +1 -1
- data/src/{util → lib}/hb_string.c +2 -2
- data/src/{location.c → location/location.c} +2 -2
- data/src/{position.c → location/position.c} +2 -2
- data/src/{range.c → location/range.c} +1 -1
- data/src/main.c +11 -11
- data/src/parser/dot_notation.c +100 -0
- data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
- data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
- data/src/parser.c +68 -32
- data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
- data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
- data/src/{html_util.c → util/html_util.c} +4 -4
- data/src/{io.c → util/io.c} +3 -3
- data/src/util/ruby_util.c +42 -0
- data/src/{utf8.c → util/utf8.c} +2 -2
- data/src/{util.c → util/util.c} +4 -4
- data/src/visitor.c +35 -3
- data/templates/ext/herb/error_helpers.c.erb +2 -2
- data/templates/ext/herb/nodes.c.erb +1 -1
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/error_helpers.h.erb +2 -2
- data/templates/java/nodes.c.erb +4 -4
- data/templates/java/nodes.h.erb +1 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
- data/templates/lib/herb/visitor.rb.erb +14 -0
- data/templates/src/analyze/missing_end.c.erb +2 -2
- data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
- data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
- data/templates/src/errors.c.erb +8 -8
- data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
- data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
- data/templates/src/include/errors.h.erb +7 -7
- data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
- data/templates/src/visitor.c.erb +3 -3
- data/templates/wasm/error_helpers.cpp.erb +4 -4
- data/templates/wasm/nodes.cpp.erb +5 -5
- metadata +76 -68
- data/src/include/element_source.h +0 -10
- /data/src/include/{util → lib}/hb_allocator.h +0 -0
- /data/src/include/{util → lib}/hb_arena.h +0 -0
- /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
- /data/src/include/{util → lib}/hb_array.h +0 -0
- /data/src/include/{util → lib}/hb_buffer.h +0 -0
- /data/src/include/{util → lib}/hb_narray.h +0 -0
- /data/src/include/{util → lib}/string.h +0 -0
- /data/src/include/{position.h → location/position.h} +0 -0
- /data/src/include/{range.h → location/range.h} +0 -0
- /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
- /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
- /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
- /data/src/include/{io.h → util/io.h} +0 -0
- /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
data/src/include/version.h
CHANGED
data/src/include/visitor.h
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#ifndef HERB_VISITOR_H
|
|
2
2
|
#define HERB_VISITOR_H
|
|
3
3
|
|
|
4
|
-
#include "ast_node.h"
|
|
5
|
-
#include "ast_nodes.h"
|
|
6
|
-
#include "
|
|
4
|
+
#include "ast/ast_node.h"
|
|
5
|
+
#include "ast/ast_nodes.h"
|
|
6
|
+
#include "lib/hb_array.h"
|
|
7
7
|
|
|
8
8
|
void herb_visit_node(const AST_NODE_T* node, bool (*visitor)(const AST_NODE_T*, void*), void* data);
|
|
9
9
|
void herb_visit_child_nodes(const AST_NODE_T* node, bool (*visitor)(const AST_NODE_T* node, void* data), void* data);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
#include "include/token.h"
|
|
2
|
-
#include "include/
|
|
3
|
-
#include "include/
|
|
4
|
-
#include "include/
|
|
5
|
-
#include "include/
|
|
6
|
-
#include "include/
|
|
7
|
-
#include "include/
|
|
8
|
-
#include "include/util/
|
|
1
|
+
#include "../include/lexer/token.h"
|
|
2
|
+
#include "../include/lexer/token_struct.h"
|
|
3
|
+
#include "../include/lib/hb_allocator.h"
|
|
4
|
+
#include "../include/lib/hb_buffer.h"
|
|
5
|
+
#include "../include/lib/hb_string.h"
|
|
6
|
+
#include "../include/location/position.h"
|
|
7
|
+
#include "../include/location/range.h"
|
|
8
|
+
#include "../include/util/util.h"
|
|
9
9
|
|
|
10
10
|
#include <stdarg.h>
|
|
11
11
|
#include <stdbool.h>
|
data/src/lexer.c
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#include "include/lexer_peek_helpers.h"
|
|
1
|
+
#include "include/lexer/lexer_peek_helpers.h"
|
|
2
|
+
#include "include/lexer/token.h"
|
|
3
|
+
#include "include/lib/hb_string.h"
|
|
2
4
|
#include "include/macros.h"
|
|
3
|
-
#include "include/
|
|
4
|
-
#include "include/
|
|
5
|
-
#include "include/util.h"
|
|
6
|
-
#include "include/util/hb_string.h"
|
|
5
|
+
#include "include/util/utf8.h"
|
|
6
|
+
#include "include/util/util.h"
|
|
7
7
|
|
|
8
8
|
#include <ctype.h>
|
|
9
9
|
#include <stdint.h>
|
|
@@ -75,7 +75,7 @@ token_T* lexer_error(lexer_T* lexer, const char* message) {
|
|
|
75
75
|
size_t length = strlen(buffer);
|
|
76
76
|
char* error_message = hb_allocator_strndup(lexer->allocator, buffer, length);
|
|
77
77
|
|
|
78
|
-
return token_init((
|
|
78
|
+
return token_init(hb_string_from_data(error_message, length), TOKEN_ERROR, lexer);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
static void lexer_advance(lexer_T* lexer) {
|
data/src/{util → lib}/hb_arena.c
RENAMED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
#include <stdio.h>
|
|
3
3
|
#include <string.h>
|
|
4
4
|
|
|
5
|
-
#include "../include/
|
|
6
|
-
#include "../include/
|
|
5
|
+
#include "../include/lib/hb_arena.h"
|
|
6
|
+
#include "../include/lib/hb_arena_debug.h"
|
|
7
7
|
|
|
8
8
|
#define ANSI_COLOR_GREEN "\033[32m"
|
|
9
9
|
#define ANSI_COLOR_YELLOW "\033[33m"
|
data/src/{util → lib}/hb_array.c
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#include <stdint.h>
|
|
2
2
|
#include <stdio.h>
|
|
3
3
|
|
|
4
|
+
#include "../include/lib/hb_allocator.h"
|
|
5
|
+
#include "../include/lib/hb_array.h"
|
|
4
6
|
#include "../include/macros.h"
|
|
5
|
-
#include "../include/util/hb_allocator.h"
|
|
6
|
-
#include "../include/util/hb_array.h"
|
|
7
7
|
|
|
8
8
|
size_t hb_array_sizeof(void) {
|
|
9
9
|
return sizeof(hb_array_T);
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
#include <stdio.h>
|
|
3
3
|
#include <string.h>
|
|
4
4
|
|
|
5
|
+
#include "../include/lib/hb_allocator.h"
|
|
6
|
+
#include "../include/lib/hb_buffer.h"
|
|
5
7
|
#include "../include/macros.h"
|
|
6
|
-
#include "../include/util/hb_allocator.h"
|
|
7
|
-
#include "../include/util/hb_buffer.h"
|
|
8
8
|
|
|
9
9
|
static bool hb_buffer_has_capacity(hb_buffer_T* buffer, const size_t required_length) {
|
|
10
10
|
return (buffer->length + required_length <= buffer->capacity);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
#include "include/position.h"
|
|
2
|
-
#include "include/util.h"
|
|
1
|
+
#include "../include/location/position.h"
|
|
2
|
+
#include "../include/util/util.h"
|
|
3
3
|
|
|
4
4
|
position_T position_from_source_with_offset(const char* source, size_t offset) {
|
|
5
5
|
position_T position = { .line = 1, .column = 0 };
|
data/src/main.c
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#define _POSIX_C_SOURCE 199309L // Enables `clock_gettime()`
|
|
2
2
|
|
|
3
|
-
#include "include/ast_node.h"
|
|
4
|
-
#include "include/ast_nodes.h"
|
|
3
|
+
#include "include/ast/ast_node.h"
|
|
4
|
+
#include "include/ast/ast_nodes.h"
|
|
5
5
|
|
|
6
6
|
#ifndef HERB_EXCLUDE_PRETTYPRINT
|
|
7
|
-
# include "include/ast_pretty_print.h"
|
|
7
|
+
# include "include/ast/ast_pretty_print.h"
|
|
8
8
|
#endif
|
|
9
9
|
|
|
10
10
|
#include "include/extract.h"
|
|
11
11
|
#include "include/herb.h"
|
|
12
|
-
#include "include/
|
|
13
|
-
#include "include/
|
|
12
|
+
#include "include/lexer/lex_helpers.h"
|
|
13
|
+
#include "include/lib/hb_allocator.h"
|
|
14
|
+
#include "include/lib/hb_arena.h"
|
|
15
|
+
#include "include/lib/hb_arena_debug.h"
|
|
16
|
+
#include "include/lib/hb_buffer.h"
|
|
17
|
+
#include "include/lib/string.h"
|
|
14
18
|
#include "include/macros.h"
|
|
15
|
-
#include "include/ruby_parser.h"
|
|
16
|
-
#include "include/util/
|
|
17
|
-
#include "include/util/hb_arena.h"
|
|
18
|
-
#include "include/util/hb_arena_debug.h"
|
|
19
|
-
#include "include/util/hb_buffer.h"
|
|
20
|
-
#include "include/util/string.h"
|
|
19
|
+
#include "include/prism/ruby_parser.h"
|
|
20
|
+
#include "include/util/io.h"
|
|
21
21
|
|
|
22
22
|
#include <stdio.h>
|
|
23
23
|
#include <stdlib.h>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#include "../include/parser/dot_notation.h"
|
|
2
|
+
#include "../include/errors.h"
|
|
3
|
+
#include "../include/lexer/lexer.h"
|
|
4
|
+
#include "../include/lexer/token.h"
|
|
5
|
+
#include "../include/parser/parser_helpers.h"
|
|
6
|
+
|
|
7
|
+
#include <ctype.h>
|
|
8
|
+
|
|
9
|
+
static bool token_is_dot(token_T* token) {
|
|
10
|
+
return token->type == TOKEN_CHARACTER && token->value.length == 1 && token->value.data[0] == '.';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static bool current_token_is_dot(parser_T* parser) {
|
|
14
|
+
return token_is_dot(parser->current_token);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static void consume_dot_notation_loop(parser_T* parser, token_T* tag_name, hb_array_T* errors) {
|
|
18
|
+
while (current_token_is_dot(parser)) {
|
|
19
|
+
token_T* dot = parser_advance(parser);
|
|
20
|
+
token_T* segment = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
21
|
+
|
|
22
|
+
if (segment == NULL || segment->value.length == 0) {
|
|
23
|
+
if (segment) { token_free(segment, parser->allocator); }
|
|
24
|
+
token_free(dot, parser->allocator);
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
uint32_t new_length = (uint32_t) (segment->value.data + segment->value.length - tag_name->value.data);
|
|
29
|
+
tag_name->value.length = new_length;
|
|
30
|
+
tag_name->location.end = segment->location.end;
|
|
31
|
+
tag_name->range.to = segment->range.to;
|
|
32
|
+
|
|
33
|
+
token_free(segment, parser->allocator);
|
|
34
|
+
token_free(dot, parser->allocator);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
bool parser_lookahead_is_valid_dot_notation_open_tag(parser_T* parser) {
|
|
39
|
+
lexer_T lexer_copy = *parser->lexer;
|
|
40
|
+
token_T* name = lexer_next_token(&lexer_copy);
|
|
41
|
+
|
|
42
|
+
if (name == NULL || name->type != TOKEN_IDENTIFIER) {
|
|
43
|
+
if (name) { token_free(name, parser->allocator); }
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
bool first_is_upper = name->value.length > 0 && isupper((unsigned char) name->value.data[0]);
|
|
48
|
+
token_free(name, parser->allocator);
|
|
49
|
+
token_T* next = lexer_next_token(&lexer_copy);
|
|
50
|
+
|
|
51
|
+
if (next == NULL) { return true; }
|
|
52
|
+
|
|
53
|
+
bool is_dot = token_is_dot(next);
|
|
54
|
+
token_free(next, parser->allocator);
|
|
55
|
+
|
|
56
|
+
if (!is_dot) { return true; }
|
|
57
|
+
if (!parser->options.dot_notation_tags) { return true; }
|
|
58
|
+
if (!first_is_upper) { return true; }
|
|
59
|
+
|
|
60
|
+
next = lexer_next_token(&lexer_copy);
|
|
61
|
+
|
|
62
|
+
while (next != NULL) {
|
|
63
|
+
if (next->type != TOKEN_IDENTIFIER || next->value.length == 0) {
|
|
64
|
+
token_free(next, parser->allocator);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
token_free(next, parser->allocator);
|
|
69
|
+
next = lexer_next_token(&lexer_copy);
|
|
70
|
+
|
|
71
|
+
if (next == NULL) { return true; }
|
|
72
|
+
|
|
73
|
+
is_dot = token_is_dot(next);
|
|
74
|
+
token_free(next, parser->allocator);
|
|
75
|
+
|
|
76
|
+
if (!is_dot) { return true; }
|
|
77
|
+
|
|
78
|
+
next = lexer_next_token(&lexer_copy);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void parser_consume_dot_notation_segments(parser_T* parser, token_T* tag_name, hb_array_T* errors) {
|
|
85
|
+
if (!parser->options.dot_notation_tags) { return; }
|
|
86
|
+
if (tag_name == NULL || tag_name->value.length == 0) { return; }
|
|
87
|
+
if (!current_token_is_dot(parser)) { return; }
|
|
88
|
+
|
|
89
|
+
if (!isupper((unsigned char) tag_name->value.data[0])) {
|
|
90
|
+
append_dot_notation_casing_error(
|
|
91
|
+
tag_name,
|
|
92
|
+
tag_name->location.start,
|
|
93
|
+
tag_name->location.end,
|
|
94
|
+
parser->allocator,
|
|
95
|
+
errors
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
consume_dot_notation_loop(parser, tag_name, errors);
|
|
100
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
-
// be modified manually. See /home/runner/work/herb/herb/templates/src/
|
|
2
|
+
// be modified manually. See /home/runner/work/herb/herb/templates/src/parser/match_tags.c.erb
|
|
3
3
|
|
|
4
|
-
#include "include/parser.h"
|
|
5
|
-
#include "include/ast_nodes.h"
|
|
6
|
-
#include "include/
|
|
7
|
-
#include "include/visitor.h"
|
|
4
|
+
#include "../include/parser/parser.h"
|
|
5
|
+
#include "../include/ast/ast_nodes.h"
|
|
6
|
+
#include "../include/lib/hb_array.h"
|
|
7
|
+
#include "../include/visitor.h"
|
|
8
8
|
|
|
9
9
|
bool match_tags_visitor(const AST_NODE_T* node, void* data) {
|
|
10
10
|
match_tags_context_T* context = (match_tags_context_T*) data;
|
|
@@ -205,6 +205,15 @@ bool match_tags_visitor(const AST_NODE_T* node, void* data) {
|
|
|
205
205
|
if (erb_block_node->body != NULL) {
|
|
206
206
|
match_tags_in_node_array(erb_block_node->body, context->errors, context->options, context->allocator);
|
|
207
207
|
}
|
|
208
|
+
if (erb_block_node->rescue_clause != NULL) {
|
|
209
|
+
herb_visit_node((AST_NODE_T*) erb_block_node->rescue_clause, match_tags_visitor, context);
|
|
210
|
+
}
|
|
211
|
+
if (erb_block_node->else_clause != NULL) {
|
|
212
|
+
herb_visit_node((AST_NODE_T*) erb_block_node->else_clause, match_tags_visitor, context);
|
|
213
|
+
}
|
|
214
|
+
if (erb_block_node->ensure_clause != NULL) {
|
|
215
|
+
herb_visit_node((AST_NODE_T*) erb_block_node->ensure_clause, match_tags_visitor, context);
|
|
216
|
+
}
|
|
208
217
|
if (erb_block_node->end_node != NULL) {
|
|
209
218
|
herb_visit_node((AST_NODE_T*) erb_block_node->end_node, match_tags_visitor, context);
|
|
210
219
|
}
|
|
@@ -380,6 +389,26 @@ bool match_tags_visitor(const AST_NODE_T* node, void* data) {
|
|
|
380
389
|
|
|
381
390
|
|
|
382
391
|
|
|
392
|
+
case AST_RUBY_STRICT_LOCAL_NODE: {
|
|
393
|
+
const AST_RUBY_STRICT_LOCAL_NODE_T* ruby_strict_local_node = (const AST_RUBY_STRICT_LOCAL_NODE_T*) node;
|
|
394
|
+
|
|
395
|
+
if (ruby_strict_local_node->default_value != NULL) {
|
|
396
|
+
herb_visit_node((AST_NODE_T*) ruby_strict_local_node->default_value, match_tags_visitor, context);
|
|
397
|
+
}
|
|
398
|
+
} break;
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
case AST_ERB_STRICT_LOCALS_NODE: {
|
|
403
|
+
const AST_ERB_STRICT_LOCALS_NODE_T* erb_strict_locals_node = (const AST_ERB_STRICT_LOCALS_NODE_T*) node;
|
|
404
|
+
|
|
405
|
+
if (erb_strict_locals_node->locals != NULL) {
|
|
406
|
+
match_tags_in_node_array(erb_strict_locals_node->locals, context->errors, context->options, context->allocator);
|
|
407
|
+
}
|
|
408
|
+
} break;
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
383
412
|
|
|
384
413
|
|
|
385
414
|
case AST_ERB_IN_NODE: {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#include "include/parser_helpers.h"
|
|
2
|
-
#include "include/ast_nodes.h"
|
|
3
|
-
#include "include/errors.h"
|
|
4
|
-
#include "include/lexer.h"
|
|
5
|
-
#include "include/
|
|
6
|
-
#include "include/
|
|
7
|
-
#include "include/
|
|
8
|
-
#include "include/
|
|
9
|
-
#include "include/
|
|
1
|
+
#include "../include/parser/parser_helpers.h"
|
|
2
|
+
#include "../include/ast/ast_nodes.h"
|
|
3
|
+
#include "../include/errors.h"
|
|
4
|
+
#include "../include/lexer/lexer.h"
|
|
5
|
+
#include "../include/lexer/token.h"
|
|
6
|
+
#include "../include/lib/hb_array.h"
|
|
7
|
+
#include "../include/lib/hb_buffer.h"
|
|
8
|
+
#include "../include/lib/hb_string.h"
|
|
9
|
+
#include "../include/parser/parser.h"
|
|
10
10
|
|
|
11
11
|
#include <stdarg.h>
|
|
12
12
|
#include <stdio.h>
|
|
@@ -219,7 +219,7 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
|
|
|
219
219
|
body,
|
|
220
220
|
NULL,
|
|
221
221
|
false,
|
|
222
|
-
|
|
222
|
+
hb_string("HTML"),
|
|
223
223
|
open_tag->base.location.start,
|
|
224
224
|
open_tag->base.location.end,
|
|
225
225
|
errors,
|
data/src/parser.c
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
#include "include/parser.h"
|
|
2
|
-
#include "include/ast_node.h"
|
|
3
|
-
#include "include/ast_nodes.h"
|
|
1
|
+
#include "include/parser/parser.h"
|
|
2
|
+
#include "include/ast/ast_node.h"
|
|
3
|
+
#include "include/ast/ast_nodes.h"
|
|
4
4
|
#include "include/errors.h"
|
|
5
|
-
#include "include/
|
|
6
|
-
#include "include/lexer.h"
|
|
7
|
-
#include "include/
|
|
8
|
-
#include "include/
|
|
9
|
-
#include "include/
|
|
10
|
-
#include "include/
|
|
11
|
-
#include "include/
|
|
12
|
-
#include "include/
|
|
13
|
-
#include "include/
|
|
14
|
-
#include "include/
|
|
15
|
-
#include "include/util/
|
|
5
|
+
#include "include/lexer/lexer.h"
|
|
6
|
+
#include "include/lexer/lexer_peek_helpers.h"
|
|
7
|
+
#include "include/lexer/token.h"
|
|
8
|
+
#include "include/lexer/token_matchers.h"
|
|
9
|
+
#include "include/lib/hb_array.h"
|
|
10
|
+
#include "include/lib/hb_buffer.h"
|
|
11
|
+
#include "include/lib/hb_string.h"
|
|
12
|
+
#include "include/lib/string.h"
|
|
13
|
+
#include "include/parser/dot_notation.h"
|
|
14
|
+
#include "include/parser/parser_helpers.h"
|
|
15
|
+
#include "include/util/html_util.h"
|
|
16
|
+
#include "include/util/util.h"
|
|
16
17
|
#include "include/visitor.h"
|
|
17
18
|
|
|
18
19
|
#include <stdio.h>
|
|
@@ -38,9 +39,14 @@ const parser_options_T HERB_DEFAULT_PARSER_OPTIONS = { .track_whitespace = false
|
|
|
38
39
|
.strict = true,
|
|
39
40
|
.action_view_helpers = false,
|
|
40
41
|
.render_nodes = false,
|
|
42
|
+
.strict_locals = false,
|
|
41
43
|
.prism_nodes_deep = false,
|
|
42
44
|
.prism_nodes = false,
|
|
43
|
-
.prism_program = false
|
|
45
|
+
.prism_program = false,
|
|
46
|
+
.dot_notation_tags = false,
|
|
47
|
+
.html = true,
|
|
48
|
+
.start_line = 0,
|
|
49
|
+
.start_column = 0 };
|
|
44
50
|
|
|
45
51
|
size_t parser_sizeof(void) {
|
|
46
52
|
return sizeof(struct PARSER_STRUCT);
|
|
@@ -473,7 +479,9 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
|
|
|
473
479
|
|
|
474
480
|
if (equals_token && equals_token->type == TOKEN_EQUALS) {
|
|
475
481
|
token_T* after_equals = lexer_next_token(parser->lexer);
|
|
476
|
-
looks_like_new_attribute =
|
|
482
|
+
looks_like_new_attribute =
|
|
483
|
+
(after_equals && after_equals->type == TOKEN_QUOTE && opening_quote != NULL
|
|
484
|
+
&& hb_string_equals(after_equals->value, opening_quote->value));
|
|
477
485
|
|
|
478
486
|
if (after_equals) { token_free(after_equals, parser->allocator); }
|
|
479
487
|
}
|
|
@@ -767,7 +775,7 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
|
|
|
767
775
|
equals_with_whitespace->type = TOKEN_EQUALS;
|
|
768
776
|
|
|
769
777
|
char* arena_copy = hb_allocator_strndup(parser->allocator, equals_buffer.value, equals_buffer.length);
|
|
770
|
-
equals_with_whitespace->value = (
|
|
778
|
+
equals_with_whitespace->value = hb_string_from_data(arena_copy, equals_buffer.length);
|
|
771
779
|
|
|
772
780
|
hb_buffer_free(&equals_buffer);
|
|
773
781
|
|
|
@@ -884,7 +892,7 @@ static void parser_skip_erb_content(lexer_T* lexer) {
|
|
|
884
892
|
do {
|
|
885
893
|
token = lexer_next_token(lexer);
|
|
886
894
|
|
|
887
|
-
if (token->type == TOKEN_ERB_END) {
|
|
895
|
+
if (token->type == TOKEN_ERB_END || token->type == TOKEN_EOF) {
|
|
888
896
|
token_free(token, lexer->allocator);
|
|
889
897
|
break;
|
|
890
898
|
}
|
|
@@ -899,6 +907,11 @@ static bool parser_lookahead_erb_is_attribute(lexer_T* lexer) {
|
|
|
899
907
|
do {
|
|
900
908
|
after = lexer_next_token(lexer);
|
|
901
909
|
|
|
910
|
+
if (after->type == TOKEN_EOF) {
|
|
911
|
+
token_free(after, lexer->allocator);
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
|
|
902
915
|
if (after->type == TOKEN_EQUALS) {
|
|
903
916
|
token_free(after, lexer->allocator);
|
|
904
917
|
return true;
|
|
@@ -929,14 +942,30 @@ static bool parser_lookahead_erb_is_attribute(lexer_T* lexer) {
|
|
|
929
942
|
|
|
930
943
|
static bool starts_with_keyword(hb_string_T string, const char* keyword) {
|
|
931
944
|
hb_string_T prefix = hb_string(keyword);
|
|
945
|
+
|
|
932
946
|
if (string.length < prefix.length) { return false; }
|
|
933
947
|
if (strncmp(string.data, prefix.data, prefix.length) != 0) { return false; }
|
|
934
|
-
|
|
935
948
|
if (string.length == prefix.length) { return true; }
|
|
936
949
|
|
|
937
950
|
return is_whitespace(string.data[prefix.length]);
|
|
938
951
|
}
|
|
939
952
|
|
|
953
|
+
static AST_HTML_TEXT_NODE_T* parser_advance_as_text(parser_T* parser) {
|
|
954
|
+
token_T* token = parser_advance(parser);
|
|
955
|
+
|
|
956
|
+
AST_HTML_TEXT_NODE_T* text = ast_html_text_node_init(
|
|
957
|
+
token->value,
|
|
958
|
+
token->location.start,
|
|
959
|
+
token->location.end,
|
|
960
|
+
hb_array_init(0, parser->allocator),
|
|
961
|
+
parser->allocator
|
|
962
|
+
);
|
|
963
|
+
|
|
964
|
+
token_free(token, parser->allocator);
|
|
965
|
+
|
|
966
|
+
return text;
|
|
967
|
+
}
|
|
968
|
+
|
|
940
969
|
// TODO: ideally we could avoid basing this off of strings, and use the step in analyze.c
|
|
941
970
|
static bool parser_lookahead_erb_is_control_flow(parser_T* parser) {
|
|
942
971
|
lexer_T lexer_copy = *parser->lexer;
|
|
@@ -1005,6 +1034,8 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
|
|
|
1005
1034
|
token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, errors);
|
|
1006
1035
|
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
1007
1036
|
|
|
1037
|
+
parser_consume_dot_notation_segments(parser, tag_name, errors);
|
|
1038
|
+
|
|
1008
1039
|
while (token_is_none_of(parser, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)) {
|
|
1009
1040
|
if (token_is_any_of(parser, TOKEN_HTML_TAG_START, TOKEN_HTML_TAG_START_CLOSE)) {
|
|
1010
1041
|
append_unclosed_open_tag_error(
|
|
@@ -1182,6 +1213,8 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser)
|
|
|
1182
1213
|
|
|
1183
1214
|
token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
|
|
1184
1215
|
|
|
1216
|
+
parser_consume_dot_notation_segments(parser, tag_name, errors);
|
|
1217
|
+
|
|
1185
1218
|
parser_consume_whitespace(parser, children);
|
|
1186
1219
|
|
|
1187
1220
|
token_T* tag_closing = parser_consume_if_present(parser, TOKEN_HTML_TAG_END);
|
|
@@ -1246,7 +1279,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_self_closing_element(
|
|
|
1246
1279
|
NULL,
|
|
1247
1280
|
NULL,
|
|
1248
1281
|
true,
|
|
1249
|
-
|
|
1282
|
+
hb_string("HTML"),
|
|
1250
1283
|
open_tag->base.location.start,
|
|
1251
1284
|
open_tag->base.location.end,
|
|
1252
1285
|
NULL,
|
|
@@ -1318,7 +1351,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element(
|
|
|
1318
1351
|
body,
|
|
1319
1352
|
(AST_NODE_T*) close_tag,
|
|
1320
1353
|
false,
|
|
1321
|
-
|
|
1354
|
+
hb_string("HTML"),
|
|
1322
1355
|
open_tag->base.location.start,
|
|
1323
1356
|
close_tag->base.location.end,
|
|
1324
1357
|
errors,
|
|
@@ -1408,13 +1441,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1408
1441
|
hb_buffer_init(&content, 1024, parser->allocator);
|
|
1409
1442
|
position_T start = parser->current_token->location.start;
|
|
1410
1443
|
hb_string_T expected_closing_tag = parser_get_foreign_content_closing_tag(parser->foreign_content_type);
|
|
1411
|
-
|
|
1412
|
-
if (hb_string_is_empty(expected_closing_tag)) {
|
|
1413
|
-
parser_exit_foreign_content(parser);
|
|
1414
|
-
hb_buffer_free(&content);
|
|
1415
|
-
|
|
1416
|
-
return;
|
|
1417
|
-
}
|
|
1444
|
+
bool has_closing_tag = !hb_string_is_empty(expected_closing_tag);
|
|
1418
1445
|
|
|
1419
1446
|
while (!token_is(parser, TOKEN_EOF)) {
|
|
1420
1447
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
@@ -1428,7 +1455,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1428
1455
|
continue;
|
|
1429
1456
|
}
|
|
1430
1457
|
|
|
1431
|
-
if (token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) {
|
|
1458
|
+
if (has_closing_tag && token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) {
|
|
1432
1459
|
lexer_state_snapshot_T saved_state = lexer_save_state(parser->lexer);
|
|
1433
1460
|
|
|
1434
1461
|
token_T* next_token = lexer_next_token(parser->lexer);
|
|
@@ -1463,6 +1490,11 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
|
|
|
1463
1490
|
}
|
|
1464
1491
|
|
|
1465
1492
|
static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T* errors) {
|
|
1493
|
+
if (!parser->options.html) {
|
|
1494
|
+
parser_parse_foreign_content(parser, children, errors);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1466
1498
|
while (token_is_not(parser, TOKEN_EOF)) {
|
|
1467
1499
|
|
|
1468
1500
|
if (token_is(parser, TOKEN_ERB_START)) {
|
|
@@ -1496,7 +1528,11 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
|
|
|
1496
1528
|
}
|
|
1497
1529
|
|
|
1498
1530
|
if (token_is(parser, TOKEN_HTML_TAG_START)) {
|
|
1499
|
-
|
|
1531
|
+
if (parser_lookahead_is_valid_dot_notation_open_tag(parser)) {
|
|
1532
|
+
hb_array_append(children, parser_parse_html_element(parser));
|
|
1533
|
+
} else {
|
|
1534
|
+
hb_array_append(children, parser_advance_as_text(parser));
|
|
1535
|
+
}
|
|
1500
1536
|
parser->consecutive_error_count = 0;
|
|
1501
1537
|
continue;
|
|
1502
1538
|
}
|
|
@@ -1683,7 +1719,7 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1683
1719
|
processed_body,
|
|
1684
1720
|
(AST_NODE_T*) omitted_close_tag,
|
|
1685
1721
|
false,
|
|
1686
|
-
|
|
1722
|
+
hb_string("HTML"),
|
|
1687
1723
|
open_tag->base.location.start,
|
|
1688
1724
|
end_position,
|
|
1689
1725
|
element_errors,
|
|
@@ -1726,7 +1762,7 @@ static hb_array_T* parser_build_elements_from_tags(
|
|
|
1726
1762
|
processed_body,
|
|
1727
1763
|
(AST_NODE_T*) close_tag,
|
|
1728
1764
|
false,
|
|
1729
|
-
|
|
1765
|
+
hb_string("HTML"),
|
|
1730
1766
|
open_tag->base.location.start,
|
|
1731
1767
|
close_tag->base.location.end,
|
|
1732
1768
|
element_errors,
|