kpeg 0.10.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  | "\"" { "\\\"" }