packcr 0.0.6 → 0.0.7
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/lib/packcr/cli.rb +18 -16
- data/lib/packcr/code_block.rb +0 -1
- data/lib/packcr/context.rb +19 -17
- data/lib/packcr/generated/context.rb +440 -0
- data/lib/packcr/generated/node/action_node.rb +60 -0
- data/lib/packcr/generated/node/alternate_node.rb +98 -0
- data/lib/packcr/generated/node/capture_node.rb +39 -0
- data/lib/packcr/generated/node/charclass_node.rb +372 -0
- data/lib/packcr/generated/node/eof_node.rb +20 -0
- data/lib/packcr/generated/node/error_node.rb +67 -0
- data/lib/packcr/generated/node/expand_node.rb +30 -0
- data/lib/packcr/generated/node/predicate_node.rb +140 -0
- data/lib/packcr/generated/node/quantity_node.rb +167 -0
- data/lib/packcr/generated/node/reference_node.rb +70 -0
- data/lib/packcr/generated/node/rule_node.rb +63 -0
- data/lib/packcr/generated/node/sequence_node.rb +42 -0
- data/lib/packcr/generated/node/string_node.rb +60 -0
- data/lib/packcr/generator.rb +2 -1
- data/lib/packcr/node/action_node.rb +4 -2
- data/lib/packcr/node/alternate_node.rb +3 -1
- data/lib/packcr/node/capture_node.rb +3 -1
- data/lib/packcr/node/charclass_node.rb +24 -28
- data/lib/packcr/node/eof_node.rb +4 -2
- data/lib/packcr/node/error_node.rb +3 -1
- data/lib/packcr/node/expand_node.rb +8 -5
- data/lib/packcr/node/predicate_node.rb +4 -2
- data/lib/packcr/node/quantity_node.rb +12 -10
- data/lib/packcr/node/reference_node.rb +11 -5
- data/lib/packcr/node/root_node.rb +1 -0
- data/lib/packcr/node/rule_node.rb +7 -4
- data/lib/packcr/node/sequence_node.rb +3 -1
- data/lib/packcr/node/string_node.rb +9 -6
- data/lib/packcr/node.rb +3 -5
- data/lib/packcr/parser.rb +4375 -4056
- data/lib/packcr/stream.rb +17 -12
- data/lib/packcr/templates/context/source.c.erb +187 -410
- data/lib/packcr/templates/context/source.rb.erb +91 -156
- data/lib/packcr/templates/node/action.c.erb +3 -3
- data/lib/packcr/templates/node/action.rb.erb +2 -2
- data/lib/packcr/templates/node/alternate.c.erb +8 -8
- data/lib/packcr/templates/node/alternate.rb.erb +4 -5
- data/lib/packcr/templates/node/capture.c.erb +6 -6
- data/lib/packcr/templates/node/capture.rb.erb +4 -4
- data/lib/packcr/templates/node/charclass.c.erb +12 -12
- data/lib/packcr/templates/node/charclass.rb.erb +6 -6
- data/lib/packcr/templates/node/charclass_any.c.erb +3 -3
- data/lib/packcr/templates/node/charclass_any.rb.erb +2 -2
- data/lib/packcr/templates/node/charclass_fail.c.erb +1 -1
- data/lib/packcr/templates/node/charclass_one.c.erb +8 -8
- data/lib/packcr/templates/node/charclass_one.rb.erb +6 -6
- data/lib/packcr/templates/node/charclass_utf8.c.erb +7 -7
- data/lib/packcr/templates/node/charclass_utf8.rb.erb +3 -3
- data/lib/packcr/templates/node/charclass_utf8_reverse.rb.erb +5 -5
- data/lib/packcr/templates/node/eof.c.erb +1 -1
- data/lib/packcr/templates/node/error.c.erb +7 -7
- data/lib/packcr/templates/node/error.rb.erb +2 -2
- data/lib/packcr/templates/node/expand.c.erb +5 -5
- data/lib/packcr/templates/node/expand.rb.erb +3 -3
- data/lib/packcr/templates/node/predicate.c.erb +10 -10
- data/lib/packcr/templates/node/predicate.rb.erb +6 -6
- data/lib/packcr/templates/node/predicate_neg.c.erb +8 -8
- data/lib/packcr/templates/node/predicate_neg.rb.erb +6 -6
- data/lib/packcr/templates/node/{quantify_many.c.erb → quantity_many.c.erb} +11 -11
- data/lib/packcr/templates/node/{quantify_many.rb.erb → quantity_many.rb.erb} +9 -9
- data/lib/packcr/templates/node/{quantify_one.c.erb → quantity_one.c.erb} +7 -7
- data/lib/packcr/templates/node/{quantify_one.rb.erb → quantity_one.rb.erb} +4 -4
- data/lib/packcr/templates/node/reference.c.erb +14 -2
- data/lib/packcr/templates/node/reference.rb.erb +16 -4
- data/lib/packcr/templates/node/reference_reverse.rb.erb +16 -4
- data/lib/packcr/templates/node/rule.c.erb +9 -2
- data/lib/packcr/templates/node/rule.rb.erb +26 -19
- data/lib/packcr/templates/node/string_many.c.erb +5 -5
- data/lib/packcr/templates/node/string_many.rb.erb +3 -3
- data/lib/packcr/templates/node/string_one.c.erb +4 -4
- data/lib/packcr/templates/node/string_one.rb.erb +3 -3
- data/lib/packcr/util.rb +21 -16
- data/lib/packcr/version.rb +1 -1
- data/lib/packcr.rb +8 -11
- metadata +37 -9
- data/lib/packcr/tokenizer.rb +0 -2948
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7f6f8510a8922ec8a3f379de4470af6889a01a0f98aebf46b69f16e2c398c64
|
4
|
+
data.tar.gz: aa728bb984a9a343c71099fe6652b7a37c5a3a20b535ad6d5cbc29feaaa776d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ceee0d72c7fa96a8a71fd76d8015591f70c4ba321242966ed295522d55e37e2ce71cf8ab51bda644971f5b0ad675c4c0dbdd225e8f2eded2d5eb8f5a3957922f
|
7
|
+
data.tar.gz: fd819a73b1b16827316ddef020068383952cf6d188ac728f5d06157330b49b0010561552676fce3652cc90b0f838f7750242622b83d0677335e6bc6235199d4f
|
data/lib/packcr/cli.rb
CHANGED
@@ -1,25 +1,27 @@
|
|
1
1
|
require "packcr"
|
2
2
|
require "optparse"
|
3
3
|
|
4
|
-
class Packcr
|
5
|
-
class
|
6
|
-
|
7
|
-
|
4
|
+
class Packcr
|
5
|
+
class Cli
|
6
|
+
class << self
|
7
|
+
def run(argv)
|
8
|
+
new.run(argv)
|
9
|
+
end
|
8
10
|
end
|
9
|
-
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
def run(argv)
|
13
|
+
lang = nil
|
14
|
+
debug = false
|
15
|
+
ascii = false
|
16
|
+
opt = OptionParser.new
|
17
|
+
opt.on("-l", "--lang=VAL") { |v| lang = v.to_sym }
|
18
|
+
opt.on("-d", "--debug") { |_v| debug = true }
|
19
|
+
opt.on("-a", "--ascii") { |_v| ascii = true }
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
opt.parse!(argv)
|
22
|
+
argv.each do |ifile|
|
23
|
+
::Packcr.new(ifile, lang: lang, debug: debug, ascii: ascii).run
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
data/lib/packcr/code_block.rb
CHANGED
data/lib/packcr/context.rb
CHANGED
@@ -34,15 +34,15 @@ class Packcr
|
|
34
34
|
@lang = lang.to_sym
|
35
35
|
case @lang
|
36
36
|
when :c
|
37
|
-
@hname = path
|
37
|
+
@hname = "#{path}.h"
|
38
38
|
@patterns = {
|
39
|
-
|
40
|
-
|
39
|
+
get_source_code: "#{path}.c",
|
40
|
+
get_header_code: @hname,
|
41
41
|
}
|
42
42
|
@hid = File.basename(@hname).upcase.gsub(/[^A-Z0-9]/, "_")
|
43
43
|
when :rb
|
44
44
|
@patterns = {
|
45
|
-
|
45
|
+
get_source_code: "#{path}.rb",
|
46
46
|
}
|
47
47
|
else
|
48
48
|
raise "unexpected lang: #{@lang}"
|
@@ -57,9 +57,9 @@ class Packcr
|
|
57
57
|
@codes = {}
|
58
58
|
@root = Node::RootNode.new
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
return unless block_given?
|
61
|
+
|
62
|
+
yield(self)
|
63
63
|
end
|
64
64
|
|
65
65
|
def code(name)
|
@@ -67,7 +67,7 @@ class Packcr
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def inspect
|
70
|
-
"
|
70
|
+
format("#<%s:0x%016x>", self.class, object_id)
|
71
71
|
end
|
72
72
|
|
73
73
|
def error(line, col, message)
|
@@ -97,7 +97,7 @@ class Packcr
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def class_name
|
100
|
-
prefix.gsub(/(?:_|^|(\W))([a-z])/) { "#{
|
100
|
+
prefix.gsub(/(?:_|^|(\W))([a-z])/) { "#{::Regexp.last_match(1)}#{::Regexp.last_match(2)}".upcase }
|
101
101
|
end
|
102
102
|
|
103
103
|
def auxil_def
|
@@ -141,24 +141,24 @@ class Packcr
|
|
141
141
|
def generate
|
142
142
|
results = []
|
143
143
|
|
144
|
-
@patterns.each do |
|
144
|
+
@patterns.each do |meth, ofile|
|
145
145
|
result = Tempfile.new
|
146
146
|
result.unlink
|
147
147
|
results << [ofile, result]
|
148
148
|
stream = Packcr::Stream.new(result, ofile, @lines ? 0 : nil)
|
149
|
-
stream.write Packcr.
|
149
|
+
stream.write Packcr.format_code(public_send(meth, @lang, stream)), rewrite_line_directive: true
|
150
150
|
|
151
|
-
if
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
return false
|
151
|
+
next if @errnum.zero?
|
152
|
+
|
153
|
+
results.each do |_, r|
|
154
|
+
r.close
|
156
155
|
end
|
156
|
+
return false
|
157
157
|
end
|
158
158
|
|
159
159
|
results.each do |(name, result)|
|
160
160
|
result.rewind
|
161
|
-
open(name, "wt") do |f|
|
161
|
+
File.open(name, "wt") do |f|
|
162
162
|
IO.copy_stream(result, f)
|
163
163
|
end
|
164
164
|
end
|
@@ -166,3 +166,5 @@ class Packcr
|
|
166
166
|
end
|
167
167
|
end
|
168
168
|
end
|
169
|
+
|
170
|
+
require "packcr/generated/context"
|
@@ -0,0 +1,440 @@
|
|
1
|
+
class Packcr
|
2
|
+
class Context
|
3
|
+
def get_header_code(lang, stream)
|
4
|
+
case lang
|
5
|
+
when :c
|
6
|
+
erbout = +""
|
7
|
+
erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\n".freeze
|
8
|
+
|
9
|
+
code(:eheader).each do |code|
|
10
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
11
|
+
end
|
12
|
+
if !code(:eheader).empty?
|
13
|
+
erbout << "\n".freeze
|
14
|
+
end
|
15
|
+
erbout << "#ifndef PCC_INCLUDED_#{@hid}\n#define PCC_INCLUDED_#{@hid}\n\n".freeze
|
16
|
+
|
17
|
+
code(:header).each do |code|
|
18
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
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
|
21
|
+
|
22
|
+
erbout
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_source_code(lang, stream)
|
27
|
+
case lang
|
28
|
+
when :c
|
29
|
+
erbout = +""
|
30
|
+
erbout << "/* A packrat parser generated by PackCR #{Packcr::VERSION} */\n\n".freeze
|
31
|
+
|
32
|
+
code(:esource).each do |code|
|
33
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
34
|
+
end
|
35
|
+
if !code(:esource).empty?
|
36
|
+
erbout << "\n".freeze
|
37
|
+
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
|
39
|
+
|
40
|
+
if !code(:location).empty?
|
41
|
+
erbout << "\n".freeze
|
42
|
+
|
43
|
+
code(:location).each do |code|
|
44
|
+
erbout << "#{stream.get_code_block(code, 4, @iname)}".freeze
|
45
|
+
end
|
46
|
+
end
|
47
|
+
erbout << "\n".freeze
|
48
|
+
|
49
|
+
code(:source).each do |code|
|
50
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
51
|
+
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
|
53
|
+
|
54
|
+
if @location
|
55
|
+
erbout << " pcc_location_t start_loc;\n pcc_location_t end_loc;\n".freeze
|
56
|
+
end
|
57
|
+
erbout << "} pcc_range_t;\n\ntypedef #{value_def}pcc_value_t;\n\ntypedef #{auxil_def}pcc_auxil_t;\n\n".freeze
|
58
|
+
|
59
|
+
if prefix != "pcc"
|
60
|
+
erbout << "typedef #{prefix}_context_t pcc_context_t;\n\n".freeze
|
61
|
+
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
|
63
|
+
|
64
|
+
if @location
|
65
|
+
erbout << " pcc_location_t pos_loc;\n".freeze
|
66
|
+
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
|
68
|
+
|
69
|
+
if @location
|
70
|
+
erbout << " pcc_location_t offset_loc;\n".freeze
|
71
|
+
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
|
73
|
+
if @location
|
74
|
+
erbout << ", pcc_location_t".freeze
|
75
|
+
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
|
77
|
+
|
78
|
+
if @location
|
79
|
+
erbout << " pcc_location_t buffer_start_position_loc;\n pcc_location_t position_offset_loc;\n".freeze
|
80
|
+
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
|
82
|
+
|
83
|
+
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
|
85
|
+
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
|
87
|
+
|
88
|
+
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
|
90
|
+
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
|
92
|
+
if @location
|
93
|
+
erbout << ", pcc_location_t offset_loc".freeze
|
94
|
+
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
|
96
|
+
|
97
|
+
if @location
|
98
|
+
erbout << " memo->offset_loc = offset_loc;\n".freeze
|
99
|
+
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
|
101
|
+
|
102
|
+
if @location
|
103
|
+
erbout << ", memo->offset_loc".freeze
|
104
|
+
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
|
106
|
+
|
107
|
+
if @location
|
108
|
+
erbout << " pcc_location_init(&ctx->buffer_start_position_loc);\n pcc_location_init(&ctx->position_offset_loc);\n".freeze
|
109
|
+
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
|
111
|
+
|
112
|
+
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
|
114
|
+
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
|
116
|
+
|
117
|
+
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
|
119
|
+
end
|
120
|
+
erbout << "static void pcc_grow_lr(pcc_context_t *ctx, pcc_rule_t rule, size_t offset".freeze
|
121
|
+
if @location
|
122
|
+
erbout << ", pcc_location_t offset_loc".freeze
|
123
|
+
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
|
125
|
+
|
126
|
+
if @location
|
127
|
+
erbout << " ctx->position_offset_loc = offset_loc;\n".freeze
|
128
|
+
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
|
130
|
+
|
131
|
+
if @location
|
132
|
+
erbout << ", offset_loc".freeze
|
133
|
+
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
|
135
|
+
|
136
|
+
if @location
|
137
|
+
erbout << " memo->offset_loc = ctx->position_offset_loc;\n".freeze
|
138
|
+
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
|
140
|
+
|
141
|
+
if @location
|
142
|
+
erbout << " pcc_location_t offset_loc = ctx->position_offset_loc;\n".freeze
|
143
|
+
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
|
145
|
+
|
146
|
+
if @location
|
147
|
+
erbout << ", offset_loc".freeze
|
148
|
+
end
|
149
|
+
erbout << ");\n pcc_lr_table__set_memo(ctx, &ctx->lrtable, offset, rule, a);\n c = rule(ctx, offset".freeze
|
150
|
+
|
151
|
+
if @location
|
152
|
+
erbout << ", offset_loc".freeze
|
153
|
+
end
|
154
|
+
erbout << ", NULL);\n pcc_lr_memo__set_chunk(ctx, a, c);\n a->offset = ctx->position_offset;\n".freeze
|
155
|
+
|
156
|
+
if @location
|
157
|
+
erbout << " a->offset_loc = ctx->position_offset_loc;\n".freeze
|
158
|
+
end
|
159
|
+
erbout << " if (a->grow) {\n pcc_grow_lr(ctx, rule, offset".freeze
|
160
|
+
|
161
|
+
if @location
|
162
|
+
erbout << ", offset_loc".freeze
|
163
|
+
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
|
165
|
+
|
166
|
+
if @location
|
167
|
+
erbout << ", pcc_location_t offset_loc".freeze
|
168
|
+
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
|
170
|
+
|
171
|
+
if @location
|
172
|
+
erbout << ", offset_loc".freeze
|
173
|
+
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
|
175
|
+
|
176
|
+
@root.rules.each do |rule|
|
177
|
+
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
|
179
|
+
|
180
|
+
code.vars.each do |ref|
|
181
|
+
erbout << "#define #{ref.var} (*__pcc_in->data.leaf.values.buf[#{ref.index}])\n".freeze
|
182
|
+
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
|
184
|
+
|
185
|
+
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
|
187
|
+
end
|
188
|
+
if @capture_in_code
|
189
|
+
erbout << "#define _0c __pcc_in->data.leaf.capt0\n".freeze
|
190
|
+
end
|
191
|
+
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
|
193
|
+
|
194
|
+
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
|
196
|
+
end
|
197
|
+
next unless @capture_in_code
|
198
|
+
|
199
|
+
erbout << "#define _#{capture.index + 1}c (*__pcc_in->data.leaf.capts.buf[#{capture.index}])\n".freeze
|
200
|
+
end
|
201
|
+
erbout << "#{stream.get_code_block(code.code, 4, @iname)}".freeze
|
202
|
+
code.capts.reverse_each do |capture|
|
203
|
+
if @location
|
204
|
+
erbout << "#undef _#{capture.index + 1}el\n#undef _#{capture.index + 1}sl\n".freeze
|
205
|
+
end
|
206
|
+
erbout << "#undef _#{capture.index + 1}e\n#undef _#{capture.index + 1}s\n#undef _#{capture.index + 1}\n".freeze
|
207
|
+
end
|
208
|
+
erbout << "#undef _0e\n#undef _0s\n#undef _0\n".freeze
|
209
|
+
|
210
|
+
code.vars.reverse_each do |ref|
|
211
|
+
erbout << "#undef #{ref.var}\n".freeze
|
212
|
+
end
|
213
|
+
erbout << "#undef __\n#undef auxil\n}\n\n".freeze
|
214
|
+
end
|
215
|
+
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
|
+
erbout << "\n".freeze
|
224
|
+
|
225
|
+
@root.rules.each do |rule|
|
226
|
+
gen = ::Packcr::Generator.new(rule, @ascii, @location)
|
227
|
+
erbout << "#{gen.generate_code(rule, 0, 0, false)}\n".freeze
|
228
|
+
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
|
+
if !code(:lsource).empty?
|
241
|
+
erbout << "\n".freeze
|
242
|
+
|
243
|
+
code(:lsource).each do |code|
|
244
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
245
|
+
end
|
246
|
+
end
|
247
|
+
erbout
|
248
|
+
when :rb
|
249
|
+
erbout = +""
|
250
|
+
erbout << "# A packrat parser generated by PackCR #{Packcr::VERSION}\n".freeze
|
251
|
+
|
252
|
+
if !code(:source).empty?
|
253
|
+
erbout << "\n".freeze
|
254
|
+
|
255
|
+
code(:source).each do |code|
|
256
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
257
|
+
end
|
258
|
+
end
|
259
|
+
erbout << "\nclass #{class_name}\n def initialize(".freeze
|
260
|
+
if @auxil_type
|
261
|
+
erbout << "#{auxil_type}, ".freeze
|
262
|
+
end
|
263
|
+
erbout << "debug: false)\n".freeze
|
264
|
+
|
265
|
+
if @utf8
|
266
|
+
erbout << " @buffer = +\"\"\n".freeze
|
267
|
+
|
268
|
+
else
|
269
|
+
erbout << " @buffer = +\"\".b\n".freeze
|
270
|
+
end
|
271
|
+
erbout << "\n @buffer_start_position = 0\n @position_offset = 0\n @level = 0\n @thunk = ThunkNode.new([], nil, 0)\n @memos = LrMemoTable.new\n @debug = debug\n @global_values = {}\n".freeze
|
272
|
+
|
273
|
+
if @location
|
274
|
+
erbout << " @buffer_start_position_loc = Location.new\n @position_offset_loc = Location.new\n".freeze
|
275
|
+
end
|
276
|
+
code(:init).each do |code|
|
277
|
+
erbout << "#{stream.get_code_block(code, 4, @iname)}".freeze
|
278
|
+
end
|
279
|
+
erbout << " end\n\n def debug\n yield if @debug\n end\n\n def getc\n".freeze
|
280
|
+
|
281
|
+
if @utf8
|
282
|
+
erbout << " $stdin.getc\n".freeze
|
283
|
+
|
284
|
+
else
|
285
|
+
erbout << " $stdin.getc&.b\n".freeze
|
286
|
+
end
|
287
|
+
erbout << " end\n\n def refill_buffer(num, mode = nil)\n len = @buffer.length\n if len >= @position_offset + num\n return len - @position_offset\n end\n while len < @position_offset + num\n c = getc\n break if !c\n @buffer << c\n len = @buffer.length\n end\n return len - @position_offset\n end\n\n def commit_buffer\n @buffer = @buffer[@position_offset, @buffer.length - @position_offset]\n @buffer_start_position += @position_offset\n @memos.clear\n @position_offset = 0\n".freeze
|
288
|
+
|
289
|
+
if @location
|
290
|
+
erbout << " @buffer_start_position_loc = @buffer_start_position_loc + @position_offset_loc\n @position_offset_loc = Location.new\n".freeze
|
291
|
+
end
|
292
|
+
erbout << " end\n\n def parse\n pos = @buffer_start_position\n".freeze
|
293
|
+
|
294
|
+
if !@root.rules.empty?
|
295
|
+
erbout << " if apply_rule(:evaluate_rule_#{@root.rules[0].name}, @thunk.thunks, nil, 0, @buffer_start_position".freeze
|
296
|
+
if @location
|
297
|
+
erbout << ", @buffer_start_position_loc".freeze
|
298
|
+
end
|
299
|
+
erbout << ")\n @thunk.do_action(self, nil, 0)\n else\n raise SyntaxError, \"can't parse\"\n end\n commit_buffer\n".freeze
|
300
|
+
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
|
338
|
+
if @location
|
339
|
+
erbout << ", offset_loc".freeze
|
340
|
+
end
|
341
|
+
erbout << ")\n while true\n old_offset = @position_offset\n @position_offset = offset\n".freeze
|
342
|
+
|
343
|
+
if @location
|
344
|
+
erbout << " @position_offset_loc = offset_loc\n".freeze
|
345
|
+
end
|
346
|
+
erbout << " answer = public_send(rule, offset".freeze
|
347
|
+
if @location
|
348
|
+
erbout << ", offset_loc".freeze
|
349
|
+
end
|
350
|
+
erbout << ", limits: {rule => true})\n if !answer || @position_offset <= old_offset\n break\n end\n memo = @memos[offset, rule]\n memo.answer = answer\n memo.offset = @position_offset\n".freeze
|
351
|
+
|
352
|
+
if @location
|
353
|
+
erbout << " memo.offset_loc = @position_offset_loc\n".freeze
|
354
|
+
end
|
355
|
+
erbout << " end\n end\n\n def rule_answer(rule)\n offset = @position_offset\n".freeze
|
356
|
+
|
357
|
+
if @location
|
358
|
+
erbout << " offset_loc = @position_offset_loc\n".freeze
|
359
|
+
end
|
360
|
+
erbout << " memo = @memos[offset, rule]\n\n if !memo\n memo = LrMemo.new(offset".freeze
|
361
|
+
|
362
|
+
if @location
|
363
|
+
erbout << ", offset_loc".freeze
|
364
|
+
end
|
365
|
+
erbout << ")\n @memos[offset, rule] = memo\n answer = public_send(rule, offset".freeze
|
366
|
+
|
367
|
+
if @location
|
368
|
+
erbout << ", offset_loc".freeze
|
369
|
+
end
|
370
|
+
erbout << ")\n memo.answer = answer\n memo.offset = @position_offset\n".freeze
|
371
|
+
|
372
|
+
if @location
|
373
|
+
erbout << " memo.offset_loc = @position_offset_loc\n".freeze
|
374
|
+
end
|
375
|
+
erbout << " if memo.grow\n grow_lr(rule, offset".freeze
|
376
|
+
|
377
|
+
if @location
|
378
|
+
erbout << ", offset_loc".freeze
|
379
|
+
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
|
381
|
+
if @location
|
382
|
+
erbout << ", offset_loc".freeze
|
383
|
+
end
|
384
|
+
erbout << ", limits: nil)\n if limits\n limits = limits.merge(rule => true)\n answer = public_send(rule, offset".freeze
|
385
|
+
|
386
|
+
if @location
|
387
|
+
erbout << ", offset_loc".freeze
|
388
|
+
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
|
390
|
+
|
391
|
+
code(:location).each do |code|
|
392
|
+
erbout << "#{stream.get_code_block(code, 2, @iname)}\n".freeze
|
393
|
+
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
|
395
|
+
|
396
|
+
if @location
|
397
|
+
erbout << " attr_accessor :offset_loc\n".freeze
|
398
|
+
end
|
399
|
+
erbout << "\n def initialize(offset".freeze
|
400
|
+
if @location
|
401
|
+
erbout << ", offset_loc".freeze
|
402
|
+
end
|
403
|
+
erbout << ")\n @offset = offset\n".freeze
|
404
|
+
|
405
|
+
if @location
|
406
|
+
erbout << " @offset_loc = offset_loc\n".freeze
|
407
|
+
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
|
409
|
+
|
410
|
+
if @location
|
411
|
+
erbout << " attr_accessor :pos_loc\n".freeze
|
412
|
+
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
|
414
|
+
|
415
|
+
if @location
|
416
|
+
erbout << " attr_accessor :start_loc, :end_loc\n".freeze
|
417
|
+
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
|
421
|
+
end
|
422
|
+
erbout << ")\n @range_start = range_start\n @range_end = range_end\n".freeze
|
423
|
+
|
424
|
+
if @location
|
425
|
+
erbout << " @start_loc = start_loc || Location.new\n @end_loc = end_loc || Location.new\n".freeze
|
426
|
+
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
|
428
|
+
|
429
|
+
if !code(:lsource).empty?
|
430
|
+
erbout << "\n".freeze
|
431
|
+
|
432
|
+
code(:lsource).each do |code|
|
433
|
+
erbout << "#{stream.get_code_block(code, 0, @iname)}".freeze
|
434
|
+
end
|
435
|
+
end
|
436
|
+
erbout
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|