raabro 1.1.3 → 1.1.4

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