herb 0.1.0-x86_64-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 +7 -0
- data/License.txt +21 -0
- data/Makefile +121 -0
- data/README.md +166 -0
- data/Rakefile +184 -0
- data/exe/herb +5 -0
- data/ext/herb/error_helpers.c +302 -0
- data/ext/herb/error_helpers.h +15 -0
- data/ext/herb/extconf.rb +75 -0
- data/ext/herb/extension.c +110 -0
- data/ext/herb/extension.h +6 -0
- data/ext/herb/extension_helpers.c +117 -0
- data/ext/herb/extension_helpers.h +24 -0
- data/ext/herb/nodes.c +936 -0
- data/ext/herb/nodes.h +12 -0
- data/herb.gemspec +49 -0
- 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/ast/node.rb +61 -0
- data/lib/herb/ast/nodes.rb +1542 -0
- data/lib/herb/ast.rb +6 -0
- data/lib/herb/cli.rb +164 -0
- data/lib/herb/errors.rb +352 -0
- data/lib/herb/lex_result.rb +20 -0
- data/lib/herb/libherb/array.rb +48 -0
- data/lib/herb/libherb/ast_node.rb +47 -0
- data/lib/herb/libherb/buffer.rb +53 -0
- data/lib/herb/libherb/extract_result.rb +17 -0
- data/lib/herb/libherb/lex_result.rb +29 -0
- data/lib/herb/libherb/libherb.rb +49 -0
- data/lib/herb/libherb/parse_result.rb +17 -0
- data/lib/herb/libherb/token.rb +43 -0
- data/lib/herb/libherb.rb +32 -0
- data/lib/herb/location.rb +42 -0
- data/lib/herb/parse_result.rb +26 -0
- data/lib/herb/position.rb +36 -0
- data/lib/herb/project.rb +361 -0
- data/lib/herb/range.rb +40 -0
- data/lib/herb/result.rb +21 -0
- data/lib/herb/token.rb +43 -0
- data/lib/herb/token_list.rb +11 -0
- data/lib/herb/version.rb +5 -0
- data/lib/herb.rb +32 -0
- data/src/analyze.c +989 -0
- data/src/analyze_helpers.c +241 -0
- data/src/analyzed_ruby.c +35 -0
- data/src/array.c +137 -0
- data/src/ast_node.c +81 -0
- data/src/ast_nodes.c +866 -0
- data/src/ast_pretty_print.c +588 -0
- data/src/buffer.c +199 -0
- data/src/errors.c +740 -0
- data/src/extract.c +110 -0
- data/src/herb.c +103 -0
- data/src/html_util.c +143 -0
- data/src/include/analyze.h +36 -0
- data/src/include/analyze_helpers.h +43 -0
- data/src/include/analyzed_ruby.h +33 -0
- data/src/include/array.h +33 -0
- data/src/include/ast_node.h +35 -0
- data/src/include/ast_nodes.h +303 -0
- data/src/include/ast_pretty_print.h +17 -0
- data/src/include/buffer.h +36 -0
- data/src/include/errors.h +125 -0
- data/src/include/extract.h +20 -0
- data/src/include/herb.h +32 -0
- data/src/include/html_util.h +13 -0
- data/src/include/io.h +9 -0
- data/src/include/json.h +28 -0
- data/src/include/lexer.h +13 -0
- data/src/include/lexer_peek_helpers.h +23 -0
- data/src/include/lexer_struct.h +32 -0
- data/src/include/location.h +25 -0
- data/src/include/macros.h +10 -0
- data/src/include/memory.h +12 -0
- data/src/include/parser.h +22 -0
- data/src/include/parser_helpers.h +33 -0
- data/src/include/position.h +22 -0
- data/src/include/pretty_print.h +53 -0
- data/src/include/prism_helpers.h +18 -0
- data/src/include/range.h +23 -0
- data/src/include/ruby_parser.h +6 -0
- data/src/include/token.h +25 -0
- data/src/include/token_matchers.h +21 -0
- data/src/include/token_struct.h +51 -0
- data/src/include/util.h +25 -0
- data/src/include/version.h +6 -0
- data/src/include/visitor.h +11 -0
- data/src/io.c +30 -0
- data/src/json.c +205 -0
- data/src/lexer.c +284 -0
- data/src/lexer_peek_helpers.c +59 -0
- data/src/location.c +41 -0
- data/src/main.c +162 -0
- data/src/memory.c +53 -0
- data/src/parser.c +704 -0
- data/src/parser_helpers.c +161 -0
- data/src/position.c +33 -0
- data/src/pretty_print.c +242 -0
- data/src/prism_helpers.c +50 -0
- data/src/range.c +38 -0
- data/src/ruby_parser.c +47 -0
- data/src/token.c +194 -0
- data/src/token_matchers.c +32 -0
- data/src/util.c +128 -0
- data/src/visitor.c +321 -0
- metadata +159 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
#include "include/parser_helpers.h"
|
2
|
+
#include "include/array.h"
|
3
|
+
#include "include/ast_node.h"
|
4
|
+
#include "include/ast_nodes.h"
|
5
|
+
#include "include/buffer.h"
|
6
|
+
#include "include/errors.h"
|
7
|
+
#include "include/html_util.h"
|
8
|
+
#include "include/lexer.h"
|
9
|
+
#include "include/parser.h"
|
10
|
+
#include "include/token.h"
|
11
|
+
|
12
|
+
#include <stdio.h>
|
13
|
+
#include <strings.h>
|
14
|
+
|
15
|
+
void parser_push_open_tag(const parser_T* parser, token_T* tag_name) {
|
16
|
+
token_T* copy = token_copy(tag_name);
|
17
|
+
array_push(parser->open_tags_stack, copy);
|
18
|
+
}
|
19
|
+
|
20
|
+
bool parser_check_matching_tag(const parser_T* parser, const char* tag_name) {
|
21
|
+
if (array_size(parser->open_tags_stack) == 0) { return false; }
|
22
|
+
|
23
|
+
token_T* top_token = array_last(parser->open_tags_stack);
|
24
|
+
if (top_token == NULL || top_token->value == NULL) { return false; };
|
25
|
+
|
26
|
+
return (strcasecmp(top_token->value, tag_name) == 0);
|
27
|
+
}
|
28
|
+
|
29
|
+
token_T* parser_pop_open_tag(const parser_T* parser) {
|
30
|
+
if (array_size(parser->open_tags_stack) == 0) { return NULL; }
|
31
|
+
|
32
|
+
return array_pop(parser->open_tags_stack);
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Checks if any element in the open tags stack is an SVG element.
|
37
|
+
*
|
38
|
+
* @param parser The parser containing the open tags stack.
|
39
|
+
* @return true if an SVG tag is found in the stack, false otherwise.
|
40
|
+
*/
|
41
|
+
bool parser_in_svg_context(const parser_T* parser) {
|
42
|
+
if (!parser || !parser->open_tags_stack) { return false; }
|
43
|
+
|
44
|
+
size_t stack_size = array_size(parser->open_tags_stack);
|
45
|
+
|
46
|
+
for (size_t i = 0; i < stack_size; i++) {
|
47
|
+
token_T* tag = (token_T*) array_get(parser->open_tags_stack, i);
|
48
|
+
|
49
|
+
if (tag && tag->value) {
|
50
|
+
if (strcasecmp(tag->value, "svg") == 0) { return true; }
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
return false;
|
55
|
+
}
|
56
|
+
|
57
|
+
void parser_append_unexpected_error(parser_T* parser, const char* description, const char* expected, array_T* errors) {
|
58
|
+
token_T* token = parser_advance(parser);
|
59
|
+
|
60
|
+
append_unexpected_error(
|
61
|
+
description,
|
62
|
+
expected,
|
63
|
+
token_type_to_string(token->type),
|
64
|
+
token->location->start,
|
65
|
+
token->location->end,
|
66
|
+
errors
|
67
|
+
);
|
68
|
+
|
69
|
+
token_free(token);
|
70
|
+
}
|
71
|
+
|
72
|
+
void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, array_T* errors) {
|
73
|
+
append_unexpected_token_error(
|
74
|
+
expected_type,
|
75
|
+
parser->current_token,
|
76
|
+
parser->current_token->location->start,
|
77
|
+
parser->current_token->location->end,
|
78
|
+
errors
|
79
|
+
);
|
80
|
+
}
|
81
|
+
|
82
|
+
void parser_append_literal_node_from_buffer(
|
83
|
+
const parser_T* parser, buffer_T* buffer, array_T* children, position_T* start
|
84
|
+
) {
|
85
|
+
if (buffer_length(buffer) == 0) { return; }
|
86
|
+
|
87
|
+
AST_LITERAL_NODE_T* literal =
|
88
|
+
ast_literal_node_init(buffer_value(buffer), start, parser->current_token->location->start, NULL);
|
89
|
+
|
90
|
+
if (children != NULL) { array_append(children, literal); }
|
91
|
+
buffer_clear(buffer);
|
92
|
+
}
|
93
|
+
|
94
|
+
token_T* parser_advance(parser_T* parser) {
|
95
|
+
token_T* token = parser->current_token;
|
96
|
+
parser->current_token = lexer_next_token(parser->lexer);
|
97
|
+
return token;
|
98
|
+
}
|
99
|
+
|
100
|
+
token_T* parser_consume_if_present(parser_T* parser, const token_type_T type) {
|
101
|
+
if (parser->current_token->type != type) { return NULL; }
|
102
|
+
return parser_advance(parser);
|
103
|
+
}
|
104
|
+
|
105
|
+
token_T* parser_consume_expected(parser_T* parser, const token_type_T expected_type, array_T* array) {
|
106
|
+
token_T* token = parser_consume_if_present(parser, expected_type);
|
107
|
+
|
108
|
+
if (token == NULL) {
|
109
|
+
token = parser_advance(parser);
|
110
|
+
|
111
|
+
append_unexpected_token_error(expected_type, token, token->location->start, token->location->end, array);
|
112
|
+
}
|
113
|
+
|
114
|
+
return token;
|
115
|
+
}
|
116
|
+
|
117
|
+
AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
|
118
|
+
AST_HTML_OPEN_TAG_NODE_T* open_tag, array_T* body, array_T* errors
|
119
|
+
) {
|
120
|
+
append_missing_closing_tag_error(
|
121
|
+
open_tag->tag_name,
|
122
|
+
open_tag->tag_name->location->start,
|
123
|
+
open_tag->tag_name->location->end,
|
124
|
+
errors
|
125
|
+
);
|
126
|
+
|
127
|
+
return ast_html_element_node_init(
|
128
|
+
open_tag,
|
129
|
+
open_tag->tag_name,
|
130
|
+
body,
|
131
|
+
NULL,
|
132
|
+
false,
|
133
|
+
open_tag->base.location->start,
|
134
|
+
open_tag->base.location->end,
|
135
|
+
errors
|
136
|
+
);
|
137
|
+
}
|
138
|
+
|
139
|
+
void parser_handle_mismatched_tags(
|
140
|
+
const parser_T* parser, const AST_HTML_CLOSE_TAG_NODE_T* close_tag, array_T* errors
|
141
|
+
) {
|
142
|
+
if (array_size(parser->open_tags_stack) > 0) {
|
143
|
+
token_T* expected_tag = array_last(parser->open_tags_stack);
|
144
|
+
token_T* actual_tag = close_tag->tag_name;
|
145
|
+
|
146
|
+
append_tag_names_mismatch_error(
|
147
|
+
expected_tag,
|
148
|
+
actual_tag,
|
149
|
+
actual_tag->location->start,
|
150
|
+
actual_tag->location->end,
|
151
|
+
errors
|
152
|
+
);
|
153
|
+
} else {
|
154
|
+
append_missing_opening_tag_error(
|
155
|
+
close_tag->tag_name,
|
156
|
+
close_tag->tag_name->location->start,
|
157
|
+
close_tag->tag_name->location->end,
|
158
|
+
errors
|
159
|
+
);
|
160
|
+
}
|
161
|
+
}
|
data/src/position.c
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#include "include/position.h"
|
2
|
+
#include "include/memory.h"
|
3
|
+
|
4
|
+
size_t position_sizeof(void) {
|
5
|
+
return sizeof(position_T);
|
6
|
+
}
|
7
|
+
|
8
|
+
position_T* position_init(const size_t line, const size_t column) {
|
9
|
+
position_T* position = safe_malloc(position_sizeof());
|
10
|
+
|
11
|
+
position->line = line;
|
12
|
+
position->column = column;
|
13
|
+
|
14
|
+
return position;
|
15
|
+
}
|
16
|
+
|
17
|
+
size_t position_line(const position_T* position) {
|
18
|
+
return position->line;
|
19
|
+
}
|
20
|
+
|
21
|
+
size_t position_column(const position_T* position) {
|
22
|
+
return position->column;
|
23
|
+
}
|
24
|
+
|
25
|
+
position_T* position_copy(position_T* position) {
|
26
|
+
if (position == NULL) { return NULL; }
|
27
|
+
|
28
|
+
return position_init(position_line(position), position_column(position));
|
29
|
+
}
|
30
|
+
|
31
|
+
void position_free(position_T* position) {
|
32
|
+
free(position);
|
33
|
+
}
|
data/src/pretty_print.c
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
#include "include/pretty_print.h"
|
2
|
+
#include "include/analyzed_ruby.h"
|
3
|
+
#include "include/ast_node.h"
|
4
|
+
#include "include/ast_nodes.h"
|
5
|
+
#include "include/ast_pretty_print.h"
|
6
|
+
#include "include/buffer.h"
|
7
|
+
#include "include/errors.h"
|
8
|
+
#include "include/token_struct.h"
|
9
|
+
#include "include/util.h"
|
10
|
+
|
11
|
+
#include <stdbool.h>
|
12
|
+
#include <stdio.h>
|
13
|
+
#include <stdlib.h>
|
14
|
+
|
15
|
+
void pretty_print_indent(buffer_T* buffer, const size_t indent) {
|
16
|
+
for (size_t i = 0; i < indent; i++) {
|
17
|
+
buffer_append(buffer, " ");
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
void pretty_print_newline(const size_t indent, const size_t relative_indent, buffer_T* buffer) {
|
22
|
+
pretty_print_indent(buffer, indent);
|
23
|
+
pretty_print_indent(buffer, relative_indent);
|
24
|
+
buffer_append(buffer, "\n");
|
25
|
+
}
|
26
|
+
|
27
|
+
void pretty_print_label(
|
28
|
+
const char* name, const size_t indent, const size_t relative_indent, const bool last_property, buffer_T* buffer
|
29
|
+
) {
|
30
|
+
pretty_print_indent(buffer, indent);
|
31
|
+
pretty_print_indent(buffer, relative_indent);
|
32
|
+
|
33
|
+
if (last_property) {
|
34
|
+
buffer_append(buffer, "└── ");
|
35
|
+
} else {
|
36
|
+
buffer_append(buffer, "├── ");
|
37
|
+
}
|
38
|
+
|
39
|
+
buffer_append(buffer, name);
|
40
|
+
buffer_append(buffer, ": ");
|
41
|
+
}
|
42
|
+
|
43
|
+
void pretty_print_quoted_property(
|
44
|
+
const char* name, const char* value, const size_t indent, const size_t relative_indent, const bool last_property,
|
45
|
+
buffer_T* buffer
|
46
|
+
) {
|
47
|
+
char* quoted = quoted_string(value);
|
48
|
+
pretty_print_property(name, quoted, indent, relative_indent, last_property, buffer);
|
49
|
+
free(quoted);
|
50
|
+
}
|
51
|
+
|
52
|
+
void pretty_print_boolean_property(
|
53
|
+
const char* name, bool value, const size_t indent, const size_t relative_indent, const bool last_property,
|
54
|
+
buffer_T* buffer
|
55
|
+
) {
|
56
|
+
pretty_print_property(name, value ? "true" : "false", indent, relative_indent, last_property, buffer);
|
57
|
+
}
|
58
|
+
|
59
|
+
void pretty_print_property(
|
60
|
+
const char* name, const char* value, const size_t indent, const size_t relative_indent, const bool last_property,
|
61
|
+
buffer_T* buffer
|
62
|
+
) {
|
63
|
+
pretty_print_label(name, indent, relative_indent, last_property, buffer);
|
64
|
+
buffer_append(buffer, value);
|
65
|
+
buffer_append(buffer, "\n");
|
66
|
+
}
|
67
|
+
|
68
|
+
void pretty_print_size_t_property(
|
69
|
+
size_t value, const char* name, const size_t indent, const size_t relative_indent, const bool last_property,
|
70
|
+
buffer_T* buffer
|
71
|
+
) {
|
72
|
+
pretty_print_label(name, indent, relative_indent, last_property, buffer);
|
73
|
+
char* string = size_t_to_string(value);
|
74
|
+
buffer_append(buffer, string);
|
75
|
+
buffer_append(buffer, "\n");
|
76
|
+
free(string);
|
77
|
+
}
|
78
|
+
|
79
|
+
void pretty_print_array(
|
80
|
+
const char* name, array_T* array, const size_t indent, const size_t relative_indent, const bool last_property,
|
81
|
+
buffer_T* buffer
|
82
|
+
) {
|
83
|
+
if (array == NULL) {
|
84
|
+
pretty_print_property(name, "∅", indent, relative_indent, last_property, buffer);
|
85
|
+
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
if (array_size(array) == 0) {
|
90
|
+
pretty_print_property(name, "[]", indent, relative_indent, last_property, buffer);
|
91
|
+
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
|
95
|
+
pretty_print_label(name, indent, relative_indent, last_property, buffer);
|
96
|
+
|
97
|
+
buffer_append(buffer, "(");
|
98
|
+
|
99
|
+
char count[16];
|
100
|
+
sprintf(count, "%zu", array_size(array));
|
101
|
+
buffer_append(buffer, count);
|
102
|
+
buffer_append(buffer, ")\n");
|
103
|
+
|
104
|
+
if (indent < 20) {
|
105
|
+
for (size_t i = 0; i < array_size(array); i++) {
|
106
|
+
AST_NODE_T* child = array_get(array, i);
|
107
|
+
pretty_print_indent(buffer, indent);
|
108
|
+
pretty_print_indent(buffer, relative_indent + 1);
|
109
|
+
|
110
|
+
if (i == array_size(array) - 1) {
|
111
|
+
buffer_append(buffer, "└── ");
|
112
|
+
} else {
|
113
|
+
buffer_append(buffer, "├── ");
|
114
|
+
}
|
115
|
+
|
116
|
+
ast_pretty_print_node(child, indent + 1, relative_indent + 1, buffer);
|
117
|
+
|
118
|
+
if (i != array_size(array) - 1) { pretty_print_newline(indent + 1, relative_indent, buffer); }
|
119
|
+
}
|
120
|
+
}
|
121
|
+
buffer_append(buffer, "\n");
|
122
|
+
}
|
123
|
+
|
124
|
+
void pretty_print_errors(
|
125
|
+
AST_NODE_T* node, const size_t indent, const size_t relative_indent, const bool last_property, buffer_T* buffer
|
126
|
+
) {
|
127
|
+
if (node->errors != NULL && array_size(node->errors) > 0) {
|
128
|
+
error_pretty_print_array("errors", node->errors, indent, relative_indent, last_property, buffer);
|
129
|
+
buffer_append(buffer, "\n");
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
void pretty_print_location(location_T* location, buffer_T* buffer) {
|
134
|
+
buffer_append(buffer, "(location: (");
|
135
|
+
char location_string[128];
|
136
|
+
sprintf(
|
137
|
+
location_string,
|
138
|
+
"%zu,%zu)-(%zu,%zu",
|
139
|
+
(location->start && location->start->line) ? location->start->line : 0,
|
140
|
+
(location->start && location->start->column) ? location->start->column : 0,
|
141
|
+
(location->end && location->end->line) ? location->end->line : 0,
|
142
|
+
(location->end && location->end->column) ? location->end->column : 0
|
143
|
+
);
|
144
|
+
buffer_append(buffer, location_string);
|
145
|
+
buffer_append(buffer, "))");
|
146
|
+
}
|
147
|
+
|
148
|
+
void pretty_print_position_property(
|
149
|
+
position_T* position, const char* name, const size_t indent, const size_t relative_indent, const bool last_property,
|
150
|
+
buffer_T* buffer
|
151
|
+
) {
|
152
|
+
pretty_print_label(name, indent, relative_indent, last_property, buffer);
|
153
|
+
|
154
|
+
if (position != NULL) {
|
155
|
+
buffer_append(buffer, "(");
|
156
|
+
|
157
|
+
char position_string[128];
|
158
|
+
|
159
|
+
sprintf(
|
160
|
+
position_string,
|
161
|
+
"%zu:%zu",
|
162
|
+
(position->line) ? position->line : 0,
|
163
|
+
(position->column) ? position->column : 0
|
164
|
+
);
|
165
|
+
|
166
|
+
buffer_append(buffer, position_string);
|
167
|
+
buffer_append(buffer, ")");
|
168
|
+
} else {
|
169
|
+
buffer_append(buffer, "∅");
|
170
|
+
}
|
171
|
+
|
172
|
+
buffer_append(buffer, "\n");
|
173
|
+
}
|
174
|
+
|
175
|
+
void pretty_print_token_property(
|
176
|
+
token_T* token, const char* name, const size_t indent, const size_t relative_indent, const bool last_property,
|
177
|
+
buffer_T* buffer
|
178
|
+
) {
|
179
|
+
pretty_print_label(name, indent, relative_indent, last_property, buffer);
|
180
|
+
|
181
|
+
if (token != NULL && token->value != NULL) {
|
182
|
+
char* quoted = quoted_string(token->value);
|
183
|
+
buffer_append(buffer, quoted);
|
184
|
+
free(quoted);
|
185
|
+
|
186
|
+
buffer_append(buffer, " ");
|
187
|
+
pretty_print_location(token->location, buffer);
|
188
|
+
} else {
|
189
|
+
buffer_append(buffer, "∅");
|
190
|
+
}
|
191
|
+
|
192
|
+
buffer_append(buffer, "\n");
|
193
|
+
}
|
194
|
+
|
195
|
+
void pretty_print_string_property(
|
196
|
+
const char* string, const char* name, const size_t indent, const size_t relative_indent, const bool last_property,
|
197
|
+
buffer_T* buffer
|
198
|
+
) {
|
199
|
+
const char* value = "∅";
|
200
|
+
char* escaped = NULL;
|
201
|
+
char* quoted = NULL;
|
202
|
+
|
203
|
+
if (string != NULL) {
|
204
|
+
escaped = escape_newlines(string);
|
205
|
+
quoted = quoted_string(escaped);
|
206
|
+
value = quoted;
|
207
|
+
}
|
208
|
+
|
209
|
+
pretty_print_property(name, value, indent, relative_indent, last_property, buffer);
|
210
|
+
|
211
|
+
if (string != NULL) {
|
212
|
+
if (escaped != NULL) { free(escaped); }
|
213
|
+
if (quoted != NULL) { free(quoted); }
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
void pretty_print_analyed_ruby(analyzed_ruby_T* analyzed, const char* source) {
|
218
|
+
printf(
|
219
|
+
"------------------------\nanalyzed (%p)\n------------------------\n%s\n------------------------\n if: %i\n "
|
220
|
+
" elsif: %i\n else: %i\n end: %i\n block: %i\n block_closing: %i\n case: %i\n when: %i\n for: "
|
221
|
+
"%i\n while: %i\n "
|
222
|
+
" until: %i\n begin: %i\n "
|
223
|
+
"rescue: %i\n ensure: %i\n unless: %i\n==================\n\n",
|
224
|
+
(void*) analyzed,
|
225
|
+
source,
|
226
|
+
analyzed->has_if_node,
|
227
|
+
analyzed->has_elsif_node,
|
228
|
+
analyzed->has_else_node,
|
229
|
+
analyzed->has_end,
|
230
|
+
analyzed->has_block_node,
|
231
|
+
analyzed->has_block_closing,
|
232
|
+
analyzed->has_case_node,
|
233
|
+
analyzed->has_when_node,
|
234
|
+
analyzed->has_for_node,
|
235
|
+
analyzed->has_while_node,
|
236
|
+
analyzed->has_until_node,
|
237
|
+
analyzed->has_begin_node,
|
238
|
+
analyzed->has_rescue_node,
|
239
|
+
analyzed->has_ensure_node,
|
240
|
+
analyzed->has_unless_node
|
241
|
+
);
|
242
|
+
}
|
data/src/prism_helpers.c
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#include "include/prism_helpers.h"
|
2
|
+
#include "include/ast_nodes.h"
|
3
|
+
#include "include/errors.h"
|
4
|
+
#include "include/position.h"
|
5
|
+
#include "include/util.h"
|
6
|
+
|
7
|
+
#include <prism.h>
|
8
|
+
|
9
|
+
const char* pm_error_level_to_string(pm_error_level_t level) {
|
10
|
+
switch (level) {
|
11
|
+
case PM_ERROR_LEVEL_SYNTAX: return "syntax";
|
12
|
+
case PM_ERROR_LEVEL_ARGUMENT: return "argument";
|
13
|
+
case PM_ERROR_LEVEL_LOAD: return "load";
|
14
|
+
|
15
|
+
default: return "Unknown pm_error_level_t";
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
position_T* position_from_source_with_offset(const char* source, size_t offset) {
|
20
|
+
position_T* position = position_init(1, 0);
|
21
|
+
|
22
|
+
for (size_t i = 0; i < offset; i++) {
|
23
|
+
if (is_newline(source[i])) {
|
24
|
+
position->line++;
|
25
|
+
position->column = 0;
|
26
|
+
} else {
|
27
|
+
position->column++;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
return position;
|
32
|
+
}
|
33
|
+
|
34
|
+
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
|
35
|
+
const pm_diagnostic_t* error, const AST_NODE_T* node, const char* source, pm_parser_t* parser
|
36
|
+
) {
|
37
|
+
size_t start_offset = (size_t) (error->location.start - parser->start);
|
38
|
+
size_t end_offset = (size_t) (error->location.end - parser->start);
|
39
|
+
|
40
|
+
position_T* start = position_from_source_with_offset(source, start_offset);
|
41
|
+
position_T* end = position_from_source_with_offset(source, end_offset);
|
42
|
+
|
43
|
+
return ruby_parse_error_init(
|
44
|
+
error->message,
|
45
|
+
pm_diagnostic_id_human(error->diag_id),
|
46
|
+
pm_error_level_to_string(error->level),
|
47
|
+
start,
|
48
|
+
end
|
49
|
+
);
|
50
|
+
}
|
data/src/range.c
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#include "include/range.h"
|
2
|
+
|
3
|
+
size_t range_sizeof(void) {
|
4
|
+
return sizeof(range_T);
|
5
|
+
}
|
6
|
+
|
7
|
+
range_T* range_init(const size_t from, const size_t to) {
|
8
|
+
range_T* range = calloc(1, range_sizeof());
|
9
|
+
|
10
|
+
range->from = from;
|
11
|
+
range->to = to;
|
12
|
+
|
13
|
+
return range;
|
14
|
+
}
|
15
|
+
|
16
|
+
size_t range_from(const range_T* range) {
|
17
|
+
return range->from;
|
18
|
+
}
|
19
|
+
|
20
|
+
size_t range_to(const range_T* range) {
|
21
|
+
return range->to;
|
22
|
+
}
|
23
|
+
|
24
|
+
size_t range_length(range_T* range) {
|
25
|
+
return range_to(range) - range_from(range);
|
26
|
+
}
|
27
|
+
|
28
|
+
range_T* range_copy(range_T* range) {
|
29
|
+
if (!range) { return NULL; }
|
30
|
+
|
31
|
+
return range_init(range_from(range), range_to(range));
|
32
|
+
}
|
33
|
+
|
34
|
+
void range_free(range_T* range) {
|
35
|
+
if (range == NULL) { return; }
|
36
|
+
|
37
|
+
free(range);
|
38
|
+
}
|
data/src/ruby_parser.c
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#include "include/ruby_parser.h"
|
2
|
+
|
3
|
+
#include <prism.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <string.h>
|
6
|
+
|
7
|
+
static bool herb_prism_visit(const pm_node_t* node, void* data) {
|
8
|
+
const size_t* indent = (size_t*) data;
|
9
|
+
|
10
|
+
for (size_t i = 0; i < *indent * 2; i++) {
|
11
|
+
putc(' ', stdout);
|
12
|
+
}
|
13
|
+
|
14
|
+
printf("%s\n", pm_node_type_to_str(node->type));
|
15
|
+
|
16
|
+
size_t next_indent = *indent + 1;
|
17
|
+
size_t* next_data = &next_indent;
|
18
|
+
pm_visit_child_nodes(node, herb_prism_visit, next_data);
|
19
|
+
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
|
23
|
+
void herb_parse_ruby_to_stdout(char* source) {
|
24
|
+
size_t length = strlen(source);
|
25
|
+
|
26
|
+
pm_parser_t parser;
|
27
|
+
pm_parser_init(&parser, (const uint8_t*) source, length, NULL);
|
28
|
+
|
29
|
+
pm_buffer_t buffer;
|
30
|
+
pm_buffer_init(&buffer);
|
31
|
+
|
32
|
+
size_t indent = 0;
|
33
|
+
pm_node_t* root = pm_parse(&parser);
|
34
|
+
size_t* data = &indent;
|
35
|
+
|
36
|
+
const char* root_type = pm_node_type_to_str(root->type);
|
37
|
+
printf("Root Type: %s\n", root_type);
|
38
|
+
|
39
|
+
pm_visit_node(root, herb_prism_visit, data);
|
40
|
+
|
41
|
+
pm_prettyprint(&buffer, &parser, root);
|
42
|
+
printf("%s\n", buffer.value);
|
43
|
+
|
44
|
+
pm_buffer_free(&buffer);
|
45
|
+
pm_node_destroy(&parser, root);
|
46
|
+
pm_parser_free(&parser);
|
47
|
+
}
|