packcr 0.0.4 → 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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/exe/packcr +3 -0
  3. data/lib/packcr/broadcast.rb +17 -0
  4. data/lib/packcr/cli.rb +27 -0
  5. data/lib/packcr/code_block.rb +2 -4
  6. data/lib/packcr/context.rb +66 -61
  7. data/lib/packcr/generated/context.rb +440 -0
  8. data/lib/packcr/generated/node/action_node.rb +60 -0
  9. data/lib/packcr/generated/node/alternate_node.rb +98 -0
  10. data/lib/packcr/generated/node/capture_node.rb +39 -0
  11. data/lib/packcr/generated/node/charclass_node.rb +372 -0
  12. data/lib/packcr/generated/node/eof_node.rb +20 -0
  13. data/lib/packcr/generated/node/error_node.rb +67 -0
  14. data/lib/packcr/generated/node/expand_node.rb +30 -0
  15. data/lib/packcr/generated/node/predicate_node.rb +140 -0
  16. data/lib/packcr/generated/node/quantity_node.rb +167 -0
  17. data/lib/packcr/generated/node/reference_node.rb +70 -0
  18. data/lib/packcr/generated/node/rule_node.rb +63 -0
  19. data/lib/packcr/generated/node/sequence_node.rb +42 -0
  20. data/lib/packcr/generated/node/string_node.rb +60 -0
  21. data/lib/packcr/generator.rb +14 -11
  22. data/lib/packcr/node/action_node.rb +18 -7
  23. data/lib/packcr/node/alternate_node.rb +22 -12
  24. data/lib/packcr/node/capture_node.rb +14 -12
  25. data/lib/packcr/node/charclass_node.rb +44 -24
  26. data/lib/packcr/node/eof_node.rb +25 -0
  27. data/lib/packcr/node/error_node.rb +20 -13
  28. data/lib/packcr/node/expand_node.rb +18 -9
  29. data/lib/packcr/node/predicate_node.rb +19 -26
  30. data/lib/packcr/node/quantity_node.rb +31 -24
  31. data/lib/packcr/node/reference_node.rb +31 -9
  32. data/lib/packcr/node/root_node.rb +61 -0
  33. data/lib/packcr/node/rule_node.rb +29 -3
  34. data/lib/packcr/node/sequence_node.rb +48 -31
  35. data/lib/packcr/node/string_node.rb +19 -16
  36. data/lib/packcr/node.rb +34 -5
  37. data/lib/packcr/parser.rb +4493 -3896
  38. data/lib/packcr/stream.rb +22 -22
  39. data/lib/packcr/templates/context/header.c.erb +29 -0
  40. data/lib/packcr/templates/context/source.c.erb +1069 -0
  41. data/lib/packcr/templates/context/source.rb.erb +341 -0
  42. data/lib/packcr/templates/node/action.c.erb +16 -0
  43. data/lib/packcr/templates/node/action.rb.erb +21 -0
  44. data/lib/packcr/templates/node/alternate.c.erb +34 -0
  45. data/lib/packcr/templates/node/alternate.rb.erb +39 -0
  46. data/lib/packcr/templates/node/capture.c.erb +17 -0
  47. data/lib/packcr/templates/node/capture.rb.erb +14 -0
  48. data/lib/packcr/templates/node/charclass.c.erb +47 -0
  49. data/lib/packcr/templates/node/charclass.rb.erb +49 -0
  50. data/lib/packcr/templates/node/charclass_any.c.erb +5 -0
  51. data/lib/packcr/templates/node/charclass_any.rb.erb +7 -0
  52. data/lib/packcr/templates/node/charclass_fail.c.erb +1 -0
  53. data/lib/packcr/templates/node/charclass_fail.rb.erb +1 -0
  54. data/lib/packcr/templates/node/charclass_one.c.erb +19 -0
  55. data/lib/packcr/templates/node/charclass_one.rb.erb +23 -0
  56. data/lib/packcr/templates/node/charclass_utf8.c.erb +49 -0
  57. data/lib/packcr/templates/node/charclass_utf8.rb.erb +50 -0
  58. data/lib/packcr/templates/node/charclass_utf8_reverse.rb.erb +51 -0
  59. data/lib/packcr/templates/node/eof.c.erb +1 -0
  60. data/lib/packcr/templates/node/eof.rb.erb +3 -0
  61. data/lib/packcr/templates/node/error.c.erb +28 -0
  62. data/lib/packcr/templates/node/error.rb.erb +34 -0
  63. data/lib/packcr/templates/node/expand.c.erb +16 -0
  64. data/lib/packcr/templates/node/expand.rb.erb +16 -0
  65. data/lib/packcr/templates/node/predicate.c.erb +30 -0
  66. data/lib/packcr/templates/node/predicate.rb.erb +28 -0
  67. data/lib/packcr/templates/node/predicate_neg.c.erb +23 -0
  68. data/lib/packcr/templates/node/predicate_neg.rb.erb +22 -0
  69. data/lib/packcr/templates/node/quantity_many.c.erb +45 -0
  70. data/lib/packcr/templates/node/quantity_many.rb.erb +47 -0
  71. data/lib/packcr/templates/node/quantity_one.c.erb +21 -0
  72. data/lib/packcr/templates/node/quantity_one.rb.erb +23 -0
  73. data/lib/packcr/templates/node/reference.c.erb +17 -0
  74. data/lib/packcr/templates/node/reference.rb.erb +21 -0
  75. data/lib/packcr/templates/node/reference_reverse.rb.erb +21 -0
  76. data/lib/packcr/templates/node/rule.c.erb +26 -0
  77. data/lib/packcr/templates/node/rule.rb.erb +30 -0
  78. data/lib/packcr/templates/node/sequence.c.erb +12 -0
  79. data/lib/packcr/templates/node/sequence.rb.erb +12 -0
  80. data/lib/packcr/templates/node/string_many.c.erb +11 -0
  81. data/lib/packcr/templates/node/string_many.rb.erb +10 -0
  82. data/lib/packcr/templates/node/string_one.c.erb +8 -0
  83. data/lib/packcr/templates/node/string_one.rb.erb +10 -0
  84. data/lib/packcr/util.rb +21 -24
  85. data/lib/packcr/version.rb +1 -1
  86. data/lib/packcr.rb +9 -13
  87. metadata +117 -10
  88. data/lib/packcr/buffer.rb +0 -47
@@ -0,0 +1,167 @@
1
+ class Packcr
2
+ class Node
3
+ class QuantityNode
4
+ def get_many_code(gen, onfail, indent, bare, oncut)
5
+ case gen.lang
6
+ when :c
7
+ erbout = +""
8
+ erbout << "{\n".freeze
9
+
10
+ if min > 0
11
+ erbout << " const size_t p0 = ctx->position_offset;\n".freeze
12
+
13
+ if gen.location
14
+ erbout << " const pcc_location_t p0_loc = ctx->position_offset_loc;\n".freeze
15
+ end
16
+ erbout << " const size_t n0 = chunk->thunks.len;\n".freeze
17
+ end
18
+ erbout << " int i;\n".freeze
19
+
20
+ if max < 0
21
+ erbout << " for (i = 0;; i++) {\n".freeze
22
+
23
+ else
24
+ erbout << " for (i = 0; i < #{max}; i++) {\n".freeze
25
+ end
26
+ erbout << " const size_t p = ctx->position_offset;\n".freeze
27
+
28
+ if gen.location
29
+ erbout << " const pcc_location_t p_loc = ctx->position_offset_loc;\n".freeze
30
+ end
31
+ erbout << " const size_t n = chunk->thunks.len;\n".freeze
32
+
33
+ l = gen.next_label
34
+ r = expr.reachability
35
+ erbout << "#{gen.generate_code(expr, l, 8, false)} if (ctx->position_offset == p) break;\n".freeze
36
+
37
+ if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
38
+ erbout << " continue;\n L#{format("%04d", l)}:;\n ctx->position_offset = p;\n".freeze
39
+
40
+ if gen.location
41
+ erbout << " ctx->position_offset_loc = p_loc;\n".freeze
42
+ end
43
+ erbout << " pcc_thunk_array__revert(ctx->auxil, &chunk->thunks, n);\n break;\n".freeze
44
+ end
45
+ erbout << " }\n".freeze
46
+
47
+ if min > 0
48
+ erbout << " if (i < #{min}) {\n ctx->position_offset = p0;\n".freeze
49
+
50
+ if gen.location
51
+ erbout << " ctx->position_offset_loc = p0_loc;\n".freeze
52
+ end
53
+ erbout << " pcc_thunk_array__revert(ctx->auxil, &chunk->thunks, n0);\n goto L#{format("%04d", onfail)};\n }\n".freeze
54
+ end
55
+ erbout << "}\n".freeze
56
+
57
+ erbout
58
+ when :rb
59
+ erbout = +""
60
+ if min > 0
61
+ erbout << "q#{gen.level} = @position_offset\n".freeze
62
+
63
+ if gen.location
64
+ erbout << "q_loc#{gen.level} = @position_offset_loc\n".freeze
65
+ end
66
+ erbout << "m#{gen.level} = answer.thunks.length\n".freeze
67
+ end
68
+ erbout << "i#{gen.level} = 0\npos#{gen.level} = nil\n".freeze
69
+
70
+ if gen.location
71
+ erbout << "p_loc#{gen.level} = nil\n".freeze
72
+ end
73
+ erbout << "n#{gen.level} = nil\n".freeze
74
+
75
+ l = gen.next_label
76
+ erbout << "catch(#{l}) do\n pos#{gen.level} = @position_offset\n".freeze
77
+
78
+ if gen.location
79
+ erbout << " p_loc#{gen.level} = @position_offset_loc\n".freeze
80
+ end
81
+ erbout << " n#{gen.level} = answer.thunks.length\n".freeze
82
+
83
+ r = expr.reachability
84
+
85
+ erbout << "#{gen.generate_code(expr, l, 2, false)} i#{gen.level} += 1\n if @position_offset != pos#{gen.level}".freeze
86
+ if max >= 0
87
+ erbout << " || i#{gen.level} < #{max}".freeze
88
+ end
89
+ erbout << "\n redo\n end\n pos#{gen.level} = nil\nend\n".freeze
90
+
91
+ if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
92
+ erbout << "if pos#{gen.level}\n @position_offset = pos#{gen.level}\n".freeze
93
+
94
+ if gen.location
95
+ erbout << " @position_offset_loc = p_loc#{gen.level}\n".freeze
96
+ end
97
+ erbout << " answer.thunks[n#{gen.level}..-1] = []\nend\n".freeze
98
+ end
99
+ if min > 0
100
+ erbout << "if i#{gen.level} < #{min}\n @position_offset = q#{gen.level}\n".freeze
101
+
102
+ if gen.location
103
+ erbout << " @position_offset_loc = q_loc#{gen.level}\n".freeze
104
+ end
105
+ erbout << " answer.thunks[m#{gen.level}..-1] = []\n throw(#{onfail})\nend\n".freeze
106
+ end
107
+ erbout
108
+ end
109
+ end
110
+
111
+ def get_one_code(gen, onfail, indent, bare, oncut)
112
+ case gen.lang
113
+ when :c
114
+ erbout = +""
115
+ erbout << "{\n".freeze
116
+
117
+ l = gen.next_label
118
+ erbout << " const size_t p = ctx->position_offset;\n".freeze
119
+
120
+ if gen.location
121
+ erbout << " const pcc_location_t p_loc = ctx->position_offset_loc;\n".freeze
122
+ end
123
+ erbout << " const size_t n = chunk->thunks.len;\n".freeze
124
+
125
+ r = expr.reachability
126
+ erbout << "#{gen.generate_code(expr, l, 4, false)}".freeze
127
+ if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
128
+ m = gen.next_label
129
+ erbout << " goto L#{format("%04d", m)};\nL#{format("%04d", l)}:;\n".freeze
130
+
131
+ if gen.location
132
+ erbout << " ctx->position_offset_loc = p_loc;\n".freeze
133
+ end
134
+ erbout << " ctx->position_offset = p;\n pcc_thunk_array__revert(ctx->auxil, &chunk->thunks, n);\nL#{format("%04d", m)}:;\n".freeze
135
+ end
136
+ erbout << "}\n".freeze
137
+
138
+ erbout
139
+ when :rb
140
+ erbout = +""
141
+ l = gen.next_label
142
+ erbout << "pos#{gen.level} = @position_offset\n".freeze
143
+
144
+ if gen.location
145
+ erbout << "p_loc#{gen.level} = @position_offset_loc\n".freeze
146
+ end
147
+ erbout << "n#{gen.level} = answer.thunks.length\n".freeze
148
+
149
+ r = expr.reachability
150
+ if r == Packcr::CODE_REACH__ALWAYS_SUCCEED
151
+
152
+ erbout << "#{gen.generate_code(expr, l, 0, false)}".freeze
153
+ else
154
+ m = gen.next_label
155
+ erbout << "catch(#{m}) do\n catch(#{l}) do\n#{gen.generate_code(expr, l, 4, false)} throw(#{m})\n end\n".freeze
156
+
157
+ if gen.location
158
+ erbout << " @position_offset_loc = p_loc#{gen.level}\n".freeze
159
+ end
160
+ erbout << " @position_offset = pos#{gen.level}\n answer.thunks[n#{gen.level}..-1] = []\nend\n".freeze
161
+ end
162
+ erbout
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,70 @@
1
+ class Packcr
2
+ class Node
3
+ class ReferenceNode
4
+ def get_code(gen, onfail, indent, bare, oncut)
5
+ case gen.lang
6
+ when :c
7
+ erbout = +""
8
+ if index.nil?
9
+ erbout << "{\n pcc_rule_set_t *l = NULL;\n if (limits && ctx->position_offset == offset && pcc_rule_set__index(ctx->auxil, limits, pcc_evaluate_rule_#{name}) == PCC_VOID_VALUE) {\n l = limits;\n }\n if (!pcc_apply_rule(ctx, pcc_evaluate_rule_#{name}, &chunk->thunks, NULL, offset".freeze
10
+ else
11
+ erbout << "{\n pcc_rule_set_t *l = NULL;\n if (limits && ctx->position_offset == offset && pcc_rule_set__index(ctx->auxil, limits, pcc_evaluate_rule_#{name}) == PCC_VOID_VALUE) {\n l = limits;\n }\n if (!pcc_apply_rule(ctx, pcc_evaluate_rule_#{name}, &chunk->thunks, &(chunk->values.buf[#{index}]), offset".freeze
12
+
13
+ end
14
+ if gen.location
15
+ erbout << ", offset_loc".freeze
16
+ end
17
+ erbout << ", l)) goto L#{format("%04d", onfail)};\n}\n".freeze
18
+ erbout
19
+ when :rb
20
+ erbout = +""
21
+ if index.nil?
22
+ erbout << "if limits && @position_offset == offset && !limits[:evaluate_rule_#{name}]\n if !apply_rule(:evaluate_rule_#{name}, answer.thunks, nil, 0, offset".freeze
23
+ if gen.location
24
+ erbout << ", offset_loc".freeze
25
+ end
26
+ erbout << ", limits: limits)\n throw(#{onfail})\n end\nelse\n if !apply_rule(:evaluate_rule_#{name}, answer.thunks, nil, 0, offset".freeze
27
+ else
28
+ erbout << "if limits && @position_offset == offset && !limits[:evaluate_rule_#{name}]\n if !apply_rule(:evaluate_rule_#{name}, answer.thunks, answer.values, #{index}, offset".freeze
29
+ if gen.location
30
+ erbout << ", offset_loc".freeze
31
+ end
32
+ erbout << ", limits: limits)\n throw(#{onfail})\n end\nelse\n if !apply_rule(:evaluate_rule_#{name}, answer.thunks, answer.values, #{index}, offset".freeze
33
+
34
+ end
35
+ if gen.location
36
+ erbout << ", offset_loc".freeze
37
+ end
38
+ erbout << ")\n throw(#{onfail})\n end\nend\n".freeze
39
+ erbout
40
+ end
41
+ end
42
+
43
+ def get_reverse_code(gen, onsuccess, indent, bare, oncut)
44
+ case gen.lang
45
+ when :rb
46
+ erbout = +""
47
+ if index.nil?
48
+ erbout << "if limits && @position_offset == offset && !limits[:evaluate_rule_#{name}]\n if apply_rule(:evaluate_rule_#{name}, answer.thunks, nil, 0, offset".freeze
49
+ if gen.location
50
+ erbout << ", offset_loc".freeze
51
+ end
52
+ erbout << ", limits: limits)\n throw(#{onsuccess})\n end\nelse\n if apply_rule(:evaluate_rule_#{name}, answer.thunks, nil, 0, offset".freeze
53
+ else
54
+ erbout << "if limits && @position_offset == offset && !limits[:evaluate_rule_#{name}]\n if apply_rule(:evaluate_rule_#{name}, answer.thunks, answer.values, #{index}, offset".freeze
55
+ if gen.location
56
+ erbout << ", offset_loc".freeze
57
+ end
58
+ erbout << ", limits: limits)\n throw(#{onsuccess})\n end\nelse\n if apply_rule(:evaluate_rule_#{name}, answer.thunks, answer.values, #{index}, offset".freeze
59
+
60
+ end
61
+ if gen.location
62
+ erbout << ", offset_loc".freeze
63
+ end
64
+ erbout << ")\n throw(#{onsuccess})\n end\nend\n".freeze
65
+ erbout
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,63 @@
1
+ class Packcr
2
+ class Node
3
+ class RuleNode
4
+ def get_code(gen, onfail, indent, bare, oncut)
5
+ case gen.lang
6
+ when :c
7
+ erbout = +""
8
+ erbout << "static pcc_thunk_chunk_t *pcc_evaluate_rule_#{name}(pcc_context_t *ctx, size_t offset".freeze
9
+ if gen.location
10
+ erbout << ", pcc_location_t offset_loc".freeze
11
+ end
12
+ erbout << ", pcc_rule_set_t *limits) {\n pcc_thunk_chunk_t *const chunk = pcc_thunk_chunk__create(ctx);\n chunk->pos = ctx->position_offset;\n".freeze
13
+
14
+ if gen.location
15
+ erbout << " chunk->pos_loc = ctx->position_offset_loc;\n".freeze
16
+ end
17
+ erbout << " PCC_DEBUG(ctx->auxil, PCC_DBG_EVALUATE, \"#{name}\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->buffer.len - chunk->pos));\n ctx->level++;\n pcc_value_table__resize(ctx->auxil, &chunk->values, #{vars.length});\n pcc_capture_table__resize(ctx->auxil, &chunk->capts, #{capts.length});\n".freeze
18
+
19
+ if !vars.empty?
20
+ erbout << " pcc_value_table__clear(ctx->auxil, &chunk->values);\n".freeze
21
+ end
22
+ r = expr.reachability
23
+
24
+ erbout << "#{gen.generate_code(expr, 0, 4, false)} ctx->level--;\n PCC_DEBUG(ctx->auxil, PCC_DBG_MATCH, \"#{name}\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->position_offset - chunk->pos));\n return chunk;\n".freeze
25
+
26
+ if r != Packcr::CODE_REACH__ALWAYS_SUCCEED
27
+ erbout << "L0000:;\n ctx->level--;\n PCC_DEBUG(ctx->auxil, PCC_DBG_NOMATCH, \"#{name}\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->position_offset - chunk->pos));\n pcc_thunk_chunk__destroy(ctx, chunk);\n return NULL;\n".freeze
28
+ end
29
+ erbout << "}\n".freeze
30
+
31
+ erbout
32
+ when :rb
33
+ erbout = +""
34
+ erbout << "def evaluate_rule_#{name}(offset".freeze
35
+ if gen.location
36
+ erbout << ", offset_loc".freeze
37
+ end
38
+ erbout << ", limits: nil)\n answer = ThunkChunk.new\n answer.pos = @position_offset\n".freeze
39
+
40
+ if gen.location
41
+ erbout << " answer.pos_loc = @position_offset_loc\n".freeze
42
+ end
43
+ erbout << " debug { warn \"\#{ \" \" * @level}EVAL #{name} \#{answer.pos} \#{@buffer[answer.pos..-1].inspect}\" }\n @level += 1\n answer.resize_captures(#{capts.length})\n".freeze
44
+
45
+ if !vars.empty?
46
+ erbout << " answer.values = {}\n".freeze
47
+ end
48
+ r = expr.reachability
49
+ if r == Packcr::CODE_REACH__ALWAYS_SUCCEED
50
+
51
+ erbout << "#{gen.generate_code(expr, 0, 2, false)} @level -= 1\n debug { warn \"\#{ \" \" * @level}MATCH #{name} \#{answer.pos} \#{@buffer[answer.pos...@position_offset].inspect}\" }\n return answer\n".freeze
52
+
53
+ else
54
+ erbout << " catch(0) do\n#{gen.generate_code(expr, 0, 4, false)} @level -= 1\n debug { warn \"\#{ \" \" * @level}MATCH #{name} \#{answer.pos} \#{@buffer[answer.pos...@position_offset].inspect}\" }\n return answer\n end\n @level -= 1\n debug { warn \"\#{ \" \" * @level}NOMATCH #{name} \#{answer.pos} \#{@buffer[answer.pos...@position_offset].inspect}\" }\n return nil\n".freeze
55
+ end
56
+ erbout << "end\n".freeze
57
+
58
+ erbout
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,42 @@
1
+ class Packcr
2
+ class Node
3
+ class SequenceNode
4
+ def get_code(gen, onfail, indent, bare, oncut)
5
+ case gen.lang
6
+ when :c
7
+ erbout = +""
8
+ if @cut && oncut
9
+ onfail = oncut
10
+ oncut = nil
11
+ end
12
+ nodes.each_with_index do |expr, i|
13
+ erbout << "#{gen.generate_code(expr, onfail, 0, false, oncut: oncut)}".freeze
14
+ next unless expr.reachability == Packcr::CODE_REACH__ALWAYS_FAIL
15
+
16
+ if i + 1 < nodes.length
17
+ erbout << "/* unreachable codes omitted */\n".freeze
18
+ end
19
+ break
20
+ end
21
+ erbout
22
+ when :rb
23
+ erbout = +""
24
+ if @cut && oncut
25
+ onfail = oncut
26
+ oncut = nil
27
+ end
28
+ nodes.each_with_index do |expr, i|
29
+ erbout << "#{gen.generate_code(expr, onfail, 0, false, oncut: oncut)}".freeze
30
+ next unless expr.reachability == Packcr::CODE_REACH__ALWAYS_FAIL
31
+
32
+ if i + 1 < nodes.length
33
+ erbout << "# unreachable codes omitted\n".freeze
34
+ end
35
+ break
36
+ end
37
+ erbout
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,60 @@
1
+ class Packcr
2
+ class Node
3
+ class StringNode
4
+ def get_many_code(gen, onfail, indent, bare, oncut, n)
5
+ case gen.lang
6
+ when :c
7
+ erbout = +""
8
+ erbout << "if (\n pcc_refill_buffer(ctx, #{n}) < #{n} ||\n".freeze
9
+
10
+ (n - 1).times do |i|
11
+ erbout << " (ctx->buffer.buf + ctx->position_offset)[#{i}] != '#{Packcr.escape_character(value[i])}' ||\n".freeze
12
+ end
13
+ erbout << " (ctx->buffer.buf + ctx->position_offset)[#{n - 1}] != '#{Packcr.escape_character(value[n - 1])}'\n) goto L#{format("%04d", onfail)};\n".freeze
14
+
15
+ if gen.location
16
+ erbout << "pcc_location_forward(&ctx->position_offset_loc, ctx->buffer.buf + ctx->position_offset, n);\n".freeze
17
+ end
18
+ erbout << "ctx->position_offset += #{n};\n".freeze
19
+
20
+ erbout
21
+ when :rb
22
+ erbout = +""
23
+ erbout << "if (\n refill_buffer(#{n}) < #{n} ||\n @buffer[@position_offset, #{n}] != #{value[0, n].dump}\n)\n throw(#{onfail})\nend\n".freeze
24
+
25
+ if gen.location
26
+ erbout << "@position_offset_loc = @position_offset_loc.forward(@buffer, @position_offset, #{n})\n".freeze
27
+ end
28
+ erbout << "@position_offset += #{n}\n".freeze
29
+
30
+ erbout
31
+ end
32
+ end
33
+
34
+ def get_one_code(gen, onfail, indent, bare, oncut, n)
35
+ case gen.lang
36
+ when :c
37
+ erbout = +""
38
+ erbout << "if (\n pcc_refill_buffer(ctx, 1) < 1 ||\n ctx->buffer.buf[ctx->position_offset] != '#{Packcr.escape_character(value[0])}'\n) goto L#{format("%04d", onfail)};\n".freeze
39
+
40
+ if gen.location
41
+ erbout << " pcc_location_forward(&ctx->position_offset_loc, ctx->buffer.buf + ctx->position_offset, 1);\n".freeze
42
+ end
43
+ erbout << "ctx->position_offset++;\n".freeze
44
+
45
+ erbout
46
+ when :rb
47
+ erbout = +""
48
+ erbout << "if (\n refill_buffer(1) < 1 ||\n @buffer[@position_offset] != \"#{Packcr.escape_character(value[0])}\"\n)\n throw(#{onfail})\nend\n".freeze
49
+
50
+ if gen.location
51
+ erbout << "@position_offset_loc = @position_offset_loc.forward(@buffer, @position_offset, 1)\n".freeze
52
+ end
53
+ erbout << "@position_offset += 1\n".freeze
54
+
55
+ erbout
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,8 +1,6 @@
1
- require "stringio"
2
-
3
1
  class Packcr
4
2
  class Generator
5
- attr_reader :ascii, :rule, :location, :lang
3
+ attr_reader :ascii, :rule, :location, :lang, :level
6
4
 
7
5
  def initialize(rule, ascii, location, lang = :c)
8
6
  @rule = rule
@@ -10,27 +8,32 @@ class Packcr
10
8
  @ascii = !!ascii
11
9
  @location = !!location
12
10
  @lang = lang
11
+ @level = 0
13
12
  end
14
13
 
15
14
  def next_label
16
15
  @label += 1
17
16
  end
18
17
 
19
- def generate_code(node, onfail, indent, bare)
20
- node.generate_code(self, onfail, indent, bare)
21
- end
22
-
23
- def generate_code_str(node, onfail, indent, bare)
24
- @stream, stream = StringIO.new, @stream
18
+ def generate_code(node, onescape, indent, bare, reverse: false, oncut: nil)
19
+ stream = @stream
20
+ @stream = +""
21
+ @level += 1
25
22
  begin
26
- return generate_code(node, onfail, indent, bare), @stream.string
23
+ if reverse
24
+ node.generate_reverse_code(self, onescape, indent, bare, oncut: oncut)
25
+ else
26
+ node.generate_code(self, onescape, indent, bare, oncut: oncut)
27
+ end
28
+ @stream
27
29
  ensure
30
+ @level -= 1
28
31
  @stream = stream
29
32
  end
30
33
  end
31
34
 
32
35
  def write(str)
33
- @stream.write(str)
36
+ @stream << str
34
37
  end
35
38
  end
36
39
  end
@@ -33,26 +33,37 @@ class Packcr
33
33
  end
34
34
  end
35
35
 
36
- def generate_code(gen, onfail, indent, bare)
37
- gen.write Packcr.template("node/action.#{gen.lang}.erb", binding, indent: indent, unwrap: bare)
38
- return Packcr::CODE_REACH__ALWAYS_SUCCEED
36
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
37
+ gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
38
+ end
39
+
40
+ def reachability
41
+ Packcr::CODE_REACH__ALWAYS_SUCCEED
39
42
  end
40
43
 
41
44
  def verify_variables(vars)
42
45
  @vars = vars
43
46
  end
44
47
 
45
- def verify_captures(ctx, capts)
48
+ def verify_captures(_ctx, capts)
46
49
  @capts = capts
47
50
  end
48
51
 
49
- def link_references(ctx)
50
- end
51
-
52
52
  def setup_rule(rule)
53
53
  @index = rule.codes.length
54
54
  rule.codes.push(self)
55
55
  end
56
+
57
+ def to_h
58
+ {
59
+ type: :action,
60
+ code: code&.text,
61
+ vars: vars&.map(&:to_h),
62
+ capts: capts&.map(&:to_h),
63
+ }
64
+ end
56
65
  end
57
66
  end
58
67
  end
68
+
69
+ require "packcr/generated/node/action_node"
@@ -9,7 +9,7 @@ class Packcr
9
9
  end
10
10
 
11
11
  def alt(node)
12
- @nodes << node
12
+ @nodes << node if node
13
13
  self
14
14
  end
15
15
 
@@ -27,14 +27,21 @@ class Packcr
27
27
  m
28
28
  end
29
29
 
30
- def generate_code(gen, onfail, indent, bare)
31
- b = false
32
- m = gen.next_label
33
-
34
- reach = nil
35
- gen.write Packcr.template("node/alternate.#{gen.lang}.erb", binding, indent: indent - 4, unwrap: bare)
30
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
31
+ gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent, unwrap: bare)
32
+ end
36
33
 
37
- reach || Packcr::CODE_REACH__ALWAYS_FAIL
34
+ def reachability
35
+ r = Packcr::CODE_REACH__ALWAYS_FAIL
36
+ nodes.each do |expr|
37
+ case expr.reachability
38
+ when Packcr::CODE_REACH__ALWAYS_SUCCEED
39
+ return Packcr::CODE_REACH__ALWAYS_SUCCEED
40
+ when Packcr::CODE_REACH__BOTH
41
+ r = Packcr::CODE_REACH__BOTH
42
+ end
43
+ end
44
+ r
38
45
  end
39
46
 
40
47
  def verify_variables(vars)
@@ -66,11 +73,14 @@ class Packcr
66
73
  end
67
74
  end
68
75
 
69
- def link_references(ctx)
70
- nodes.each do |node|
71
- node.link_references(ctx)
72
- end
76
+ def to_h
77
+ {
78
+ type: :alternate,
79
+ nodes: nodes&.map(&:to_h),
80
+ }
73
81
  end
74
82
  end
75
83
  end
76
84
  end
85
+
86
+ require "packcr/generated/node/alternate_node"
@@ -15,25 +15,19 @@ class Packcr
15
15
  $stdout.print "#{" " * indent}}\n"
16
16
  end
17
17
 
18
- def generate_code(gen, onfail, indent, bare)
19
- r = nil
20
- gen.write Packcr.template("node/capture.#{gen.lang}.erb", binding, indent: indent)
21
- return r
18
+ def generate_code(gen, onfail, indent, bare, oncut: nil)
19
+ gen.write Packcr.format_code(get_code(gen, onfail, indent, bare, oncut), indent: indent)
22
20
  end
23
21
 
24
- def verify_variables(vars)
25
- expr.verify_variables(vars)
22
+ def reachability
23
+ expr.reachability
26
24
  end
27
25
 
28
26
  def verify_captures(ctx, capts)
29
- expr.verify_captures(ctx, capts)
27
+ super
30
28
  capts.push(self)
31
29
  end
32
30
 
33
- def link_references(ctx)
34
- expr.link_references(ctx)
35
- end
36
-
37
31
  def nodes
38
32
  [expr]
39
33
  end
@@ -41,8 +35,16 @@ class Packcr
41
35
  def setup_rule(rule)
42
36
  @index = rule.capts.length
43
37
  rule.capts << self
44
- super
38
+ end
39
+
40
+ def to_h
41
+ {
42
+ type: :capture,
43
+ expr: expr&.to_h,
44
+ }
45
45
  end
46
46
  end
47
47
  end
48
48
  end
49
+
50
+ require "packcr/generated/node/capture_node"