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.
- data/CHANGELOG.md +71 -0
- data/LICENSE.txt +1 -1
- data/README.md +93 -1
- data/lib/raabro.rb +96 -5
- data/raabro.gemspec +6 -4
- metadata +10 -10
- data/CHANGELOG.txt +0 -64
data/CHANGELOG.md
ADDED
@@ -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
|
+
|
data/LICENSE.txt
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
Copyright (c) 2015-
|
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
|
-
#
|
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
|
|
data/lib/raabro.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2015-
|
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.
|
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
|
[ "[0;0m", "[1;30m", "[0;32m", "[1;33m", "[0;34m", "[0;37m" ] :
|
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
|
data/raabro.gemspec
CHANGED
@@ -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'
|
26
|
-
|
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', '
|
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.
|
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:
|
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:
|
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:
|
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:
|
63
|
+
rubyforge_project:
|
64
64
|
rubygems_version: 1.8.23.2
|
65
65
|
signing_key:
|
66
66
|
specification_version: 3
|
data/CHANGELOG.txt
DELETED
@@ -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
|
-
|