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.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/lib/packcr/context.rb +15 -6
- data/lib/packcr/generated/context.rb +290 -143
- data/lib/packcr/generated/node/action_node.rb +19 -2
- data/lib/packcr/generated/node/alternate_node.rb +54 -8
- data/lib/packcr/generated/node/capture_node.rb +16 -1
- data/lib/packcr/generated/node/charclass_node.rb +76 -9
- data/lib/packcr/generated/node/eof_node.rb +8 -1
- data/lib/packcr/generated/node/error_node.rb +9 -2
- data/lib/packcr/generated/node/expand_node.rb +9 -2
- data/lib/packcr/generated/node/predicate_node.rb +35 -2
- data/lib/packcr/generated/node/quantity_node.rb +84 -31
- data/lib/packcr/generated/node/reference_node.rb +16 -2
- data/lib/packcr/generated/node/rule_node.rb +38 -7
- data/lib/packcr/generated/node/sequence_node.rb +18 -0
- data/lib/packcr/generated/node/string_node.rb +28 -4
- data/lib/packcr/node/reference_node.rb +1 -0
- data/lib/packcr/node/rule_node.rb +2 -1
- data/lib/packcr/parser.rb +993 -838
- data/lib/packcr/stream.rb +1 -1
- data/lib/packcr/templates/context/header.c.erb +3 -3
- data/lib/packcr/templates/context/source.c.erb +438 -420
- data/lib/packcr/templates/context/source.rb.erb +185 -167
- data/lib/packcr/templates/context/source.rs.erb +625 -0
- data/lib/packcr/templates/node/action.c.erb +2 -2
- data/lib/packcr/templates/node/action.rs.erb +6 -0
- data/lib/packcr/templates/node/alternate.c.erb +2 -2
- data/lib/packcr/templates/node/alternate.rs.erb +39 -0
- data/lib/packcr/templates/node/capture.c.erb +2 -2
- data/lib/packcr/templates/node/capture.rs.erb +13 -0
- data/lib/packcr/templates/node/charclass.c.erb +4 -4
- data/lib/packcr/templates/node/charclass_any.c.erb +2 -2
- data/lib/packcr/templates/node/charclass_one.c.erb +4 -4
- data/lib/packcr/templates/node/charclass_utf8.c.erb +2 -2
- data/lib/packcr/templates/node/charclass_utf8.rs.erb +41 -0
- data/lib/packcr/templates/node/eof.c.erb +1 -1
- data/lib/packcr/templates/node/error.c.erb +4 -4
- data/lib/packcr/templates/node/expand.c.erb +2 -2
- data/lib/packcr/templates/node/predicate.c.erb +1 -1
- data/lib/packcr/templates/node/predicate_neg.c.erb +1 -1
- data/lib/packcr/templates/node/predicate_neg.rs.erb +24 -0
- data/lib/packcr/templates/node/quantity_many.c.erb +9 -7
- data/lib/packcr/templates/node/quantity_many.rs.erb +50 -0
- data/lib/packcr/templates/node/quantity_one.c.erb +9 -7
- data/lib/packcr/templates/node/quantity_one.rb.erb +4 -4
- data/lib/packcr/templates/node/reference.c.erb +6 -6
- data/lib/packcr/templates/node/reference.rs.erb +3 -0
- data/lib/packcr/templates/node/rule.c.erb +9 -9
- data/lib/packcr/templates/node/rule.rs.erb +34 -0
- data/lib/packcr/templates/node/sequence.rs.erb +12 -0
- data/lib/packcr/templates/node/string_many.c.erb +2 -2
- data/lib/packcr/templates/node/string_many.rs.erb +10 -0
- data/lib/packcr/templates/node/string_one.c.erb +2 -2
- data/lib/packcr/templates/node/string_one.rs.erb +9 -0
- data/lib/packcr/util.rb +10 -1
- data/lib/packcr/version.rb +1 -1
- 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
|
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 /* !
|
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
|
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
|
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 << "
|
57
|
+
erbout << " packcr_location_t start_loc;\n packcr_location_t end_loc;\n".freeze
|
56
58
|
end
|
57
|
-
erbout << "}
|
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 != "
|
60
|
-
erbout << "typedef #{prefix}_context_t
|
61
|
+
if prefix != "packcr"
|
62
|
+
erbout << "typedef #{prefix}_context_t packcr_context_t;\n\n".freeze
|
61
63
|
end
|
62
|
-
erbout << "typedef struct
|
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 << "
|
67
|
+
erbout << " packcr_location_t pos_loc;\n".freeze
|
66
68
|
end
|
67
|
-
erbout << "}
|
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 << "
|
72
|
+
erbout << " packcr_location_t offset_loc;\n".freeze
|
71
73
|
end
|
72
|
-
erbout << "
|
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 << ",
|
76
|
+
erbout << ", packcr_location_t".freeze
|
75
77
|
end
|
76
|
-
erbout << ",
|
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 << "
|
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
|
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 << "
|
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
|
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 << "
|
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
|
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 << ",
|
95
|
+
erbout << ", packcr_location_t offset_loc".freeze
|
94
96
|
end
|
95
|
-
erbout << ") {\n
|
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 =
|
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
|
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 << "
|
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
|
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 =
|
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 *
|
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
|
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
|
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 << ",
|
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
|
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 << "
|
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
|
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
|
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 << "
|
144
|
+
erbout << " packcr_location_t offset_loc = ctx->position_offset_loc;\n".freeze
|
143
145
|
end
|
144
|
-
erbout << "
|
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
|
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
|
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 << "
|
159
|
+
erbout << " memo->offset_loc = ctx->position_offset_loc;\n".freeze
|
158
160
|
end
|
159
|
-
erbout << " if (
|
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
|
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 << ",
|
179
|
+
erbout << ", packcr_location_t offset_loc".freeze
|
168
180
|
end
|
169
|
-
erbout << ",
|
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
|
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
|
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} (*
|
225
|
+
erbout << "#define #{ref.var} (*__packcr_in->data.leaf.values.buf[#{ref.index}])\n".freeze
|
182
226
|
end
|
183
|
-
erbout << "#define _0
|
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
|
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
|
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}
|
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
|
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 (*
|
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
|
-
|
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 << "
|
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
|
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
|
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
|
-
|
392
|
-
erbout << "
|
431
|
+
if @location
|
432
|
+
erbout << " @position_offset_loc = memo.offset_loc\n".freeze
|
393
433
|
end
|
394
|
-
erbout << "
|
434
|
+
erbout << " end\n else\n memo.answer = answer\n memo.offset = @position_offset\n".freeze
|
395
435
|
|
396
436
|
if @location
|
397
|
-
erbout << "
|
437
|
+
erbout << " memo.offset_loc = @position_offset_loc\n".freeze
|
398
438
|
end
|
399
|
-
erbout << "\n def
|
400
|
-
|
401
|
-
|
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
|
-
|
470
|
+
@root.rules.each do |rule|
|
471
|
+
erbout << "\n".freeze
|
404
472
|
|
405
|
-
|
406
|
-
|
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 << "
|
477
|
+
erbout << "end\n".freeze
|
409
478
|
|
410
|
-
if
|
411
|
-
erbout << "
|
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
|
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
|
416
|
-
erbout << "
|
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
|
-
|
419
|
-
if
|
420
|
-
|
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
|
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
|
425
|
-
erbout << "
|
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 << "
|
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
|