herb 0.8.10-arm-linux-gnu → 0.9.0-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/Makefile +11 -3
- data/README.md +64 -34
- data/Rakefile +48 -40
- data/config.yml +317 -34
- data/ext/herb/error_helpers.c +367 -140
- data/ext/herb/error_helpers.h +1 -0
- data/ext/herb/extconf.rb +67 -28
- data/ext/herb/extension.c +317 -51
- data/ext/herb/extension.h +1 -0
- data/ext/herb/extension_helpers.c +23 -14
- data/ext/herb/extension_helpers.h +2 -2
- data/ext/herb/nodes.c +537 -270
- data/ext/herb/nodes.h +1 -0
- data/herb.gemspec +3 -2
- 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/helpers.rb +3 -3
- data/lib/herb/ast/node.rb +15 -2
- data/lib/herb/ast/nodes.rb +1132 -157
- data/lib/herb/bootstrap.rb +87 -0
- data/lib/herb/cli.rb +341 -31
- data/lib/herb/configuration.rb +248 -0
- data/lib/herb/defaults.yml +32 -0
- data/lib/herb/engine/compiler.rb +78 -11
- data/lib/herb/engine/debug_visitor.rb +13 -3
- data/lib/herb/engine/error_formatter.rb +13 -9
- data/lib/herb/engine/parser_error_overlay.rb +10 -6
- data/lib/herb/engine/validator.rb +8 -3
- data/lib/herb/engine/validators/nesting_validator.rb +2 -2
- data/lib/herb/engine.rb +82 -35
- data/lib/herb/errors.rb +563 -88
- data/lib/herb/lex_result.rb +1 -0
- data/lib/herb/location.rb +7 -3
- data/lib/herb/parse_result.rb +12 -2
- data/lib/herb/parser_options.rb +57 -0
- data/lib/herb/position.rb +1 -0
- data/lib/herb/prism_inspect.rb +116 -0
- data/lib/herb/project.rb +923 -331
- data/lib/herb/range.rb +1 -0
- data/lib/herb/token.rb +7 -1
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +37 -2
- data/lib/herb/warnings.rb +6 -1
- data/lib/herb.rb +35 -3
- data/sig/herb/ast/helpers.rbs +2 -2
- data/sig/herb/ast/node.rbs +12 -2
- data/sig/herb/ast/nodes.rbs +641 -128
- data/sig/herb/bootstrap.rbs +31 -0
- data/sig/herb/configuration.rbs +89 -0
- data/sig/herb/engine/compiler.rbs +9 -1
- data/sig/herb/engine/debug_visitor.rbs +2 -0
- data/sig/herb/engine/validator.rbs +5 -1
- data/sig/herb/engine.rbs +17 -3
- data/sig/herb/errors.rbs +258 -63
- data/sig/herb/location.rbs +4 -0
- data/sig/herb/parse_result.rbs +4 -2
- data/sig/herb/parser_options.rbs +42 -0
- data/sig/herb/position.rbs +1 -0
- data/sig/herb/prism_inspect.rbs +28 -0
- data/sig/herb/range.rbs +1 -0
- data/sig/herb/token.rbs +6 -0
- data/sig/herb/visitor.rbs +25 -4
- data/sig/herb/warnings.rbs +6 -1
- data/sig/herb.rbs +14 -0
- data/sig/herb_c_extension.rbs +5 -2
- data/sig/serialized_ast_errors.rbs +54 -6
- data/sig/serialized_ast_nodes.rbs +60 -6
- data/src/analyze/action_view/attribute_extraction_helpers.c +290 -0
- data/src/analyze/action_view/content_tag.c +70 -0
- data/src/analyze/action_view/link_to.c +143 -0
- data/src/analyze/action_view/registry.c +60 -0
- data/src/analyze/action_view/tag.c +64 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
- data/src/analyze/action_view/tag_helpers.c +748 -0
- data/src/analyze/action_view/turbo_frame_tag.c +88 -0
- data/src/analyze/analyze.c +882 -0
- data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
- data/src/analyze/builders.c +343 -0
- data/src/analyze/conditional_elements.c +594 -0
- data/src/analyze/conditional_open_tags.c +640 -0
- data/src/analyze/control_type.c +250 -0
- data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
- data/src/analyze/invalid_structures.c +193 -0
- data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
- data/src/analyze/parse_errors.c +84 -0
- data/src/analyze/prism_annotate.c +397 -0
- data/src/{analyze_transform.c → analyze/transform.c} +17 -3
- data/src/ast_node.c +17 -7
- data/src/ast_nodes.c +662 -387
- data/src/ast_pretty_print.c +190 -6
- data/src/errors.c +1076 -520
- data/src/extract.c +145 -49
- data/src/herb.c +52 -34
- data/src/html_util.c +241 -12
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +41 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
- data/src/include/analyze/action_view/tag_helpers.h +38 -0
- data/src/include/{analyze.h → analyze/analyze.h} +14 -4
- data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
- data/src/include/analyze/builders.h +27 -0
- data/src/include/analyze/conditional_elements.h +9 -0
- data/src/include/analyze/conditional_open_tags.h +9 -0
- data/src/include/analyze/control_type.h +14 -0
- data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
- data/src/include/analyze/invalid_structures.h +11 -0
- data/src/include/analyze/prism_annotate.h +16 -0
- data/src/include/ast_node.h +11 -5
- data/src/include/ast_nodes.h +117 -38
- data/src/include/ast_pretty_print.h +5 -0
- data/src/include/element_source.h +3 -8
- data/src/include/errors.h +148 -55
- data/src/include/extract.h +21 -5
- data/src/include/herb.h +18 -6
- data/src/include/herb_prism_node.h +13 -0
- data/src/include/html_util.h +7 -2
- data/src/include/io.h +3 -1
- data/src/include/lex_helpers.h +29 -0
- data/src/include/lexer.h +1 -1
- data/src/include/lexer_peek_helpers.h +87 -13
- data/src/include/lexer_struct.h +2 -0
- data/src/include/location.h +2 -1
- data/src/include/parser.h +27 -2
- data/src/include/parser_helpers.h +19 -3
- data/src/include/pretty_print.h +10 -5
- data/src/include/prism_context.h +45 -0
- data/src/include/prism_helpers.h +10 -7
- data/src/include/prism_serialized.h +12 -0
- data/src/include/token.h +16 -4
- data/src/include/token_struct.h +10 -3
- data/src/include/utf8.h +2 -1
- data/src/include/util/hb_allocator.h +78 -0
- data/src/include/util/hb_arena.h +6 -1
- data/src/include/util/hb_arena_debug.h +12 -1
- data/src/include/util/hb_array.h +7 -3
- data/src/include/util/hb_buffer.h +6 -4
- data/src/include/util/hb_foreach.h +79 -0
- data/src/include/util/hb_narray.h +8 -4
- data/src/include/util/hb_string.h +56 -9
- data/src/include/util.h +6 -3
- data/src/include/version.h +1 -1
- data/src/io.c +3 -2
- data/src/lexer.c +42 -30
- data/src/lexer_peek_helpers.c +12 -74
- data/src/location.c +2 -2
- data/src/main.c +53 -28
- data/src/parser.c +783 -247
- data/src/parser_helpers.c +110 -23
- data/src/parser_match_tags.c +109 -48
- data/src/pretty_print.c +29 -24
- data/src/prism_helpers.c +30 -27
- data/src/ruby_parser.c +2 -0
- data/src/token.c +151 -66
- data/src/token_matchers.c +0 -1
- data/src/utf8.c +7 -6
- data/src/util/hb_allocator.c +341 -0
- data/src/util/hb_arena.c +81 -56
- data/src/util/hb_arena_debug.c +32 -17
- data/src/util/hb_array.c +30 -15
- data/src/util/hb_buffer.c +17 -21
- data/src/util/hb_narray.c +22 -7
- data/src/util/hb_string.c +49 -35
- data/src/util.c +21 -11
- data/src/visitor.c +47 -0
- data/templates/ext/herb/error_helpers.c.erb +24 -11
- data/templates/ext/herb/error_helpers.h.erb +1 -0
- data/templates/ext/herb/nodes.c.erb +50 -16
- data/templates/ext/herb/nodes.h.erb +1 -0
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/nodes.c.erb +30 -8
- data/templates/java/org/herb/ast/Errors.java.erb +24 -1
- data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
- data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
- data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
- data/templates/lib/herb/ast/nodes.rb.erb +88 -31
- data/templates/lib/herb/errors.rb.erb +15 -3
- data/templates/lib/herb/visitor.rb.erb +2 -2
- data/templates/rust/src/ast/nodes.rs.erb +97 -44
- data/templates/rust/src/errors.rs.erb +2 -1
- data/templates/rust/src/nodes.rs.erb +167 -15
- data/templates/rust/src/union_types.rs.erb +60 -0
- data/templates/rust/src/visitor.rs.erb +81 -0
- data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
- data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
- data/templates/src/ast_nodes.c.erb +34 -26
- data/templates/src/ast_pretty_print.c.erb +24 -5
- data/templates/src/errors.c.erb +60 -54
- data/templates/src/include/ast_nodes.h.erb +6 -2
- data/templates/src/include/ast_pretty_print.h.erb +5 -0
- data/templates/src/include/errors.h.erb +15 -11
- data/templates/src/include/util/hb_foreach.h.erb +20 -0
- data/templates/src/parser_match_tags.c.erb +10 -4
- data/templates/src/visitor.c.erb +2 -2
- data/templates/template.rb +204 -29
- data/templates/wasm/error_helpers.cpp.erb +9 -5
- data/templates/wasm/nodes.cpp.erb +41 -4
- metadata +57 -16
- data/src/analyze.c +0 -1608
- data/src/element_source.c +0 -12
- data/src/include/util/hb_system.h +0 -9
- data/src/util/hb_system.c +0 -30
data/src/include/extract.h
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
#ifndef HERB_EXTRACT_H
|
|
2
2
|
#define HERB_EXTRACT_H
|
|
3
3
|
|
|
4
|
+
#include "util/hb_allocator.h"
|
|
4
5
|
#include "util/hb_buffer.h"
|
|
5
6
|
|
|
7
|
+
#include <stdbool.h>
|
|
8
|
+
|
|
6
9
|
typedef enum {
|
|
7
10
|
HERB_EXTRACT_LANGUAGE_RUBY,
|
|
8
11
|
HERB_EXTRACT_LANGUAGE_HTML,
|
|
9
12
|
} herb_extract_language_T;
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
typedef struct {
|
|
15
|
+
bool semicolons;
|
|
16
|
+
bool comments;
|
|
17
|
+
bool preserve_positions;
|
|
18
|
+
} herb_extract_ruby_options_T;
|
|
19
|
+
|
|
20
|
+
extern const herb_extract_ruby_options_T HERB_EXTRACT_RUBY_DEFAULT_OPTIONS;
|
|
21
|
+
|
|
22
|
+
void herb_extract_ruby_to_buffer_with_options(
|
|
23
|
+
const char* source,
|
|
24
|
+
hb_buffer_T* output,
|
|
25
|
+
const herb_extract_ruby_options_T* options,
|
|
26
|
+
hb_allocator_T* allocator
|
|
27
|
+
);
|
|
28
|
+
void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output, hb_allocator_T* allocator);
|
|
29
|
+
void herb_extract_html_to_buffer(const char* source, hb_buffer_T* output, hb_allocator_T* allocator);
|
|
13
30
|
|
|
14
|
-
char* herb_extract_ruby_with_semicolons(const char* source);
|
|
31
|
+
char* herb_extract_ruby_with_semicolons(const char* source, hb_allocator_T* allocator);
|
|
15
32
|
|
|
16
|
-
char* herb_extract(const char* source, herb_extract_language_T language);
|
|
17
|
-
char* herb_extract_from_file(const char* path, herb_extract_language_T language);
|
|
33
|
+
char* herb_extract(const char* source, herb_extract_language_T language, hb_allocator_T* allocator);
|
|
18
34
|
|
|
19
35
|
#endif
|
data/src/include/herb.h
CHANGED
|
@@ -5,26 +5,38 @@
|
|
|
5
5
|
#include "extract.h"
|
|
6
6
|
#include "macros.h"
|
|
7
7
|
#include "parser.h"
|
|
8
|
+
#include "util/hb_allocator.h"
|
|
8
9
|
#include "util/hb_array.h"
|
|
9
10
|
#include "util/hb_buffer.h"
|
|
10
11
|
|
|
12
|
+
#include <prism.h>
|
|
13
|
+
#include <stdbool.h>
|
|
11
14
|
#include <stdint.h>
|
|
12
15
|
|
|
13
16
|
#ifdef __cplusplus
|
|
14
17
|
extern "C" {
|
|
15
18
|
#endif
|
|
16
19
|
|
|
17
|
-
HERB_EXPORTED_FUNCTION
|
|
20
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex(const char* source, hb_allocator_T* allocator);
|
|
18
21
|
|
|
19
|
-
HERB_EXPORTED_FUNCTION
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
HERB_EXPORTED_FUNCTION AST_DOCUMENT_NODE_T* herb_parse(
|
|
23
|
+
const char* source,
|
|
24
|
+
const parser_options_T* options,
|
|
25
|
+
hb_allocator_T* allocator
|
|
26
|
+
);
|
|
23
27
|
|
|
24
28
|
HERB_EXPORTED_FUNCTION const char* herb_version(void);
|
|
25
29
|
HERB_EXPORTED_FUNCTION const char* herb_prism_version(void);
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
typedef struct {
|
|
32
|
+
pm_parser_t parser;
|
|
33
|
+
pm_node_t* root;
|
|
34
|
+
pm_options_t options;
|
|
35
|
+
} herb_ruby_parse_result_T;
|
|
36
|
+
|
|
37
|
+
HERB_EXPORTED_FUNCTION herb_ruby_parse_result_T* herb_parse_ruby(const char* source, size_t length);
|
|
38
|
+
HERB_EXPORTED_FUNCTION void herb_free_ruby_parse_result(herb_ruby_parse_result_T* result);
|
|
39
|
+
HERB_EXPORTED_FUNCTION void herb_free_tokens(hb_array_T** tokens, hb_allocator_T* allocator);
|
|
28
40
|
|
|
29
41
|
#ifdef __cplusplus
|
|
30
42
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#ifndef HERB_PRISM_NODE_H
|
|
2
|
+
#define HERB_PRISM_NODE_H
|
|
3
|
+
|
|
4
|
+
#include <prism.h>
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
pm_node_t* node;
|
|
8
|
+
pm_parser_t* parser;
|
|
9
|
+
} herb_prism_node_T;
|
|
10
|
+
|
|
11
|
+
#define HERB_PRISM_NODE_EMPTY ((herb_prism_node_T) { .node = NULL, .parser = NULL })
|
|
12
|
+
|
|
13
|
+
#endif
|
data/src/include/html_util.h
CHANGED
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
#include "util/hb_string.h"
|
|
5
5
|
#include <stdbool.h>
|
|
6
6
|
|
|
7
|
+
struct hb_allocator;
|
|
8
|
+
|
|
7
9
|
bool is_void_element(hb_string_T tag_name);
|
|
10
|
+
bool has_optional_end_tag(hb_string_T tag_name);
|
|
11
|
+
bool should_implicitly_close(hb_string_T open_tag_name, hb_string_T next_tag_name);
|
|
12
|
+
bool parent_closes_element(hb_string_T open_tag_name, hb_string_T parent_close_tag_name);
|
|
8
13
|
|
|
9
|
-
hb_string_T html_closing_tag_string(hb_string_T tag_name);
|
|
10
|
-
hb_string_T html_self_closing_tag_string(hb_string_T tag_name);
|
|
14
|
+
hb_string_T html_closing_tag_string(hb_string_T tag_name, struct hb_allocator* allocator);
|
|
15
|
+
hb_string_T html_self_closing_tag_string(hb_string_T tag_name, struct hb_allocator* allocator);
|
|
11
16
|
|
|
12
17
|
#endif
|
data/src/include/io.h
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#ifndef HERB_LEX_HELPERS_H
|
|
2
|
+
#define HERB_LEX_HELPERS_H
|
|
3
|
+
|
|
4
|
+
#include "herb.h"
|
|
5
|
+
#include "token.h"
|
|
6
|
+
#include "util/hb_allocator.h"
|
|
7
|
+
#include "util/hb_array.h"
|
|
8
|
+
#include "util/hb_buffer.h"
|
|
9
|
+
#include "util/hb_string.h"
|
|
10
|
+
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
|
|
13
|
+
static inline void herb_lex_to_buffer(const char* source, hb_buffer_T* output, hb_allocator_T* allocator) {
|
|
14
|
+
hb_array_T* tokens = herb_lex(source, allocator);
|
|
15
|
+
|
|
16
|
+
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
17
|
+
token_T* token = hb_array_get(tokens, i);
|
|
18
|
+
|
|
19
|
+
hb_string_T type = token_to_string(allocator, token);
|
|
20
|
+
hb_buffer_append_string(output, type);
|
|
21
|
+
hb_allocator_dealloc(allocator, type.data);
|
|
22
|
+
|
|
23
|
+
hb_buffer_append(output, "\n");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
herb_free_tokens(&tokens, allocator);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#endif
|
data/src/include/lexer.h
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#include "lexer_struct.h"
|
|
5
5
|
#include "token_struct.h"
|
|
6
6
|
|
|
7
|
-
void lexer_init(lexer_T* lexer, const char* source);
|
|
7
|
+
void lexer_init(lexer_T* lexer, const char* source, hb_allocator_T* allocator);
|
|
8
8
|
token_T* lexer_next_token(lexer_T* lexer);
|
|
9
9
|
token_T* lexer_error(lexer_T* lexer, const char* message);
|
|
10
10
|
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
#define HERB_LEXER_PEEK_HELPERS_H
|
|
3
3
|
|
|
4
4
|
#include "lexer_struct.h"
|
|
5
|
+
#include "macros.h"
|
|
5
6
|
#include "token_struct.h"
|
|
7
|
+
#include "util/hb_string.h"
|
|
6
8
|
|
|
9
|
+
#include <ctype.h>
|
|
7
10
|
#include <stdbool.h>
|
|
8
11
|
#include <stdint.h>
|
|
9
12
|
#include <stdio.h>
|
|
@@ -20,27 +23,98 @@ typedef struct {
|
|
|
20
23
|
lexer_state_T state;
|
|
21
24
|
} lexer_state_snapshot_T;
|
|
22
25
|
|
|
23
|
-
char lexer_peek(const lexer_T* lexer, uint32_t offset);
|
|
24
26
|
bool lexer_peek_for_doctype(const lexer_T* lexer, uint32_t offset);
|
|
25
27
|
bool lexer_peek_for_xml_declaration(const lexer_T* lexer, uint32_t offset);
|
|
26
28
|
bool lexer_peek_for_cdata_start(const lexer_T* lexer, uint32_t offset);
|
|
27
29
|
bool lexer_peek_for_cdata_end(const lexer_T* lexer, uint32_t offset);
|
|
28
|
-
|
|
29
30
|
bool lexer_peek_for_html_comment_start(const lexer_T* lexer, uint32_t offset);
|
|
30
|
-
bool
|
|
31
|
+
bool lexer_peek_for_token_type_after_whitespace(lexer_T* lexer, token_type_T token_type);
|
|
32
|
+
bool lexer_peek_for_close_tag_start(const lexer_T* lexer, uint32_t offset);
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
bool lexer_peek_erb_equals_close_tag(const lexer_T* lexer, uint32_t offset);
|
|
36
|
-
bool lexer_peek_erb_end(const lexer_T* lexer, uint32_t offset);
|
|
34
|
+
static inline char lexer_peek(const lexer_T* lexer, uint32_t offset) {
|
|
35
|
+
return lexer->source.data[MIN(lexer->current_position + offset, lexer->source.length)];
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
char lexer_backtrack(const lexer_T* lexer, uint32_t offset)
|
|
38
|
+
static inline char lexer_backtrack(const lexer_T* lexer, uint32_t offset) {
|
|
39
|
+
return lexer->source.data[MAX(lexer->current_position - offset, 0)];
|
|
40
|
+
}
|
|
39
41
|
|
|
40
|
-
bool
|
|
41
|
-
|
|
42
|
+
static inline bool lexer_peek_for_html_comment_end(const lexer_T* lexer, uint32_t offset) {
|
|
43
|
+
uint32_t position = lexer->current_position + offset;
|
|
44
|
+
|
|
45
|
+
return position + 2 < lexer->source.length && lexer->source.data[position] == '-'
|
|
46
|
+
&& lexer->source.data[position + 1] == '-' && lexer->source.data[position + 2] == '>';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static inline bool lexer_peek_for_html_comment_invalid_end(const lexer_T* lexer, uint32_t offset) {
|
|
50
|
+
uint32_t position = lexer->current_position + offset;
|
|
51
|
+
|
|
52
|
+
return position + 3 < lexer->source.length && lexer->source.data[position] == '-'
|
|
53
|
+
&& lexer->source.data[position + 1] == '-' && lexer->source.data[position + 2] == '!'
|
|
54
|
+
&& lexer->source.data[position + 3] == '>';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static inline bool lexer_peek_erb_start(const lexer_T* lexer, uint32_t offset) {
|
|
58
|
+
uint32_t position = lexer->current_position + offset;
|
|
59
|
+
|
|
60
|
+
return position + 1 < lexer->source.length && lexer->source.data[position] == '<'
|
|
61
|
+
&& lexer->source.data[position + 1] == '%';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static inline bool lexer_peek_erb_close_tag(const lexer_T* lexer, uint32_t offset) {
|
|
65
|
+
uint32_t position = lexer->current_position + offset;
|
|
66
|
+
|
|
67
|
+
return position + 1 < lexer->source.length && lexer->source.data[position] == '%'
|
|
68
|
+
&& lexer->source.data[position + 1] == '>';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static inline bool lexer_peek_erb_dash_close_tag(const lexer_T* lexer, uint32_t offset) {
|
|
72
|
+
uint32_t position = lexer->current_position + offset;
|
|
73
|
+
|
|
74
|
+
return position + 2 < lexer->source.length && lexer->source.data[position] == '-'
|
|
75
|
+
&& lexer->source.data[position + 1] == '%' && lexer->source.data[position + 2] == '>';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static inline bool lexer_peek_erb_percent_close_tag(const lexer_T* lexer, uint32_t offset) {
|
|
79
|
+
uint32_t position = lexer->current_position + offset;
|
|
80
|
+
|
|
81
|
+
return position + 2 < lexer->source.length && lexer->source.data[position] == '%'
|
|
82
|
+
&& lexer->source.data[position + 1] == '%' && lexer->source.data[position + 2] == '>';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static inline bool lexer_peek_erb_equals_close_tag(const lexer_T* lexer, uint32_t offset) {
|
|
86
|
+
uint32_t position = lexer->current_position + offset;
|
|
87
|
+
|
|
88
|
+
return position + 2 < lexer->source.length && lexer->source.data[position] == '='
|
|
89
|
+
&& lexer->source.data[position + 1] == '%' && lexer->source.data[position + 2] == '>';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static inline bool lexer_peek_erb_end(const lexer_T* lexer, uint32_t offset) {
|
|
93
|
+
return lexer_peek_erb_close_tag(lexer, offset) || lexer_peek_erb_dash_close_tag(lexer, offset)
|
|
94
|
+
|| lexer_peek_erb_percent_close_tag(lexer, offset) || lexer_peek_erb_equals_close_tag(lexer, offset);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static inline lexer_state_snapshot_T lexer_save_state(lexer_T* lexer) {
|
|
98
|
+
lexer_state_snapshot_T snapshot = { .position = lexer->current_position,
|
|
99
|
+
.line = lexer->current_line,
|
|
100
|
+
.column = lexer->current_column,
|
|
101
|
+
.previous_position = lexer->previous_position,
|
|
102
|
+
.previous_line = lexer->previous_line,
|
|
103
|
+
.previous_column = lexer->previous_column,
|
|
104
|
+
.current_character = lexer->current_character,
|
|
105
|
+
.state = lexer->state };
|
|
106
|
+
return snapshot;
|
|
107
|
+
}
|
|
42
108
|
|
|
43
|
-
|
|
44
|
-
|
|
109
|
+
static inline void lexer_restore_state(lexer_T* lexer, lexer_state_snapshot_T snapshot) {
|
|
110
|
+
lexer->current_position = snapshot.position;
|
|
111
|
+
lexer->current_line = snapshot.line;
|
|
112
|
+
lexer->current_column = snapshot.column;
|
|
113
|
+
lexer->previous_position = snapshot.previous_position;
|
|
114
|
+
lexer->previous_line = snapshot.previous_line;
|
|
115
|
+
lexer->previous_column = snapshot.previous_column;
|
|
116
|
+
lexer->current_character = snapshot.current_character;
|
|
117
|
+
lexer->state = snapshot.state;
|
|
118
|
+
}
|
|
45
119
|
|
|
46
120
|
#endif
|
data/src/include/lexer_struct.h
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#ifndef HERB_LEXER_STRUCT_H
|
|
2
2
|
#define HERB_LEXER_STRUCT_H
|
|
3
3
|
|
|
4
|
+
#include "util/hb_allocator.h"
|
|
4
5
|
#include "util/hb_string.h"
|
|
5
6
|
|
|
6
7
|
#include <stdbool.h>
|
|
@@ -14,6 +15,7 @@ typedef enum {
|
|
|
14
15
|
} lexer_state_T;
|
|
15
16
|
|
|
16
17
|
typedef struct LEXER_STRUCT {
|
|
18
|
+
hb_allocator_T* allocator;
|
|
17
19
|
hb_string_T source;
|
|
18
20
|
|
|
19
21
|
uint32_t current_line;
|
data/src/include/location.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <stdlib.h>
|
|
6
6
|
|
|
7
7
|
#include "position.h"
|
|
8
|
+
#include "util/hb_allocator.h"
|
|
8
9
|
|
|
9
10
|
typedef struct LOCATION_STRUCT {
|
|
10
11
|
position_T start;
|
|
@@ -21,6 +22,6 @@ void location_from(
|
|
|
21
22
|
|
|
22
23
|
void location_from_positions(location_T* location, position_T start, position_T end);
|
|
23
24
|
|
|
24
|
-
location_T* location_create(position_T start, position_T end);
|
|
25
|
+
location_T* location_create(position_T start, position_T end, hb_allocator_T* allocator);
|
|
25
26
|
|
|
26
27
|
#endif
|
data/src/include/parser.h
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include "ast_node.h"
|
|
5
5
|
#include "lexer.h"
|
|
6
|
+
#include "util/hb_allocator.h"
|
|
6
7
|
#include "util/hb_array.h"
|
|
7
8
|
|
|
8
9
|
typedef enum {
|
|
@@ -17,17 +18,32 @@ typedef enum { PARSER_STATE_DATA, PARSER_STATE_FOREIGN_CONTENT } parser_state_T;
|
|
|
17
18
|
|
|
18
19
|
typedef struct PARSER_OPTIONS_STRUCT {
|
|
19
20
|
bool track_whitespace;
|
|
21
|
+
bool analyze;
|
|
22
|
+
bool strict;
|
|
23
|
+
bool action_view_helpers;
|
|
24
|
+
bool prism_program;
|
|
25
|
+
bool prism_nodes;
|
|
26
|
+
bool prism_nodes_deep;
|
|
20
27
|
} parser_options_T;
|
|
21
28
|
|
|
29
|
+
typedef struct MATCH_TAGS_CONTEXT_STRUCT {
|
|
30
|
+
hb_array_T* errors;
|
|
31
|
+
const parser_options_T* options;
|
|
32
|
+
hb_allocator_T* allocator;
|
|
33
|
+
} match_tags_context_T;
|
|
34
|
+
|
|
22
35
|
extern const parser_options_T HERB_DEFAULT_PARSER_OPTIONS;
|
|
23
36
|
|
|
24
37
|
typedef struct PARSER_STRUCT {
|
|
38
|
+
hb_allocator_T* allocator;
|
|
25
39
|
lexer_T* lexer;
|
|
26
40
|
token_T* current_token;
|
|
27
41
|
hb_array_T* open_tags_stack;
|
|
28
42
|
parser_state_T state;
|
|
29
43
|
foreign_content_type_T foreign_content_type;
|
|
30
44
|
parser_options_T options;
|
|
45
|
+
size_t consecutive_error_count;
|
|
46
|
+
bool in_recovery_mode;
|
|
31
47
|
} parser_T;
|
|
32
48
|
|
|
33
49
|
size_t parser_sizeof(void);
|
|
@@ -36,10 +52,19 @@ void herb_parser_init(parser_T* parser, lexer_T* lexer, parser_options_T options
|
|
|
36
52
|
|
|
37
53
|
AST_DOCUMENT_NODE_T* herb_parser_parse(parser_T* parser);
|
|
38
54
|
|
|
39
|
-
void herb_parser_match_html_tags_post_analyze(
|
|
55
|
+
void herb_parser_match_html_tags_post_analyze(
|
|
56
|
+
AST_DOCUMENT_NODE_T* document,
|
|
57
|
+
const parser_options_T* options,
|
|
58
|
+
hb_allocator_T* allocator
|
|
59
|
+
);
|
|
40
60
|
void herb_parser_deinit(parser_T* parser);
|
|
41
61
|
|
|
42
|
-
void match_tags_in_node_array(
|
|
62
|
+
void match_tags_in_node_array(
|
|
63
|
+
hb_array_T* nodes,
|
|
64
|
+
hb_array_T* errors,
|
|
65
|
+
const parser_options_T* options,
|
|
66
|
+
hb_allocator_T* allocator
|
|
67
|
+
);
|
|
43
68
|
bool match_tags_visitor(const AST_NODE_T* node, void* data);
|
|
44
69
|
|
|
45
70
|
#endif
|
|
@@ -13,11 +13,21 @@ void parser_push_open_tag(const parser_T* parser, token_T* tag_name);
|
|
|
13
13
|
bool parser_check_matching_tag(const parser_T* parser, hb_string_T tag_name);
|
|
14
14
|
token_T* parser_pop_open_tag(const parser_T* parser);
|
|
15
15
|
|
|
16
|
-
void
|
|
16
|
+
void parser_append_unexpected_error_impl(
|
|
17
17
|
parser_T* parser,
|
|
18
|
+
hb_array_T* errors,
|
|
18
19
|
const char* description,
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
token_type_T first_token,
|
|
21
|
+
...
|
|
22
|
+
);
|
|
23
|
+
#define parser_append_unexpected_error(parser, errors, description, ...) \
|
|
24
|
+
parser_append_unexpected_error_impl(parser, errors, description, __VA_ARGS__, TOKEN_SENTINEL)
|
|
25
|
+
|
|
26
|
+
void parser_append_unexpected_error_string(
|
|
27
|
+
parser_T* parser,
|
|
28
|
+
hb_array_T* errors,
|
|
29
|
+
const char* description,
|
|
30
|
+
const char* expected
|
|
21
31
|
);
|
|
22
32
|
void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T* errors);
|
|
23
33
|
|
|
@@ -44,6 +54,7 @@ token_T* parser_consume_if_present(parser_T* parser, token_type_T type);
|
|
|
44
54
|
token_T* parser_consume_expected(parser_T* parser, token_type_T type, hb_array_T* array);
|
|
45
55
|
|
|
46
56
|
AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
|
|
57
|
+
parser_T* parser,
|
|
47
58
|
AST_HTML_OPEN_TAG_NODE_T* open_tag,
|
|
48
59
|
hb_array_T* body,
|
|
49
60
|
hb_array_T* errors
|
|
@@ -54,4 +65,9 @@ void parser_handle_mismatched_tags(
|
|
|
54
65
|
hb_array_T* errors
|
|
55
66
|
);
|
|
56
67
|
|
|
68
|
+
void parser_synchronize(parser_T* parser, hb_array_T* errors);
|
|
69
|
+
|
|
70
|
+
bool parser_can_close_ancestor(const parser_T* parser, hb_string_T tag_name);
|
|
71
|
+
size_t parser_find_ancestor_depth(const parser_T* parser, hb_string_T tag_name);
|
|
72
|
+
|
|
57
73
|
#endif
|
data/src/include/pretty_print.h
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#ifndef HERB_PRETTY_PRINT_H
|
|
2
2
|
#define HERB_PRETTY_PRINT_H
|
|
3
3
|
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
#include "util/hb_buffer.h"
|
|
4
|
+
#ifdef HERB_EXCLUDE_PRETTYPRINT
|
|
5
|
+
// Pretty print support excluded
|
|
6
|
+
#else
|
|
8
7
|
|
|
9
|
-
#include
|
|
8
|
+
# include "analyze/analyzed_ruby.h"
|
|
9
|
+
# include "ast_nodes.h"
|
|
10
|
+
# include "location.h"
|
|
11
|
+
# include "util/hb_buffer.h"
|
|
12
|
+
|
|
13
|
+
# include <stdbool.h>
|
|
10
14
|
|
|
11
15
|
void pretty_print_indent(hb_buffer_T* buffer, size_t indent);
|
|
12
16
|
void pretty_print_newline(size_t indent, size_t relative_indent, hb_buffer_T* buffer);
|
|
@@ -101,3 +105,4 @@ void pretty_print_errors(
|
|
|
101
105
|
);
|
|
102
106
|
|
|
103
107
|
#endif
|
|
108
|
+
#endif
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#ifndef HERB_PRISM_CONTEXT_H
|
|
2
|
+
#define HERB_PRISM_CONTEXT_H
|
|
3
|
+
|
|
4
|
+
#include "util/hb_allocator.h"
|
|
5
|
+
#include "util/hb_buffer.h"
|
|
6
|
+
#include <prism.h>
|
|
7
|
+
#include <stdbool.h>
|
|
8
|
+
|
|
9
|
+
typedef struct {
|
|
10
|
+
pm_parser_t parser;
|
|
11
|
+
pm_options_t pm_opts;
|
|
12
|
+
pm_node_t* root;
|
|
13
|
+
hb_buffer_T ruby_buf;
|
|
14
|
+
|
|
15
|
+
bool has_structural;
|
|
16
|
+
pm_parser_t structural_parser;
|
|
17
|
+
pm_options_t structural_pm_opts;
|
|
18
|
+
pm_node_t* structural_root;
|
|
19
|
+
hb_buffer_T structural_buf;
|
|
20
|
+
|
|
21
|
+
hb_allocator_T* allocator;
|
|
22
|
+
} herb_prism_context_T;
|
|
23
|
+
|
|
24
|
+
static inline void herb_prism_context_free(herb_prism_context_T* context) {
|
|
25
|
+
if (!context) { return; }
|
|
26
|
+
|
|
27
|
+
if (context->root) { pm_node_destroy(&context->parser, context->root); }
|
|
28
|
+
|
|
29
|
+
pm_parser_free(&context->parser);
|
|
30
|
+
pm_options_free(&context->pm_opts);
|
|
31
|
+
hb_buffer_free(&context->ruby_buf);
|
|
32
|
+
|
|
33
|
+
if (context->has_structural) {
|
|
34
|
+
if (context->structural_root) { pm_node_destroy(&context->structural_parser, context->structural_root); }
|
|
35
|
+
|
|
36
|
+
pm_parser_free(&context->structural_parser);
|
|
37
|
+
pm_options_free(&context->structural_pm_opts);
|
|
38
|
+
|
|
39
|
+
if (context->structural_buf.value) { hb_buffer_free(&context->structural_buf); }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
hb_allocator_dealloc(context->allocator, context);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#endif
|
data/src/include/prism_helpers.h
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
#ifndef HERB_PRISM_HELPERS_H
|
|
2
2
|
#define HERB_PRISM_HELPERS_H
|
|
3
3
|
|
|
4
|
-
#include "analyzed_ruby.h"
|
|
4
|
+
#include "analyze/analyzed_ruby.h"
|
|
5
5
|
#include "ast_nodes.h"
|
|
6
6
|
#include "errors.h"
|
|
7
7
|
#include "location.h"
|
|
8
8
|
#include "position.h"
|
|
9
|
+
#include "util/hb_allocator.h"
|
|
9
10
|
|
|
10
11
|
#include <prism.h>
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
hb_string_T pm_error_level_to_string(pm_error_level_t level);
|
|
13
14
|
|
|
14
15
|
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
|
|
15
16
|
const pm_diagnostic_t* error,
|
|
16
17
|
const AST_NODE_T* node,
|
|
17
18
|
const char* source,
|
|
18
|
-
pm_parser_t* parser
|
|
19
|
+
pm_parser_t* parser,
|
|
20
|
+
hb_allocator_T* allocator
|
|
19
21
|
);
|
|
20
22
|
|
|
21
23
|
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
|
|
22
24
|
const pm_diagnostic_t* error,
|
|
23
25
|
position_T start,
|
|
24
|
-
position_T end
|
|
26
|
+
position_T end,
|
|
27
|
+
hb_allocator_T* allocator
|
|
25
28
|
);
|
|
26
29
|
|
|
27
|
-
location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source);
|
|
28
|
-
location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause);
|
|
29
|
-
location_T* get_then_keyword_location_elsif_wrapped(const char* source);
|
|
30
|
+
location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source, hb_allocator_T* allocator);
|
|
31
|
+
location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause, hb_allocator_T* allocator);
|
|
32
|
+
location_T* get_then_keyword_location_elsif_wrapped(const char* source, hb_allocator_T* allocator);
|
|
30
33
|
|
|
31
34
|
#endif
|
data/src/include/token.h
CHANGED
|
@@ -4,15 +4,27 @@
|
|
|
4
4
|
#include "lexer_struct.h"
|
|
5
5
|
#include "position.h"
|
|
6
6
|
#include "token_struct.h"
|
|
7
|
+
#include "util/hb_allocator.h"
|
|
7
8
|
#include "util/hb_string.h"
|
|
8
9
|
|
|
10
|
+
#include <stdarg.h>
|
|
11
|
+
|
|
9
12
|
token_T* token_init(hb_string_T value, token_type_T type, lexer_T* lexer);
|
|
10
|
-
hb_string_T token_to_string(const token_T* token);
|
|
11
|
-
|
|
13
|
+
hb_string_T token_to_string(hb_allocator_T* allocator, const token_T* token);
|
|
14
|
+
hb_string_T token_type_to_string(token_type_T type);
|
|
15
|
+
hb_string_T token_type_to_friendly_string(token_type_T type);
|
|
16
|
+
char* token_types_to_friendly_string_va(hb_allocator_T* allocator, token_type_T first_token, ...);
|
|
17
|
+
char* token_types_to_friendly_string_valist(hb_allocator_T* allocator, token_type_T first_token, va_list args);
|
|
18
|
+
|
|
19
|
+
#define token_types_to_friendly_string(allocator, ...) \
|
|
20
|
+
token_types_to_friendly_string_va(allocator, __VA_ARGS__, TOKEN_SENTINEL)
|
|
21
|
+
|
|
22
|
+
hb_string_T token_value(const token_T* token);
|
|
23
|
+
int token_type(const token_T* token);
|
|
12
24
|
|
|
13
|
-
token_T* token_copy(token_T* token);
|
|
25
|
+
token_T* token_copy(token_T* token, hb_allocator_T* allocator);
|
|
14
26
|
|
|
15
|
-
void token_free(token_T* token);
|
|
27
|
+
void token_free(token_T* token, hb_allocator_T* allocator);
|
|
16
28
|
|
|
17
29
|
bool token_value_empty(const token_T* token);
|
|
18
30
|
|
data/src/include/token_struct.h
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#ifndef HERB_TOKEN_STRUCT_H
|
|
2
2
|
#define HERB_TOKEN_STRUCT_H
|
|
3
3
|
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
|
|
4
6
|
#include "location.h"
|
|
5
7
|
#include "range.h"
|
|
8
|
+
#include "util/hb_string.h"
|
|
6
9
|
|
|
7
10
|
typedef enum {
|
|
8
11
|
TOKEN_WHITESPACE, // ' '
|
|
@@ -21,8 +24,9 @@ typedef enum {
|
|
|
21
24
|
TOKEN_HTML_TAG_END, // >
|
|
22
25
|
TOKEN_HTML_TAG_SELF_CLOSE, // />
|
|
23
26
|
|
|
24
|
-
TOKEN_HTML_COMMENT_START,
|
|
25
|
-
TOKEN_HTML_COMMENT_END,
|
|
27
|
+
TOKEN_HTML_COMMENT_START, // <!--
|
|
28
|
+
TOKEN_HTML_COMMENT_END, // -->
|
|
29
|
+
TOKEN_HTML_COMMENT_INVALID_END, // --!>
|
|
26
30
|
|
|
27
31
|
TOKEN_ERB_START, // <%, <%=, <%%=, <%#, <%-, <%==, <%%
|
|
28
32
|
TOKEN_ERB_CONTENT, // Ruby Code
|
|
@@ -48,8 +52,11 @@ typedef enum {
|
|
|
48
52
|
TOKEN_EOF,
|
|
49
53
|
} token_type_T;
|
|
50
54
|
|
|
55
|
+
// Sentinel value for variadic functions
|
|
56
|
+
#define TOKEN_SENTINEL 99999999
|
|
57
|
+
|
|
51
58
|
typedef struct TOKEN_STRUCT {
|
|
52
|
-
|
|
59
|
+
hb_string_T value;
|
|
53
60
|
range_T range;
|
|
54
61
|
location_T location;
|
|
55
62
|
token_type_T type;
|
data/src/include/utf8.h
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#ifndef HERB_UTF8_H
|
|
2
2
|
#define HERB_UTF8_H
|
|
3
3
|
|
|
4
|
+
#include "util/hb_string.h"
|
|
4
5
|
#include <stdbool.h>
|
|
5
6
|
#include <stdint.h>
|
|
6
7
|
#include <stdlib.h>
|
|
7
8
|
|
|
8
9
|
uint32_t utf8_char_byte_length(unsigned char first_byte);
|
|
9
|
-
uint32_t utf8_sequence_length(
|
|
10
|
+
uint32_t utf8_sequence_length(hb_string_T value);
|
|
10
11
|
bool utf8_is_valid_continuation_byte(unsigned char byte);
|
|
11
12
|
|
|
12
13
|
#endif
|