packcr 0.0.4 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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"