kpeg 0.10.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/kpeg.gemspec CHANGED
@@ -1,42 +1,42 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # stub: kpeg 1.0.0.20140103162640 ruby lib
2
3
 
3
4
  Gem::Specification.new do |s|
4
5
  s.name = "kpeg"
5
- s.version = "0.8.5.20120306163408"
6
+ s.version = "1.0.0.20140103162640"
6
7
 
7
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Eric Hodel"]
9
- s.cert_chain = ["/Users/drbrain/.gem/gem-public_cert.pem"]
10
- s.date = "2012-03-07"
9
+ s.authors = ["Evan Phoenix"]
10
+ s.date = "2014-01-04"
11
11
  s.description = "KPeg is a simple PEG library for Ruby. It provides an API as well as native\ngrammar to build the grammar.\n\nKPeg strives to provide a simple, powerful API without being too exotic.\n\nKPeg supports direct left recursion of rules via the\n{OMeta memoization}[http://www.vpri.org/pdf/tr2008003_experimenting.pdf] trick."
12
- s.email = ["drbrain@segment7.net"]
12
+ s.email = ["evan@fallingsnow.net"]
13
13
  s.executables = ["kpeg"]
14
- s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
15
- s.files = [".autotest", "Gemfile", "Gemfile.lock", "History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "bin/kpeg", "examples/calculator/calculator.kpeg", "examples/calculator/calculator.rb", "examples/foreign_reference/literals.kpeg", "examples/foreign_reference/matcher.kpeg", "examples/foreign_reference/matcher.rb", "examples/lua_string/driver.rb", "examples/lua_string/lua_string.kpeg", "examples/lua_string/lua_string.kpeg.rb", "examples/phone_number/README.md", "examples/phone_number/phone_number.kpeg", "examples/phone_number/phone_number.rb", "examples/upper/README.md", "examples/upper/upper.kpeg", "examples/upper/upper.rb", "kpeg.gemspec", "lib/kpeg.rb", "lib/kpeg/code_generator.rb", "lib/kpeg/compiled_parser.rb", "lib/kpeg/format.kpeg", "lib/kpeg/format_parser.rb", "lib/kpeg/grammar.rb", "lib/kpeg/grammar_renderer.rb", "lib/kpeg/match.rb", "lib/kpeg/parser.rb", "lib/kpeg/position.rb", "lib/kpeg/string_escape.kpeg", "lib/kpeg/string_escape.rb", "lib/kpeg/version.rb", "test/inputs/comments.kpeg", "test/test_file_parser_roundtrip.rb", "test/test_gen_calc.rb", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_left_recursion.rb", "vim/syntax_kpeg/ftdetect/kpeg.vim", "vim/syntax_kpeg/syntax/kpeg.vim", ".gemtest"]
14
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc", "examples/phone_number/README.md", "examples/upper/README.md"]
15
+ s.files = [".autotest", ".travis.yml", "History.txt", "LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "bin/kpeg", "examples/calculator/calculator.kpeg", "examples/calculator/calculator.rb", "examples/foreign_reference/literals.kpeg", "examples/foreign_reference/matcher.kpeg", "examples/foreign_reference/matcher.rb", "examples/lua_string/driver.rb", "examples/lua_string/lua_string.kpeg", "examples/lua_string/lua_string.kpeg.rb", "examples/phone_number/README.md", "examples/phone_number/phone_number.kpeg", "examples/phone_number/phone_number.rb", "examples/upper/README.md", "examples/upper/upper.kpeg", "examples/upper/upper.rb", "kpeg.gemspec", "lib/hoe/kpeg.rb", "lib/kpeg.rb", "lib/kpeg/code_generator.rb", "lib/kpeg/compiled_parser.rb", "lib/kpeg/format_parser.kpeg", "lib/kpeg/format_parser.rb", "lib/kpeg/grammar.rb", "lib/kpeg/grammar_renderer.rb", "lib/kpeg/match.rb", "lib/kpeg/parser.rb", "lib/kpeg/position.rb", "lib/kpeg/string_escape.kpeg", "lib/kpeg/string_escape.rb", "test/inputs/comments.kpeg", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_format_parser_round_trip.rb", "test/test_kpeg_grammar.rb", "test/test_kpeg_grammar_renderer.rb", "vim/syntax_kpeg/ftdetect/kpeg.vim", "vim/syntax_kpeg/syntax/kpeg.vim", "test/test_kpeg_string_escape.rb", ".gemtest"]
16
16
  s.homepage = "https://github.com/evanphx/kpeg"
17
+ s.licenses = ["MIT"]
17
18
  s.rdoc_options = ["--main", "README.rdoc"]
18
19
  s.require_paths = ["lib"]
19
20
  s.rubyforge_project = "kpeg"
20
- s.rubygems_version = "1.8.12"
21
- s.signing_key = "/Users/drbrain/.gem/gem-private_key.pem"
21
+ s.rubygems_version = "2.1.10"
22
22
  s.summary = "KPeg is a simple PEG library for Ruby"
23
- s.test_files = ["test/test_file_parser_roundtrip.rb", "test/test_gen_calc.rb", "test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_left_recursion.rb"]
23
+ s.test_files = ["test/test_kpeg.rb", "test/test_kpeg_code_generator.rb", "test/test_kpeg_compiled_parser.rb", "test/test_kpeg_format.rb", "test/test_kpeg_format_parser_round_trip.rb", "test/test_kpeg_grammar.rb", "test/test_kpeg_grammar_renderer.rb", "test/test_kpeg_string_escape.rb"]
24
24
 
25
25
  if s.respond_to? :specification_version then
26
- s.specification_version = 3
26
+ s.specification_version = 4
27
27
 
28
28
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
29
- s.add_development_dependency(%q<minitest>, ["~> 2.11"])
30
- s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
31
- s.add_development_dependency(%q<hoe>, ["~> 2.15"])
29
+ s.add_development_dependency(%q<minitest>, ["~> 5.2"])
30
+ s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
31
+ s.add_development_dependency(%q<hoe>, ["~> 3.7"])
32
32
  else
33
- s.add_dependency(%q<minitest>, ["~> 2.11"])
34
- s.add_dependency(%q<rdoc>, ["~> 3.10"])
35
- s.add_dependency(%q<hoe>, ["~> 2.15"])
33
+ s.add_dependency(%q<minitest>, ["~> 5.2"])
34
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
35
+ s.add_dependency(%q<hoe>, ["~> 3.7"])
36
36
  end
37
37
  else
38
- s.add_dependency(%q<minitest>, ["~> 2.11"])
39
- s.add_dependency(%q<rdoc>, ["~> 3.10"])
40
- s.add_dependency(%q<hoe>, ["~> 2.15"])
38
+ s.add_dependency(%q<minitest>, ["~> 5.2"])
39
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
40
+ s.add_dependency(%q<hoe>, ["~> 3.7"])
41
41
  end
42
42
  end
@@ -83,11 +83,14 @@ module KPeg
83
83
 
84
84
  if output_node
85
85
  code << " end\n"
86
+ code << " module #{root}Construction\n"
86
87
  methods.each do |short, name, attrs|
87
- code << " def #{short}(#{attrs.join(', ')})\n"
88
- code << " #{root}::#{name}.new(#{attrs.join(', ')})\n"
89
- code << " end\n"
88
+ code << " def #{short}(#{attrs.join(', ')})\n"
89
+ code << " #{root}::#{name}.new(#{attrs.join(', ')})\n"
90
+ code << " end\n"
90
91
  end
92
+ code << " end\n"
93
+ code << " include #{root}Construction\n"
91
94
  end
92
95
  end
93
96
 
@@ -109,7 +112,7 @@ module KPeg
109
112
  # Let default ruby string handling figure it out
110
113
  lang = ""
111
114
  end
112
- code << indentify("_tmp = scan(/\\A#{op.regexp}/#{lang})\n", indent)
115
+ code << indentify("_tmp = scan(/\\G#{op.regexp}/#{lang})\n", indent)
113
116
  when CharRange
114
117
  ss = save()
115
118
  if op.start.bytesize == 1 and op.fin.bytesize == 1
@@ -124,7 +127,7 @@ module KPeg
124
127
  left = op.start[0]
125
128
  right = op.fin[0]
126
129
  end
127
-
130
+
128
131
  code << indentify(" unless _tmp >= #{left} and _tmp <= #{right}\n", indent)
129
132
  code << indentify(" self.pos = #{ss}\n", indent)
130
133
  code << indentify(" _tmp = nil\n", indent)
@@ -140,7 +143,7 @@ module KPeg
140
143
  code << indentify("while true # choice\n", indent)
141
144
  op.ops.each_with_index do |n,idx|
142
145
  output_op code, n, (indent+1)
143
-
146
+
144
147
  code << indentify(" break if _tmp\n", indent)
145
148
  code << indentify(" self.pos = #{ss}\n", indent)
146
149
  if idx == op.ops.size - 1
@@ -447,7 +450,7 @@ module KPeg
447
450
  cpi = standalone_region("compiled_parser.rb", "INITIALIZE")
448
451
  pp = standalone_region("position.rb")
449
452
 
450
- cp.gsub!(/include Position/, pp)
453
+ cp.gsub!(/^\s*include Position/, pp)
451
454
  code << " # :stopdoc:\n"
452
455
  code << cpi << "\n" unless @grammar.variables['custom_initialize']
453
456
  code << cp << "\n"
@@ -27,12 +27,12 @@ module KPeg
27
27
  # Prepares for parsing +str+. If you define a custom initialize you must
28
28
  # call this method before #parse
29
29
  def setup_parser(str, debug=false)
30
- @string = str
31
- @pos = 0
30
+ set_string str, 0
32
31
  @memoizations = Hash.new { |h,k| h[k] = {} }
33
32
  @result = nil
34
33
  @failed_rule = nil
35
34
  @failing_rule_offset = -1
35
+ @line_offsets = nil
36
36
 
37
37
  setup_foreign_grammar
38
38
  end
@@ -47,6 +47,13 @@ module KPeg
47
47
  @string[start..@pos-1]
48
48
  end
49
49
 
50
+ # Sets the string and current parsing position for the parser.
51
+ def set_string string, pos
52
+ @string = string
53
+ @string_size = string ? string.size : 0
54
+ @pos = pos
55
+ end
56
+
50
57
  def show_pos
51
58
  width = 10
52
59
  if @pos < width
@@ -144,28 +151,27 @@ module KPeg
144
151
  end
145
152
 
146
153
  def scan(reg)
147
- if m = reg.match(@string[@pos..-1])
148
- width = m.end(0)
149
- @pos += width
154
+ if m = reg.match(@string, @pos)
155
+ @pos = m.end(0)
150
156
  return true
151
157
  end
152
158
 
153
159
  return nil
154
160
  end
155
161
 
156
- if "".respond_to? :getbyte
162
+ if "".respond_to? :ord
157
163
  def get_byte
158
- if @pos >= @string.size
164
+ if @pos >= @string_size
159
165
  return nil
160
166
  end
161
167
 
162
- s = @string.getbyte @pos
168
+ s = @string[@pos].ord
163
169
  @pos += 1
164
170
  s
165
171
  end
166
172
  else
167
173
  def get_byte
168
- if @pos >= @string.size
174
+ if @pos >= @string_size
169
175
  return nil
170
176
  end
171
177
 
@@ -214,8 +220,7 @@ module KPeg
214
220
  old_pos = @pos
215
221
  old_string = @string
216
222
 
217
- @pos = other.pos
218
- @string = other.string
223
+ set_string other.string, other.pos
219
224
 
220
225
  begin
221
226
  if val = __send__(rule, *args)
@@ -226,8 +231,7 @@ module KPeg
226
231
  end
227
232
  val
228
233
  ensure
229
- @pos = old_pos
230
- @string = old_string
234
+ set_string old_string, old_pos
231
235
  end
232
236
  end
233
237
 
@@ -261,8 +265,6 @@ module KPeg
261
265
  else
262
266
  return ans
263
267
  end
264
-
265
- return ans
266
268
  end
267
269
  end
268
270
 
@@ -295,8 +297,6 @@ module KPeg
295
297
  else
296
298
  return ans
297
299
  end
298
-
299
- return ans
300
300
  end
301
301
  end
302
302
 
@@ -77,7 +77,7 @@ sgl_escape_quote = "\\'" { "'" }
77
77
  | "[" - range_num:e - "]" { [e.to_i, e.to_i] }
78
78
 
79
79
  curly_block = curly
80
- curly = "{" < (/[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
80
+ curly = "{" < (spaces | /[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
81
81
  nested_paren = "(" (/[^()"']+/ | string | nested_paren)* ")"
82
82
 
83
83
  value = value:v ":" var:n { @g.t(v,n) }
@@ -5,12 +5,12 @@ class KPeg::FormatParser
5
5
  # Prepares for parsing +str+. If you define a custom initialize you must
6
6
  # call this method before #parse
7
7
  def setup_parser(str, debug=false)
8
- @string = str
9
- @pos = 0
8
+ set_string str, 0
10
9
  @memoizations = Hash.new { |h,k| h[k] = {} }
11
10
  @result = nil
12
11
  @failed_rule = nil
13
12
  @failing_rule_offset = -1
13
+ @line_offsets = nil
14
14
 
15
15
  setup_foreign_grammar
16
16
  end
@@ -19,7 +19,6 @@ class KPeg::FormatParser
19
19
  attr_reader :failing_rule_offset
20
20
  attr_accessor :result, :pos
21
21
 
22
-
23
22
  def current_column(target=pos)
24
23
  if c = string.rindex("\n", target-1)
25
24
  return target - c - 1
@@ -28,17 +27,32 @@ class KPeg::FormatParser
28
27
  target + 1
29
28
  end
30
29
 
31
- def current_line(target=pos)
32
- cur_offset = 0
33
- cur_line = 0
30
+ if [].respond_to? :bsearch_index
31
+ def current_line(target=pos)
32
+ unless @line_offsets
33
+ @line_offsets = []
34
+ total = 0
35
+ string.each_line do |line|
36
+ total += line.size
37
+ @line_offsets << total
38
+ end
39
+ end
34
40
 
35
- string.each_line do |line|
36
- cur_line += 1
37
- cur_offset += line.size
38
- return cur_line if cur_offset >= target
41
+ @line_offsets.bsearch_index {|x| x >= target } + 1 || -1
39
42
  end
43
+ else
44
+ def current_line(target=pos)
45
+ cur_offset = 0
46
+ cur_line = 0
40
47
 
41
- -1
48
+ string.each_line do |line|
49
+ cur_line += 1
50
+ cur_offset += line.size
51
+ return cur_line if cur_offset >= target
52
+ end
53
+
54
+ -1
55
+ end
42
56
  end
43
57
 
44
58
  def lines
@@ -53,6 +67,13 @@ class KPeg::FormatParser
53
67
  @string[start..@pos-1]
54
68
  end
55
69
 
70
+ # Sets the string and current parsing position for the parser.
71
+ def set_string string, pos
72
+ @string = string
73
+ @string_size = string ? string.size : 0
74
+ @pos = pos
75
+ end
76
+
56
77
  def show_pos
57
78
  width = 10
58
79
  if @pos < width
@@ -150,28 +171,27 @@ class KPeg::FormatParser
150
171
  end
151
172
 
152
173
  def scan(reg)
153
- if m = reg.match(@string[@pos..-1])
154
- width = m.end(0)
155
- @pos += width
174
+ if m = reg.match(@string, @pos)
175
+ @pos = m.end(0)
156
176
  return true
157
177
  end
158
178
 
159
179
  return nil
160
180
  end
161
181
 
162
- if "".respond_to? :getbyte
182
+ if "".respond_to? :ord
163
183
  def get_byte
164
- if @pos >= @string.size
184
+ if @pos >= @string_size
165
185
  return nil
166
186
  end
167
187
 
168
- s = @string.getbyte @pos
188
+ s = @string[@pos].ord
169
189
  @pos += 1
170
190
  s
171
191
  end
172
192
  else
173
193
  def get_byte
174
- if @pos >= @string.size
194
+ if @pos >= @string_size
175
195
  return nil
176
196
  end
177
197
 
@@ -220,8 +240,7 @@ class KPeg::FormatParser
220
240
  old_pos = @pos
221
241
  old_string = @string
222
242
 
223
- @pos = other.pos
224
- @string = other.string
243
+ set_string other.string, other.pos
225
244
 
226
245
  begin
227
246
  if val = __send__(rule, *args)
@@ -232,8 +251,7 @@ class KPeg::FormatParser
232
251
  end
233
252
  val
234
253
  ensure
235
- @pos = old_pos
236
- @string = old_string
254
+ set_string old_string, old_pos
237
255
  end
238
256
  end
239
257
 
@@ -267,8 +285,6 @@ class KPeg::FormatParser
267
285
  else
268
286
  return ans
269
287
  end
270
-
271
- return ans
272
288
  end
273
289
  end
274
290
 
@@ -301,8 +317,6 @@ class KPeg::FormatParser
301
317
  else
302
318
  return ans
303
319
  end
304
-
305
- return ans
306
320
  end
307
321
  end
308
322
 
@@ -523,7 +537,7 @@ class KPeg::FormatParser
523
537
  _tmp = match_string("-")
524
538
  break if _tmp
525
539
  self.pos = _save1
526
- _tmp = scan(/\A(?i-mx:[a-z][\w-]*)/)
540
+ _tmp = scan(/\G(?i-mx:[a-z][\w-]*)/)
527
541
  break if _tmp
528
542
  self.pos = _save1
529
543
  break
@@ -554,7 +568,7 @@ class KPeg::FormatParser
554
568
  _save = self.pos
555
569
  while true # sequence
556
570
  _text_start = self.pos
557
- _tmp = scan(/\A(?i-mx:[a-z_]\w*)/)
571
+ _tmp = scan(/\G(?i-mx:[a-z_]\w*)/)
558
572
  if _tmp
559
573
  text = get_text(_text_start)
560
574
  end
@@ -818,7 +832,7 @@ class KPeg::FormatParser
818
832
  _save1 = self.pos
819
833
  while true # sequence
820
834
  _text_start = self.pos
821
- _tmp = scan(/\A(?-mix:[0-7]{1,3})/)
835
+ _tmp = scan(/\G(?-mix:[0-7]{1,3})/)
822
836
  if _tmp
823
837
  text = get_text(_text_start)
824
838
  end
@@ -845,7 +859,7 @@ class KPeg::FormatParser
845
859
  break
846
860
  end
847
861
  _text_start = self.pos
848
- _tmp = scan(/\A(?i-mx:[a-f\d]{2})/)
862
+ _tmp = scan(/\G(?i-mx:[a-f\d]{2})/)
849
863
  if _tmp
850
864
  text = get_text(_text_start)
851
865
  end
@@ -876,7 +890,7 @@ class KPeg::FormatParser
876
890
  _save = self.pos
877
891
  while true # sequence
878
892
  _text_start = self.pos
879
- _tmp = scan(/\A(?-mix:[^\\"]+)/)
893
+ _tmp = scan(/\G(?-mix:[^\\"]+)/)
880
894
  if _tmp
881
895
  text = get_text(_text_start)
882
896
  end
@@ -1014,7 +1028,7 @@ class KPeg::FormatParser
1014
1028
  _save = self.pos
1015
1029
  while true # sequence
1016
1030
  _text_start = self.pos
1017
- _tmp = scan(/\A(?-mix:[^'])/)
1031
+ _tmp = scan(/\G(?-mix:[^'])/)
1018
1032
  if _tmp
1019
1033
  text = get_text(_text_start)
1020
1034
  end
@@ -1139,7 +1153,7 @@ class KPeg::FormatParser
1139
1153
  _tmp = match_string("\\/")
1140
1154
  break if _tmp
1141
1155
  self.pos = _save2
1142
- _tmp = scan(/\A(?-mix:[^\/])/)
1156
+ _tmp = scan(/\G(?-mix:[^\/])/)
1143
1157
  break if _tmp
1144
1158
  self.pos = _save2
1145
1159
  break
@@ -1153,7 +1167,7 @@ class KPeg::FormatParser
1153
1167
  _tmp = match_string("\\/")
1154
1168
  break if _tmp
1155
1169
  self.pos = _save3
1156
- _tmp = scan(/\A(?-mix:[^\/])/)
1170
+ _tmp = scan(/\G(?-mix:[^\/])/)
1157
1171
  break if _tmp
1158
1172
  self.pos = _save3
1159
1173
  break
@@ -1266,7 +1280,7 @@ class KPeg::FormatParser
1266
1280
  _save = self.pos
1267
1281
  while true # sequence
1268
1282
  _text_start = self.pos
1269
- _tmp = scan(/\A(?i-mx:[a-z\d])/)
1283
+ _tmp = scan(/\G(?i-mx:[a-z\d])/)
1270
1284
  if _tmp
1271
1285
  text = get_text(_text_start)
1272
1286
  end
@@ -1336,7 +1350,7 @@ class KPeg::FormatParser
1336
1350
  _save = self.pos
1337
1351
  while true # sequence
1338
1352
  _text_start = self.pos
1339
- _tmp = scan(/\A(?-mix:[1-9]\d*)/)
1353
+ _tmp = scan(/\G(?-mix:[1-9]\d*)/)
1340
1354
  if _tmp
1341
1355
  text = get_text(_text_start)
1342
1356
  end
@@ -1511,7 +1525,7 @@ class KPeg::FormatParser
1511
1525
  return _tmp
1512
1526
  end
1513
1527
 
1514
- # curly = "{" < (/[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
1528
+ # curly = "{" < (spaces | /[^{}"']+/ | string | curly)* > "}" { @g.action(text) }
1515
1529
  def _curly
1516
1530
 
1517
1531
  _save = self.pos
@@ -1526,7 +1540,10 @@ class KPeg::FormatParser
1526
1540
 
1527
1541
  _save2 = self.pos
1528
1542
  while true # choice
1529
- _tmp = scan(/\A(?-mix:[^{}"']+)/)
1543
+ _tmp = apply(:_spaces)
1544
+ break if _tmp
1545
+ self.pos = _save2
1546
+ _tmp = scan(/\G(?-mix:[^{}"']+)/)
1530
1547
  break if _tmp
1531
1548
  self.pos = _save2
1532
1549
  _tmp = apply(:_string)
@@ -1579,7 +1596,7 @@ class KPeg::FormatParser
1579
1596
 
1580
1597
  _save2 = self.pos
1581
1598
  while true # choice
1582
- _tmp = scan(/\A(?-mix:[^()"']+)/)
1599
+ _tmp = scan(/\G(?-mix:[^()"']+)/)
1583
1600
  break if _tmp
1584
1601
  self.pos = _save2
1585
1602
  _tmp = apply(:_string)
@@ -2616,7 +2633,7 @@ class KPeg::FormatParser
2616
2633
  break
2617
2634
  end
2618
2635
  _text_start = self.pos
2619
- _tmp = scan(/\A(?-mix:[:\w]+)/)
2636
+ _tmp = scan(/\G(?-mix:[:\w]+)/)
2620
2637
  if _tmp
2621
2638
  text = get_text(_text_start)
2622
2639
  end
@@ -2914,7 +2931,7 @@ class KPeg::FormatParser
2914
2931
  _save = self.pos
2915
2932
  while true # sequence
2916
2933
  _text_start = self.pos
2917
- _tmp = scan(/\A(?-mix:[A-Z]\w*)/)
2934
+ _tmp = scan(/\G(?-mix:[A-Z]\w*)/)
2918
2935
  if _tmp
2919
2936
  text = get_text(_text_start)
2920
2937
  end
@@ -2940,7 +2957,7 @@ class KPeg::FormatParser
2940
2957
  _save = self.pos
2941
2958
  while true # sequence
2942
2959
  _text_start = self.pos
2943
- _tmp = scan(/\A(?i-mx:[a-z_]\w*)/)
2960
+ _tmp = scan(/\G(?i-mx:[a-z_]\w*)/)
2944
2961
  if _tmp
2945
2962
  text = get_text(_text_start)
2946
2963
  end
@@ -3157,7 +3174,7 @@ class KPeg::FormatParser
3157
3174
  Rules[:_range_elem] = rule_info("range_elem", "< (range_num | kleene) > { text }")
3158
3175
  Rules[:_mult_range] = rule_info("mult_range", "(\"[\" - range_elem:l - \",\" - range_elem:r - \"]\" { [l == \"*\" ? nil : l.to_i, r == \"*\" ? nil : r.to_i] } | \"[\" - range_num:e - \"]\" { [e.to_i, e.to_i] })")
3159
3176
  Rules[:_curly_block] = rule_info("curly_block", "curly")
3160
- Rules[:_curly] = rule_info("curly", "\"{\" < (/[^{}\"']+/ | string | curly)* > \"}\" { @g.action(text) }")
3177
+ Rules[:_curly] = rule_info("curly", "\"{\" < (spaces | /[^{}\"']+/ | string | curly)* > \"}\" { @g.action(text) }")
3161
3178
  Rules[:_nested_paren] = rule_info("nested_paren", "\"(\" (/[^()\"']+/ | string | nested_paren)* \")\"")
3162
3179
  Rules[:_value] = rule_info("value", "(value:v \":\" var:n { @g.t(v,n) } | value:v \"?\" { @g.maybe(v) } | value:v \"+\" { @g.many(v) } | value:v \"*\" { @g.kleene(v) } | value:v mult_range:r { @g.multiple(v, *r) } | \"&\" value:v { @g.andp(v) } | \"!\" value:v { @g.notp(v) } | \"(\" - expression:o - \")\" { o } | \"@<\" - expression:o - \">\" { @g.bounds(o) } | \"<\" - expression:o - \">\" { @g.collect(o) } | curly_block | \"~\" method:m < nested_paren? > { @g.action(\"\#{m}\#{text}\") } | \".\" { @g.dot } | \"@\" var:name < nested_paren? > !(- \"=\") { @g.invoke(name, text.empty? ? nil : text) } | \"^\" var:name < nested_paren? > { @g.foreign_invoke(\"parent\", name, text) } | \"%\" var:gram \".\" var:name < nested_paren? > { @g.foreign_invoke(gram, name, text) } | var:name < nested_paren? > !(- \"=\") { @g.ref(name, nil, text.empty? ? nil : text) } | char_range | regexp | string)")
3163
3180
  Rules[:_spaces] = rule_info("spaces", "(space | comment)+")
data/lib/kpeg/grammar.rb CHANGED
@@ -834,7 +834,7 @@ module KPeg
834
834
  # Invoke a rule defined on a foreign grammar
835
835
  # == Parameters:
836
836
  # gram::
837
- # The name of the grammar that the rule will be reference from
837
+ # The name of the grammar that the rule will be reference from
838
838
  # name::
839
839
  # The name of the rule that will be invoked
840
840
  # args::
data/lib/kpeg/position.rb CHANGED
@@ -10,17 +10,32 @@ module KPeg
10
10
  target + 1
11
11
  end
12
12
 
13
- def current_line(target=pos)
14
- cur_offset = 0
15
- cur_line = 0
16
-
17
- string.each_line do |line|
18
- cur_line += 1
19
- cur_offset += line.size
20
- return cur_line if cur_offset >= target
13
+ if [].respond_to? :bsearch_index
14
+ def current_line(target=pos)
15
+ unless @line_offsets
16
+ @line_offsets = []
17
+ total = 0
18
+ string.each_line do |line|
19
+ total += line.size
20
+ @line_offsets << total
21
+ end
22
+ end
23
+
24
+ @line_offsets.bsearch_index {|x| x >= target } + 1 || -1
25
+ end
26
+ else
27
+ def current_line(target=pos)
28
+ cur_offset = 0
29
+ cur_line = 0
30
+
31
+ string.each_line do |line|
32
+ cur_line += 1
33
+ cur_offset += line.size
34
+ return cur_line if cur_offset >= target
35
+ end
36
+
37
+ -1
21
38
  end
22
-
23
- -1
24
39
  end
25
40
 
26
41
  def lines
@@ -7,6 +7,7 @@
7
7
  segment = < /[\w ]+/ > { text } # Don't use \s because that matchs \n
8
8
  | "\\" { "\\\\" }
9
9
  | "\n" { "\\n" }
10
+ | "\r" { "\\r" }
10
11
  | "\t" { "\\t" }
11
12
  | "\b" { "\\b" }
12
13
  | "\"" { "\\\"" }