packcr 0.0.7 → 0.1.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +73 -0
  4. data/lib/packcr/context.rb +15 -6
  5. data/lib/packcr/generated/context.rb +290 -143
  6. data/lib/packcr/generated/node/action_node.rb +19 -2
  7. data/lib/packcr/generated/node/alternate_node.rb +54 -8
  8. data/lib/packcr/generated/node/capture_node.rb +16 -1
  9. data/lib/packcr/generated/node/charclass_node.rb +76 -9
  10. data/lib/packcr/generated/node/eof_node.rb +8 -1
  11. data/lib/packcr/generated/node/error_node.rb +9 -2
  12. data/lib/packcr/generated/node/expand_node.rb +9 -2
  13. data/lib/packcr/generated/node/predicate_node.rb +35 -2
  14. data/lib/packcr/generated/node/quantity_node.rb +84 -31
  15. data/lib/packcr/generated/node/reference_node.rb +16 -2
  16. data/lib/packcr/generated/node/rule_node.rb +38 -7
  17. data/lib/packcr/generated/node/sequence_node.rb +18 -0
  18. data/lib/packcr/generated/node/string_node.rb +28 -4
  19. data/lib/packcr/node/reference_node.rb +1 -0
  20. data/lib/packcr/node/rule_node.rb +2 -1
  21. data/lib/packcr/parser.rb +993 -838
  22. data/lib/packcr/stream.rb +1 -1
  23. data/lib/packcr/templates/context/header.c.erb +3 -3
  24. data/lib/packcr/templates/context/source.c.erb +438 -420
  25. data/lib/packcr/templates/context/source.rb.erb +185 -167
  26. data/lib/packcr/templates/context/source.rs.erb +625 -0
  27. data/lib/packcr/templates/node/action.c.erb +2 -2
  28. data/lib/packcr/templates/node/action.rs.erb +6 -0
  29. data/lib/packcr/templates/node/alternate.c.erb +2 -2
  30. data/lib/packcr/templates/node/alternate.rs.erb +39 -0
  31. data/lib/packcr/templates/node/capture.c.erb +2 -2
  32. data/lib/packcr/templates/node/capture.rs.erb +13 -0
  33. data/lib/packcr/templates/node/charclass.c.erb +4 -4
  34. data/lib/packcr/templates/node/charclass_any.c.erb +2 -2
  35. data/lib/packcr/templates/node/charclass_one.c.erb +4 -4
  36. data/lib/packcr/templates/node/charclass_utf8.c.erb +2 -2
  37. data/lib/packcr/templates/node/charclass_utf8.rs.erb +41 -0
  38. data/lib/packcr/templates/node/eof.c.erb +1 -1
  39. data/lib/packcr/templates/node/error.c.erb +4 -4
  40. data/lib/packcr/templates/node/expand.c.erb +2 -2
  41. data/lib/packcr/templates/node/predicate.c.erb +1 -1
  42. data/lib/packcr/templates/node/predicate_neg.c.erb +1 -1
  43. data/lib/packcr/templates/node/predicate_neg.rs.erb +24 -0
  44. data/lib/packcr/templates/node/quantity_many.c.erb +9 -7
  45. data/lib/packcr/templates/node/quantity_many.rs.erb +50 -0
  46. data/lib/packcr/templates/node/quantity_one.c.erb +9 -7
  47. data/lib/packcr/templates/node/quantity_one.rb.erb +4 -4
  48. data/lib/packcr/templates/node/reference.c.erb +6 -6
  49. data/lib/packcr/templates/node/reference.rs.erb +3 -0
  50. data/lib/packcr/templates/node/rule.c.erb +9 -9
  51. data/lib/packcr/templates/node/rule.rs.erb +34 -0
  52. data/lib/packcr/templates/node/sequence.rs.erb +12 -0
  53. data/lib/packcr/templates/node/string_many.c.erb +2 -2
  54. data/lib/packcr/templates/node/string_many.rs.erb +10 -0
  55. data/lib/packcr/templates/node/string_one.c.erb +2 -2
  56. data/lib/packcr/templates/node/string_one.rs.erb +9 -0
  57. data/lib/packcr/util.rb +10 -1
  58. data/lib/packcr/version.rb +1 -1
  59. metadata +18 -65
@@ -12,14 +12,16 @@ class Packcr
12
12
  if !code(:eheader).empty?
13
13
  erbout << "\n".freeze
14
14
  end
15
- erbout << "#ifndef PCC_INCLUDED_#{@hid}\n#define PCC_INCLUDED_#{@hid}\n\n".freeze
15
+ erbout << "#ifndef PACKCR_INCLUDED_#{@hid}\n#define PACKCR_INCLUDED_#{@hid}\n\n".freeze
16
16
 
17
17
  code(:header).each do |code|
18
18
  erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
19
19
  end
20
- erbout << "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct #{prefix}_context_tag #{prefix}_context_t;\n\n#{prefix}_context_t *#{prefix}_create(#{auxil_def}auxil);\nint #{prefix}_parse(#{prefix}_context_t *ctx, #{value_def}*ret);\nvoid #{prefix}_destroy(#{prefix}_context_t *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* !PCC_INCLUDED_#{@hid} */\n".freeze
20
+ erbout << "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct #{prefix}_context_tag #{prefix}_context_t;\n\n#{prefix}_context_t *#{prefix}_create(#{auxil_def}auxil);\nint #{prefix}_parse(#{prefix}_context_t *ctx, #{value_def}*ret);\nvoid #{prefix}_destroy(#{prefix}_context_t *ctx);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* !PACKCR_INCLUDED_#{@hid} */\n".freeze
21
21
 
22
22
  erbout
23
+ else
24
+ raise "unknown lang #{lang}"
23
25
  end
24
26
  end
25
27
 
@@ -29,13 +31,13 @@ class Packcr
29
31
  erbout = +""
30
32
  erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\n".freeze
31
33
 
32
- code(:esource).each do |code|
33
- erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
34
- end
35
34
  if !code(:esource).empty?
35
+ code(:esource).each do |code|
36
+ erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
37
+ end
36
38
  erbout << "\n".freeze
37
39
  end
38
- erbout << "#ifdef _MSC_VER\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#endif /* _MSC_VER */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifndef _MSC_VER\n#if defined __GNUC__ && defined _WIN32 /* MinGW */\n#ifndef PCC_USE_SYSTEM_STRNLEN\n#define strnlen(str, maxlen) pcc_strnlen(str, maxlen)\nstatic size_t pcc_strnlen(const char *str, size_t maxlen) {\n size_t i;\n for (i = 0; i < maxlen && str[i]; i++);\n return i;\n}\n#endif /* !PCC_USE_SYSTEM_STRNLEN */\n#endif /* defined __GNUC__ && defined _WIN32 */\n#endif /* !_MSC_VER */\n\n#include \"#{@hname}\"\n".freeze
40
+ erbout << "#ifdef _MSC_VER\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#endif /* _MSC_VER */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifndef _MSC_VER\n#if defined __GNUC__ && defined _WIN32 /* MinGW */\n#ifndef PACKCR_USE_SYSTEM_STRNLEN\n#define strnlen(str, maxlen) packcr_strnlen(str, maxlen)\nstatic size_t packcr_strnlen(const char *str, size_t maxlen) {\n size_t i;\n for (i = 0; i < maxlen && str[i]; i++);\n return i;\n}\n#endif /* !PACKCR_USE_SYSTEM_STRNLEN */\n#endif /* defined __GNUC__ && defined _WIN32 */\n#endif /* !_MSC_VER */\n\n#include \"#{@hname}\"\n".freeze
39
41
 
40
42
  if !code(:location).empty?
41
43
  erbout << "\n".freeze
@@ -49,154 +51,196 @@ class Packcr
49
51
  code(:source).each do |code|
50
52
  erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
51
53
  end
52
- erbout << "#if !defined __has_attribute || defined _MSC_VER\n#define __attribute__(x)\n#endif\n\n#ifdef _MSC_VER\n#define MARK_FUNC_AS_USED __pragma(warning(suppress:4505))\n#else\n#define MARK_FUNC_AS_USED __attribute__((__unused__))\n#endif\n\n#ifndef PCC_BUFFER_MIN_SIZE\n#define PCC_BUFFER_MIN_SIZE 256\n#endif /* !PCC_BUFFER_MIN_SIZE */\n\n#ifndef PCC_ARRAY_MIN_SIZE\n#define PCC_ARRAY_MIN_SIZE 2\n#endif /* !PCC_ARRAY_MIN_SIZE */\n\n#ifndef PCC_POOL_MIN_SIZE\n#define PCC_POOL_MIN_SIZE 65536\n#endif /* !PCC_POOL_MIN_SIZE */\n\n#define PCC_DBG_EVALUATE 0\n#define PCC_DBG_MATCH 1\n#define PCC_DBG_NOMATCH 2\n\n#define PCC_VOID_VALUE (~(size_t)0)\n\ntypedef enum pcc_bool_tag {\n PCC_FALSE = 0,\n PCC_TRUE\n} pcc_bool_t;\n\ntypedef struct pcc_char_array_tag {\n char *buf;\n size_t max;\n size_t len;\n} pcc_char_array_t;\n\ntypedef struct pcc_range_tag {\n size_t start;\n size_t end;\n".freeze
54
+ erbout << "#if !defined __has_attribute || defined _MSC_VER\n#define __attribute__(x)\n#endif\n\n#ifdef _MSC_VER\n#define MARK_FUNC_AS_USED __pragma(warning(suppress:4505))\n#else\n#define MARK_FUNC_AS_USED __attribute__((__unused__))\n#endif\n\n#ifndef PACKCR_BUFFER_MIN_SIZE\n#define PACKCR_BUFFER_MIN_SIZE 256\n#endif /* !PACKCR_BUFFER_MIN_SIZE */\n\n#ifndef PACKCR_ARRAY_MIN_SIZE\n#define PACKCR_ARRAY_MIN_SIZE 2\n#endif /* !PACKCR_ARRAY_MIN_SIZE */\n\n#ifndef PACKCR_POOL_MIN_SIZE\n#define PACKCR_POOL_MIN_SIZE 65536\n#endif /* !PACKCR_POOL_MIN_SIZE */\n\n#define PACKCR_DBG_EVALUATE 0\n#define PACKCR_DBG_MATCH 1\n#define PACKCR_DBG_NOMATCH 2\n\n#define PACKCR_VOID_VALUE (~(size_t)0)\n\ntypedef enum packcr_bool_tag {\n PACKCR_FALSE = 0,\n PACKCR_TRUE\n} packcr_bool_t;\n\ntypedef struct packcr_char_array_tag {\n char *buf;\n size_t max;\n size_t len;\n} packcr_char_array_t;\n\ntypedef struct packcr_range_tag {\n size_t start;\n size_t end;\n".freeze
53
55
 
54
56
  if @location
55
- erbout << " pcc_location_t start_loc;\n pcc_location_t end_loc;\n".freeze
57
+ erbout << " packcr_location_t start_loc;\n packcr_location_t end_loc;\n".freeze
56
58
  end
57
- erbout << "} pcc_range_t;\n\ntypedef #{value_def}pcc_value_t;\n\ntypedef #{auxil_def}pcc_auxil_t;\n\n".freeze
59
+ erbout << "} packcr_range_t;\n\ntypedef #{value_def}packcr_value_t;\n\ntypedef #{auxil_def}packcr_auxil_t;\n\n".freeze
58
60
 
59
- if prefix != "pcc"
60
- erbout << "typedef #{prefix}_context_t pcc_context_t;\n\n".freeze
61
+ if prefix != "packcr"
62
+ erbout << "typedef #{prefix}_context_t packcr_context_t;\n\n".freeze
61
63
  end
62
- erbout << "typedef struct pcc_value_table_tag {\n pcc_value_t *buf;\n size_t max;\n size_t len;\n} pcc_value_table_t;\n\ntypedef struct pcc_value_refer_table_tag {\n pcc_value_t **buf;\n size_t max;\n size_t len;\n} pcc_value_refer_table_t;\n\ntypedef struct pcc_capture_tag {\n pcc_range_t range;\n char *string; /* mutable */\n} pcc_capture_t;\n\ntypedef struct pcc_capture_table_tag {\n pcc_capture_t *buf;\n size_t max;\n size_t len;\n} pcc_capture_table_t;\n\ntypedef struct pcc_capture_const_table_tag {\n const pcc_capture_t **buf;\n size_t max;\n size_t len;\n} pcc_capture_const_table_t;\n\ntypedef struct pcc_thunk_tag pcc_thunk_t;\ntypedef struct pcc_thunk_array_tag pcc_thunk_array_t;\n\ntypedef void (*pcc_action_t)(pcc_context_t *, pcc_thunk_t *, pcc_value_t *);\n\ntypedef enum pcc_thunk_type_tag {\n PCC_THUNK_LEAF,\n PCC_THUNK_NODE\n} pcc_thunk_type_t;\n\ntypedef struct pcc_thunk_leaf_tag {\n pcc_value_refer_table_t values;\n pcc_capture_const_table_t capts;\n pcc_capture_t capt0;\n pcc_action_t action;\n} pcc_thunk_leaf_t;\n\ntypedef struct pcc_thunk_node_tag {\n const pcc_thunk_array_t *thunks; /* just a reference */\n pcc_value_t *value; /* just a reference */\n} pcc_thunk_node_t;\n\ntypedef union pcc_thunk_data_tag {\n pcc_thunk_leaf_t leaf;\n pcc_thunk_node_t node;\n} pcc_thunk_data_t;\n\nstruct pcc_thunk_tag {\n pcc_thunk_type_t type;\n pcc_thunk_data_t data;\n};\n\nstruct pcc_thunk_array_tag {\n pcc_thunk_t **buf;\n size_t max;\n size_t len;\n};\n\ntypedef struct pcc_thunk_chunk_tag {\n pcc_value_table_t values;\n pcc_capture_table_t capts;\n pcc_thunk_array_t thunks;\n size_t pos; /* the starting position in the character buffer */\n".freeze
64
+ erbout << "typedef struct packcr_value_table_tag {\n packcr_value_t *buf;\n size_t max;\n size_t len;\n} packcr_value_table_t;\n\ntypedef struct packcr_value_refer_table_tag {\n packcr_value_t **buf;\n size_t max;\n size_t len;\n} packcr_value_refer_table_t;\n\ntypedef struct packcr_capture_tag {\n packcr_range_t range;\n char *string; /* mutable */\n} packcr_capture_t;\n\ntypedef struct packcr_capture_table_tag {\n packcr_capture_t *buf;\n size_t max;\n size_t len;\n} packcr_capture_table_t;\n\ntypedef struct packcr_capture_const_table_tag {\n const packcr_capture_t **buf;\n size_t max;\n size_t len;\n} packcr_capture_const_table_t;\n\ntypedef struct packcr_thunk_tag packcr_thunk_t;\ntypedef struct packcr_thunk_array_tag packcr_thunk_array_t;\n\ntypedef void (*packcr_action_t)(packcr_context_t *, packcr_thunk_t *, packcr_value_t *);\n\ntypedef enum packcr_thunk_type_tag {\n PACKCR_THUNK_LEAF,\n PACKCR_THUNK_NODE\n} packcr_thunk_type_t;\n\ntypedef struct packcr_thunk_leaf_tag {\n packcr_value_refer_table_t values;\n packcr_capture_const_table_t capts;\n packcr_capture_t capt0;\n packcr_action_t action;\n} packcr_thunk_leaf_t;\n\ntypedef struct packcr_thunk_node_tag {\n const packcr_thunk_array_t *thunks; /* just a reference */\n packcr_value_t *value; /* just a reference */\n} packcr_thunk_node_t;\n\ntypedef union packcr_thunk_data_tag {\n packcr_thunk_leaf_t leaf;\n packcr_thunk_node_t node;\n} packcr_thunk_data_t;\n\nstruct packcr_thunk_tag {\n packcr_thunk_type_t type;\n packcr_thunk_data_t data;\n};\n\nstruct packcr_thunk_array_tag {\n packcr_thunk_t **buf;\n size_t max;\n size_t len;\n};\n\ntypedef struct packcr_thunk_chunk_tag {\n packcr_value_table_t values;\n packcr_capture_table_t capts;\n packcr_thunk_array_t thunks;\n size_t pos; /* the starting position in the character buffer */\n".freeze
63
65
 
64
66
  if @location
65
- erbout << " pcc_location_t pos_loc;\n".freeze
67
+ erbout << " packcr_location_t pos_loc;\n".freeze
66
68
  end
67
- erbout << "} pcc_thunk_chunk_t;\n\ntypedef struct pcc_lr_memo_tag pcc_lr_memo_t;\n\nstruct pcc_lr_memo_tag {\n size_t offset;\n".freeze
69
+ erbout << "} packcr_thunk_chunk_t;\n\ntypedef struct packcr_lr_memo_tag packcr_lr_memo_t;\n\nstruct packcr_lr_memo_tag {\n size_t offset;\n".freeze
68
70
 
69
71
  if @location
70
- erbout << " pcc_location_t offset_loc;\n".freeze
72
+ erbout << " packcr_location_t offset_loc;\n".freeze
71
73
  end
72
- erbout << " pcc_lr_memo_t *hold;\n pcc_thunk_chunk_t *chunk;\n pcc_bool_t fail;\n pcc_bool_t grow;\n};\n\ntypedef struct pcc_rule_set_tag pcc_rule_set_t;\n\ntypedef pcc_thunk_chunk_t *(*pcc_rule_t)(pcc_context_t *, size_t".freeze
74
+ erbout << " packcr_lr_memo_t *hold;\n packcr_thunk_chunk_t *chunk;\n packcr_bool_t fail;\n packcr_bool_t grow;\n};\n\ntypedef struct packcr_rule_set_tag packcr_rule_set_t;\n\ntypedef packcr_thunk_chunk_t *(*packcr_rule_t)(packcr_context_t *, size_t".freeze
73
75
  if @location
74
- erbout << ", pcc_location_t".freeze
76
+ erbout << ", packcr_location_t".freeze
75
77
  end
76
- erbout << ", pcc_rule_set_t*);\n\ntypedef struct pcc_rule_set_tag {\n pcc_rule_t *buf;\n size_t max;\n size_t len;\n} pcc_rule_set_t;\n\ntypedef struct pcc_lr_memo_map_entry_tag {\n pcc_rule_t rule;\n pcc_lr_memo_t *memo;\n} pcc_lr_memo_map_entry_t;\n\ntypedef struct pcc_lr_memo_map_tag {\n pcc_lr_memo_map_entry_t *buf;\n size_t max;\n size_t len;\n} pcc_lr_memo_map_t;\n\ntypedef struct pcc_lr_table_tag {\n pcc_lr_memo_map_t **buf;\n size_t max;\n size_t len;\n size_t ofs;\n} pcc_lr_table_t;\n\ntypedef struct pcc_memory_entry_tag pcc_memory_entry_t;\ntypedef struct pcc_memory_pool_tag pcc_memory_pool_t;\n\nstruct pcc_memory_entry_tag {\n pcc_memory_entry_t *next;\n};\n\nstruct pcc_memory_pool_tag {\n pcc_memory_pool_t *next;\n size_t allocated;\n size_t unused;\n};\n\ntypedef struct pcc_memory_recycler_tag {\n pcc_memory_pool_t *pool_list;\n pcc_memory_entry_t *entry_list;\n size_t element_size;\n} pcc_memory_recycler_t;\n\nstruct #{prefix}_context_tag {\n size_t buffer_start_position; /* the position in the input of the first character currently buffered */\n size_t position_offset; /* the current parsing position in the character buffer */\n".freeze
78
+ erbout << ", packcr_rule_set_t*);\n\ntypedef struct packcr_rule_set_tag {\n packcr_rule_t *buf;\n size_t max;\n size_t len;\n} packcr_rule_set_t;\n\ntypedef struct packcr_lr_memo_map_entry_tag {\n packcr_rule_t rule;\n packcr_lr_memo_t *memo;\n} packcr_lr_memo_map_entry_t;\n\ntypedef struct packcr_lr_memo_map_tag {\n packcr_lr_memo_map_entry_t *buf;\n size_t max;\n size_t len;\n} packcr_lr_memo_map_t;\n\ntypedef struct packcr_lr_table_tag {\n packcr_lr_memo_map_t **buf;\n size_t max;\n size_t len;\n size_t ofs;\n} packcr_lr_table_t;\n\ntypedef struct packcr_memory_entry_tag packcr_memory_entry_t;\ntypedef struct packcr_memory_pool_tag packcr_memory_pool_t;\n\nstruct packcr_memory_entry_tag {\n packcr_memory_entry_t *next;\n};\n\nstruct packcr_memory_pool_tag {\n packcr_memory_pool_t *next;\n size_t allocated;\n size_t unused;\n};\n\ntypedef struct packcr_memory_recycler_tag {\n packcr_memory_pool_t *pool_list;\n packcr_memory_entry_t *entry_list;\n size_t element_size;\n} packcr_memory_recycler_t;\n\nstruct #{prefix}_context_tag {\n size_t buffer_start_position; /* the position in the input of the first character currently buffered */\n size_t position_offset; /* the current parsing position in the character buffer */\n".freeze
77
79
 
78
80
  if @location
79
- erbout << " pcc_location_t buffer_start_position_loc;\n pcc_location_t position_offset_loc;\n".freeze
81
+ erbout << " packcr_location_t buffer_start_position_loc;\n packcr_location_t position_offset_loc;\n".freeze
80
82
  end
81
- erbout << " size_t level;\n pcc_char_array_t buffer;\n pcc_lr_table_t lrtable;\n pcc_thunk_array_t thunks;\n pcc_auxil_t auxil;\n pcc_memory_recycler_t thunk_chunk_recycler;\n pcc_memory_recycler_t lr_memo_recycler;\n};\n\n#ifndef PCC_ERROR\n#define PCC_ERROR(auxil) pcc_error()\nMARK_FUNC_AS_USED\nstatic void pcc_error(void) {\n fprintf(stderr, \"Syntax error\\n\");\n exit(1);\n}\n#endif /* !PCC_ERROR */\n\n#ifndef PCC_GETCHAR\n#define PCC_GETCHAR(auxil) getchar()\n#endif /* !PCC_GETCHAR */\n\n#ifndef PCC_MALLOC\n#define PCC_MALLOC(auxil, size) pcc_malloc_e(size)\nstatic void *pcc_malloc_e(size_t size) {\n void *const p = malloc(size);\n if (p == NULL) {\n fprintf(stderr, \"Out of memory\\n\");\n exit(1);\n }\n return p;\n}\n#endif /* !PCC_MALLOC */\n\n#ifndef PCC_REALLOC\n#define PCC_REALLOC(auxil, ptr, size) pcc_realloc_e(ptr, size)\nstatic void *pcc_realloc_e(void *ptr, size_t size) {\n void *const p = realloc(ptr, size);\n if (p == NULL) {\n fprintf(stderr, \"Out of memory\\n\");\n exit(1);\n }\n return p;\n}\n#endif /* !PCC_REALLOC */\n\n#ifndef PCC_FREE\n#define PCC_FREE(auxil, ptr) free(ptr)\n#endif /* !PCC_FREE */\n\n#ifndef PCC_DEBUG\n#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) ((void)0)\n#endif /* !PCC_DEBUG */\n\nstatic char *pcc_strndup_e(pcc_auxil_t auxil, const char *str, size_t len) {\n const size_t m = strnlen(str, len);\n char *const s = (char *)PCC_MALLOC(auxil, m + 1);\n memcpy(s, str, m);\n s[m] = '\\0';\n return s;\n}\n\nstatic void pcc_char_array__init(pcc_auxil_t auxil, pcc_char_array_t *array) {\n array->len = 0;\n array->max = 0;\n array->buf = NULL;\n}\n\nstatic void pcc_char_array__add(pcc_auxil_t auxil, pcc_char_array_t *array, char ch) {\n if (array->max <= array->len) {\n const size_t n = array->len + 1;\n size_t m = array->max;\n if (m == 0) m = PCC_BUFFER_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n array->buf = (char *)PCC_REALLOC(auxil, array->buf, m);\n array->max = m;\n }\n array->buf[array->len++] = ch;\n}\n\nstatic void pcc_char_array__term(pcc_auxil_t auxil, pcc_char_array_t *array) {\n PCC_FREE(auxil, array->buf);\n}\n\nstatic void pcc_value_table__init(pcc_auxil_t auxil, pcc_value_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nMARK_FUNC_AS_USED\nstatic void pcc_value_table__resize(pcc_auxil_t auxil, pcc_value_table_t *table, size_t len) {\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (pcc_value_t *)PCC_REALLOC(auxil, table->buf, sizeof(pcc_value_t) * m);\n table->max = m;\n }\n table->len = len;\n}\n\nMARK_FUNC_AS_USED\nstatic void pcc_value_table__clear(pcc_auxil_t auxil, pcc_value_table_t *table) {\n memset(table->buf, 0, sizeof(pcc_value_t) * table->len);\n}\n\nstatic void pcc_value_table__term(pcc_auxil_t auxil, pcc_value_table_t *table) {\n PCC_FREE(auxil, table->buf);\n}\n\nstatic void pcc_value_refer_table__init(pcc_auxil_t auxil, pcc_value_refer_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void pcc_value_refer_table__resize(pcc_auxil_t auxil, pcc_value_refer_table_t *table, size_t len) {\n size_t i;\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (pcc_value_t **)PCC_REALLOC(auxil, table->buf, sizeof(pcc_value_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void pcc_value_refer_table__term(pcc_auxil_t auxil, pcc_value_refer_table_t *table) {\n PCC_FREE(auxil, table->buf);\n}\n\nstatic void pcc_capture_table__init(pcc_auxil_t auxil, pcc_capture_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nMARK_FUNC_AS_USED\nstatic void pcc_capture_table__resize(pcc_auxil_t auxil, pcc_capture_table_t *table, size_t len) {\n size_t i;\n for (i = len; i < table->len; i++) PCC_FREE(auxil, table->buf[i].string);\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (pcc_capture_t *)PCC_REALLOC(auxil, table->buf, sizeof(pcc_capture_t) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) {\n table->buf[i].range.start = 0;\n table->buf[i].range.end = 0;\n".freeze
83
+ erbout << " size_t level;\n packcr_char_array_t buffer;\n packcr_lr_table_t lrtable;\n packcr_thunk_array_t thunks;\n packcr_auxil_t auxil;\n packcr_memory_recycler_t thunk_chunk_recycler;\n packcr_memory_recycler_t lr_memo_recycler;\n};\n\n#ifndef PACKCR_ERROR\n#define PACKCR_ERROR(auxil) packcr_error()\nMARK_FUNC_AS_USED\nstatic void packcr_error(void) {\n fprintf(stderr, \"Syntax error\\n\");\n exit(1);\n}\n#endif /* !PACKCR_ERROR */\n\n#ifndef PACKCR_GETCHAR\n#define PACKCR_GETCHAR(auxil) getchar()\n#endif /* !PACKCR_GETCHAR */\n\n#ifndef PACKCR_MALLOC\n#define PACKCR_MALLOC(auxil, size) packcr_malloc_e(size)\nstatic void *packcr_malloc_e(size_t size) {\n void *const p = malloc(size);\n if (p == NULL) {\n fprintf(stderr, \"Out of memory\\n\");\n exit(1);\n }\n return p;\n}\n#endif /* !PACKCR_MALLOC */\n\n#ifndef PACKCR_REALLOC\n#define PACKCR_REALLOC(auxil, ptr, size) packcr_realloc_e(ptr, size)\nstatic void *packcr_realloc_e(void *ptr, size_t size) {\n void *const p = realloc(ptr, size);\n if (p == NULL) {\n fprintf(stderr, \"Out of memory\\n\");\n exit(1);\n }\n return p;\n}\n#endif /* !PACKCR_REALLOC */\n\n#ifndef PACKCR_FREE\n#define PACKCR_FREE(auxil, ptr) free(ptr)\n#endif /* !PACKCR_FREE */\n\n#ifndef PACKCR_DEBUG\n#define PACKCR_DEBUG(auxil, event, rule, level, pos, buffer, length) ((void)0)\n#endif /* !PACKCR_DEBUG */\n\nstatic char *packcr_strndup_e(packcr_auxil_t auxil, const char *str, size_t len) {\n const size_t m = strnlen(str, len);\n char *const s = (char *)PACKCR_MALLOC(auxil, m + 1);\n memcpy(s, str, m);\n s[m] = '\\0';\n return s;\n}\n\nstatic void packcr_char_array__init(packcr_auxil_t auxil, packcr_char_array_t *array) {\n array->len = 0;\n array->max = 0;\n array->buf = NULL;\n}\n\nstatic void packcr_char_array__add(packcr_auxil_t auxil, packcr_char_array_t *array, char ch) {\n if (array->max <= array->len) {\n const size_t n = array->len + 1;\n size_t m = array->max;\n if (m == 0) m = PACKCR_BUFFER_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n array->buf = (char *)PACKCR_REALLOC(auxil, array->buf, m);\n array->max = m;\n }\n array->buf[array->len++] = ch;\n}\n\nstatic void packcr_char_array__term(packcr_auxil_t auxil, packcr_char_array_t *array) {\n PACKCR_FREE(auxil, array->buf);\n}\n\nstatic void packcr_value_table__init(packcr_auxil_t auxil, packcr_value_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nMARK_FUNC_AS_USED\nstatic void packcr_value_table__resize(packcr_auxil_t auxil, packcr_value_table_t *table, size_t len) {\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (packcr_value_t *)PACKCR_REALLOC(auxil, table->buf, sizeof(packcr_value_t) * m);\n table->max = m;\n }\n table->len = len;\n}\n\nMARK_FUNC_AS_USED\nstatic void packcr_value_table__clear(packcr_auxil_t auxil, packcr_value_table_t *table) {\n memset(table->buf, 0, sizeof(packcr_value_t) * table->len);\n}\n\nstatic void packcr_value_table__term(packcr_auxil_t auxil, packcr_value_table_t *table) {\n PACKCR_FREE(auxil, table->buf);\n}\n\nstatic void packcr_value_refer_table__init(packcr_auxil_t auxil, packcr_value_refer_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void packcr_value_refer_table__resize(packcr_auxil_t auxil, packcr_value_refer_table_t *table, size_t len) {\n size_t i;\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (packcr_value_t **)PACKCR_REALLOC(auxil, table->buf, sizeof(packcr_value_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void packcr_value_refer_table__term(packcr_auxil_t auxil, packcr_value_refer_table_t *table) {\n PACKCR_FREE(auxil, table->buf);\n}\n\nstatic void packcr_capture_table__init(packcr_auxil_t auxil, packcr_capture_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nMARK_FUNC_AS_USED\nstatic void packcr_capture_table__resize(packcr_auxil_t auxil, packcr_capture_table_t *table, size_t len) {\n size_t i;\n for (i = len; i < table->len; i++) PACKCR_FREE(auxil, table->buf[i].string);\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (packcr_capture_t *)PACKCR_REALLOC(auxil, table->buf, sizeof(packcr_capture_t) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) {\n table->buf[i].range.start = 0;\n table->buf[i].range.end = 0;\n".freeze
82
84
 
83
85
  if @location
84
- erbout << " pcc_location_init(&table->buf[i].range.start_loc);\n pcc_location_init(&table->buf[i].range.end_loc);\n".freeze
86
+ erbout << " packcr_location_init(&table->buf[i].range.start_loc);\n packcr_location_init(&table->buf[i].range.end_loc);\n".freeze
85
87
  end
86
- erbout << " table->buf[i].string = NULL;\n }\n table->len = len;\n}\n\nstatic void pcc_capture_table__term(pcc_auxil_t auxil, pcc_capture_table_t *table) {\n while (table->len > 0) {\n table->len--;\n PCC_FREE(auxil, table->buf[table->len].string);\n }\n PCC_FREE(auxil, table->buf);\n}\n\nstatic void pcc_capture_const_table__init(pcc_auxil_t auxil, pcc_capture_const_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void pcc_capture_const_table__resize(pcc_auxil_t auxil, pcc_capture_const_table_t *table, size_t len) {\n size_t i;\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (const pcc_capture_t **)PCC_REALLOC(auxil, (pcc_capture_t **)table->buf, sizeof(const pcc_capture_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void pcc_capture_const_table__term(pcc_auxil_t auxil, pcc_capture_const_table_t *table) {\n PCC_FREE(auxil, (void *)table->buf);\n}\n\nMARK_FUNC_AS_USED\nstatic pcc_thunk_t *pcc_thunk__create_leaf(pcc_auxil_t auxil, pcc_action_t action, size_t valuec, size_t captc) {\n pcc_thunk_t *const thunk = (pcc_thunk_t *)PCC_MALLOC(auxil, sizeof(pcc_thunk_t));\n thunk->type = PCC_THUNK_LEAF;\n pcc_value_refer_table__init(auxil, &thunk->data.leaf.values);\n pcc_value_refer_table__resize(auxil, &thunk->data.leaf.values, valuec);\n pcc_capture_const_table__init(auxil, &thunk->data.leaf.capts);\n pcc_capture_const_table__resize(auxil, &thunk->data.leaf.capts, captc);\n thunk->data.leaf.capt0.range.start = 0;\n thunk->data.leaf.capt0.range.end = 0;\n".freeze
88
+ erbout << " table->buf[i].string = NULL;\n }\n table->len = len;\n}\n\nstatic void packcr_capture_table__term(packcr_auxil_t auxil, packcr_capture_table_t *table) {\n while (table->len > 0) {\n table->len--;\n PACKCR_FREE(auxil, table->buf[table->len].string);\n }\n PACKCR_FREE(auxil, table->buf);\n}\n\nstatic void packcr_capture_const_table__init(packcr_auxil_t auxil, packcr_capture_const_table_t *table) {\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void packcr_capture_const_table__resize(packcr_auxil_t auxil, packcr_capture_const_table_t *table, size_t len) {\n size_t i;\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (const packcr_capture_t **)PACKCR_REALLOC(auxil, (packcr_capture_t **)table->buf, sizeof(const packcr_capture_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void packcr_capture_const_table__term(packcr_auxil_t auxil, packcr_capture_const_table_t *table) {\n PACKCR_FREE(auxil, (void *)table->buf);\n}\n\nMARK_FUNC_AS_USED\nstatic packcr_thunk_t *packcr_thunk__create_leaf(packcr_auxil_t auxil, packcr_action_t action, size_t valuec, size_t captc) {\n packcr_thunk_t *const thunk = (packcr_thunk_t *)PACKCR_MALLOC(auxil, sizeof(packcr_thunk_t));\n thunk->type = PACKCR_THUNK_LEAF;\n packcr_value_refer_table__init(auxil, &thunk->data.leaf.values);\n packcr_value_refer_table__resize(auxil, &thunk->data.leaf.values, valuec);\n packcr_capture_const_table__init(auxil, &thunk->data.leaf.capts);\n packcr_capture_const_table__resize(auxil, &thunk->data.leaf.capts, captc);\n thunk->data.leaf.capt0.range.start = 0;\n thunk->data.leaf.capt0.range.end = 0;\n".freeze
87
89
 
88
90
  if @location
89
- erbout << " pcc_location_init(&thunk->data.leaf.capt0.range.start_loc);\n pcc_location_init(&thunk->data.leaf.capt0.range.end_loc);\n".freeze
91
+ erbout << " packcr_location_init(&thunk->data.leaf.capt0.range.start_loc);\n packcr_location_init(&thunk->data.leaf.capt0.range.end_loc);\n".freeze
90
92
  end
91
- erbout << " thunk->data.leaf.capt0.string = NULL;\n thunk->data.leaf.action = action;\n return thunk;\n}\n\nstatic pcc_thunk_t *pcc_thunk__create_node(pcc_auxil_t auxil, const pcc_thunk_array_t *thunks, pcc_value_t *value) {\n pcc_thunk_t *const thunk = (pcc_thunk_t *)PCC_MALLOC(auxil, sizeof(pcc_thunk_t));\n thunk->type = PCC_THUNK_NODE;\n thunk->data.node.thunks = thunks;\n thunk->data.node.value = value;\n return thunk;\n}\n\nstatic void pcc_thunk__destroy(pcc_auxil_t auxil, pcc_thunk_t *thunk) {\n if (thunk == NULL) return;\n switch (thunk->type) {\n case PCC_THUNK_LEAF:\n PCC_FREE(auxil, thunk->data.leaf.capt0.string);\n pcc_capture_const_table__term(auxil, &thunk->data.leaf.capts);\n pcc_value_refer_table__term(auxil, &thunk->data.leaf.values);\n break;\n case PCC_THUNK_NODE:\n break;\n default: /* unknown */\n break;\n }\n PCC_FREE(auxil, thunk);\n}\n\nstatic void pcc_thunk_array__init(pcc_auxil_t auxil, pcc_thunk_array_t *array) {\n array->len = 0;\n array->max = 0;\n array->buf = NULL;\n}\n\nstatic void pcc_thunk_array__add(pcc_auxil_t auxil, pcc_thunk_array_t *array, pcc_thunk_t *thunk) {\n if (array->max <= array->len) {\n const size_t n = array->len + 1;\n size_t m = array->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n array->buf = (pcc_thunk_t **)PCC_REALLOC(auxil, array->buf, sizeof(pcc_thunk_t *) * m);\n array->max = m;\n }\n array->buf[array->len++] = thunk;\n}\n\nstatic void pcc_thunk_array__revert(pcc_auxil_t auxil, pcc_thunk_array_t *array, size_t len) {\n while (array->len > len) {\n array->len--;\n pcc_thunk__destroy(auxil, array->buf[array->len]);\n }\n}\n\nstatic void pcc_thunk_array__term(pcc_auxil_t auxil, pcc_thunk_array_t *array) {\n while (array->len > 0) {\n array->len--;\n pcc_thunk__destroy(auxil, array->buf[array->len]);\n }\n PCC_FREE(auxil, array->buf);\n}\n\nstatic void pcc_memory_recycler__init(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler, size_t element_size) {\n recycler->pool_list = NULL;\n recycler->entry_list = NULL;\n recycler->element_size = element_size;\n}\n\nstatic void *pcc_memory_recycler__supply(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler) {\n if (recycler->entry_list) {\n pcc_memory_entry_t *const tmp = recycler->entry_list;\n recycler->entry_list = tmp->next;\n return tmp;\n }\n if (!recycler->pool_list || recycler->pool_list->unused == 0) {\n size_t size = PCC_POOL_MIN_SIZE;\n if (recycler->pool_list) {\n size = recycler->pool_list->allocated << 1;\n if (size == 0) size = recycler->pool_list->allocated;\n }\n {\n pcc_memory_pool_t *const pool = (pcc_memory_pool_t *)PCC_MALLOC(\n auxil, sizeof(pcc_memory_pool_t) + recycler->element_size * size\n );\n pool->allocated = size;\n pool->unused = size;\n pool->next = recycler->pool_list;\n recycler->pool_list = pool;\n }\n }\n recycler->pool_list->unused--;\n return (char *)recycler->pool_list + sizeof(pcc_memory_pool_t) + recycler->element_size * recycler->pool_list->unused;\n}\n\nstatic void pcc_memory_recycler__recycle(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler, void *ptr) {\n pcc_memory_entry_t *const tmp = (pcc_memory_entry_t *)ptr;\n tmp->next = recycler->entry_list;\n recycler->entry_list = tmp;\n}\n\nstatic void pcc_memory_recycler__term(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler) {\n while (recycler->pool_list) {\n pcc_memory_pool_t *const tmp = recycler->pool_list;\n recycler->pool_list = tmp->next;\n PCC_FREE(auxil, tmp);\n }\n}\n\nMARK_FUNC_AS_USED\nstatic pcc_thunk_chunk_t *pcc_thunk_chunk__create(pcc_context_t *ctx) {\n pcc_thunk_chunk_t *const chunk = (pcc_thunk_chunk_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->thunk_chunk_recycler);\n pcc_value_table__init(ctx->auxil, &chunk->values);\n pcc_capture_table__init(ctx->auxil, &chunk->capts);\n pcc_thunk_array__init(ctx->auxil, &chunk->thunks);\n chunk->pos = 0;\n return chunk;\n}\n\nstatic void pcc_thunk_chunk__destroy(pcc_context_t *ctx, pcc_thunk_chunk_t *chunk) {\n if (chunk == NULL) return;\n pcc_thunk_array__term(ctx->auxil, &chunk->thunks);\n pcc_capture_table__term(ctx->auxil, &chunk->capts);\n pcc_value_table__term(ctx->auxil, &chunk->values);\n pcc_memory_recycler__recycle(ctx->auxil, &ctx->thunk_chunk_recycler, chunk);\n}\n\nstatic void pcc_rule_set__init(pcc_auxil_t auxil, pcc_rule_set_t *set) {\n set->len = 0;\n set->max = 0;\n set->buf = NULL;\n}\n\nstatic size_t pcc_rule_set__index(pcc_auxil_t auxil, const pcc_rule_set_t *set, pcc_rule_t rule) {\n size_t i;\n for (i = 0; i < set->len; i++) {\n if (set->buf[i] == rule) return i;\n }\n return PCC_VOID_VALUE;\n}\n\nstatic pcc_bool_t pcc_rule_set__add(pcc_auxil_t auxil, pcc_rule_set_t *set, pcc_rule_t rule) {\n const size_t i = pcc_rule_set__index(auxil, set, rule);\n if (i != PCC_VOID_VALUE) return PCC_FALSE;\n if (set->max <= set->len) {\n const size_t n = set->len + 1;\n size_t m = set->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n set->buf = (pcc_rule_t *)PCC_REALLOC(auxil, set->buf, sizeof(pcc_rule_t) * m);\n set->max = m;\n }\n set->buf[set->len++] = rule;\n return PCC_TRUE;\n}\n\nstatic void pcc_rule_set__term(pcc_auxil_t auxil, pcc_rule_set_t *set) {\n PCC_FREE(auxil, set->buf);\n}\n\nstatic pcc_lr_memo_t *pcc_lr_memo__create(pcc_context_t *ctx, size_t offset".freeze
93
+ erbout << " thunk->data.leaf.capt0.string = NULL;\n thunk->data.leaf.action = action;\n return thunk;\n}\n\nstatic packcr_thunk_t *packcr_thunk__create_node(packcr_auxil_t auxil, const packcr_thunk_array_t *thunks, packcr_value_t *value) {\n packcr_thunk_t *const thunk = (packcr_thunk_t *)PACKCR_MALLOC(auxil, sizeof(packcr_thunk_t));\n thunk->type = PACKCR_THUNK_NODE;\n thunk->data.node.thunks = thunks;\n thunk->data.node.value = value;\n return thunk;\n}\n\nstatic void packcr_thunk__destroy(packcr_auxil_t auxil, packcr_thunk_t *thunk) {\n if (thunk == NULL) return;\n switch (thunk->type) {\n case PACKCR_THUNK_LEAF:\n PACKCR_FREE(auxil, thunk->data.leaf.capt0.string);\n packcr_capture_const_table__term(auxil, &thunk->data.leaf.capts);\n packcr_value_refer_table__term(auxil, &thunk->data.leaf.values);\n break;\n case PACKCR_THUNK_NODE:\n break;\n default: /* unknown */\n break;\n }\n PACKCR_FREE(auxil, thunk);\n}\n\nstatic void packcr_thunk_array__init(packcr_auxil_t auxil, packcr_thunk_array_t *array) {\n array->len = 0;\n array->max = 0;\n array->buf = NULL;\n}\n\nstatic void packcr_thunk_array__add(packcr_auxil_t auxil, packcr_thunk_array_t *array, packcr_thunk_t *thunk) {\n if (array->max <= array->len) {\n const size_t n = array->len + 1;\n size_t m = array->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n array->buf = (packcr_thunk_t **)PACKCR_REALLOC(auxil, array->buf, sizeof(packcr_thunk_t *) * m);\n array->max = m;\n }\n array->buf[array->len++] = thunk;\n}\n\nstatic void packcr_thunk_array__revert(packcr_auxil_t auxil, packcr_thunk_array_t *array, size_t len) {\n while (array->len > len) {\n array->len--;\n packcr_thunk__destroy(auxil, array->buf[array->len]);\n }\n}\n\nstatic void packcr_thunk_array__term(packcr_auxil_t auxil, packcr_thunk_array_t *array) {\n while (array->len > 0) {\n array->len--;\n packcr_thunk__destroy(auxil, array->buf[array->len]);\n }\n PACKCR_FREE(auxil, array->buf);\n}\n\nstatic void packcr_memory_recycler__init(packcr_auxil_t auxil, packcr_memory_recycler_t *recycler, size_t element_size) {\n recycler->pool_list = NULL;\n recycler->entry_list = NULL;\n recycler->element_size = element_size;\n}\n\nstatic void *packcr_memory_recycler__supply(packcr_auxil_t auxil, packcr_memory_recycler_t *recycler) {\n if (recycler->entry_list) {\n packcr_memory_entry_t *const tmp = recycler->entry_list;\n recycler->entry_list = tmp->next;\n return tmp;\n }\n if (!recycler->pool_list || recycler->pool_list->unused == 0) {\n size_t size = PACKCR_POOL_MIN_SIZE;\n if (recycler->pool_list) {\n size = recycler->pool_list->allocated << 1;\n if (size == 0) size = recycler->pool_list->allocated;\n }\n {\n packcr_memory_pool_t *const pool = (packcr_memory_pool_t *)PACKCR_MALLOC(\n auxil, sizeof(packcr_memory_pool_t) + recycler->element_size * size\n );\n pool->allocated = size;\n pool->unused = size;\n pool->next = recycler->pool_list;\n recycler->pool_list = pool;\n }\n }\n recycler->pool_list->unused--;\n return (char *)recycler->pool_list + sizeof(packcr_memory_pool_t) + recycler->element_size * recycler->pool_list->unused;\n}\n\nstatic void packcr_memory_recycler__recycle(packcr_auxil_t auxil, packcr_memory_recycler_t *recycler, void *ptr) {\n packcr_memory_entry_t *const tmp = (packcr_memory_entry_t *)ptr;\n tmp->next = recycler->entry_list;\n recycler->entry_list = tmp;\n}\n\nstatic void packcr_memory_recycler__term(packcr_auxil_t auxil, packcr_memory_recycler_t *recycler) {\n while (recycler->pool_list) {\n packcr_memory_pool_t *const tmp = recycler->pool_list;\n recycler->pool_list = tmp->next;\n PACKCR_FREE(auxil, tmp);\n }\n}\n\nMARK_FUNC_AS_USED\nstatic packcr_thunk_chunk_t *packcr_thunk_chunk__create(packcr_context_t *ctx) {\n packcr_thunk_chunk_t *const chunk = (packcr_thunk_chunk_t *)packcr_memory_recycler__supply(ctx->auxil, &ctx->thunk_chunk_recycler);\n packcr_value_table__init(ctx->auxil, &chunk->values);\n packcr_capture_table__init(ctx->auxil, &chunk->capts);\n packcr_thunk_array__init(ctx->auxil, &chunk->thunks);\n chunk->pos = 0;\n return chunk;\n}\n\nstatic void packcr_thunk_chunk__destroy(packcr_context_t *ctx, packcr_thunk_chunk_t *chunk) {\n if (chunk == NULL) return;\n packcr_thunk_array__term(ctx->auxil, &chunk->thunks);\n packcr_capture_table__term(ctx->auxil, &chunk->capts);\n packcr_value_table__term(ctx->auxil, &chunk->values);\n packcr_memory_recycler__recycle(ctx->auxil, &ctx->thunk_chunk_recycler, chunk);\n}\n\nstatic void packcr_rule_set__init(packcr_auxil_t auxil, packcr_rule_set_t *set) {\n set->len = 0;\n set->max = 0;\n set->buf = NULL;\n}\n\nstatic size_t packcr_rule_set__index(packcr_auxil_t auxil, const packcr_rule_set_t *set, packcr_rule_t rule) {\n size_t i;\n for (i = 0; i < set->len; i++) {\n if (set->buf[i] == rule) return i;\n }\n return PACKCR_VOID_VALUE;\n}\n\nstatic packcr_bool_t packcr_rule_set__add(packcr_auxil_t auxil, packcr_rule_set_t *set, packcr_rule_t rule) {\n const size_t i = packcr_rule_set__index(auxil, set, rule);\n if (i != PACKCR_VOID_VALUE) return PACKCR_FALSE;\n if (set->max <= set->len) {\n const size_t n = set->len + 1;\n size_t m = set->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n set->buf = (packcr_rule_t *)PACKCR_REALLOC(auxil, set->buf, sizeof(packcr_rule_t) * m);\n set->max = m;\n }\n set->buf[set->len++] = rule;\n return PACKCR_TRUE;\n}\n\nstatic void packcr_rule_set__term(packcr_auxil_t auxil, packcr_rule_set_t *set) {\n PACKCR_FREE(auxil, set->buf);\n}\n\nstatic packcr_lr_memo_t *packcr_lr_memo__create(packcr_context_t *ctx, size_t offset".freeze
92
94
  if @location
93
- erbout << ", pcc_location_t offset_loc".freeze
95
+ erbout << ", packcr_location_t offset_loc".freeze
94
96
  end
95
- erbout << ") {\n pcc_lr_memo_t *memo = (pcc_lr_memo_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->lr_memo_recycler);\n memo->offset = offset;\n".freeze
97
+ erbout << ") {\n packcr_lr_memo_t *memo = (packcr_lr_memo_t *)packcr_memory_recycler__supply(ctx->auxil, &ctx->lr_memo_recycler);\n memo->offset = offset;\n".freeze
96
98
 
97
99
  if @location
98
100
  erbout << " memo->offset_loc = offset_loc;\n".freeze
99
101
  end
100
- erbout << " memo->chunk = NULL;\n memo->fail = PCC_TRUE;\n memo->grow = PCC_FALSE;\n memo->hold = NULL;\n return memo;\n}\n\nstatic void pcc_lr_memo__set_chunk(pcc_context_t *ctx, pcc_lr_memo_t *memo, pcc_thunk_chunk_t *chunk) {\n if (memo->chunk) {\n pcc_lr_memo_t *const a = pcc_lr_memo__create(ctx, memo->offset".freeze
102
+ erbout << " memo->chunk = NULL;\n memo->fail = PACKCR_TRUE;\n memo->grow = PACKCR_FALSE;\n memo->hold = NULL;\n return memo;\n}\n\nstatic void packcr_lr_memo__set_chunk(packcr_context_t *ctx, packcr_lr_memo_t *memo, packcr_thunk_chunk_t *chunk) {\n if (memo->chunk) {\n packcr_lr_memo_t *const new_hold_memo = packcr_lr_memo__create(ctx, memo->offset".freeze
101
103
 
102
104
  if @location
103
105
  erbout << ", memo->offset_loc".freeze
104
106
  end
105
- erbout << ");\n a->chunk = memo->chunk;\n a->hold = memo->hold;\n memo->hold = a;\n }\n memo->chunk = chunk;\n memo->fail = PCC_FALSE;\n}\n\nstatic void pcc_lr_memo__destroy(pcc_context_t *ctx, pcc_lr_memo_t *memo) {\n while (memo != NULL) {\n pcc_lr_memo_t *const a = memo->hold;\n pcc_thunk_chunk__destroy(ctx, memo->chunk);\n pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_memo_recycler, memo);\n memo = a;\n }\n}\n\nstatic void pcc_lr_memo_map__init(pcc_auxil_t auxil, pcc_lr_memo_map_t *map) {\n map->len = 0;\n map->max = 0;\n map->buf = NULL;\n}\n\nstatic size_t pcc_lr_memo_map__index(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule) {\n size_t i;\n for (i = 0; i < map->len; i++) {\n if (map->buf[i].rule == rule) return i;\n }\n return PCC_VOID_VALUE;\n}\n\nstatic void pcc_lr_memo_map__put(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule, pcc_lr_memo_t *memo) {\n const size_t i = pcc_lr_memo_map__index(ctx, map, rule);\n if (i != PCC_VOID_VALUE) {\n pcc_lr_memo__destroy(ctx, map->buf[i].memo);\n map->buf[i].memo = memo;\n }\n else {\n if (map->max <= map->len) {\n const size_t n = map->len + 1;\n size_t m = map->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n map->buf = (pcc_lr_memo_map_entry_t *)PCC_REALLOC(ctx->auxil, map->buf, sizeof(pcc_lr_memo_map_entry_t) * m);\n map->max = m;\n }\n map->buf[map->len].rule = rule;\n map->buf[map->len].memo = memo;\n map->len++;\n }\n}\n\nstatic pcc_lr_memo_t *pcc_lr_memo_map__get(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule) {\n const size_t i = pcc_lr_memo_map__index(ctx, map, rule);\n return (i != PCC_VOID_VALUE) ? map->buf[i].memo : NULL;\n}\n\nstatic void pcc_lr_memo_map__term(pcc_context_t *ctx, pcc_lr_memo_map_t *map) {\n while (map->len > 0) {\n map->len--;\n pcc_lr_memo__destroy(ctx, map->buf[map->len].memo);\n }\n PCC_FREE(ctx->auxil, map->buf);\n}\n\nstatic pcc_lr_memo_map_t *pcc_lr_memo_map__create(pcc_context_t *ctx) {\n pcc_lr_memo_map_t *const memo = (pcc_lr_memo_map_t *)PCC_MALLOC(ctx->auxil, sizeof(pcc_lr_memo_map_t));\n pcc_lr_memo_map__init(ctx->auxil, memo);\n return memo;\n}\n\nstatic void pcc_lr_memo_map__destroy(pcc_context_t *ctx, pcc_lr_memo_map_t *memo) {\n if (memo == NULL) return;\n pcc_lr_memo_map__term(ctx, memo);\n PCC_FREE(ctx->auxil, memo);\n}\n\nstatic void pcc_lr_table__init(pcc_auxil_t auxil, pcc_lr_table_t *table) {\n table->ofs = 0;\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void pcc_lr_table__resize(pcc_context_t *ctx, pcc_lr_table_t *table, size_t len) {\n size_t i;\n for (i = len; i < table->len; i++) pcc_lr_memo_map__destroy(ctx, table->buf[i]);\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (pcc_lr_memo_map_t **)PCC_REALLOC(ctx->auxil, table->buf, sizeof(pcc_lr_memo_map_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void pcc_lr_table__set_memo(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_rule_t rule, pcc_lr_memo_t *memo) {\n index += table->ofs;\n if (index >= table->len) pcc_lr_table__resize(ctx, table, index + 1);\n if (table->buf[index] == NULL) table->buf[index] = pcc_lr_memo_map__create(ctx);\n pcc_lr_memo_map__put(ctx, table->buf[index], rule, memo);\n}\n\nstatic pcc_lr_memo_t *pcc_lr_table__get_memo(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_rule_t rule) {\n index += table->ofs;\n if (index >= table->len || table->buf[index] == NULL) return NULL;\n return pcc_lr_memo_map__get(ctx, table->buf[index], rule);\n}\n\nstatic void pcc_lr_table__shift(pcc_context_t *ctx, pcc_lr_table_t *table, size_t count) {\n size_t i;\n if (count > table->len - table->ofs) count = table->len - table->ofs;\n for (i = 0; i < count; i++) pcc_lr_memo_map__destroy(ctx, table->buf[table->ofs++]);\n if (table->ofs > (table->max >> 1)) {\n memmove(table->buf, table->buf + table->ofs, sizeof(pcc_lr_memo_map_t *) * (table->len - table->ofs));\n table->len -= table->ofs;\n table->ofs = 0;\n }\n}\n\nstatic void pcc_lr_table__term(pcc_context_t *ctx, pcc_lr_table_t *table) {\n while (table->len > table->ofs) {\n table->len--;\n pcc_lr_memo_map__destroy(ctx, table->buf[table->len]);\n }\n PCC_FREE(ctx->auxil, table->buf);\n}\n\nstatic pcc_context_t *pcc_context__create(pcc_auxil_t auxil) {\n pcc_context_t *const ctx = (pcc_context_t *)PCC_MALLOC(auxil, sizeof(pcc_context_t));\n ctx->buffer_start_position = 0;\n ctx->position_offset = 0;\n".freeze
107
+ erbout << ");\n new_hold_memo->chunk = memo->chunk;\n new_hold_memo->hold = memo->hold;\n memo->hold = new_hold_memo;\n }\n memo->chunk = chunk;\n memo->fail = PACKCR_FALSE;\n}\n\nstatic void packcr_lr_memo__destroy(packcr_context_t *ctx, packcr_lr_memo_t *memo) {\n while (memo != NULL) {\n packcr_lr_memo_t *const hold_memo = memo->hold;\n packcr_thunk_chunk__destroy(ctx, memo->chunk);\n packcr_memory_recycler__recycle(ctx->auxil, &ctx->lr_memo_recycler, memo);\n memo = hold_memo;\n }\n}\n\nstatic void packcr_lr_memo_map__init(packcr_auxil_t auxil, packcr_lr_memo_map_t *map) {\n map->len = 0;\n map->max = 0;\n map->buf = NULL;\n}\n\nstatic size_t packcr_lr_memo_map__index(packcr_context_t *ctx, packcr_lr_memo_map_t *map, packcr_rule_t rule) {\n size_t i;\n for (i = 0; i < map->len; i++) {\n if (map->buf[i].rule == rule) return i;\n }\n return PACKCR_VOID_VALUE;\n}\n\nstatic void packcr_lr_memo_map__put(packcr_context_t *ctx, packcr_lr_memo_map_t *map, packcr_rule_t rule, packcr_lr_memo_t *memo) {\n const size_t i = packcr_lr_memo_map__index(ctx, map, rule);\n if (i != PACKCR_VOID_VALUE) {\n packcr_lr_memo__destroy(ctx, map->buf[i].memo);\n map->buf[i].memo = memo;\n }\n else {\n if (map->max <= map->len) {\n const size_t n = map->len + 1;\n size_t m = map->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < n && m != 0) m <<= 1;\n if (m == 0) m = n;\n map->buf = (packcr_lr_memo_map_entry_t *)PACKCR_REALLOC(ctx->auxil, map->buf, sizeof(packcr_lr_memo_map_entry_t) * m);\n map->max = m;\n }\n map->buf[map->len].rule = rule;\n map->buf[map->len].memo = memo;\n map->len++;\n }\n}\n\nstatic packcr_lr_memo_t *packcr_lr_memo_map__get(packcr_context_t *ctx, packcr_lr_memo_map_t *map, packcr_rule_t rule) {\n const size_t i = packcr_lr_memo_map__index(ctx, map, rule);\n return (i != PACKCR_VOID_VALUE) ? map->buf[i].memo : NULL;\n}\n\nstatic void packcr_lr_memo_map__term(packcr_context_t *ctx, packcr_lr_memo_map_t *map) {\n while (map->len > 0) {\n map->len--;\n packcr_lr_memo__destroy(ctx, map->buf[map->len].memo);\n }\n PACKCR_FREE(ctx->auxil, map->buf);\n}\n\nstatic packcr_lr_memo_map_t *packcr_lr_memo_map__create(packcr_context_t *ctx) {\n packcr_lr_memo_map_t *const memo = (packcr_lr_memo_map_t *)PACKCR_MALLOC(ctx->auxil, sizeof(packcr_lr_memo_map_t));\n packcr_lr_memo_map__init(ctx->auxil, memo);\n return memo;\n}\n\nstatic void packcr_lr_memo_map__destroy(packcr_context_t *ctx, packcr_lr_memo_map_t *memo) {\n if (memo == NULL) return;\n packcr_lr_memo_map__term(ctx, memo);\n PACKCR_FREE(ctx->auxil, memo);\n}\n\nstatic void packcr_lr_table__init(packcr_auxil_t auxil, packcr_lr_table_t *table) {\n table->ofs = 0;\n table->len = 0;\n table->max = 0;\n table->buf = NULL;\n}\n\nstatic void packcr_lr_table__resize(packcr_context_t *ctx, packcr_lr_table_t *table, size_t len) {\n size_t i;\n for (i = len; i < table->len; i++) packcr_lr_memo_map__destroy(ctx, table->buf[i]);\n if (table->max < len) {\n size_t m = table->max;\n if (m == 0) m = PACKCR_ARRAY_MIN_SIZE;\n while (m < len && m != 0) m <<= 1;\n if (m == 0) m = len;\n table->buf = (packcr_lr_memo_map_t **)PACKCR_REALLOC(ctx->auxil, table->buf, sizeof(packcr_lr_memo_map_t *) * m);\n table->max = m;\n }\n for (i = table->len; i < len; i++) table->buf[i] = NULL;\n table->len = len;\n}\n\nstatic void packcr_lr_table__set_memo(packcr_context_t *ctx, packcr_lr_table_t *table, size_t index, packcr_rule_t rule, packcr_lr_memo_t *memo) {\n index += table->ofs;\n if (index >= table->len) packcr_lr_table__resize(ctx, table, index + 1);\n if (table->buf[index] == NULL) table->buf[index] = packcr_lr_memo_map__create(ctx);\n packcr_lr_memo_map__put(ctx, table->buf[index], rule, memo);\n}\n\nstatic packcr_lr_memo_t *packcr_lr_table__get_memo(packcr_context_t *ctx, packcr_lr_table_t *table, size_t index, packcr_rule_t rule) {\n index += table->ofs;\n if (index >= table->len || table->buf[index] == NULL) return NULL;\n return packcr_lr_memo_map__get(ctx, table->buf[index], rule);\n}\n\nstatic void packcr_lr_table__shift(packcr_context_t *ctx, packcr_lr_table_t *table, size_t count) {\n size_t i;\n if (count > table->len - table->ofs) count = table->len - table->ofs;\n for (i = 0; i < count; i++) packcr_lr_memo_map__destroy(ctx, table->buf[table->ofs++]);\n if (table->ofs > (table->max >> 1)) {\n memmove(table->buf, table->buf + table->ofs, sizeof(packcr_lr_memo_map_t *) * (table->len - table->ofs));\n table->len -= table->ofs;\n table->ofs = 0;\n }\n}\n\nstatic void packcr_lr_table__term(packcr_context_t *ctx, packcr_lr_table_t *table) {\n while (table->len > table->ofs) {\n table->len--;\n packcr_lr_memo_map__destroy(ctx, table->buf[table->len]);\n }\n PACKCR_FREE(ctx->auxil, table->buf);\n}\n\nstatic packcr_context_t *packcr_context__create(packcr_auxil_t auxil) {\n packcr_context_t *const ctx = (packcr_context_t *)PACKCR_MALLOC(auxil, sizeof(packcr_context_t));\n ctx->buffer_start_position = 0;\n ctx->position_offset = 0;\n".freeze
106
108
 
107
109
  if @location
108
- erbout << " pcc_location_init(&ctx->buffer_start_position_loc);\n pcc_location_init(&ctx->position_offset_loc);\n".freeze
110
+ erbout << " packcr_location_init(&ctx->buffer_start_position_loc);\n packcr_location_init(&ctx->position_offset_loc);\n".freeze
109
111
  end
110
- erbout << " ctx->level = 0;\n pcc_char_array__init(auxil, &ctx->buffer);\n pcc_lr_table__init(auxil, &ctx->lrtable);\n pcc_thunk_array__init(auxil, &ctx->thunks);\n pcc_memory_recycler__init(auxil, &ctx->thunk_chunk_recycler, sizeof(pcc_thunk_chunk_t));\n pcc_memory_recycler__init(auxil, &ctx->lr_memo_recycler, sizeof(pcc_lr_memo_t));\n ctx->auxil = auxil;\n return ctx;\n}\n\nstatic void pcc_context__destroy(pcc_context_t *ctx) {\n if (ctx == NULL) return;\n pcc_thunk_array__term(ctx->auxil, &ctx->thunks);\n pcc_lr_table__term(ctx, &ctx->lrtable);\n pcc_char_array__term(ctx->auxil, &ctx->buffer);\n pcc_memory_recycler__term(ctx->auxil, &ctx->thunk_chunk_recycler);\n pcc_memory_recycler__term(ctx->auxil, &ctx->lr_memo_recycler);\n PCC_FREE(ctx->auxil, ctx);\n}\n\nstatic size_t pcc_refill_buffer(pcc_context_t *ctx, size_t num) {\n if (ctx->buffer.len >= ctx->position_offset + num) return ctx->buffer.len - ctx->position_offset;\n while (ctx->buffer.len < ctx->position_offset + num) {\n const int c = PCC_GETCHAR(ctx->auxil);\n if (c < 0) break;\n pcc_char_array__add(ctx->auxil, &ctx->buffer, (char)c);\n }\n return ctx->buffer.len - ctx->position_offset;\n}\n\nMARK_FUNC_AS_USED\nstatic void pcc_commit_buffer(pcc_context_t *ctx) {\n memmove(ctx->buffer.buf, ctx->buffer.buf + ctx->position_offset, ctx->buffer.len - ctx->position_offset);\n ctx->buffer.len -= ctx->position_offset;\n ctx->buffer_start_position += ctx->position_offset;\n pcc_lr_table__shift(ctx, &ctx->lrtable, ctx->position_offset);\n ctx->position_offset = 0;\n".freeze
112
+ erbout << " ctx->level = 0;\n packcr_char_array__init(auxil, &ctx->buffer);\n packcr_lr_table__init(auxil, &ctx->lrtable);\n packcr_thunk_array__init(auxil, &ctx->thunks);\n packcr_memory_recycler__init(auxil, &ctx->thunk_chunk_recycler, sizeof(packcr_thunk_chunk_t));\n packcr_memory_recycler__init(auxil, &ctx->lr_memo_recycler, sizeof(packcr_lr_memo_t));\n ctx->auxil = auxil;\n return ctx;\n}\n\nstatic void packcr_context__destroy(packcr_context_t *ctx) {\n if (ctx == NULL) return;\n packcr_thunk_array__term(ctx->auxil, &ctx->thunks);\n packcr_lr_table__term(ctx, &ctx->lrtable);\n packcr_char_array__term(ctx->auxil, &ctx->buffer);\n packcr_memory_recycler__term(ctx->auxil, &ctx->thunk_chunk_recycler);\n packcr_memory_recycler__term(ctx->auxil, &ctx->lr_memo_recycler);\n PACKCR_FREE(ctx->auxil, ctx);\n}\n\nstatic size_t packcr_refill_buffer(packcr_context_t *ctx, size_t num) {\n if (ctx->buffer.len >= ctx->position_offset + num) return ctx->buffer.len - ctx->position_offset;\n while (ctx->buffer.len < ctx->position_offset + num) {\n const int c = PACKCR_GETCHAR(ctx->auxil);\n if (c < 0) break;\n packcr_char_array__add(ctx->auxil, &ctx->buffer, (char)c);\n }\n return ctx->buffer.len - ctx->position_offset;\n}\n\nMARK_FUNC_AS_USED\nstatic void packcr_commit_buffer(packcr_context_t *ctx) {\n memmove(ctx->buffer.buf, ctx->buffer.buf + ctx->position_offset, ctx->buffer.len - ctx->position_offset);\n ctx->buffer.len -= ctx->position_offset;\n ctx->buffer_start_position += ctx->position_offset;\n packcr_lr_table__shift(ctx, &ctx->lrtable, ctx->position_offset);\n ctx->position_offset = 0;\n".freeze
111
113
 
112
114
  if @location
113
- erbout << " ctx->buffer_start_position_loc = pcc_location_add(ctx->buffer_start_position_loc, ctx->position_offset_loc);\n pcc_location_init(&ctx->position_offset_loc);\n".freeze
115
+ erbout << " ctx->buffer_start_position_loc = packcr_location_add(ctx->buffer_start_position_loc, ctx->position_offset_loc);\n packcr_location_init(&ctx->position_offset_loc);\n".freeze
114
116
  end
115
- erbout << "}\n\nMARK_FUNC_AS_USED\nstatic const char *pcc_get_capture_string(pcc_context_t *ctx, const pcc_capture_t *capt) {\n if (capt->string == NULL)\n ((pcc_capture_t *)capt)->string =\n pcc_strndup_e(ctx->auxil, ctx->buffer.buf + capt->range.start, capt->range.end - capt->range.start);\n return capt->string;\n}\n\n".freeze
117
+ erbout << "}\n\nMARK_FUNC_AS_USED\nstatic const char *packcr_get_capture_string(packcr_context_t *ctx, const packcr_capture_t *capt) {\n if (capt->string == NULL)\n ((packcr_capture_t *)capt)->string =\n packcr_strndup_e(ctx->auxil, ctx->buffer.buf + capt->range.start, capt->range.end - capt->range.start);\n return capt->string;\n}\n\n".freeze
116
118
 
117
119
  if @utf8
118
- erbout << "static size_t pcc_get_char_as_utf32(pcc_context_t *ctx, int *out) { /* with checking UTF-8 validity */\n int c, u;\n size_t n;\n if (pcc_refill_buffer(ctx, 1) < 1) return 0;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset];\n n = (c < 0x80) ? 1 :\n ((c & 0xe0) == 0xc0) ? 2 :\n ((c & 0xf0) == 0xe0) ? 3 :\n ((c & 0xf8) == 0xf0) ? 4 : 0;\n if (n < 1) return 0;\n if (pcc_refill_buffer(ctx, n) < n) return 0;\n switch (n) {\n case 1:\n u = c;\n break;\n case 2:\n u = c & 0x1f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x80) return 0;\n break;\n case 3:\n u = c & 0x0f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 2];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x800) return 0;\n break;\n case 4:\n u = c & 0x07;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 2];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 3];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x10000 || u > 0x10ffff) return 0;\n break;\n default:\n return 0;\n }\n if (out) *out = u;\n return n;\n}\n\n".freeze
120
+ erbout << "static size_t packcr_get_char_as_utf32(packcr_context_t *ctx, int *out) { /* with checking UTF-8 validity */\n int c, u;\n size_t n;\n if (packcr_refill_buffer(ctx, 1) < 1) return 0;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset];\n n = (c < 0x80) ? 1 :\n ((c & 0xe0) == 0xc0) ? 2 :\n ((c & 0xf0) == 0xe0) ? 3 :\n ((c & 0xf8) == 0xf0) ? 4 : 0;\n if (n < 1) return 0;\n if (packcr_refill_buffer(ctx, n) < n) return 0;\n switch (n) {\n case 1:\n u = c;\n break;\n case 2:\n u = c & 0x1f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x80) return 0;\n break;\n case 3:\n u = c & 0x0f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 2];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x800) return 0;\n break;\n case 4:\n u = c & 0x07;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 1];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 2];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n c = (int)(unsigned char)ctx->buffer.buf[ctx->position_offset + 3];\n if ((c & 0xc0) != 0x80) return 0;\n u <<= 6; u |= c & 0x3f;\n if (u < 0x10000 || u > 0x10ffff) return 0;\n break;\n default:\n return 0;\n }\n if (out) *out = u;\n return n;\n}\n\n".freeze
119
121
  end
120
- erbout << "static void pcc_grow_lr(pcc_context_t *ctx, pcc_rule_t rule, size_t offset".freeze
122
+ erbout << "static void packcr_grow_lr(packcr_context_t *ctx, packcr_rule_t rule, size_t offset".freeze
121
123
  if @location
122
- erbout << ", pcc_location_t offset_loc".freeze
124
+ erbout << ", packcr_location_t offset_loc".freeze
123
125
  end
124
- erbout << ") {\n while(1) {\n const size_t old_offset = ctx->position_offset;\n pcc_thunk_chunk_t *chunk;\n pcc_lr_memo_t *memo;\n pcc_rule_set_t limits;\n ctx->position_offset = offset;\n".freeze
126
+ erbout << ") {\n while(1) {\n const size_t old_offset = ctx->position_offset;\n packcr_thunk_chunk_t *chunk;\n packcr_lr_memo_t *memo;\n packcr_rule_set_t limits;\n ctx->position_offset = offset;\n".freeze
125
127
 
126
128
  if @location
127
129
  erbout << " ctx->position_offset_loc = offset_loc;\n".freeze
128
130
  end
129
- erbout << " pcc_rule_set__init(ctx->auxil, &limits);\n pcc_rule_set__add(ctx->auxil, &limits, rule);\n chunk = rule(ctx, offset".freeze
131
+ erbout << " packcr_rule_set__init(ctx->auxil, &limits);\n packcr_rule_set__add(ctx->auxil, &limits, rule);\n chunk = rule(ctx, offset".freeze
130
132
 
131
133
  if @location
132
134
  erbout << ", offset_loc".freeze
133
135
  end
134
- erbout << ", &limits);\n pcc_rule_set__term(ctx->auxil, &limits);\n if (!chunk)\n break;\n if (ctx->position_offset <= old_offset) {\n pcc_thunk_chunk__destroy(ctx, chunk);\n break;\n }\n memo = pcc_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n pcc_lr_memo__set_chunk(ctx, memo, chunk);\n memo->offset = ctx->position_offset;\n".freeze
136
+ erbout << ", &limits);\n packcr_rule_set__term(ctx->auxil, &limits);\n if (!chunk)\n break;\n if (ctx->position_offset <= old_offset) {\n packcr_thunk_chunk__destroy(ctx, chunk);\n break;\n }\n memo = packcr_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n packcr_lr_memo__set_chunk(ctx, memo, chunk);\n memo->offset = ctx->position_offset;\n".freeze
135
137
 
136
138
  if @location
137
139
  erbout << " memo->offset_loc = ctx->position_offset_loc;\n".freeze
138
140
  end
139
- erbout << " }\n}\n\nMARK_FUNC_AS_USED\nstatic pcc_thunk_chunk_t *pcc_get_rule_thunk_chunk(pcc_context_t *ctx, pcc_rule_t rule) {\n pcc_thunk_chunk_t *c = NULL;\n size_t offset = ctx->position_offset;\n".freeze
141
+ erbout << " }\n}\n\nMARK_FUNC_AS_USED\nstatic packcr_thunk_chunk_t *packcr_get_rule_thunk_chunk(packcr_context_t *ctx, packcr_rule_t rule) {\n packcr_thunk_chunk_t *c = NULL;\n size_t offset = ctx->position_offset;\n".freeze
140
142
 
141
143
  if @location
142
- erbout << " pcc_location_t offset_loc = ctx->position_offset_loc;\n".freeze
144
+ erbout << " packcr_location_t offset_loc = ctx->position_offset_loc;\n".freeze
143
145
  end
144
- erbout << " pcc_lr_memo_t *a = pcc_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n\n if (a == NULL) {\n a = pcc_lr_memo__create(ctx, offset".freeze
146
+ erbout << " packcr_lr_memo_t *memo = packcr_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n\n if (memo == NULL) {\n memo = packcr_lr_memo__create(ctx, offset".freeze
145
147
 
146
148
  if @location
147
149
  erbout << ", offset_loc".freeze
148
150
  end
149
- erbout << ");\n pcc_lr_table__set_memo(ctx, &ctx->lrtable, offset, rule, a);\n c = rule(ctx, offset".freeze
151
+ erbout << ");\n packcr_lr_table__set_memo(ctx, &ctx->lrtable, offset, rule, memo);\n c = rule(ctx, offset".freeze
150
152
 
151
153
  if @location
152
154
  erbout << ", offset_loc".freeze
153
155
  end
154
- erbout << ", NULL);\n pcc_lr_memo__set_chunk(ctx, a, c);\n a->offset = ctx->position_offset;\n".freeze
156
+ erbout << ", NULL);\n packcr_lr_memo__set_chunk(ctx, memo, c);\n memo->offset = ctx->position_offset;\n".freeze
155
157
 
156
158
  if @location
157
- erbout << " a->offset_loc = ctx->position_offset_loc;\n".freeze
159
+ erbout << " memo->offset_loc = ctx->position_offset_loc;\n".freeze
158
160
  end
159
- erbout << " if (a->grow) {\n pcc_grow_lr(ctx, rule, offset".freeze
161
+ erbout << " if (memo->grow) {\n packcr_grow_lr(ctx, rule, offset".freeze
160
162
 
161
163
  if @location
162
164
  erbout << ", offset_loc".freeze
163
165
  end
164
- erbout << ");\n a->grow = PCC_FALSE;\n ctx->position_offset = a->offset;\n return a->chunk;\n }\n return c;\n } else if (a->fail) {\n pcc_lr_memo__set_chunk(ctx, a, NULL);\n a->grow = PCC_TRUE;\n return NULL;\n }\n ctx->position_offset = a->offset;\n return a->chunk;\n}\n\nMARK_FUNC_AS_USED\nstatic pcc_bool_t pcc_apply_rule(pcc_context_t *ctx, pcc_rule_t rule, pcc_thunk_array_t *thunks, pcc_value_t *value, size_t offset".freeze
166
+ erbout << ");\n memo->grow = PACKCR_FALSE;\n ctx->position_offset = memo->offset;\n".freeze
167
+
168
+ if @location
169
+ erbout << " ctx->position_offset_loc = memo->offset_loc;\n".freeze
170
+ end
171
+ erbout << " return memo->chunk;\n }\n return c;\n } else if (memo->fail) {\n packcr_lr_memo__set_chunk(ctx, memo, NULL);\n memo->grow = PACKCR_TRUE;\n return NULL;\n }\n ctx->position_offset = memo->offset;\n".freeze
172
+
173
+ if @location
174
+ erbout << " ctx->position_offset_loc = memo->offset_loc;\n".freeze
175
+ end
176
+ erbout << " return memo->chunk;\n}\n\nMARK_FUNC_AS_USED\nstatic packcr_bool_t packcr_apply_rule(packcr_context_t *ctx, packcr_rule_t rule, packcr_thunk_array_t *thunks, packcr_value_t *value, size_t offset".freeze
165
177
 
166
178
  if @location
167
- erbout << ", pcc_location_t offset_loc".freeze
179
+ erbout << ", packcr_location_t offset_loc".freeze
168
180
  end
169
- erbout << ", pcc_rule_set_t *limits) {\n static pcc_value_t null;\n pcc_thunk_chunk_t *c;\n if (limits != NULL) {\n pcc_lr_memo_t *a;\n pcc_rule_set__add(ctx->auxil, limits, rule);\n c = rule(ctx, offset".freeze
181
+ erbout << ", packcr_rule_set_t *limits) {\n static packcr_value_t null;\n packcr_thunk_chunk_t *c;\n if (limits != NULL) {\n packcr_lr_memo_t *memo;\n packcr_rule_set__add(ctx->auxil, limits, rule);\n c = rule(ctx, offset".freeze
170
182
 
171
183
  if @location
172
184
  erbout << ", offset_loc".freeze
173
185
  end
174
- erbout << ", limits);\n a = pcc_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n if (a == NULL || ctx->position_offset <= a->offset) {\n c = a->chunk;\n ctx->position_offset = a->offset;\n } else {\n pcc_lr_memo__set_chunk(ctx, a, c);\n a->offset = ctx->position_offset;\n }\n } else {\n c = pcc_get_rule_thunk_chunk(ctx, rule);\n }\n if (c == NULL) return PCC_FALSE;\n if (value == NULL) value = &null;\n memset(value, 0, sizeof(pcc_value_t)); /* in case */\n pcc_thunk_array__add(ctx->auxil, thunks, pcc_thunk__create_node(ctx->auxil, &c->thunks, value));\n return PCC_TRUE;\n}\n\nMARK_FUNC_AS_USED\nstatic void pcc_do_action(pcc_context_t *ctx, const pcc_thunk_array_t *thunks, pcc_value_t *value) {\n size_t i;\n for (i = 0; i < thunks->len; i++) {\n pcc_thunk_t *const thunk = thunks->buf[i];\n switch (thunk->type) {\n case PCC_THUNK_LEAF:\n thunk->data.leaf.action(ctx, thunk, value);\n break;\n case PCC_THUNK_NODE:\n pcc_do_action(ctx, thunk->data.node.thunks, thunk->data.node.value);\n break;\n default: /* unknown */\n break;\n }\n }\n}\n\n".freeze
186
+ erbout << ", limits);\n memo = packcr_lr_table__get_memo(ctx, &ctx->lrtable, offset, rule);\n if (memo == NULL || ctx->position_offset <= memo->offset) {\n if (memo) {\n c = memo->chunk;\n ctx->position_offset = memo->offset;\n".freeze
187
+
188
+ if @location
189
+ erbout << " ctx->position_offset_loc = memo->offset_loc;\n".freeze
190
+ end
191
+ erbout << " }\n } else {\n packcr_lr_memo__set_chunk(ctx, memo, c);\n memo->offset = ctx->position_offset;\n".freeze
192
+
193
+ if @location
194
+ erbout << " memo->offset_loc = ctx->position_offset_loc;\n".freeze
195
+ end
196
+ erbout << " }\n } else {\n c = packcr_get_rule_thunk_chunk(ctx, rule);\n }\n if (c == NULL) return PACKCR_FALSE;\n if (value == NULL) value = &null;\n memset(value, 0, sizeof(packcr_value_t)); /* in case */\n packcr_thunk_array__add(ctx->auxil, thunks, packcr_thunk__create_node(ctx->auxil, &c->thunks, value));\n return PACKCR_TRUE;\n}\n\nMARK_FUNC_AS_USED\nstatic void packcr_do_action(packcr_context_t *ctx, const packcr_thunk_array_t *thunks, packcr_value_t *value) {\n size_t i;\n for (i = 0; i < thunks->len; i++) {\n packcr_thunk_t *const thunk = thunks->buf[i];\n switch (thunk->type) {\n case PACKCR_THUNK_LEAF:\n thunk->data.leaf.action(ctx, thunk, value);\n break;\n case PACKCR_THUNK_NODE:\n packcr_do_action(ctx, thunk->data.node.thunks, thunk->data.node.value);\n break;\n default: /* unknown */\n break;\n }\n }\n}\n\n#{prefix}_context_t *#{prefix}_create(#{auxil_def}auxil) {\n return packcr_context__create(auxil);\n}\n\nvoid #{prefix}_destroy(#{prefix}_context_t *ctx) {\n packcr_context__destroy(ctx);\n}\n".freeze
197
+
198
+ if !@root.rules.empty?
199
+ erbout << "\n".freeze
200
+
201
+ @root.rules.each do |rule|
202
+ erbout << "static packcr_thunk_chunk_t *packcr_evaluate_rule_#{rule.name}(packcr_context_t *ctx, size_t offset".freeze
203
+ if @location
204
+ erbout << ", packcr_location_t offset_loc".freeze
205
+ end
206
+ erbout << ", packcr_rule_set_t *limits);\n".freeze
207
+ end
208
+ end
209
+ erbout << "\nint #{prefix}_parse(#{prefix}_context_t *ctx, #{value_def}*ret) {\n size_t pos = ctx->buffer_start_position;\n".freeze
210
+
211
+ if !@root.rules.empty?
212
+ erbout << " if (packcr_apply_rule(ctx, packcr_evaluate_rule_#{@root.rules[0].name}, &ctx->thunks, ret, ctx->position_offset".freeze
213
+ if @location
214
+ erbout << ", ctx->position_offset_loc".freeze
215
+ end
216
+ erbout << ", NULL))\n packcr_do_action(ctx, &ctx->thunks, ret);\n else\n PACKCR_ERROR(ctx->auxil);\n packcr_commit_buffer(ctx);\n".freeze
217
+ end
218
+ erbout << " packcr_thunk_array__revert(ctx->auxil, &ctx->thunks, 0);\n return pos != ctx->buffer_start_position && packcr_refill_buffer(ctx, 1) >= 1;\n}\n\n".freeze
175
219
 
176
220
  @root.rules.each do |rule|
177
221
  rule.codes.each do |code|
178
- erbout << "static void pcc_action_#{rule.name}_#{code.index}(#{prefix}_context_t *__pcc_ctx, pcc_thunk_t *__pcc_in, pcc_value_t *__pcc_out) {\n#define auxil (__pcc_ctx->auxil)\n#define __ (*__pcc_out)\n".freeze
222
+ erbout << "static void packcr_action_#{rule.name}_#{code.index}(#{prefix}_context_t *__packcr_ctx, packcr_thunk_t *__packcr_in, packcr_value_t *__packcr_out) {\n#define auxil (__packcr_ctx->auxil)\n#define __ (*__packcr_out)\n".freeze
179
223
 
180
224
  code.vars.each do |ref|
181
- erbout << "#define #{ref.var} (*__pcc_in->data.leaf.values.buf[#{ref.index}])\n".freeze
225
+ erbout << "#define #{ref.var} (*__packcr_in->data.leaf.values.buf[#{ref.index}])\n".freeze
182
226
  end
183
- erbout << "#define _0 pcc_get_capture_string(__pcc_ctx, &__pcc_in->data.leaf.capt0)\n#define _0s ((const size_t)(__pcc_ctx->buffer_start_position + __pcc_in->data.leaf.capt0.range.start))\n#define _0e ((const size_t)(__pcc_ctx->buffer_start_position + __pcc_in->data.leaf.capt0.range.end))\n".freeze
227
+ erbout << "#define _0 packcr_get_capture_string(__packcr_ctx, &__packcr_in->data.leaf.capt0)\n#define _0s ((const size_t)(__packcr_ctx->buffer_start_position + __packcr_in->data.leaf.capt0.range.start))\n#define _0e ((const size_t)(__packcr_ctx->buffer_start_position + __packcr_in->data.leaf.capt0.range.end))\n".freeze
184
228
 
185
229
  if @location
186
- erbout << "#define _0sl ((const pcc_location_t)(pcc_location_add(__pcc_ctx->buffer_start_position_loc, __pcc_in->data.leaf.capt0.range.start_loc)))\n#define _0el ((const pcc_location_t)(pcc_location_add(__pcc_ctx->buffer_start_position_loc, __pcc_in->data.leaf.capt0.range.end_loc)))\n".freeze
230
+ erbout << "#define _0sl ((const packcr_location_t)(packcr_location_add(__packcr_ctx->buffer_start_position_loc, __packcr_in->data.leaf.capt0.range.start_loc)))\n#define _0el ((const packcr_location_t)(packcr_location_add(__packcr_ctx->buffer_start_position_loc, __packcr_in->data.leaf.capt0.range.end_loc)))\n".freeze
187
231
  end
188
232
  if @capture_in_code
189
- erbout << "#define _0c __pcc_in->data.leaf.capt0\n".freeze
233
+ erbout << "#define _0c __packcr_in->data.leaf.capt0\n".freeze
190
234
  end
191
235
  code.capts.each do |capture|
192
- erbout << "#define _#{capture.index + 1} pcc_get_capture_string(__pcc_ctx, __pcc_in->data.leaf.capts.buf[#{capture.index}])\n#define _#{capture.index + 1}s ((const size_t)(__pcc_ctx->buffer_start_position + __pcc_in->data.leaf.capts.buf[#{capture.index}]->range.start))\n#define _#{capture.index + 1}e ((const size_t)(__pcc_ctx->buffer_start_position + __pcc_in->data.leaf.capts.buf[#{capture.index}]->range.end))\n".freeze
236
+ erbout << "#define _#{capture.index + 1} packcr_get_capture_string(__packcr_ctx, __packcr_in->data.leaf.capts.buf[#{capture.index}])\n#define _#{capture.index + 1}s ((const size_t)(__packcr_ctx->buffer_start_position + __packcr_in->data.leaf.capts.buf[#{capture.index}]->range.start))\n#define _#{capture.index + 1}e ((const size_t)(__packcr_ctx->buffer_start_position + __packcr_in->data.leaf.capts.buf[#{capture.index}]->range.end))\n".freeze
193
237
 
194
238
  if @location
195
- erbout << "#define _#{capture.index + 1}sl ((const pcc_location_t)(pcc_location_add(__pcc_ctx->buffer_start_position_loc, __pcc_in->data.leaf.capts.buf[#{capture.index}]->range.start_loc)))\n#define _#{capture.index + 1}el ((const pcc_location_t)(pcc_location_add(__pcc_ctx->buffer_start_position_loc, __pcc_in->data.leaf.capts.buf[#{capture.index}]->range.end_loc)))\n".freeze
239
+ erbout << "#define _#{capture.index + 1}sl ((const packcr_location_t)(packcr_location_add(__packcr_ctx->buffer_start_position_loc, __packcr_in->data.leaf.capts.buf[#{capture.index}]->range.start_loc)))\n#define _#{capture.index + 1}el ((const packcr_location_t)(packcr_location_add(__packcr_ctx->buffer_start_position_loc, __packcr_in->data.leaf.capts.buf[#{capture.index}]->range.end_loc)))\n".freeze
196
240
  end
197
241
  next unless @capture_in_code
198
242
 
199
- erbout << "#define _#{capture.index + 1}c (*__pcc_in->data.leaf.capts.buf[#{capture.index}])\n".freeze
243
+ erbout << "#define _#{capture.index + 1}c (*__packcr_in->data.leaf.capts.buf[#{capture.index}])\n".freeze
200
244
  end
201
245
  erbout << "#{stream.get_code_block(code.code, 4, @iname)}".freeze
202
246
  code.capts.reverse_each do |capture|
@@ -213,30 +257,12 @@ class Packcr
213
257
  erbout << "#undef __\n#undef auxil\n}\n\n".freeze
214
258
  end
215
259
  end
216
- @root.rules.each do |rule|
217
- erbout << "static pcc_thunk_chunk_t *pcc_evaluate_rule_#{rule.name}(pcc_context_t *ctx, size_t offset".freeze
218
- if @location
219
- erbout << ", pcc_location_t offset_loc".freeze
220
- end
221
- erbout << ", pcc_rule_set_t *limits);\n".freeze
222
- end
223
260
  erbout << "\n".freeze
224
261
 
225
262
  @root.rules.each do |rule|
226
263
  gen = ::Packcr::Generator.new(rule, @ascii, @location)
227
264
  erbout << "#{gen.generate_code(rule, 0, 0, false)}\n".freeze
228
265
  end
229
- erbout << "#{prefix}_context_t *#{prefix}_create(#{auxil_def}auxil) {\n return pcc_context__create(auxil);\n}\n\nint #{prefix}_parse(#{prefix}_context_t *ctx, #{value_def}*ret) {\n size_t pos = ctx->buffer_start_position;\n".freeze
230
-
231
- if !@root.rules.empty?
232
- erbout << " if (pcc_apply_rule(ctx, pcc_evaluate_rule_#{@root.rules[0].name}, &ctx->thunks, ret, ctx->position_offset".freeze
233
- if @location
234
- erbout << ", ctx->position_offset_loc".freeze
235
- end
236
- erbout << ", NULL))\n pcc_do_action(ctx, &ctx->thunks, ret);\n else\n PCC_ERROR(ctx->auxil);\n pcc_commit_buffer(ctx);\n".freeze
237
- end
238
- erbout << " pcc_thunk_array__revert(ctx->auxil, &ctx->thunks, 0);\n return pos != ctx->buffer_start_position && pcc_refill_buffer(ctx, 1) >= 1;\n}\n\nvoid #{prefix}_destroy(#{prefix}_context_t *ctx) {\n pcc_context__destroy(ctx);\n}\n".freeze
239
-
240
266
  if !code(:lsource).empty?
241
267
  erbout << "\n".freeze
242
268
 
@@ -247,16 +273,56 @@ class Packcr
247
273
  erbout
248
274
  when :rb
249
275
  erbout = +""
250
- erbout << "# A packrat parser generated by PackCR #{Packcr::VERSION}\n".freeze
251
-
252
- if !code(:source).empty?
253
- erbout << "\n".freeze
276
+ erbout << "# A packrat parser generated by PackCR #{Packcr::VERSION}\n\n".freeze
254
277
 
255
- code(:source).each do |code|
278
+ if !code(:esource).empty?
279
+ code(:esource).each do |code|
256
280
  erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
257
281
  end
282
+ erbout << "\n".freeze
258
283
  end
259
- erbout << "\nclass #{class_name}\n def initialize(".freeze
284
+ erbout << "class #{class_name}\n".freeze
285
+
286
+ code(:location).each do |code|
287
+ erbout << "#{stream.get_code_block(code, 2, @iname)}\n".freeze
288
+ end
289
+ code(:source).each do |code|
290
+ erbout << " #{stream.get_code_block(code, 2, @iname)}\n".freeze
291
+ end
292
+ erbout << " class LrMemoTable\n def initialize\n @memos = {}\n end\n\n def clear\n @memos.clear\n end\n\n def []=(index, rule_name, memo)\n entry = @memos[index] ||= {}\n entry[rule_name] = memo\n end\n\n def [](index, rule_name)\n @memos.dig(index, rule_name)\n end\n end\n\n class LrMemo\n attr_accessor :grow, :answer, :offset, :fail\n".freeze
293
+
294
+ if @location
295
+ erbout << " attr_accessor :offset_loc\n".freeze
296
+ end
297
+ erbout << "\n def initialize(offset".freeze
298
+ if @location
299
+ erbout << ", offset_loc".freeze
300
+ end
301
+ erbout << ")\n @offset = offset\n".freeze
302
+
303
+ if @location
304
+ erbout << " @offset_loc = offset_loc\n".freeze
305
+ end
306
+ erbout << " @fail = true\n @grow = false\n end\n\n def answer=(answer)\n @fail = nil\n @answer = answer\n end\n end\n\n class ThunkChunk\n attr_accessor :thunks, :capts, :pos, :values\n".freeze
307
+
308
+ if @location
309
+ erbout << " attr_accessor :pos_loc\n".freeze
310
+ end
311
+ erbout << "\n def initialize\n super\n @thunks = []\n @capts = {}\n @pos = 0\n @values = {}\n end\n\n def resize_captures(len)\n len.times do |i|\n @capts[i] = Capture.new\n end\n end\n end\n\n class ThunkLeaf\n attr_accessor :capt0, :capts, :value_refs, :action\n\n def initialize(action, capt0 = Capture.new, value_refs = {}, capts = {})\n @value_refs = value_refs\n @capts = capts\n @capt0 = capt0\n @action = action\n end\n\n def do_action(ctx, values, index)\n ctx.public_send(action, self, values, index)\n end\n end\n\n class ThunkNode\n attr_accessor :thunks, :values, :index\n\n def initialize(thunks, values, index)\n @thunks = thunks\n @values = values\n @index = index\n values[index] ||= Value.new if values\n end\n\n def do_action(ctx, _values, _index)\n @thunks.each do |thunk|\n thunk.do_action(ctx, @values, @index)\n end\n end\n\n def clear\n @thunks.clear\n end\n end\n\n class Capture\n attr_accessor :range_start, :range_end\n".freeze
312
+
313
+ if @location
314
+ erbout << " attr_accessor :start_loc, :end_loc\n".freeze
315
+ end
316
+ erbout << "\n def initialize(range_start = 0, range_end = 0".freeze
317
+ if @location
318
+ erbout << ", start_loc = nil, end_loc = nil".freeze
319
+ end
320
+ erbout << ")\n @range_start = range_start\n @range_end = range_end\n".freeze
321
+
322
+ if @location
323
+ erbout << " @start_loc = start_loc || Location.new\n @end_loc = end_loc || Location.new\n".freeze
324
+ end
325
+ erbout << " end\n\n def capture_string(buffer)\n @capture_string ||= buffer[@range_start, @range_end - @range_start]\n end\n end\n\n class Value\n attr_accessor :value\n end\n\n def initialize(".freeze
260
326
  if @auxil_type
261
327
  erbout << "#{auxil_type}, ".freeze
262
328
  end
@@ -298,43 +364,7 @@ class Packcr
298
364
  end
299
365
  erbout << ")\n @thunk.do_action(self, nil, 0)\n else\n raise SyntaxError, \"can't parse\"\n end\n commit_buffer\n".freeze
300
366
  end
301
- erbout << " @thunk.clear\n refill_buffer(1) >= 1 && pos != @buffer_start_position\n end\n\n def run\n nil while parse\n end\n\n".freeze
302
-
303
- @root.rules.each do |rule|
304
- rule.codes.each do |code|
305
- erbout << " def action_#{rule.name}_#{code.index}(__pcc_in, __pcc_vars, __pcc_index)\n ____ = (__pcc_vars[__pcc_index] ||= Value.new).value if __pcc_vars\n".freeze
306
-
307
- code.vars.each do |ref|
308
- erbout << " #{ref.var} = (__pcc_in.value_refs[#{ref.index}] ||= Value.new).value\n".freeze
309
- end
310
- erbout << " __0 = __pcc_in.capt0.capture_string(@buffer)\n __0s = @buffer_start_position + __pcc_in.capt0.range_start\n __0e = @buffer_start_position + __pcc_in.capt0.range_end\n".freeze
311
-
312
- if @location
313
- erbout << " __0sl = @buffer_start_position_loc + __pcc_in.capt0.start_loc\n __0el = @buffer_start_position_loc + __pcc_in.capt0.end_loc\n".freeze
314
- end
315
- if @capture_in_code
316
- erbout << " __0c = __pcc_in.capt0\n".freeze
317
- end
318
- code.capts.each do |capture|
319
- erbout << " __#{capture.index + 1} = __pcc_in.capts[#{capture.index}].capture_string(@buffer)\n __#{capture.index + 1}s = @buffer_start_position + __pcc_in.capts[#{capture.index}].range_start\n __#{capture.index + 1}e = @buffer_start_position + __pcc_in.capts[#{capture.index}].range_end\n".freeze
320
-
321
- if @location
322
- erbout << " __#{capture.index + 1}sl = @buffer_start_position_loc + __pcc_in.capts[#{capture.index}].start_loc\n __#{capture.index + 1}el = @buffer_start_position_loc + __pcc_in.capts[#{capture.index}].end_loc\n".freeze
323
- end
324
- next unless @capture_in_code
325
-
326
- erbout << " __#{capture.index + 1}c = __pcc_in.capts[#{capture.index}]\n".freeze
327
- end
328
-
329
- erbout << "#{stream.get_code_block(code.code, 4, @iname)}\n __pcc_vars[__pcc_index].value = ____ if __pcc_vars\n end\n\n".freeze
330
- end
331
- end
332
- @root.rules.each do |rule|
333
- gen = ::Packcr::Generator.new(rule, @ascii, @location, :rb)
334
-
335
- erbout << "#{gen.generate_code(rule, 0, 2, false)}\n".freeze
336
- end
337
- erbout << " def grow_lr(rule, offset".freeze
367
+ erbout << " @thunk.clear\n refill_buffer(1) >= 1 && pos != @buffer_start_position\n end\n\n def run\n nil while parse\n end\n\n def grow_lr(rule, offset".freeze
338
368
  if @location
339
369
  erbout << ", offset_loc".freeze
340
370
  end
@@ -377,7 +407,17 @@ class Packcr
377
407
  if @location
378
408
  erbout << ", offset_loc".freeze
379
409
  end
380
- erbout << ")\n memo.grow = false\n answer = memo.answer\n @position_offset = memo.offset\n end\n return answer\n elsif memo.fail\n memo.answer = nil\n memo.grow = true\n return nil\n else\n @position_offset = memo.offset\n return memo.answer\n end\n end\n\n def apply_rule(rule, thunks, values, index, offset".freeze
410
+ erbout << ")\n memo.grow = false\n answer = memo.answer\n @position_offset = memo.offset\n".freeze
411
+
412
+ if @location
413
+ erbout << " @position_offset_loc = memo.offset_loc\n".freeze
414
+ end
415
+ erbout << " end\n return answer\n elsif memo.fail\n memo.answer = nil\n memo.grow = true\n return nil\n else\n @position_offset = memo.offset\n".freeze
416
+
417
+ if @location
418
+ erbout << " @position_offset_loc = memo.offset_loc\n".freeze
419
+ end
420
+ erbout << " return memo.answer\n end\n end\n\n def apply_rule(rule, thunks, values, index, offset".freeze
381
421
  if @location
382
422
  erbout << ", offset_loc".freeze
383
423
  end
@@ -386,45 +426,150 @@ class Packcr
386
426
  if @location
387
427
  erbout << ", offset_loc".freeze
388
428
  end
389
- erbout << ", limits: limits)\n memo = @memos[offset, rule]\n if !answer || @position_offset <= memo.offset\n answer = memo.answer\n @position_offset = memo.offset\n else\n memo.answer = answer\n memo.offset = @position_offset\n end\n else\n answer = rule_answer(rule)\n end\n\n if !answer\n return false\n end\n values ||= @global_values\n thunks << ThunkNode.new(answer.thunks, values, index)\n return true\n end\n\n def do_action(thunks, values, index)\n thunks.each do |thunk|\n thunk.do_action(self, values, index)\n end\n end\n\n".freeze
429
+ erbout << ", limits: limits)\n memo = @memos[offset, rule]\n if !answer || @position_offset <= memo.offset\n if memo\n answer = memo.answer\n @position_offset = memo.offset\n".freeze
390
430
 
391
- code(:location).each do |code|
392
- erbout << "#{stream.get_code_block(code, 2, @iname)}\n".freeze
431
+ if @location
432
+ erbout << " @position_offset_loc = memo.offset_loc\n".freeze
393
433
  end
394
- erbout << " class LrMemoTable\n def initialize\n @memos = {}\n end\n\n def clear\n @memos.clear\n end\n\n def []=(index, rule_name, memo)\n entry = @memos[index] ||= {}\n entry[rule_name] = memo\n end\n\n def [](index, rule_name)\n @memos.dig(index, rule_name)\n end\n end\n\n class LrMemo\n attr_accessor :grow, :answer, :offset, :fail\n".freeze
434
+ erbout << " end\n else\n memo.answer = answer\n memo.offset = @position_offset\n".freeze
395
435
 
396
436
  if @location
397
- erbout << " attr_accessor :offset_loc\n".freeze
437
+ erbout << " memo.offset_loc = @position_offset_loc\n".freeze
398
438
  end
399
- erbout << "\n def initialize(offset".freeze
400
- if @location
401
- erbout << ", offset_loc".freeze
439
+ erbout << " end\n else\n answer = rule_answer(rule)\n end\n\n if !answer\n return false\n end\n values ||= @global_values\n thunks << ThunkNode.new(answer.thunks, values, index)\n return true\n end\n\n def do_action(thunks, values, index)\n thunks.each do |thunk|\n thunk.do_action(self, values, index)\n end\n end\n".freeze
440
+
441
+ @root.rules.each do |rule|
442
+ rule.codes.each do |code|
443
+ erbout << "\n def action_#{rule.name}_#{code.index}(__packcr_in, __packcr_vars, __packcr_index)\n ____ = (__packcr_vars[__packcr_index] ||= Value.new).value if __packcr_vars\n".freeze
444
+
445
+ code.vars.each do |ref|
446
+ erbout << " #{ref.var} = (__packcr_in.value_refs[#{ref.index}] ||= Value.new).value\n".freeze
447
+ end
448
+ erbout << " __0 = __packcr_in.capt0.capture_string(@buffer)\n __0s = @buffer_start_position + __packcr_in.capt0.range_start\n __0e = @buffer_start_position + __packcr_in.capt0.range_end\n".freeze
449
+
450
+ if @location
451
+ erbout << " __0sl = @buffer_start_position_loc + __packcr_in.capt0.start_loc\n __0el = @buffer_start_position_loc + __packcr_in.capt0.end_loc\n".freeze
452
+ end
453
+ if @capture_in_code
454
+ erbout << " __0c = __packcr_in.capt0\n".freeze
455
+ end
456
+ code.capts.each do |capture|
457
+ erbout << " __#{capture.index + 1} = __packcr_in.capts[#{capture.index}].capture_string(@buffer)\n __#{capture.index + 1}s = @buffer_start_position + __packcr_in.capts[#{capture.index}].range_start\n __#{capture.index + 1}e = @buffer_start_position + __packcr_in.capts[#{capture.index}].range_end\n".freeze
458
+
459
+ if @location
460
+ erbout << " __#{capture.index + 1}sl = @buffer_start_position_loc + __packcr_in.capts[#{capture.index}].start_loc\n __#{capture.index + 1}el = @buffer_start_position_loc + __packcr_in.capts[#{capture.index}].end_loc\n".freeze
461
+ end
462
+ next unless @capture_in_code
463
+
464
+ erbout << " __#{capture.index + 1}c = __packcr_in.capts[#{capture.index}]\n".freeze
465
+ end
466
+
467
+ erbout << "#{stream.get_code_block(code.code, 4, @iname)}\n __packcr_vars[__packcr_index].value = ____ if __packcr_vars\n end\n".freeze
468
+ end
402
469
  end
403
- erbout << ")\n @offset = offset\n".freeze
470
+ @root.rules.each do |rule|
471
+ erbout << "\n".freeze
404
472
 
405
- if @location
406
- erbout << " @offset_loc = offset_loc\n".freeze
473
+ gen = ::Packcr::Generator.new(rule, @ascii, @location, :rb)
474
+
475
+ erbout << "#{gen.generate_code(rule, 0, 2, false)}".freeze
407
476
  end
408
- erbout << " @fail = true\n @grow = false\n end\n\n def answer=(answer)\n @fail = nil\n @answer = answer\n end\n end\n\n class ThunkChunk\n attr_accessor :thunks, :capts, :pos, :values\n".freeze
477
+ erbout << "end\n".freeze
409
478
 
410
- if @location
411
- erbout << " attr_accessor :pos_loc\n".freeze
479
+ if !code(:lsource).empty?
480
+ erbout << "\n".freeze
481
+
482
+ code(:lsource).each do |code|
483
+ erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
484
+ end
412
485
  end
413
- erbout << "\n def initialize\n super\n @thunks = []\n @capts = {}\n @pos = 0\n @values = {}\n end\n\n def resize_captures(len)\n len.times do |i|\n @capts[i] = Capture.new\n end\n end\n end\n\n class ThunkLeaf\n attr_accessor :capt0, :capts, :value_refs, :action\n\n def initialize(action, capt0 = Capture.new, value_refs = {}, capts = {})\n @value_refs = value_refs\n @capts = capts\n @capt0 = capt0\n @action = action\n end\n\n def do_action(ctx, values, index)\n ctx.public_send(action, self, values, index)\n end\n end\n\n class ThunkNode\n attr_accessor :thunks, :values, :index\n\n def initialize(thunks, values, index)\n @thunks = thunks\n @values = values\n @index = index\n values[index] ||= Value.new if values\n end\n\n def do_action(ctx, _values, _index)\n @thunks.each do |thunk|\n thunk.do_action(ctx, @values, @index)\n end\n end\n\n def clear\n @thunks.clear\n end\n end\n\n class Capture\n attr_accessor :range_start, :range_end\n".freeze
486
+ erbout
487
+ when :rs
488
+ erbout = +""
489
+ erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\nuse std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::io::Read;\nuse std::rc::Rc;\n\n".freeze
414
490
 
415
- if @location
416
- erbout << " attr_accessor :start_loc, :end_loc\n".freeze
491
+ if !code(:esource).empty?
492
+ erbout << "\n".freeze
493
+
494
+ code(:esource).each do |code|
495
+ erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
496
+ end
417
497
  end
418
- erbout << "\n def initialize(range_start = 0, range_end = 0".freeze
419
- if @location
420
- erbout << ", start_loc = nil, end_loc = nil".freeze
498
+ use_value = @root.rules.map { |r| r.vars.size }.max > 0
499
+ erbout << "\nstruct LrMemoTable {\n memos: HashMap<usize, LrMemoMap>,\n}\nimpl LrMemoTable {\n fn new() -> Self {\n Self {\n memos: HashMap::new(),\n }\n }\n\n fn clear(&mut self) {\n self.memos.clear();\n }\n\n fn set(&mut self, index: usize, rule: Rule, memo: LrMemo) {\n let memo_map = self.memos.entry(index).or_default();\n memo_map.insert(rule, memo);\n }\n\n fn get(&mut self, index: usize, rule: Rule) -> &mut LrMemo {\n self.memos.get_mut(&index).unwrap().get_mut(&rule).unwrap()\n }\n fn has(&mut self, index: usize, rule: Rule) -> bool {\n let memo_opt = self.memos.get_mut(&index);\n if memo_opt.is_none() {\n return false;\n }\n memo_opt.unwrap().contains_key(&rule)\n }\n}\n\nstruct LrMemo {\n offset: usize,\n answer: Option<Rc<RefCell<ThunkChunk>>>,\n grow: bool,\n}\n\nimpl LrMemo {\n fn new(offset: usize) -> Self {\n Self {\n offset,\n answer: None,\n grow: false,\n }\n }\n\n fn start_grow(&mut self) -> bool {\n if self.grow || self.answer.is_some() {\n return false;\n }\n self.answer = None;\n self.grow = true;\n true\n }\n\n fn start_match(&mut self, answer: Option<ThunkChunk>, offset: usize) {\n self.answer = answer.map(|c| Rc::new(RefCell::new(c)));\n self.offset = offset;\n }\n\n fn answer_as_deref_mut(&mut self) -> Option<Rc<RefCell<ThunkChunk>>> {\n self.answer.as_ref()?;\n self.answer.as_ref().map(Rc::clone)\n }\n}\n\nstruct ThunkChunk {\n thunks: Rc<RefCell<Vec<Thunk>>>,\n capts: CaptureTable,\n pos: usize,\n values: ValueTable,\n}\n\nimpl ThunkChunk {\n fn new(pos: usize) -> Self {\n Self {\n values: ValueTable::new(),\n capts: CaptureTable::new(),\n thunks: Rc::new(RefCell::new(Vec::new())),\n pos,\n }\n }\n\n fn push_leaf(\n &self,\n action: Action,\n end: usize,\n value_indices: &[usize],\n capt_indices: &[usize],\n ) {\n {\n let start = self.pos;\n let mut value_refs = HashMap::new();\n for &index in value_indices {\n value_refs.insert(index, ValueRef::new(index, self.values.clone()));\n }\n let mut capts = HashMap::new();\n for &index in capt_indices {\n capts.insert(index, self.capts[index].clone());\n }\n let leaf = Thunk::Leaf(ThunkLeaf::new(action, start, end, value_refs, capts));\n self.thunks.borrow_mut().push(leaf);\n }\n }\n\n fn value_ref(&self, index: usize) -> ValueRef {\n ValueRef::new(index, self.values.clone())\n }\n}\n\nenum Thunk {\n Leaf(ThunkLeaf),\n Node(ThunkNode),\n}\nimpl Thunk {\n fn do_action(&self, processor: &ThunkProcessor, value: ValueRef) {\n match self {\n Thunk::Leaf(leaf) => leaf.do_action(processor, value),\n Thunk::Node(node) => node.do_action(processor),\n }\n }\n}\n\n#[allow(dead_code)]\nstruct ThunkLeaf {\n value_refs: HashMap<usize, ValueRef>,\n capts: HashMap<usize, Capture>,\n capt0: Capture,\n action: Action,\n}\nimpl ThunkLeaf {\n fn new(\n action: Action,\n start: usize,\n end: usize,\n value_refs: HashMap<usize, ValueRef>,\n capts: HashMap<usize, Capture>,\n ) -> Self {\n Self {\n value_refs,\n capts,\n capt0: Capture { start, end },\n action,\n }\n }\n\n fn do_action(&self, processor: &ThunkProcessor, mut value: ValueRef) {\n value.with_mut(|v| {\n processor.call_action(self.action, self, v);\n });\n }\n".freeze
500
+
501
+ if use_value
502
+ erbout << "\n fn values(&self) -> HashMap<usize, Value> {\n self.value_refs.iter().map(|(k, v)| (*k, v.get())).collect()\n }\n".freeze
421
503
  end
422
- erbout << ")\n @range_start = range_start\n @range_end = range_end\n".freeze
504
+ erbout << "}\n\nstruct ThunkNode {\n thunks: Rc<RefCell<Vec<Thunk>>>,\n value: ValueRef,\n}\nimpl ThunkNode {\n fn do_action(&self, processor: &ThunkProcessor) {\n for thunk in self.thunks.borrow().iter() {\n thunk.do_action(processor, self.value.clone());\n }\n }\n}\n\n#[derive(Clone)]\nstruct Capture {\n start: usize,\n end: usize,\n}\n\ntype Value = i32;\n\nstruct ValueTable {\n table: Rc<RefCell<HashMap<usize, Value>>>,\n}\nimpl ValueTable {\n fn new() -> Self {\n Self {\n table: Rc::new(RefCell::new(HashMap::new())),\n }\n }\n".freeze
423
505
 
424
- if @location
425
- erbout << " @start_loc = start_loc || Location.new\n @end_loc = end_loc || Location.new\n".freeze
506
+ if use_value
507
+ erbout << "\n fn clear(&mut self) {\n self.table.borrow_mut().clear();\n }\n".freeze
508
+ end
509
+ erbout << "\n fn with_mut<F>(&mut self, index: usize, f: F)\n where\n F: FnOnce(&mut Value),\n {\n let mut table = self.table.borrow_mut();\n let value = table.entry(index).or_insert(0);\n f(value);\n }\n}\nimpl Clone for ValueTable {\n fn clone(&self) -> Self {\n Self {\n table: self.table.clone(),\n }\n }\n}\n\nstruct ValueRef {\n values: ValueTable,\n index: usize,\n}\nimpl ValueRef {\n fn new(index: usize, values: ValueTable) -> Self {\n Self { index, values }\n }\n\n fn with_mut<F>(&mut self, f: F)\n where\n F: FnOnce(&mut i32),\n {\n self.values.with_mut(self.index, f);\n }\n\n".freeze
510
+
511
+ if use_value
512
+ erbout << " fn get(&self) -> i32 {\n *self.values.table.borrow().get(&self.index).unwrap_or(&0)\n }\n".freeze
513
+ end
514
+ erbout << "}\nimpl Clone for ValueRef {\n fn clone(&self) -> Self {\n Self {\n index: self.index,\n values: self.values.clone(),\n }\n }\n}\n\nstruct CaptureTable {\n table: HashMap<usize, Capture>,\n len: usize,\n}\n\ntype RuleSet = HashSet<Rule>;\n\ntype LrMemoMap = HashMap<Rule, LrMemo>;\n\nimpl CaptureTable {\n fn new() -> Self {\n Self {\n table: HashMap::new(),\n len: 0,\n }\n }\n\n fn resize(&mut self, len: usize) {\n let current_len = self.len;\n if len > current_len {\n for i in current_len..len {\n self.table.insert(i, Capture { start: 0, end: 0 });\n }\n } else if len < current_len {\n for i in len..current_len {\n self.table.remove(&i);\n }\n }\n self.len = len;\n }\n}\nimpl std::ops::Index<usize> for CaptureTable {\n type Output = Capture;\n\n fn index(&self, index: usize) -> &Self::Output {\n &self.table[&index]\n }\n}\nimpl std::ops::IndexMut<usize> for CaptureTable {\n fn index_mut(&mut self, index: usize) -> &mut Self::Output {\n if self.len <= index {\n self.resize(index + 1);\n }\n self.table.get_mut(&index).unwrap()\n }\n}\n\nstruct Input {\n input: Box<dyn std::io::Read>,\n start_position: usize,\n position_offset: usize,\n buffer: String,\n}\n\nimpl Input {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n input: Box::new(input),\n start_position: 0,\n position_offset: 0,\n buffer: String::new(),\n }\n }\n\n fn refill_buffer(&mut self, num: usize) -> usize {\n let mut len = self.buffer.len();\n if len >= self.position_offset + num {\n return len - self.position_offset;\n }\n\n let mut input_buffer = [0u8; 1024];\n\n while len < self.position_offset + num {\n match self.input.read(&mut input_buffer) {\n Ok(0) => break,\n Ok(bytes_read) => {\n let s = std::string::String::from_utf8_lossy(&input_buffer[..bytes_read]);\n self.buffer.push_str(&s);\n }\n Err(_) => break,\n }\n len = self.buffer.len();\n }\n\n len - self.position_offset\n }\n\n fn commit_buffer(&mut self) {\n let position_offset = self.position_offset;\n\n self.buffer.drain(..position_offset);\n\n self.start_position += position_offset;\n self.position_offset = 0;\n }\n\n #[allow(dead_code)]\n fn get_char_as_utf32(&mut self) -> (i32, usize) {\n if self.refill_buffer(1) < 1 {\n return (0, 0);\n }\n\n let current_position = self.position_offset;\n let remaining_chars: &str = &self.buffer[current_position..];\n\n if let Some(ch) = remaining_chars.chars().next() {\n let bytes_used = ch.len_utf8();\n\n if self.refill_buffer(bytes_used) < bytes_used {\n return (0, 0);\n }\n\n let utf32_value = ch as u32 as i32;\n\n return (utf32_value, bytes_used);\n }\n\n (0, 0)\n }\n\n fn back_to(&mut self, memo: &mut LrMemo) -> Option<Rc<RefCell<ThunkChunk>>> {\n self.position_offset = memo.offset;\n memo.answer_as_deref_mut()\n }\n}\n\nstruct #{class_name} {\n level: usize,\n memos: LrMemoTable,\n input: Input,\n}\n\nimpl #{class_name} {\n fn new(input: impl std::io::Read + 'static) -> Self {\n Self {\n level: 0,\n memos: LrMemoTable::new(),\n input: Input::new(input),\n }\n }\n\n fn error(&self) -> ! {\n eprintln!(\"Syntax error\");\n std::process::exit(1);\n }\n\n fn refill_buffer(&mut self, num: usize) -> usize {\n self.input.refill_buffer(num)\n }\n\n fn commit_buffer(&mut self) {\n self.input.commit_buffer();\n self.memos.clear();\n }\n\n fn parse(&mut self) -> bool {\n let mut answer = ThunkChunk::new(0);\n let pos = self.input.start_position;\n\n".freeze
515
+
516
+ if !@root.rules.empty?
517
+ erbout << " let apply_result = self.apply_rule(\n Rule::#{Packcr.camelize(@root.rules[0].name)},\n &mut answer,\n 0,\n self.input.position_offset,\n None,\n );\n\n if apply_result {\n if let Thunk::Node(node) = answer.thunks.borrow_mut().last().unwrap() {\n node.do_action(&ThunkProcessor::new(&self.input.buffer));\n }\n } else {\n self.error();\n }\n\n".freeze
518
+ end
519
+ erbout << " self.commit_buffer();\n pos != self.input.start_position && self.refill_buffer(1) >= 1\n }\n\n #[allow(dead_code)]\n fn get_char_as_utf32(&mut self) -> (i32, usize) {\n self.input.get_char_as_utf32()\n }\n\n fn grow_lr(&mut self, rule: Rule, offset: usize) {\n loop {\n let old_offset = self.input.position_offset;\n self.input.position_offset = offset;\n\n let answer = self.call_rule(rule, offset, Some(RuleSet::new()));\n if answer.is_none() || self.input.position_offset <= old_offset {\n return;\n }\n\n let memo = self.memos.get(offset, rule);\n memo.start_match(answer, self.input.position_offset);\n }\n }\n\n fn rule_answer(&mut self, rule: Rule) -> Option<Rc<RefCell<ThunkChunk>>> {\n let offset = self.input.position_offset;\n if !self.memos.has(offset, rule) {\n let memo = LrMemo::new(offset);\n self.memos.set(offset, rule, memo);\n let answer = self.call_rule(rule, offset, None);\n\n let memo = self.memos.get(offset, rule);\n memo.start_match(answer, self.input.position_offset);\n if !memo.grow {\n return self.input.back_to(memo);\n }\n self.grow_lr(rule, offset);\n\n let memo = self.memos.get(offset, rule);\n memo.grow = false;\n return self.input.back_to(memo);\n }\n\n let memo = self.memos.get(offset, rule);\n if memo.start_grow() {\n return None;\n }\n self.input.back_to(memo)\n }\n\n fn rule_answer_with_limits(\n &mut self,\n rule: Rule,\n limits: RuleSet,\n ) -> Option<Rc<RefCell<ThunkChunk>>> {\n let offset = self.input.position_offset;\n let answer = self.call_rule(rule, offset, Some(limits));\n if !self.memos.has(offset, rule) {\n answer.as_ref()?;\n return Some(Rc::new(RefCell::new(answer.unwrap())));\n }\n let memo = self.memos.get(offset, rule);\n\n if self.input.position_offset > memo.offset {\n memo.start_match(answer, self.input.position_offset);\n return memo.answer_as_deref_mut();\n }\n\n self.input.back_to(memo)\n }\n\n fn apply_rule(\n &mut self,\n rule: Rule,\n parent: &mut ThunkChunk,\n value_index: usize,\n offset: usize,\n limits: Option<RuleSet>,\n ) -> bool {\n let answer = match &limits {\n Some(limit_set)\n if self.input.position_offset == offset && !limit_set.contains(&rule) =>\n {\n self.rule_answer_with_limits(rule, limits.unwrap())\n }\n _ => self.rule_answer(rule),\n };\n\n let Some(answer) = answer else {\n return false;\n };\n\n let new_node = Thunk::Node(ThunkNode {\n thunks: answer.borrow().thunks.clone(),\n value: parent.value_ref(value_index),\n });\n parent.thunks.borrow_mut().push(new_node);\n\n true\n }\n\n fn call_rule(\n &mut self,\n rule: Rule,\n offset: usize,\n mut limits: Option<RuleSet>,\n ) -> Option<ThunkChunk> {\n if let Some(ref mut limits) = limits {\n limits.insert(rule);\n }\n match rule {\n".freeze
520
+
521
+ @root.rules.each do |rule|
522
+ erbout << " Rule::#{Packcr.camelize(rule.name)} => self.evaluate_rule_#{rule.name}(offset, limits),\n".freeze
523
+ end
524
+ erbout << " }\n }\n\n".freeze
525
+
526
+ @root.rules.each do |rule|
527
+ erbout << "\n".freeze
528
+
529
+ gen = ::Packcr::Generator.new(rule, @ascii, @location, :rs)
530
+
531
+ erbout << "#{gen.generate_code(rule, 0, 4, false)}".freeze
532
+ end
533
+ erbout << "}\n\nstruct ThunkProcessor<'a> {\n buffer: &'a str,\n}\n\nimpl<'a> ThunkProcessor<'a> {\n fn new(buffer: &'a str) -> Self {\n Self { buffer }\n }\n\n fn call_action(&self, action: Action, thunk: &ThunkLeaf, value: &mut i32) {\n match action {\n".freeze
534
+
535
+ @root.rules.each do |rule|
536
+ rule.codes.each do |code|
537
+ erbout << " Action::#{Packcr.camelize(rule.name)}#{code.index} => self.action_#{rule.name}_#{code.index}(thunk, value),\n".freeze
538
+ end
539
+ end
540
+ erbout << " }\n }\n".freeze
541
+
542
+ @root.rules.each do |rule|
543
+ rule.codes.each do |code|
544
+ erbout << "\n #[allow(unused_variables,non_snake_case)]\n fn action_#{rule.name}_#{code.index}(&self, leaf: &ThunkLeaf, out: &mut i32) {\n".freeze
545
+
546
+ code.vars.each_with_index do |ref, i|
547
+ if i == 0
548
+ erbout << " let values = leaf.values();\n".freeze
549
+ end
550
+ erbout << " let #{ref.var} = values[&#{ref.index}];\n".freeze
551
+ end
552
+ erbout << " let _0 = {\n let capt = &leaf.capt0;\n &self.buffer[(capt.start)..(capt.end)]\n };\n".freeze
553
+
554
+ code.capts.size.times do |i|
555
+ erbout << " let _#{i + 1} = {\n let capt = &leaf.capts[&#{i}];\n &self.buffer[(capt.start)..(capt.end)]\n };\n".freeze
556
+ end
557
+ erbout << " #{stream.get_code_block(code.code, 4, @iname)} }\n".freeze
558
+ end
559
+ end
560
+ erbout << "}\n\n#[derive(Copy, Clone)]\nenum Action {\n".freeze
561
+
562
+ @root.rules.each do |rule|
563
+ rule.codes.each do |code|
564
+ erbout << " #{Packcr.camelize(rule.name)}#{code.index},\n".freeze
565
+ end
566
+ end
567
+ erbout << "}\n\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\nenum Rule {\n".freeze
568
+
569
+ @root.rules.each do |rule|
570
+ erbout << " #{Packcr.camelize(rule.name)},\n".freeze
426
571
  end
427
- erbout << " end\n\n def capture_string(buffer)\n @capture_string ||= buffer[@range_start, @range_end - @range_start]\n end\n end\n\n class Value\n attr_accessor :value\n end\nend\n".freeze
572
+ erbout << "}\n".freeze
428
573
 
429
574
  if !code(:lsource).empty?
430
575
  erbout << "\n".freeze
@@ -434,6 +579,8 @@ class Packcr
434
579
  end
435
580
  end
436
581
  erbout
582
+ else
583
+ raise "unknown lang #{lang}"
437
584
  end
438
585
  end
439
586
  end