@herb-tools/node 0.1.0 → 0.2.0

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/herb-node.esm.js +1 -1
  3. package/extension/extension_helpers.cpp +2 -3
  4. package/extension/herb.cpp +9 -0
  5. package/extension/libherb/analyze.c +138 -43
  6. package/extension/libherb/analyze.h +39 -0
  7. package/extension/libherb/analyze_helpers.c +44 -1
  8. package/extension/libherb/analyze_helpers.h +49 -0
  9. package/extension/libherb/analyzed_ruby.c +10 -1
  10. package/extension/libherb/analyzed_ruby.h +36 -0
  11. package/extension/libherb/array.h +33 -0
  12. package/extension/libherb/ast_node.h +35 -0
  13. package/extension/libherb/ast_nodes.c +103 -1
  14. package/extension/libherb/ast_nodes.h +335 -0
  15. package/extension/libherb/ast_pretty_print.c +60 -0
  16. package/extension/libherb/ast_pretty_print.h +17 -0
  17. package/extension/libherb/buffer.c +60 -27
  18. package/extension/libherb/buffer.h +39 -0
  19. package/extension/libherb/errors.h +125 -0
  20. package/extension/libherb/extract.c +57 -20
  21. package/extension/libherb/extract.h +20 -0
  22. package/extension/libherb/herb.h +32 -0
  23. package/extension/libherb/html_util.h +13 -0
  24. package/extension/libherb/include/analyze.h +3 -0
  25. package/extension/libherb/include/analyze_helpers.h +6 -0
  26. package/extension/libherb/include/analyzed_ruby.h +3 -0
  27. package/extension/libherb/include/ast_nodes.h +32 -0
  28. package/extension/libherb/include/buffer.h +5 -2
  29. package/extension/libherb/include/lexer_peek_helpers.h +2 -2
  30. package/extension/libherb/include/macros.h +2 -2
  31. package/extension/libherb/include/version.h +1 -1
  32. package/extension/libherb/io.h +9 -0
  33. package/extension/libherb/json.h +28 -0
  34. package/extension/libherb/lexer.c +1 -1
  35. package/extension/libherb/lexer.h +13 -0
  36. package/extension/libherb/lexer_peek_helpers.h +23 -0
  37. package/extension/libherb/lexer_struct.h +32 -0
  38. package/extension/libherb/location.h +25 -0
  39. package/extension/libherb/macros.h +10 -0
  40. package/extension/libherb/main.c +1 -1
  41. package/extension/libherb/memory.h +12 -0
  42. package/extension/libherb/parser.c +17 -7
  43. package/extension/libherb/parser.h +22 -0
  44. package/extension/libherb/parser_helpers.h +33 -0
  45. package/extension/libherb/position.h +22 -0
  46. package/extension/libherb/pretty_print.h +53 -0
  47. package/extension/libherb/prism_helpers.h +18 -0
  48. package/extension/libherb/range.h +23 -0
  49. package/extension/libherb/ruby_parser.h +6 -0
  50. package/extension/libherb/token.c +1 -1
  51. package/extension/libherb/token.h +25 -0
  52. package/extension/libherb/token_matchers.h +21 -0
  53. package/extension/libherb/token_struct.h +51 -0
  54. package/extension/libherb/util.c +3 -1
  55. package/extension/libherb/util.h +25 -0
  56. package/extension/libherb/version.h +6 -0
  57. package/extension/libherb/visitor.c +36 -0
  58. package/extension/libherb/visitor.h +11 -0
  59. package/extension/nodes.cpp +117 -0
  60. package/extension/nodes.h +3 -0
  61. package/package.json +11 -20
@@ -13,8 +13,11 @@ typedef struct BUFFER_STRUCT {
13
13
  bool buffer_init(buffer_T* buffer);
14
14
  buffer_T buffer_new(void);
15
15
 
16
- bool buffer_increase_capacity(buffer_T* buffer, size_t required_length);
17
- bool buffer_reserve(buffer_T* buffer, size_t min_capacity);
16
+ bool buffer_increase_capacity(buffer_T* buffer, size_t additional_capacity);
17
+ bool buffer_has_capacity(buffer_T* buffer, size_t required_length);
18
+ bool buffer_expand_capacity(buffer_T* buffer);
19
+ bool buffer_expand_if_needed(buffer_T* buffer, size_t required_length);
20
+ bool buffer_resize(buffer_T* buffer, size_t new_capacity);
18
21
 
19
22
  void buffer_append(buffer_T* buffer, const char* text);
20
23
  void buffer_append_with_length(buffer_T* buffer, const char* text, size_t length);
@@ -1,5 +1,5 @@
1
- #ifndef HERB_LEXER_PEEK_H
2
- #define HERB_LEXER_PEEK_H
1
+ #ifndef HERB_LEXER_PEEK_HELPERS_H
2
+ #define HERB_LEXER_PEEK_HELPERS_H
3
3
 
4
4
  #include "lexer_struct.h"
5
5
 
@@ -1,9 +1,9 @@
1
1
  #ifndef HERB_MACROS_H
2
2
  #define HERB_MACROS_H
3
3
 
4
- #define MAX(a, b) (a) > (b) ? (a) : (b)
4
+ #define MAX(a, b) ((a) > (b) ? (a) : (b))
5
5
 
6
- #define MIN(a, b) (a) < (b) ? (a) : (b)
6
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
7
7
 
8
8
  #define unlikely(x) __builtin_expect(!!(x), 0)
9
9
 
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.1.0"
4
+ #define HERB_VERSION "0.2.0"
5
5
 
6
6
  #endif
@@ -0,0 +1,9 @@
1
+ #ifndef HERB_IO_H
2
+ #define HERB_IO_H
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+
7
+ char* herb_read_file(const char* filename);
8
+
9
+ #endif
@@ -0,0 +1,28 @@
1
+ #ifndef HERB_JSON_H
2
+ #define HERB_JSON_H
3
+
4
+ #include "buffer.h"
5
+
6
+ void json_start_root_object(buffer_T* json);
7
+ void json_start_root_array(buffer_T* json);
8
+
9
+ void json_escape_string(buffer_T* json, const char* string);
10
+
11
+ void json_add_string(buffer_T* json, const char* key, const char* value);
12
+ void json_add_int(buffer_T* json, const char* key, int value);
13
+ void json_add_size_t(buffer_T* json, const char* key, size_t value);
14
+ void json_add_double(buffer_T* json, const char* key, double value);
15
+ void json_add_bool(buffer_T* json, const char* key, int value);
16
+
17
+ void json_add_raw_string(buffer_T* json, const char* string);
18
+
19
+ void json_start_object(buffer_T* json, const char* key);
20
+ void json_end_object(buffer_T* json);
21
+
22
+ void json_start_array(buffer_T* json, const char* key);
23
+ void json_end_array(buffer_T* json);
24
+
25
+ void json_double_to_string(double value, char* buffer);
26
+ void json_int_to_string(int value, char* buffer);
27
+
28
+ #endif
@@ -72,7 +72,7 @@ token_T* lexer_error(lexer_T* lexer, const char* message) {
72
72
  lexer->current_column
73
73
  );
74
74
 
75
- return token_init(herb_strdup(error_message), TOKEN_ERROR, lexer);
75
+ return token_init(error_message, TOKEN_ERROR, lexer);
76
76
  }
77
77
 
78
78
  static void lexer_advance(lexer_T* lexer) {
@@ -0,0 +1,13 @@
1
+ #ifndef HERB_LEXER_H
2
+ #define HERB_LEXER_H
3
+
4
+ #include "lexer_struct.h"
5
+ #include "token_struct.h"
6
+
7
+ lexer_T* lexer_init(const char* source);
8
+ token_T* lexer_next_token(lexer_T* lexer);
9
+ token_T* lexer_error(lexer_T* lexer, const char* message);
10
+
11
+ void lexer_free(lexer_T* lexer);
12
+
13
+ #endif
@@ -0,0 +1,23 @@
1
+ #ifndef HERB_LEXER_PEEK_HELPERS_H
2
+ #define HERB_LEXER_PEEK_HELPERS_H
3
+
4
+ #include "lexer_struct.h"
5
+
6
+ #include <stdbool.h>
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+
10
+ char lexer_peek(const lexer_T* lexer, int offset);
11
+ bool lexer_peek_for_doctype(const lexer_T* lexer, int offset);
12
+
13
+ bool lexer_peek_for_html_comment_start(const lexer_T* lexer, int offset);
14
+ bool lexer_peek_for_html_comment_end(const lexer_T* lexer, int offset);
15
+
16
+ bool lexer_peek_erb_close_tag(const lexer_T* lexer, int offset);
17
+ bool lexer_peek_erb_dash_close_tag(const lexer_T* lexer, int offset);
18
+ bool lexer_peek_erb_percent_close_tag(const lexer_T* lexer, int offset);
19
+ bool lexer_peek_erb_end(const lexer_T* lexer, int offset);
20
+
21
+ char lexer_backtrack(const lexer_T* lexer, int offset);
22
+
23
+ #endif
@@ -0,0 +1,32 @@
1
+ #ifndef HERB_LEXER_STRUCT_H
2
+ #define HERB_LEXER_STRUCT_H
3
+
4
+ #include <stdbool.h>
5
+ #include <stdlib.h>
6
+
7
+ typedef enum {
8
+ STATE_DATA,
9
+ STATE_ERB_CONTENT,
10
+ STATE_ERB_CLOSE,
11
+ } lexer_state_T;
12
+
13
+ typedef struct LEXER_STRUCT {
14
+ const char* source;
15
+ size_t source_length;
16
+
17
+ size_t current_line;
18
+ size_t current_column;
19
+ size_t current_position;
20
+
21
+ size_t previous_line;
22
+ size_t previous_column;
23
+ size_t previous_position;
24
+
25
+ char current_character;
26
+ lexer_state_T state;
27
+ size_t stall_counter;
28
+ size_t last_position;
29
+ bool stalled;
30
+ } lexer_T;
31
+
32
+ #endif
@@ -0,0 +1,25 @@
1
+ #ifndef HERB_LOCATION_H
2
+ #define HERB_LOCATION_H
3
+
4
+ #include <stdlib.h>
5
+
6
+ #include "position.h"
7
+
8
+ typedef struct LOCATION_STRUCT {
9
+ position_T* start;
10
+ position_T* end;
11
+ } location_T;
12
+
13
+ location_T* location_init(position_T* start, position_T* end);
14
+ location_T* location_from(size_t start_line, size_t start_column, size_t end_line, size_t end_column);
15
+
16
+ position_T* location_start(location_T* location);
17
+ position_T* location_end_(location_T* location);
18
+
19
+ size_t location_sizeof(void);
20
+
21
+ location_T* location_copy(location_T* location);
22
+
23
+ void location_free(location_T* location);
24
+
25
+ #endif
@@ -0,0 +1,10 @@
1
+ #ifndef HERB_MACROS_H
2
+ #define HERB_MACROS_H
3
+
4
+ #define MAX(a, b) ((a) > (b) ? (a) : (b))
5
+
6
+ #define MIN(a, b) ((a) < (b) ? (a) : (b))
7
+
8
+ #define unlikely(x) __builtin_expect(!!(x), 0)
9
+
10
+ #endif
@@ -36,7 +36,7 @@ int main(const int argc, char* argv[]) {
36
36
  if (argc < 2) {
37
37
  printf("./herb [command] [options]\n\n");
38
38
 
39
- printf("Herb 🌿 Powerful and seamless HTML-aware ERB parsing.\n\n");
39
+ printf("Herb 🌿 Powerful and seamless HTML-aware ERB parsing and tooling.\n\n");
40
40
 
41
41
  printf("./herb lex [file] - Lex a file\n");
42
42
  printf("./herb lex_json [file] - Lex a file and return the result as json.\n");
@@ -0,0 +1,12 @@
1
+ #ifndef HERB_MEMORY_H
2
+ #define HERB_MEMORY_H
3
+
4
+ #include <stddef.h>
5
+
6
+ void* safe_malloc(size_t size);
7
+ void* safe_realloc(void* pointer, size_t new_size);
8
+
9
+ void* nullable_safe_malloc(size_t size);
10
+ void* nullable_safe_realloc(void* pointer, size_t new_size);
11
+
12
+ #endif
@@ -124,10 +124,9 @@ static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) {
124
124
  return doctype;
125
125
  }
126
126
 
127
- static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser) {
127
+ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, array_T* document_errors) {
128
128
  position_T* start = position_copy(parser->current_token->location->start);
129
129
 
130
- array_T* errors = array_init(8);
131
130
  buffer_T content = buffer_new();
132
131
 
133
132
  while (token_is_none_of(
@@ -142,16 +141,18 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser) {
142
141
  if (token_is(parser, TOKEN_ERROR)) {
143
142
  buffer_free(&content);
144
143
 
145
- token_T* token = parser_consume_expected(parser, TOKEN_ERROR, errors);
144
+ token_T* token = parser_consume_expected(parser, TOKEN_ERROR, document_errors);
146
145
  append_unexpected_error(
147
146
  "Token Error",
148
147
  "not TOKEN_ERROR",
149
148
  token->value,
150
149
  token->location->start,
151
150
  token->location->end,
152
- errors
151
+ document_errors
153
152
  );
153
+
154
154
  token_free(token);
155
+ position_free(start);
155
156
 
156
157
  return NULL;
157
158
  }
@@ -161,6 +162,8 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser) {
161
162
  token_free(token);
162
163
  }
163
164
 
165
+ array_T* errors = array_init(8);
166
+
164
167
  if (buffer_length(&content) > 0) {
165
168
  AST_HTML_TEXT_NODE_T* text_node =
166
169
  ast_html_text_node_init(buffer_value(&content), start, parser->current_token->location->start, errors);
@@ -265,7 +268,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser
265
268
  false,
266
269
  erb_node->base.location->start,
267
270
  erb_node->base.location->end,
268
- NULL
271
+ errors
269
272
  );
270
273
  }
271
274
 
@@ -284,7 +287,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser
284
287
  false,
285
288
  literal->base.location->start,
286
289
  literal->base.location->end,
287
- NULL
290
+ errors
288
291
  );
289
292
  }
290
293
 
@@ -400,6 +403,9 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
400
403
  token_free(tag_start);
401
404
  token_free(tag_name);
402
405
 
406
+ array_free(&children);
407
+ array_free(&errors);
408
+
403
409
  return NULL;
404
410
  }
405
411
 
@@ -617,7 +623,7 @@ static void parser_parse_in_data_state(parser_T* parser, array_T* children, arra
617
623
  TOKEN_UNDERSCORE,
618
624
  TOKEN_WHITESPACE
619
625
  )) {
620
- array_append(children, parser_parse_text_content(parser));
626
+ array_append(children, parser_parse_text_content(parser, errors));
621
627
  continue;
622
628
  }
623
629
 
@@ -650,6 +656,10 @@ static void parser_parse_stray_closing_tags(parser_T* parser, array_T* children,
650
656
  while (token_is_not(parser, TOKEN_EOF)) {
651
657
  if (token_is_not(parser, TOKEN_HTML_TAG_START_CLOSE)) {
652
658
  parser_append_unexpected_token_error(parser, TOKEN_HTML_TAG_START_CLOSE, errors);
659
+
660
+ token_T* unexpected = parser_advance(parser);
661
+ token_free(unexpected);
662
+
653
663
  continue;
654
664
  }
655
665
 
@@ -0,0 +1,22 @@
1
+ #ifndef HERB_PARSER_H
2
+ #define HERB_PARSER_H
3
+
4
+ #include "array.h"
5
+ #include "ast_node.h"
6
+ #include "lexer.h"
7
+
8
+ typedef struct PARSER_STRUCT {
9
+ lexer_T* lexer;
10
+ token_T* current_token;
11
+ array_T* open_tags_stack;
12
+ } parser_T;
13
+
14
+ parser_T* parser_init(lexer_T* lexer);
15
+
16
+ AST_DOCUMENT_NODE_T* parser_parse(parser_T* parser);
17
+
18
+ size_t parser_sizeof(void);
19
+
20
+ void parser_free(parser_T* parser);
21
+
22
+ #endif
@@ -0,0 +1,33 @@
1
+ #ifndef HERB_PARSER_HELPERS_H
2
+ #define HERB_PARSER_HELPERS_H
3
+
4
+ #include "array.h"
5
+ #include "ast_nodes.h"
6
+ #include "buffer.h"
7
+ #include "errors.h"
8
+ #include "parser.h"
9
+ #include "token.h"
10
+
11
+ void parser_push_open_tag(const parser_T* parser, token_T* tag_name);
12
+ bool parser_check_matching_tag(const parser_T* parser, const char* tag_name);
13
+ token_T* parser_pop_open_tag(const parser_T* parser);
14
+
15
+ void parser_append_unexpected_error(parser_T* parser, const char* description, const char* expected, array_T* errors);
16
+ void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, array_T* errors);
17
+
18
+ void parser_append_literal_node_from_buffer(
19
+ const parser_T* parser, buffer_T* buffer, array_T* children, position_T* start
20
+ );
21
+
22
+ bool parser_in_svg_context(const parser_T* parser);
23
+
24
+ token_T* parser_advance(parser_T* parser);
25
+ token_T* parser_consume_if_present(parser_T* parser, token_type_T type);
26
+ token_T* parser_consume_expected(parser_T* parser, token_type_T type, array_T* array);
27
+
28
+ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
29
+ AST_HTML_OPEN_TAG_NODE_T* open_tag, array_T* body, array_T* errors
30
+ );
31
+ void parser_handle_mismatched_tags(const parser_T* parser, const AST_HTML_CLOSE_TAG_NODE_T* close_tag, array_T* errors);
32
+
33
+ #endif
@@ -0,0 +1,22 @@
1
+ #ifndef HERB_POSITION_H
2
+ #define HERB_POSITION_H
3
+
4
+ #include <stdlib.h>
5
+
6
+ typedef struct POSITION_STRUCT {
7
+ size_t line;
8
+ size_t column;
9
+ } position_T;
10
+
11
+ position_T* position_init(size_t line, size_t column);
12
+
13
+ size_t position_line(const position_T* position);
14
+ size_t position_column(const position_T* position);
15
+
16
+ size_t position_sizeof(void);
17
+
18
+ position_T* position_copy(position_T* position);
19
+
20
+ void position_free(position_T* position);
21
+
22
+ #endif
@@ -0,0 +1,53 @@
1
+ #ifndef HERB_PRETTY_PRINT_H
2
+ #define HERB_PRETTY_PRINT_H
3
+
4
+ #include "analyzed_ruby.h"
5
+ #include "ast_nodes.h"
6
+ #include "buffer.h"
7
+ #include "location.h"
8
+
9
+ #include <stdbool.h>
10
+
11
+ void pretty_print_indent(buffer_T* buffer, size_t indent);
12
+ void pretty_print_newline(size_t indent, size_t relative_indent, buffer_T* buffer);
13
+ void pretty_print_label(const char* name, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer);
14
+
15
+ void pretty_print_position_property(
16
+ position_T* position, const char* name, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
17
+ );
18
+
19
+ void pretty_print_location(location_T* location, buffer_T* buffer);
20
+
21
+ void pretty_print_property(
22
+ const char* name, const char* value, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
23
+ );
24
+
25
+ void pretty_print_size_t_property(
26
+ size_t value, const char* name, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
27
+ );
28
+
29
+ void pretty_print_string_property(
30
+ const char* string, const char* name, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
31
+ );
32
+
33
+ void pretty_print_quoted_property(
34
+ const char* name, const char* value, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
35
+ );
36
+
37
+ void pretty_print_boolean_property(
38
+ const char* name, bool value, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
39
+ );
40
+
41
+ void pretty_print_token_property(
42
+ token_T* token, const char* name, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
43
+ );
44
+
45
+ void pretty_print_array(
46
+ const char* name, array_T* array, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer
47
+ );
48
+
49
+ void pretty_print_errors(AST_NODE_T* node, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer);
50
+
51
+ void pretty_print_analyed_ruby(analyzed_ruby_T* analyzed, const char* source);
52
+
53
+ #endif
@@ -0,0 +1,18 @@
1
+ #ifndef HERB_PRISM_HELPERS_H
2
+ #define HERB_PRISM_HELPERS_H
3
+
4
+ #include "ast_nodes.h"
5
+ #include "errors.h"
6
+ #include "position.h"
7
+
8
+ #include <prism.h>
9
+
10
+ const char* pm_error_level_to_string(pm_error_level_t level);
11
+
12
+ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error(
13
+ const pm_diagnostic_t* error, const AST_NODE_T* node, const char* source, pm_parser_t* parser
14
+ );
15
+
16
+ position_T* position_from_source_with_offset(const char* source, size_t offset);
17
+
18
+ #endif
@@ -0,0 +1,23 @@
1
+ #ifndef HERB_RANGE_H
2
+ #define HERB_RANGE_H
3
+
4
+ #include <stdlib.h>
5
+
6
+ typedef struct RANGE_STRUCT {
7
+ size_t from;
8
+ size_t to;
9
+ } range_T;
10
+
11
+ range_T* range_init(size_t from, size_t to);
12
+
13
+ size_t range_from(const range_T* range);
14
+ size_t range_to(const range_T* range);
15
+ size_t range_length(range_T* range);
16
+
17
+ range_T* range_copy(range_T* range);
18
+
19
+ size_t range_sizeof(void);
20
+
21
+ void range_free(range_T* range);
22
+
23
+ #endif
@@ -0,0 +1,6 @@
1
+ #ifndef HERB_RUBY_PARSER_H
2
+ #define HERB_RUBY_PARSER_H
3
+
4
+ void herb_parse_ruby_to_stdout(char* source);
5
+
6
+ #endif
@@ -72,7 +72,7 @@ const char* token_type_to_string(const token_type_T type) {
72
72
  case TOKEN_EOF: return "TOKEN_EOF";
73
73
  }
74
74
 
75
- return "Unkown token_type_T";
75
+ return "Unknown token_type_T";
76
76
  }
77
77
 
78
78
  char* token_to_string(const token_T* token) {
@@ -0,0 +1,25 @@
1
+ #ifndef HERB_TOKEN_H
2
+ #define HERB_TOKEN_H
3
+
4
+ #include "lexer_struct.h"
5
+ #include "position.h"
6
+ #include "token_struct.h"
7
+
8
+ token_T* token_init(const char* value, token_type_T type, lexer_T* lexer);
9
+ char* token_to_string(const token_T* token);
10
+ char* token_to_json(const token_T* token);
11
+ const char* token_type_to_string(token_type_T type);
12
+
13
+ char* token_value(const token_T* token);
14
+ int token_type(const token_T* token);
15
+
16
+ position_T* token_start_position(token_T* token);
17
+ position_T* token_end_position(token_T* token);
18
+
19
+ size_t token_sizeof(void);
20
+
21
+ token_T* token_copy(token_T* token);
22
+
23
+ void token_free(token_T* token);
24
+
25
+ #endif
@@ -0,0 +1,21 @@
1
+ #ifndef HERB_TOKEN_MATCHERS_H
2
+ #define HERB_TOKEN_MATCHERS_H
3
+
4
+ #include "parser.h"
5
+ #include "token.h"
6
+
7
+ #include <stdarg.h>
8
+ #include <stdbool.h>
9
+
10
+ // This "TOKEN" is used to terminate the va_list arguments in the token_matches_any function
11
+ #define TOKEN_SENTINEL 99999999
12
+
13
+ bool token_is(parser_T* parser, token_type_T expected_type);
14
+ bool token_is_not(parser_T* parser, token_type_T type);
15
+
16
+ bool token_matches_any(token_type_T current_token, token_type_T first_token, ...);
17
+
18
+ #define token_is_any_of(parser, ...) (token_matches_any((parser)->current_token->type, __VA_ARGS__, TOKEN_SENTINEL))
19
+ #define token_is_none_of(parser, ...) (!token_matches_any((parser)->current_token->type, __VA_ARGS__, TOKEN_SENTINEL))
20
+
21
+ #endif
@@ -0,0 +1,51 @@
1
+ #ifndef HERB_TOKEN_STRUCT_H
2
+ #define HERB_TOKEN_STRUCT_H
3
+
4
+ #include "location.h"
5
+ #include "range.h"
6
+
7
+ typedef enum {
8
+ TOKEN_WHITESPACE, // ' '
9
+ TOKEN_NBSP, // \xC2\xA0
10
+ TOKEN_NEWLINE, // \n
11
+ TOKEN_IDENTIFIER,
12
+
13
+ TOKEN_HTML_DOCTYPE, // <!DOCTYPE, <!doctype, <!DoCtYpE, <!dOcTyPe
14
+
15
+ TOKEN_HTML_TAG_START, // <
16
+ TOKEN_HTML_TAG_START_CLOSE, // </
17
+ TOKEN_HTML_TAG_END, // >
18
+ TOKEN_HTML_TAG_SELF_CLOSE, // />
19
+
20
+ TOKEN_HTML_COMMENT_START, // <!--
21
+ TOKEN_HTML_COMMENT_END, // -->
22
+
23
+ TOKEN_ERB_START, // <%, <%=, <%#, <%-, <%==, <%%
24
+ TOKEN_ERB_CONTENT, // Ruby Code
25
+ TOKEN_ERB_END, // %>, -%>, %%>
26
+
27
+ TOKEN_LT, // <
28
+ TOKEN_SLASH, // /
29
+ TOKEN_EQUALS, // =
30
+ TOKEN_QUOTE, // ", '
31
+ TOKEN_DASH, // -
32
+ TOKEN_UNDERSCORE, // _
33
+ TOKEN_EXCLAMATION, // !
34
+ TOKEN_SEMICOLON, // ;
35
+ TOKEN_COLON, // :
36
+ TOKEN_PERCENT, // %
37
+ TOKEN_AMPERSAND, // &
38
+
39
+ TOKEN_CHARACTER,
40
+ TOKEN_ERROR,
41
+ TOKEN_EOF,
42
+ } token_type_T;
43
+
44
+ typedef struct TOKEN_STRUCT {
45
+ char* value;
46
+ range_T* range;
47
+ location_T* location;
48
+ token_type_T type;
49
+ } token_T;
50
+
51
+ #endif
@@ -43,13 +43,15 @@ int count_newlines(const char* string) {
43
43
  }
44
44
 
45
45
  char* replace_char(char* string, const char find, const char replace) {
46
+ char* original_string = string;
47
+
46
48
  while (*string != '\0') {
47
49
  if (*string == find) { *string = replace; }
48
50
 
49
51
  string++;
50
52
  }
51
53
 
52
- return string;
54
+ return original_string;
53
55
  }
54
56
 
55
57
  char* escape_newlines(const char* input) {
@@ -0,0 +1,25 @@
1
+ #ifndef HERB_UTIL_H
2
+ #define HERB_UTIL_H
3
+
4
+ #include <stdbool.h>
5
+ #include <stdlib.h>
6
+
7
+ int is_whitespace(int character);
8
+ int is_newline(int character);
9
+
10
+ int count_in_string(const char* string, char character);
11
+ int count_newlines(const char* string);
12
+
13
+ char* replace_char(char* string, char find, char replace);
14
+ char* escape_newlines(const char* input);
15
+ char* quoted_string(const char* input);
16
+ char* wrap_string(const char* input, char character);
17
+
18
+ bool string_blank(const char* input);
19
+ bool string_present(const char* input);
20
+
21
+ char* herb_strdup(const char* s);
22
+
23
+ char* size_t_to_string(size_t value);
24
+
25
+ #endif
@@ -0,0 +1,6 @@
1
+ #ifndef HERB_VERSION_H
2
+ #define HERB_VERSION_H
3
+
4
+ #define HERB_VERSION "0.2.0"
5
+
6
+ #endif