herb 0.8.2 → 0.8.3
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/ext/herb/extconf.rb +1 -1
- data/ext/herb/extension.c +1 -1
- data/ext/herb/nodes.c +1 -1
- data/lib/herb/engine/error_formatter.rb +13 -5
- data/lib/herb/version.rb +1 -1
- data/src/analyze.c +42 -0
- data/src/ast_node.c +29 -0
- data/src/extract.c +5 -71
- data/src/herb.c +7 -7
- data/src/include/ast_node.h +2 -0
- data/src/include/extract.h +0 -1
- data/src/include/herb.h +8 -7
- data/src/include/macros.h +8 -0
- data/src/include/position.h +5 -0
- data/src/include/prism_helpers.h +5 -1
- data/src/include/version.h +1 -1
- data/src/position.c +27 -0
- data/src/prism_helpers.c +14 -15
- data/src/util/hb_system.c +3 -3
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a3908d930c973519ff35367b6e870825d296b040fc7b24d063cac2063bc3f444
|
|
4
|
+
data.tar.gz: 8088699f58e77d1bce02721b1808840bac6b9799e8e8ea1c978abf967c4e371a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a5702c77e7e99b6c8d9d27af6d970d0fda38e8391e14b778f6a25e2f76b17099ccbec7370263fd78ab1f6dd8446fd4820eaa625013650b1530222847672b4f8
|
|
7
|
+
data.tar.gz: fae00c8ed586d665d32f4133a1e12f4a44535e276f3924dd60524d549aa7904a65d3093994d07bae2e59b9a146bcc9638a14d8f6dcd7cb4620fa821b394b487f
|
data/ext/herb/extconf.rb
CHANGED
|
@@ -24,7 +24,7 @@ $INCFLAGS << " -I#{include_path}"
|
|
|
24
24
|
$INCFLAGS << " -I#{prism_src_path}"
|
|
25
25
|
$INCFLAGS << " -I#{prism_src_path}/util"
|
|
26
26
|
|
|
27
|
-
$CFLAGS << " -
|
|
27
|
+
$CFLAGS << " -fvisibility=hidden"
|
|
28
28
|
|
|
29
29
|
herb_src_files = Dir.glob("#{$srcdir}/../../src/**/*.c").map { |file| file.delete_prefix("../../../../ext/herb/") }.sort
|
|
30
30
|
|
data/ext/herb/extension.c
CHANGED
|
@@ -124,7 +124,7 @@ static VALUE Herb_version(VALUE self) {
|
|
|
124
124
|
return rb_funcall(rb_mKernel, rb_intern("sprintf"), 4, format_string, gem_version, libprism_version, libherb_version);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
void Init_herb(void) {
|
|
127
|
+
__attribute__((__visibility__("default"))) void Init_herb(void) {
|
|
128
128
|
mHerb = rb_define_module("Herb");
|
|
129
129
|
cPosition = rb_define_class_under(mHerb, "Position", rb_cObject);
|
|
130
130
|
cLocation = rb_define_class_under(mHerb, "Location", rb_cObject);
|
data/ext/herb/nodes.c
CHANGED
|
@@ -464,7 +464,7 @@ static VALUE rb_erb_content_node_from_c_struct(AST_ERB_CONTENT_NODE_T* erb_conte
|
|
|
464
464
|
VALUE erb_content_node_tag_opening = rb_token_from_c_struct(erb_content_node->tag_opening);
|
|
465
465
|
VALUE erb_content_node_content = rb_token_from_c_struct(erb_content_node->content);
|
|
466
466
|
VALUE erb_content_node_tag_closing = rb_token_from_c_struct(erb_content_node->tag_closing);
|
|
467
|
-
/* #<Herb::Template::AnalyzedRubyField:
|
|
467
|
+
/* #<Herb::Template::AnalyzedRubyField:0x00007f1c2e6c7a68 @name="analyzed_ruby", @options={kind: nil}> */
|
|
468
468
|
VALUE erb_content_node_analyzed_ruby = Qnil;
|
|
469
469
|
VALUE erb_content_node_parsed = (erb_content_node->parsed) ? Qtrue : Qfalse;
|
|
470
470
|
VALUE erb_content_node_valid = (erb_content_node->valid) ? Qtrue : Qfalse;
|
|
@@ -98,16 +98,24 @@ module Herb
|
|
|
98
98
|
def format_error(error, number)
|
|
99
99
|
output = String.new
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
error_name = if error.is_a?(Hash)
|
|
102
|
+
error[:code] || "UnknownError"
|
|
103
|
+
else
|
|
104
|
+
error.class.name.split("::").last.gsub(/Error$/, "")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
output << "Error ##{number}: #{error_name}\n"
|
|
102
108
|
output << ("-" * 40) << "\n"
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
location = error.is_a?(Hash) ? error[:location] : error.location
|
|
111
|
+
if location
|
|
105
112
|
output << " File: #{@filename}\n"
|
|
106
|
-
output << " Location: Line #{
|
|
113
|
+
output << " Location: Line #{location.start.line}, Column #{location.start.column}\n"
|
|
107
114
|
end
|
|
108
115
|
|
|
109
|
-
|
|
110
|
-
output <<
|
|
116
|
+
error_message = error.is_a?(Hash) ? error[:message] : error.message
|
|
117
|
+
output << " Message: #{error_message}\n\n"
|
|
118
|
+
output << format_source_context(error) if location
|
|
111
119
|
output << format_error_details(error)
|
|
112
120
|
|
|
113
121
|
output
|
data/lib/herb/version.rb
CHANGED
data/src/analyze.c
CHANGED
|
@@ -1409,6 +1409,35 @@ void herb_analyze_parse_tree(AST_DOCUMENT_NODE_T* document, const char* source)
|
|
|
1409
1409
|
free(invalid_context);
|
|
1410
1410
|
}
|
|
1411
1411
|
|
|
1412
|
+
static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source) {
|
|
1413
|
+
if (!erb_node || erb_node->type != AST_ERB_CONTENT_NODE) { return; }
|
|
1414
|
+
AST_ERB_CONTENT_NODE_T* content_node = (AST_ERB_CONTENT_NODE_T*) erb_node;
|
|
1415
|
+
|
|
1416
|
+
if (!content_node->content || !content_node->content->value) { return; }
|
|
1417
|
+
|
|
1418
|
+
const char* content = content_node->content->value;
|
|
1419
|
+
if (strlen(content) == 0) { return; }
|
|
1420
|
+
|
|
1421
|
+
pm_parser_t parser;
|
|
1422
|
+
pm_options_t options = { 0, .partial_script = true };
|
|
1423
|
+
pm_parser_init(&parser, (const uint8_t*) content, strlen(content), &options);
|
|
1424
|
+
|
|
1425
|
+
pm_node_t* root = pm_parse(&parser);
|
|
1426
|
+
|
|
1427
|
+
const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head;
|
|
1428
|
+
|
|
1429
|
+
if (error != NULL) {
|
|
1430
|
+
RUBY_PARSE_ERROR_T* parse_error =
|
|
1431
|
+
ruby_parse_error_from_prism_error_with_positions(error, erb_node->location.start, erb_node->location.end);
|
|
1432
|
+
|
|
1433
|
+
hb_array_append(erb_node->errors, parse_error);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
pm_node_destroy(&parser, root);
|
|
1437
|
+
pm_parser_free(&parser);
|
|
1438
|
+
pm_options_free(&options);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1412
1441
|
void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source) {
|
|
1413
1442
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source);
|
|
1414
1443
|
|
|
@@ -1422,6 +1451,19 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
|
1422
1451
|
|
|
1423
1452
|
for (const pm_diagnostic_t* error = (const pm_diagnostic_t*) parser.error_list.head; error != NULL;
|
|
1424
1453
|
error = (const pm_diagnostic_t*) error->node.next) {
|
|
1454
|
+
size_t error_offset = (size_t) (error->location.start - parser.start);
|
|
1455
|
+
|
|
1456
|
+
if (strstr(error->message, "unexpected ';'") != NULL) {
|
|
1457
|
+
if (error_offset < strlen(extracted_ruby) && extracted_ruby[error_offset] == ';') {
|
|
1458
|
+
if (error_offset >= strlen(source) || source[error_offset] != ';') {
|
|
1459
|
+
AST_NODE_T* erb_node = find_erb_content_at_offset(document, source, error_offset);
|
|
1460
|
+
|
|
1461
|
+
if (erb_node) { parse_erb_content_errors(erb_node, source); }
|
|
1462
|
+
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1425
1467
|
|
|
1426
1468
|
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser);
|
|
1427
1469
|
hb_array_append(document->base.errors, parse_error);
|
data/src/ast_node.c
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#include "include/ast_node.h"
|
|
2
2
|
#include "include/ast_nodes.h"
|
|
3
3
|
#include "include/errors.h"
|
|
4
|
+
#include "include/position.h"
|
|
4
5
|
#include "include/token.h"
|
|
5
6
|
#include "include/util.h"
|
|
7
|
+
#include "include/visitor.h"
|
|
6
8
|
|
|
7
9
|
#include <prism.h>
|
|
8
10
|
#include <stdio.h>
|
|
@@ -76,3 +78,30 @@ void ast_node_set_positions_from_token(AST_NODE_T* node, const token_T* token) {
|
|
|
76
78
|
bool ast_node_is(const AST_NODE_T* node, const ast_node_type_T type) {
|
|
77
79
|
return node->type == type;
|
|
78
80
|
}
|
|
81
|
+
|
|
82
|
+
typedef struct {
|
|
83
|
+
position_T position;
|
|
84
|
+
AST_NODE_T* found_node;
|
|
85
|
+
} find_erb_at_position_context_T;
|
|
86
|
+
|
|
87
|
+
static bool find_erb_at_position_visitor(const AST_NODE_T* node, void* data) {
|
|
88
|
+
find_erb_at_position_context_T* context = (find_erb_at_position_context_T*) data;
|
|
89
|
+
|
|
90
|
+
if (node->type == AST_ERB_CONTENT_NODE) {
|
|
91
|
+
if (position_is_within_range(context->position, node->location.start, node->location.end)) {
|
|
92
|
+
context->found_node = (AST_NODE_T*) node;
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
AST_NODE_T* find_erb_content_at_offset(AST_DOCUMENT_NODE_T* document, const char* source, size_t offset) {
|
|
101
|
+
position_T position = position_from_source_with_offset(source, offset);
|
|
102
|
+
find_erb_at_position_context_T context = { .position = position, .found_node = NULL };
|
|
103
|
+
|
|
104
|
+
herb_visit_node((AST_NODE_T*) document, find_erb_at_position_visitor, &context);
|
|
105
|
+
|
|
106
|
+
return context.found_node;
|
|
107
|
+
}
|
data/src/extract.c
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#include <stdlib.h>
|
|
8
8
|
#include <string.h>
|
|
9
9
|
|
|
10
|
-
void
|
|
10
|
+
void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
|
|
11
11
|
hb_array_T* tokens = herb_lex(source);
|
|
12
12
|
bool skip_erb_content = false;
|
|
13
13
|
bool is_comment_tag = false;
|
|
@@ -76,75 +76,9 @@ void herb_extract_ruby_to_buffer_with_semicolons(const char* source, hb_buffer_T
|
|
|
76
76
|
break;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for (size_t j = i + 1; j < hb_array_size(tokens); j++) {
|
|
83
|
-
const token_T* next_token = hb_array_get(tokens, j);
|
|
84
|
-
|
|
85
|
-
if (next_token->type == TOKEN_NEWLINE) { break; }
|
|
86
|
-
|
|
87
|
-
if (next_token->type == TOKEN_ERB_START && next_token->location.start.line == current_line) {
|
|
88
|
-
needs_semicolon = true;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (needs_semicolon) {
|
|
94
|
-
hb_buffer_append_char(output, ' ');
|
|
95
|
-
hb_buffer_append_char(output, ';');
|
|
96
|
-
hb_buffer_append_whitespace(output, range_length(token->range) - 2);
|
|
97
|
-
} else {
|
|
98
|
-
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
99
|
-
}
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
default: {
|
|
104
|
-
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
herb_free_tokens(&tokens);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output) {
|
|
113
|
-
hb_array_T* tokens = herb_lex(source);
|
|
114
|
-
bool skip_erb_content = false;
|
|
115
|
-
|
|
116
|
-
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
117
|
-
const token_T* token = hb_array_get(tokens, i);
|
|
118
|
-
|
|
119
|
-
switch (token->type) {
|
|
120
|
-
case TOKEN_NEWLINE: {
|
|
121
|
-
hb_buffer_append(output, token->value);
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
case TOKEN_ERB_START: {
|
|
126
|
-
if (strcmp(token->value, "<%#") == 0 || strcmp(token->value, "<%%") == 0 || strcmp(token->value, "<%%=") == 0) {
|
|
127
|
-
skip_erb_content = true;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
case TOKEN_ERB_CONTENT: {
|
|
135
|
-
if (skip_erb_content == false) {
|
|
136
|
-
hb_buffer_append(output, token->value);
|
|
137
|
-
} else {
|
|
138
|
-
hb_buffer_append_whitespace(output, range_length(token->range));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
case TOKEN_ERB_END: {
|
|
145
|
-
skip_erb_content = false;
|
|
146
|
-
|
|
147
|
-
hb_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);
|
|
148
82
|
break;
|
|
149
83
|
}
|
|
150
84
|
|
|
@@ -180,7 +114,7 @@ char* herb_extract_ruby_with_semicolons(const char* source) {
|
|
|
180
114
|
hb_buffer_T output;
|
|
181
115
|
hb_buffer_init(&output, strlen(source));
|
|
182
116
|
|
|
183
|
-
|
|
117
|
+
herb_extract_ruby_to_buffer(source, &output);
|
|
184
118
|
|
|
185
119
|
return output.value;
|
|
186
120
|
}
|
data/src/herb.c
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
#include <prism.h>
|
|
11
11
|
#include <stdlib.h>
|
|
12
12
|
|
|
13
|
-
hb_array_T* herb_lex(const char* source) {
|
|
13
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex(const char* source) {
|
|
14
14
|
lexer_T lexer = { 0 };
|
|
15
15
|
lexer_init(&lexer, source);
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ hb_array_T* herb_lex(const char* source) {
|
|
|
26
26
|
return tokens;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options) {
|
|
29
|
+
HERB_EXPORTED_FUNCTION AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options) {
|
|
30
30
|
if (!source) { source = ""; }
|
|
31
31
|
|
|
32
32
|
lexer_T lexer = { 0 };
|
|
@@ -46,7 +46,7 @@ AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options) {
|
|
|
46
46
|
return document;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
hb_array_T* herb_lex_file(const char* path) {
|
|
49
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex_file(const char* path) {
|
|
50
50
|
char* source = herb_read_file(path);
|
|
51
51
|
hb_array_T* tokens = herb_lex(source);
|
|
52
52
|
|
|
@@ -55,7 +55,7 @@ hb_array_T* herb_lex_file(const char* path) {
|
|
|
55
55
|
return tokens;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
void herb_lex_to_buffer(const char* source, hb_buffer_T* output) {
|
|
58
|
+
HERB_EXPORTED_FUNCTION void herb_lex_to_buffer(const char* source, hb_buffer_T* output) {
|
|
59
59
|
hb_array_T* tokens = herb_lex(source);
|
|
60
60
|
|
|
61
61
|
for (size_t i = 0; i < hb_array_size(tokens); i++) {
|
|
@@ -71,7 +71,7 @@ void herb_lex_to_buffer(const char* source, hb_buffer_T* output) {
|
|
|
71
71
|
herb_free_tokens(&tokens);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
void herb_free_tokens(hb_array_T** tokens) {
|
|
74
|
+
HERB_EXPORTED_FUNCTION void herb_free_tokens(hb_array_T** tokens) {
|
|
75
75
|
if (!tokens || !*tokens) { return; }
|
|
76
76
|
|
|
77
77
|
for (size_t i = 0; i < hb_array_size(*tokens); i++) {
|
|
@@ -82,10 +82,10 @@ void herb_free_tokens(hb_array_T** tokens) {
|
|
|
82
82
|
hb_array_free(tokens);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const char* herb_version(void) {
|
|
85
|
+
HERB_EXPORTED_FUNCTION const char* herb_version(void) {
|
|
86
86
|
return HERB_VERSION;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
const char* herb_prism_version(void) {
|
|
89
|
+
HERB_EXPORTED_FUNCTION const char* herb_prism_version(void) {
|
|
90
90
|
return PRISM_VERSION;
|
|
91
91
|
}
|
data/src/include/ast_node.h
CHANGED
|
@@ -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
|
data/src/include/extract.h
CHANGED
|
@@ -12,7 +12,6 @@ void herb_extract_ruby_to_buffer(const char* source, hb_buffer_T* output);
|
|
|
12
12
|
void herb_extract_html_to_buffer(const char* source, hb_buffer_T* output);
|
|
13
13
|
|
|
14
14
|
char* herb_extract_ruby_with_semicolons(const char* source);
|
|
15
|
-
void herb_extract_ruby_to_buffer_with_semicolons(const char* source, hb_buffer_T* output);
|
|
16
15
|
|
|
17
16
|
char* herb_extract(const char* source, herb_extract_language_T language);
|
|
18
17
|
char* herb_extract_from_file(const char* path, herb_extract_language_T language);
|
data/src/include/herb.h
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include "ast_node.h"
|
|
5
5
|
#include "extract.h"
|
|
6
|
+
#include "macros.h"
|
|
6
7
|
#include "parser.h"
|
|
7
8
|
#include "util/hb_array.h"
|
|
8
9
|
#include "util/hb_buffer.h"
|
|
@@ -13,17 +14,17 @@
|
|
|
13
14
|
extern "C" {
|
|
14
15
|
#endif
|
|
15
16
|
|
|
16
|
-
void herb_lex_to_buffer(const char* source, hb_buffer_T* output);
|
|
17
|
+
HERB_EXPORTED_FUNCTION void herb_lex_to_buffer(const char* source, hb_buffer_T* output);
|
|
17
18
|
|
|
18
|
-
hb_array_T* herb_lex(const char* source);
|
|
19
|
-
hb_array_T* herb_lex_file(const char* path);
|
|
19
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex(const char* source);
|
|
20
|
+
HERB_EXPORTED_FUNCTION hb_array_T* herb_lex_file(const char* path);
|
|
20
21
|
|
|
21
|
-
AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options);
|
|
22
|
+
HERB_EXPORTED_FUNCTION AST_DOCUMENT_NODE_T* herb_parse(const char* source, parser_options_T* options);
|
|
22
23
|
|
|
23
|
-
const char* herb_version(void);
|
|
24
|
-
const char* herb_prism_version(void);
|
|
24
|
+
HERB_EXPORTED_FUNCTION const char* herb_version(void);
|
|
25
|
+
HERB_EXPORTED_FUNCTION const char* herb_prism_version(void);
|
|
25
26
|
|
|
26
|
-
void herb_free_tokens(hb_array_T** tokens);
|
|
27
|
+
HERB_EXPORTED_FUNCTION void herb_free_tokens(hb_array_T** tokens);
|
|
27
28
|
|
|
28
29
|
#ifdef __cplusplus
|
|
29
30
|
}
|
data/src/include/macros.h
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
#ifndef HERB_MACROS_H
|
|
2
2
|
#define HERB_MACROS_H
|
|
3
3
|
|
|
4
|
+
#ifndef HERB_EXPORTED_FUNCTION
|
|
5
|
+
# ifdef HERB_EXPORT_SYMBOLS
|
|
6
|
+
# define HERB_EXPORTED_FUNCTION __attribute__((__visibility__("default"))) extern
|
|
7
|
+
# else
|
|
8
|
+
# define HERB_EXPORTED_FUNCTION
|
|
9
|
+
# endif
|
|
10
|
+
#endif
|
|
11
|
+
|
|
4
12
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
5
13
|
|
|
6
14
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
data/src/include/position.h
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#ifndef HERB_POSITION_H
|
|
2
2
|
#define HERB_POSITION_H
|
|
3
3
|
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <stddef.h>
|
|
4
6
|
#include <stdint.h>
|
|
5
7
|
|
|
6
8
|
typedef struct POSITION_STRUCT {
|
|
@@ -8,4 +10,7 @@ typedef struct POSITION_STRUCT {
|
|
|
8
10
|
uint32_t column;
|
|
9
11
|
} position_T;
|
|
10
12
|
|
|
13
|
+
position_T position_from_source_with_offset(const char* source, size_t offset);
|
|
14
|
+
bool position_is_within_range(position_T position, position_T start, position_T end);
|
|
15
|
+
|
|
11
16
|
#endif
|
data/src/include/prism_helpers.h
CHANGED
|
@@ -16,6 +16,10 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
|
|
|
16
16
|
pm_parser_t* parser
|
|
17
17
|
);
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
|
|
20
|
+
const pm_diagnostic_t* error,
|
|
21
|
+
position_T start,
|
|
22
|
+
position_T end
|
|
23
|
+
);
|
|
20
24
|
|
|
21
25
|
#endif
|
data/src/include/version.h
CHANGED
data/src/position.c
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#include "include/position.h"
|
|
2
|
+
#include "include/util.h"
|
|
3
|
+
|
|
4
|
+
position_T position_from_source_with_offset(const char* source, size_t offset) {
|
|
5
|
+
position_T position = { .line = 1, .column = 0 };
|
|
6
|
+
|
|
7
|
+
for (size_t i = 0; i < offset; i++) {
|
|
8
|
+
if (is_newline(source[i])) {
|
|
9
|
+
position.line++;
|
|
10
|
+
position.column = 0;
|
|
11
|
+
} else {
|
|
12
|
+
position.column++;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return position;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
bool position_is_within_range(position_T position, position_T start, position_T end) {
|
|
20
|
+
if (position.line < start.line) { return false; }
|
|
21
|
+
if (position.line == start.line && position.column < start.column) { return false; }
|
|
22
|
+
|
|
23
|
+
if (position.line > end.line) { return false; }
|
|
24
|
+
if (position.line == end.line && position.column > end.column) { return false; }
|
|
25
|
+
|
|
26
|
+
return true;
|
|
27
|
+
}
|
data/src/prism_helpers.c
CHANGED
|
@@ -16,21 +16,6 @@ const char* pm_error_level_to_string(pm_error_level_t level) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
position_T position_from_source_with_offset(const char* source, size_t offset) {
|
|
20
|
-
position_T position = { .line = 1, .column = 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
19
|
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
|
|
35
20
|
const pm_diagnostic_t* error,
|
|
36
21
|
const AST_NODE_T* node,
|
|
@@ -51,3 +36,17 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
|
|
|
51
36
|
end
|
|
52
37
|
);
|
|
53
38
|
}
|
|
39
|
+
|
|
40
|
+
RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
|
|
41
|
+
const pm_diagnostic_t* error,
|
|
42
|
+
position_T start,
|
|
43
|
+
position_T end
|
|
44
|
+
) {
|
|
45
|
+
return ruby_parse_error_init(
|
|
46
|
+
error->message,
|
|
47
|
+
pm_diagnostic_id_human(error->diag_id),
|
|
48
|
+
pm_error_level_to_string(error->level),
|
|
49
|
+
start,
|
|
50
|
+
end
|
|
51
|
+
);
|
|
52
|
+
}
|
data/src/util/hb_system.c
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#include "../include/util/hb_system.h"
|
|
2
2
|
|
|
3
3
|
#ifdef __linux__
|
|
4
|
-
#define _GNU_SOURCE
|
|
4
|
+
# define _GNU_SOURCE
|
|
5
5
|
#endif
|
|
6
6
|
|
|
7
7
|
#ifdef HB_USE_MALLOC
|
|
8
|
-
#include <stdlib.h>
|
|
8
|
+
# include <stdlib.h>
|
|
9
9
|
#else
|
|
10
|
-
#include <sys/mman.h>
|
|
10
|
+
# include <sys/mman.h>
|
|
11
11
|
#endif
|
|
12
12
|
|
|
13
13
|
void* hb_system_allocate_memory(size_t size) {
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: herb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Roth
|
|
@@ -157,6 +157,7 @@ files:
|
|
|
157
157
|
- src/parser.c
|
|
158
158
|
- src/parser_helpers.c
|
|
159
159
|
- src/parser_match_tags.c
|
|
160
|
+
- src/position.c
|
|
160
161
|
- src/pretty_print.c
|
|
161
162
|
- src/prism_helpers.c
|
|
162
163
|
- src/range.c
|