raabro 1.1.3 → 1.1.4

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.
@@ -0,0 +1,71 @@
1
+
2
+ # raabro CHANGELOG.md
3
+
4
+
5
+ ## raabro 1.1.4 released 2017-08-17
6
+
7
+ * fail with ArgumentError if Raabro.pp input is not a Raabro::Tree
8
+ * parse(x, error: true) will produce an error message
9
+ `[ line, column, offset, err_message, err_visual ]`
10
+
11
+
12
+ ## raabro 1.1.3 released 2016-07-11
13
+
14
+ * display `>nonstring(14)<` in Raabro.pp
15
+ * add "tears" to Raabro.pp
16
+
17
+
18
+ ## raabro 1.1.2 released 2016-04-04
19
+
20
+ * add Raabro.pp(tree)
21
+
22
+
23
+ ## raabro 1.1.1 released 2016-04-03
24
+
25
+ * Tree#clast
26
+
27
+
28
+ ## raabro 1.1.0 released 2016-02-09
29
+
30
+ * many improvements
31
+ * unlock custom `rewrite(t)`
32
+
33
+
34
+ ## raabro 1.0.5 released 2015-09-25
35
+
36
+ * allow for .parse(s, debug: 1 to 3)
37
+ * drop complications in _narrow(parser)
38
+
39
+
40
+ ## raabro 1.0.4 released 2015-09-24
41
+
42
+ * provide a default .rewrite implementation
43
+
44
+
45
+ ## raabro 1.0.3 released 2015-09-23
46
+
47
+ * drop the shrink! concept
48
+
49
+
50
+ ## raabro 1.0.2 released 2015-09-23
51
+
52
+ * don't let parse() shrink tree when prune: false
53
+ * let parse() return tree anyway when prune: false
54
+ * add parse(s, rewrite: false) option
55
+
56
+
57
+ ## raabro 1.0.1 released 2015-09-23
58
+
59
+ * take last parser as default :root
60
+ * provide default .parse for modules including Raabro
61
+
62
+
63
+ ## raabro 1.0.0 released 2015-09-23
64
+
65
+ * first complete (hopefully) release
66
+
67
+
68
+ ## raabro 0.9.0
69
+
70
+ * initial push to RubyGems
71
+
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2015-2016, John Mettraux, jmettraux@gmail.com
2
+ Copyright (c) 2015-2017, John Mettraux, jmettraux@gmail.com
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -125,10 +125,102 @@ def ren(name, input, parser)
125
125
  # renames the output of the wrapped parser
126
126
 
127
127
  def jseq(name, input, eltpa, seppa)
128
- # seq(name, input, eltpa, seppa, eltpa, seppa, eltpaa, seppa, ...)
128
+ #
129
+ # seq(name, input, eltpa, seppa, eltpa, seppa, eltpa, seppa, ...)
130
+ #
131
+ # a sequence of `eltpa` parsers separated (joined) by `seppa` parsers
129
132
 
130
133
  def eseq(name, input, startpa, eltpa, seppa, endpa)
134
+ #
131
135
  # seq(name, input, startpa, eltpa, seppa, eltpa, seppa, ..., endpa)
136
+ #
137
+ # a sequence of `eltpa` parsers separated (joined) by `seppa` parsers
138
+ # preceded by a `startpa` parser and followed by a `endpa` parser
139
+ ```
140
+
141
+
142
+ ## the `seq` parser and its quantifiers
143
+
144
+ `seq` is special, it understands "quantifiers": `'?'`, `'+'` or `'*'`. They make behave `seq` a bit like a classical regex.
145
+
146
+ ```ruby
147
+ module CartParser include Raabro
148
+
149
+ def fruit(i)
150
+ rex(:fruit, i, /(tomato|apple|orange)/)
151
+ end
152
+ def vegetable(i)
153
+ rex(:vegetable, i, /(potato|cabbage|carrot)/)
154
+ end
155
+
156
+ def cart(i)
157
+ seq(:cart, i, :fruit, '*', :vegetable, '*')
158
+ end
159
+ # zero or more fruits followed by zero or more vegetables
160
+ end
161
+ ```
162
+
163
+ (Yes, this sample parser parses string like "appletomatocabbage", it's not very useful, but I hope you get the point about `.seq`)
164
+
165
+
166
+ ## errors
167
+
168
+ By default, a parser will return nil when it cannot successfully parse the input.
169
+
170
+ For example, given the above [`Fun` parser](#a-sample-parserrewriter), parsing some truncated input would yield `nil`:
171
+ ```ruby
172
+ tree = Sample::Fun.parse('f(a, b')
173
+ # yields `nil`...
174
+ ```
175
+
176
+ One can reparse with `error: true` and receive an error array with the parse error details:
177
+ ```ruby
178
+ err = Sample::Fun.parse('f(a, b', error: true)
179
+ # yields:
180
+ # [ line, column, offest, error_message, error_visual ]
181
+ [ 1, 4, 3, 'parsing failed .../:exp/:fun/:arg', "f(a, b\n ^---" ]
182
+ ```
183
+
184
+ The last string in the error array looks like when printed out:
185
+ ```
186
+ f(a, b
187
+ ^---
188
+ ```
189
+
190
+ ### error when not all is consumed
191
+
192
+ Consider the following toy parser:
193
+ ```ruby
194
+ module ToPlus include Raabro
195
+
196
+ # parse
197
+
198
+ def to_plus(input); rep(:tos, input, :to, 1); end
199
+
200
+ # rewrite
201
+
202
+ def rewrite(t); [ :ok, t.string ]; end
203
+ end
204
+ ```
205
+
206
+ ```ruby
207
+ Sample::ToPlus.parse('totota')
208
+ # yields nil since all the input was not parsed, "ta" is remaining
209
+
210
+ Sample::ToPlus.parse('totota', all: false)
211
+ # yields
212
+ [ :ok, "toto" ]
213
+ # and doesn't care about the remaining input "ta"
214
+
215
+ Sample::ToPlus.parse('totota', error: true)
216
+ # yields
217
+ [ 1, 5, 4, "parsing failed, not all input was consumed", "totota\n ^---" ]
218
+ ```
219
+
220
+ The last string in the error array looks like when printed out:
221
+ ```
222
+ totota
223
+ ^---
132
224
  ```
133
225
 
134
226
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2015-2016, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2015-2017, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -25,7 +25,7 @@
25
25
 
26
26
  module Raabro
27
27
 
28
- VERSION = '1.1.3'
28
+ VERSION = '1.1.4'
29
29
 
30
30
  class Input
31
31
 
@@ -55,6 +55,11 @@ module Raabro
55
55
 
56
56
  l < 0 ? @string[@offset..l] : @string[@offset, l]
57
57
  end
58
+
59
+ def at(i)
60
+
61
+ @string[i, 1]
62
+ end
58
63
  end
59
64
 
60
65
  class Tree
@@ -181,6 +186,74 @@ module Raabro
181
186
 
182
187
  cs = []; @children.each_with_index { |c, i| cs << c if i.even? }; cs
183
188
  end
189
+
190
+ def extract_error
191
+
192
+ #Raabro.pp(self, colors: true)
193
+ err_tree, stack = lookup_error || lookup_all_error
194
+
195
+ line, column = line_and_column(err_tree.offset)
196
+
197
+ err_message =
198
+ if stack
199
+ path = stack
200
+ .compact.reverse.take(3).reverse
201
+ .collect(&:inspect).join('/')
202
+ "parsing failed .../#{path}"
203
+ else
204
+ "parsing failed, not all input was consumed"
205
+ end
206
+ visual =
207
+ visual(line, column)
208
+
209
+ [ line, column, err_tree.offset, err_message, visual ]
210
+ end
211
+
212
+ def lookup_error(stack=[])
213
+
214
+ #print "le(): "; Raabro.pp(self, colors: true)
215
+ return nil if @result != 0
216
+ return [ self, stack ] if @children.empty?
217
+ @children.each { |c|
218
+ es = c.lookup_error(stack.dup.push(self.name))
219
+ return es if es }
220
+ nil
221
+ end
222
+
223
+ # Not "lookup all errors" but "lookup all error", in other
224
+ # words lookup the point up until which the parser stopped (not
225
+ # consuming all the input)
226
+ #
227
+ def lookup_all_error
228
+
229
+ #print "lae(): "; Raabro.pp(self, colors: true)
230
+ @children.each { |c| return [ c, nil ] if c.result == 0 }
231
+ @children.reverse.each { |c| es = c.lookup_all_error; return es if es }
232
+ nil
233
+ end
234
+
235
+ def line_and_column(offset)
236
+
237
+ line = 1
238
+ column = 0
239
+
240
+ (0..offset).each do |off|
241
+
242
+ column += 1
243
+ next unless @input.at(off) == "\n"
244
+
245
+ line += 1
246
+ column = 0
247
+ end
248
+
249
+ [ line, column ]
250
+ end
251
+
252
+ def visual(line, column)
253
+
254
+ @input.string.split("\n")[line - 1] + "\n" +
255
+ ' ' * (column - 1) + '^---'
256
+ end
184
257
  end
185
258
 
186
259
  module ModuleMethods
@@ -472,6 +545,7 @@ module Raabro
472
545
  all(nil, Raabro::Input.new(input, opts), root)
473
546
  end
474
547
 
548
+ return reparse_for_error(input, opts, t) if opts[:error] && t.result != 1
475
549
  return nil if opts[:prune] != false && t.result != 1
476
550
 
477
551
  t = t.children.first if t.parter == :all
@@ -481,6 +555,17 @@ module Raabro
481
555
  t
482
556
  end
483
557
 
558
+ def reparse_for_error(input, opts, t)
559
+
560
+ t =
561
+ opts[:prune] == false ?
562
+ t :
563
+ parse(input, opts.merge(error: false, rewrite: false, prune: false))
564
+ #Raabro.pp(t, colours: true)
565
+
566
+ t.extract_error
567
+ end
568
+
484
569
  def rewrite_(tree)
485
570
 
486
571
  t = tree.lookup(nil)
@@ -520,10 +605,16 @@ module Raabro
520
605
  # Brown 0;33 Yellow 1;33
521
606
  # Light Gray 0;37 White 1;37
522
607
 
523
- def self.pp(tree, depth=0)
608
+ def self.pp(tree, depth=0, opts={})
609
+
610
+ fail ArgumentError.new(
611
+ 'tree is not an instance of Raabro::Tree'
612
+ ) unless tree.is_a?(Raabro::Tree)
613
+
614
+ depth, opts = 0, depth if depth.is_a?(Hash)
524
615
 
525
616
  _rs, _dg, _gn, _yl, _bl, _lg =
526
- $stdout.tty? ?
617
+ (opts[:colors] || opts[:colours] || $stdout.tty?) ?
527
618
  [ "", "", "", "", "", "" ] :
528
619
  [ '', '', '', '', '', '' ]
529
620
 
@@ -554,7 +645,7 @@ module Raabro
554
645
  print str
555
646
  print "#{_rs}\n"
556
647
 
557
- tree.children.each { |c| self.pp(c, depth + 1) }
648
+ tree.children.each { |c| self.pp(c, depth + 1, opts) }
558
649
 
559
650
  if depth == 0
560
651
  print _dg
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.authors = [ 'John Mettraux' ]
12
12
  s.email = [ 'jmettraux@gmail.com' ]
13
13
  s.homepage = 'http://github.com/jmettraux/raabro'
14
- s.rubyforge_project = 'rufus'
14
+ #s.rubyforge_project = 'rufus'
15
15
  s.license = 'MIT'
16
16
  s.summary = 'a very dumb PEG parser library'
17
17
 
@@ -21,14 +21,16 @@ A very dumb PEG parser library, with a horrible interface.
21
21
 
22
22
  #s.files = `git ls-files`.split("\n")
23
23
  s.files = Dir[
24
+ 'README.{md,txt}',
25
+ 'CHANGELOG.{md,txt}', 'CREDITS.{md,txt}', 'LICENSE.{md,txt}',
24
26
  'Makefile',
25
- 'lib/**/*.rb',# 'spec/**/*.rb', 'test/**/*.rb',
26
- '*.gemspec', '*.txt', '*.rdoc', '*.md'
27
+ 'lib/**/*.rb', #'spec/**/*.rb', 'test/**/*.rb',
28
+ "#{s.name}.gemspec",
27
29
  ]
28
30
 
29
31
  #s.add_runtime_dependency 'tzinfo'
30
32
 
31
- s.add_development_dependency 'rspec', '>= 2.13.0'
33
+ s.add_development_dependency 'rspec', '~> 3.4.0'
32
34
 
33
35
  s.require_path = 'lib'
34
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raabro
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-07-11 00:00:00.000000000 Z
12
+ date: 2017-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.13.0
21
+ version: 3.4.0
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 2.13.0
29
+ version: 3.4.0
30
30
  description: A very dumb PEG parser library, with a horrible interface.
31
31
  email:
32
32
  - jmettraux@gmail.com
@@ -34,12 +34,12 @@ executables: []
34
34
  extensions: []
35
35
  extra_rdoc_files: []
36
36
  files:
37
+ - README.md
38
+ - CHANGELOG.md
39
+ - LICENSE.txt
37
40
  - Makefile
38
41
  - lib/raabro.rb
39
42
  - raabro.gemspec
40
- - CHANGELOG.txt
41
- - LICENSE.txt
42
- - README.md
43
43
  homepage: http://github.com/jmettraux/raabro
44
44
  licenses:
45
45
  - MIT
@@ -60,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  requirements: []
63
- rubyforge_project: rufus
63
+ rubyforge_project:
64
64
  rubygems_version: 1.8.23.2
65
65
  signing_key:
66
66
  specification_version: 3
@@ -1,64 +0,0 @@
1
-
2
- = raabro CHANGELOG.txt
3
-
4
-
5
- == raabro 1.1.3 released 2016-07-11
6
-
7
- - display >nonstring(14)< in Raabro.pp
8
- - add "tears" to Raabro.pp
9
-
10
-
11
- == raabro 1.1.2 released 2016-04-04
12
-
13
- - add Raabro.pp(tree)
14
-
15
-
16
- == raabro 1.1.1 released 2016-04-03
17
-
18
- - Tree#clast
19
-
20
-
21
- == raabro 1.1.0 released 2016-02-09
22
-
23
- - many improvements
24
- - unlock custom `rewrite(t)`
25
-
26
-
27
- == raabro 1.0.5 released 2015-09-25
28
-
29
- - allow for .parse(s, debug: 1 to 3)
30
- - drop complications in _narrow(parser)
31
-
32
-
33
- == raabro 1.0.4 released 2015-09-24
34
-
35
- - provide a default .rewrite implementation
36
-
37
-
38
- == raabro 1.0.3 released 2015-09-23
39
-
40
- - drop the shrink! concept
41
-
42
-
43
- == raabro 1.0.2 released 2015-09-23
44
-
45
- - don't let parse() shrink tree when prune: false
46
- - let parse() return tree anyway when prune: false
47
- - add parse(s, rewrite: false) option
48
-
49
-
50
- == raabro 1.0.1 released 2015-09-23
51
-
52
- - take last parser as default :root
53
- - provide default .parse for modules including Raabro
54
-
55
-
56
- == raabro 1.0.0 released 2015-09-23
57
-
58
- - first complete (hopefully) release
59
-
60
-
61
- == raabro 0.9.0
62
-
63
- - initial push to RubyGems
64
-