herb 0.8.1-arm-linux-musl → 0.8.3-arm-linux-musl

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a65a391460fdf35d9fec782c8406c75f5508f25926a733cbc01fc9f3c23018e
4
- data.tar.gz: 55de3fe6c600251b16ee00b169345f0a25249c3ceeee6a8a5d1a881fe05eb3b9
3
+ metadata.gz: 2b278f7fd8ef4145ef6a214ace003bb7149b8d544c98660d5d61e9f938778e53
4
+ data.tar.gz: b51afcd390b02ed84e5b3d6b4267dc363ca579028fc4aac0c2db6f998c37b17a
5
5
  SHA512:
6
- metadata.gz: af46fedf2c54d921106fed264fe07316ba16d4b36fc37e8996162f91620338bc4a862556322f16fce20fd649258b05662d7c8c624e7b872631a93aec1de51aa1
7
- data.tar.gz: f3e39c2b9be4e4383b0b73ac43f4fd661959da40150f9402c4a913c9754af9f4560ea0c4aefb90d285e6db62a8d92da477d782717789c1d0a1a09908d63a4a6a
6
+ metadata.gz: 4a98e5bdaf48075a7ee597635e6eb35d09d69144391cdda49328dc2957370c6d04265f621b4eadddfce946659012cd45ec85aa0b1edf0d4dd1174d81ecd52b9d
7
+ data.tar.gz: f51e7fb7f8a25024e3153b30336c3f14efe295bcac6b39a4f9551d3b38045a2836714d071d5b2cef42972f2a5f2d62fced7b295f14da01f1eb6cc69d7b1bc7bd
data/README.md CHANGED
@@ -10,8 +10,13 @@
10
10
 
11
11
  <p align="center">
12
12
  <a href="https://rubygems.org/gems/herb"><img alt="Gem Version" src="https://img.shields.io/gem/v/herb"></a>
13
+ <a href="https://crates.io/crates/herb"><img alt="Crates.io Version" src="https://img.shields.io/crates/v/herb"></a>
14
+ <a href="https://www.npmjs.com/package/@herb-tools/core"><img alt="npm Version" src="https://img.shields.io/npm/v/@herb-tools/core"></a>
15
+ <a href="https://marketplace.visualstudio.com/items?itemName=marcoroth.herb-lsp"><img alt="VS Code Marketplace" src="https://img.shields.io/visual-studio-marketplace/v/marcoroth.herb-lsp"></a>
16
+ <a href="https://open-vsx.org/extension/marcoroth/herb-lsp"><img alt="Open VSX" src="https://img.shields.io/open-vsx/v/marcoroth/herb-lsp"></a>
13
17
  <a href="https://herb-tools.dev"><img alt="Documentation" src="https://img.shields.io/badge/documentation-available-green"></a>
14
18
  <a href="https://herb-tools.dev/playground"><img alt="playground" src="https://img.shields.io/badge/playground-Try_it_in_the_browser!-green"></a>
19
+ <a href="https://pkg.pr.new/~/marcoroth/herb"><img alt="pkg.pr.new" src="https://pkg.pr.new/badge/marcoroth/herb"></a>
15
20
  <a href="https://github.com/marcoroth/herb/blob/main/LICENSE.txt"><img alt="License" src="https://img.shields.io/github/license/marcoroth/herb"></a>
16
21
  <a href="https://github.com/marcoroth/herb/issues"><img alt="Issues" src="https://img.shields.io/github/issues/marcoroth/herb"></a>
17
22
  </p>
@@ -99,7 +104,7 @@ Commands:
99
104
  bundle exec herb version Prints the versions of the Herb gem and the libherb library.
100
105
  ```
101
106
 
102
- For detailed information, like how you can use Herb programatically in Ruby and JavaScript, visit the [documentation site](https://herb-tools.dev/bindings/ruby/reference).
107
+ For detailed information, like how you can use Herb programmatically in Ruby and JavaScript, visit the [documentation site](https://herb-tools.dev/bindings/ruby/reference).
103
108
 
104
109
 
105
110
  ## Background and Talk
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 << " -DPRISM_EXPORT_SYMBOLS=static "
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:0x00007f22b0525e98 @name="analyzed_ruby", @options={kind: nil}> */
467
+ /* #<Herb::Template::AnalyzedRubyField:0x00007f4c53a4ff00 @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;
data/lib/herb/3.0/herb.so CHANGED
Binary file
data/lib/herb/3.1/herb.so CHANGED
Binary file
data/lib/herb/3.2/herb.so CHANGED
Binary file
data/lib/herb/3.3/herb.so CHANGED
Binary file
data/lib/herb/3.4/herb.so CHANGED
Binary file
@@ -98,16 +98,24 @@ module Herb
98
98
  def format_error(error, number)
99
99
  output = String.new
100
100
 
101
- output << "Error ##{number}: #{error.class.name.split("::").last.gsub(/Error$/, "")}\n"
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
- if error.location
110
+ location = error.is_a?(Hash) ? error[:location] : error.location
111
+ if location
105
112
  output << " File: #{@filename}\n"
106
- output << " Location: Line #{error.location.start.line}, Column #{error.location.start.column}\n"
113
+ output << " Location: Line #{location.start.line}, Column #{location.start.column}\n"
107
114
  end
108
115
 
109
- output << " Message: #{error.message}\n\n"
110
- output << format_source_context(error) if error.location
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
@@ -2,5 +2,5 @@
2
2
  # typed: true
3
3
 
4
4
  module Herb
5
- VERSION = "0.8.1"
5
+ VERSION = "0.8.3"
6
6
  end
data/src/analyze.c CHANGED
@@ -288,7 +288,7 @@ static AST_NODE_T* create_control_node(
288
288
  if (end_node) {
289
289
  end_position = end_node->base.location.end;
290
290
  } else if (children && hb_array_size(children) > 0) {
291
- AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
291
+ AST_NODE_T* last_child = hb_array_last(children);
292
292
  end_position = last_child->location.end;
293
293
  } else if (subsequent) {
294
294
  end_position = subsequent->location.end;
@@ -695,10 +695,10 @@ static size_t process_control_structure(
695
695
  } else if (else_clause) {
696
696
  end_position = else_clause->base.location.end;
697
697
  } else if (hb_array_size(when_conditions) > 0) {
698
- AST_NODE_T* last_when = hb_array_get(when_conditions, hb_array_size(when_conditions) - 1);
698
+ AST_NODE_T* last_when = hb_array_last(when_conditions);
699
699
  end_position = last_when->location.end;
700
700
  } else if (hb_array_size(in_conditions) > 0) {
701
- AST_NODE_T* last_in = hb_array_get(in_conditions, hb_array_size(in_conditions) - 1);
701
+ AST_NODE_T* last_in = hb_array_last(in_conditions);
702
702
  end_position = last_in->location.end;
703
703
  }
704
704
 
@@ -955,7 +955,7 @@ static size_t process_control_structure(
955
955
  if (end_node) {
956
956
  end_position = end_node->base.location.end;
957
957
  } else if (children && hb_array_size(children) > 0) {
958
- AST_NODE_T* last_child = hb_array_get(children, hb_array_size(children) - 1);
958
+ AST_NODE_T* last_child = hb_array_last(children);
959
959
  end_position = last_child->location.end;
960
960
  }
961
961
 
@@ -1139,7 +1139,7 @@ static size_t process_block_children(
1139
1139
  hb_array_T* temp_array = hb_array_init(1);
1140
1140
  size_t new_index = process_control_structure(node, array, index, temp_array, context, child_type);
1141
1141
 
1142
- if (hb_array_size(temp_array) > 0) { hb_array_append(children_array, hb_array_get(temp_array, 0)); }
1142
+ if (hb_array_size(temp_array) > 0) { hb_array_append(children_array, hb_array_first(temp_array)); }
1143
1143
 
1144
1144
  hb_array_free(&temp_array);
1145
1145
 
@@ -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 herb_extract_ruby_to_buffer_with_semicolons(const char* source, hb_buffer_T* output) {
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
- bool needs_semicolon = false;
80
- uint32_t current_line = token->location.end.line;
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
- herb_extract_ruby_to_buffer_with_semicolons(source, &output);
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
  }
@@ -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
@@ -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))
@@ -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
@@ -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
- position_T position_from_source_with_offset(const char* source, size_t offset);
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
@@ -1,18 +1,21 @@
1
1
  #ifndef HERB_BUFFER_H
2
2
  #define HERB_BUFFER_H
3
3
 
4
+ #include "hb_arena.h"
4
5
  #include "hb_string.h"
5
6
 
6
7
  #include <stdbool.h>
7
8
  #include <stdlib.h>
8
9
 
9
10
  typedef struct HB_BUFFER_STRUCT {
11
+ hb_arena_T* allocator;
10
12
  char* value;
11
13
  size_t length;
12
14
  size_t capacity;
13
15
  } hb_buffer_T;
14
16
 
15
17
  bool hb_buffer_init(hb_buffer_T* buffer, size_t capacity);
18
+ bool hb_buffer_init_arena(hb_buffer_T* buffer, hb_arena_T* allocator, size_t capacity);
16
19
 
17
20
  void hb_buffer_append(hb_buffer_T* buffer, const char* text);
18
21
  void hb_buffer_append_with_length(hb_buffer_T* buffer, const char* text, size_t length);
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.8.1"
4
+ #define HERB_VERSION "0.8.3"
5
5
 
6
6
  #endif
data/src/parser.c CHANGED
@@ -315,8 +315,8 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T
315
315
  position_T node_end = { 0 };
316
316
 
317
317
  if (children->size > 0) {
318
- AST_NODE_T* first_child = hb_array_get(children, 0);
319
- AST_NODE_T* last_child = hb_array_get(children, children->size - 1);
318
+ AST_NODE_T* first_child = hb_array_first(children);
319
+ AST_NODE_T* last_child = hb_array_last(children);
320
320
 
321
321
  node_start = first_child->location.start;
322
322
  node_end = last_child->location.end;
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_buffer.c CHANGED
@@ -22,8 +22,14 @@ static bool hb_buffer_resize(hb_buffer_T* buffer, const size_t new_capacity) {
22
22
  fprintf(stderr, "Error: Buffer capacity would overflow system limits.\n");
23
23
  exit(1);
24
24
  }
25
+ char* new_value = NULL;
25
26
 
26
- char* new_value = realloc(buffer->value, new_capacity + 1);
27
+ if (buffer->allocator == NULL) {
28
+ new_value = realloc(buffer->value, new_capacity + 1);
29
+ } else {
30
+ new_value = hb_arena_alloc(buffer->allocator, new_capacity + 1);
31
+ memcpy(new_value, buffer->value, buffer->capacity + 1);
32
+ }
27
33
 
28
34
  if (unlikely(new_value == NULL)) {
29
35
  fprintf(stderr, "Error: Failed to resize buffer to %zu.\n", new_capacity);
@@ -61,6 +67,7 @@ static bool hb_buffer_expand_if_needed(hb_buffer_T* buffer, const size_t require
61
67
  }
62
68
 
63
69
  bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity) {
70
+ buffer->allocator = NULL;
64
71
  buffer->capacity = capacity;
65
72
  buffer->length = 0;
66
73
  buffer->value = malloc(sizeof(char) * (buffer->capacity + 1));
@@ -76,6 +83,16 @@ bool hb_buffer_init(hb_buffer_T* buffer, const size_t capacity) {
76
83
  return true;
77
84
  }
78
85
 
86
+ bool hb_buffer_init_arena(hb_buffer_T* buffer, hb_arena_T* allocator, size_t capacity) {
87
+ buffer->allocator = allocator;
88
+ buffer->capacity = capacity;
89
+ buffer->length = 0;
90
+ buffer->value = hb_arena_alloc(allocator, sizeof(char) * (buffer->capacity + 1));
91
+ buffer->value[0] = '\0';
92
+
93
+ return true;
94
+ }
95
+
79
96
  char* hb_buffer_value(const hb_buffer_T* buffer) {
80
97
  return buffer->value;
81
98
  }
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.1
4
+ version: 0.8.3
5
5
  platform: arm-linux-musl
6
6
  authors:
7
7
  - Marco Roth
@@ -161,6 +161,7 @@ files:
161
161
  - src/parser.c
162
162
  - src/parser_helpers.c
163
163
  - src/parser_match_tags.c
164
+ - src/position.c
164
165
  - src/pretty_print.c
165
166
  - src/prism_helpers.c
166
167
  - src/range.c