d-parse 0.1
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.
- checksums.yaml +7 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +104 -0
- data/Guardfile +3 -0
- data/LICENSE +19 -0
- data/NEWS.md +0 -0
- data/README.md +137 -0
- data/Rakefile +14 -0
- data/d-parse.gemspec +26 -0
- data/lib/d-parse.rb +10 -0
- data/lib/d-parse/dsl.rb +71 -0
- data/lib/d-parse/failure.rb +46 -0
- data/lib/d-parse/parser.rb +102 -0
- data/lib/d-parse/parsers.rb +26 -0
- data/lib/d-parse/parsers/combinators/alt.rb +32 -0
- data/lib/d-parse/parsers/combinators/repeat.rb +42 -0
- data/lib/d-parse/parsers/combinators/seq.rb +49 -0
- data/lib/d-parse/parsers/highlevel/char_in.rb +13 -0
- data/lib/d-parse/parsers/highlevel/intersperse.rb +18 -0
- data/lib/d-parse/parsers/highlevel/json.rb +237 -0
- data/lib/d-parse/parsers/highlevel/opt.rb +16 -0
- data/lib/d-parse/parsers/highlevel/string.rb +13 -0
- data/lib/d-parse/parsers/highlevel/whitespace_char.rb +15 -0
- data/lib/d-parse/parsers/modifiers/capturing.rb +13 -0
- data/lib/d-parse/parsers/modifiers/describe.rb +28 -0
- data/lib/d-parse/parsers/modifiers/ignore.rb +17 -0
- data/lib/d-parse/parsers/modifiers/lazy.rb +18 -0
- data/lib/d-parse/parsers/modifiers/map.rb +24 -0
- data/lib/d-parse/parsers/primitives/any.rb +22 -0
- data/lib/d-parse/parsers/primitives/bind.rb +25 -0
- data/lib/d-parse/parsers/primitives/char.rb +27 -0
- data/lib/d-parse/parsers/primitives/char_not.rb +27 -0
- data/lib/d-parse/parsers/primitives/char_not_in.rb +30 -0
- data/lib/d-parse/parsers/primitives/eof.rb +21 -0
- data/lib/d-parse/parsers/primitives/except.rb +33 -0
- data/lib/d-parse/parsers/primitives/fail.rb +17 -0
- data/lib/d-parse/parsers/primitives/succeed.rb +13 -0
- data/lib/d-parse/position.rb +31 -0
- data/lib/d-parse/success.rb +35 -0
- data/lib/d-parse/version.rb +3 -0
- data/samples/parse-bind +25 -0
- data/samples/parse-csv +19 -0
- data/samples/parse-errortest +45 -0
- data/samples/parse-fun +61 -0
- data/samples/parse-json +18 -0
- data/samples/parse-readme +27 -0
- data/spec/d-parse/failure_spec.rb +36 -0
- data/spec/d-parse/parser_spec.rb +77 -0
- data/spec/d-parse/parsers/alt_spec.rb +48 -0
- data/spec/d-parse/parsers/any_spec.rb +15 -0
- data/spec/d-parse/parsers/bind_spec.rb +31 -0
- data/spec/d-parse/parsers/capture_spec.rb +11 -0
- data/spec/d-parse/parsers/char_in_spec.rb +22 -0
- data/spec/d-parse/parsers/char_not_in_spec.rb +23 -0
- data/spec/d-parse/parsers/char_not_spec.rb +16 -0
- data/spec/d-parse/parsers/char_spec.rb +22 -0
- data/spec/d-parse/parsers/describe_spec.rb +22 -0
- data/spec/d-parse/parsers/end_of_input_spec.rb +20 -0
- data/spec/d-parse/parsers/except_spec.rb +20 -0
- data/spec/d-parse/parsers/fail_spec.rb +12 -0
- data/spec/d-parse/parsers/intersperse_spec.rb +18 -0
- data/spec/d-parse/parsers/json_spec.rb +69 -0
- data/spec/d-parse/parsers/lazy_spec.rb +16 -0
- data/spec/d-parse/parsers/map_spec.rb +54 -0
- data/spec/d-parse/parsers/optional_spec.rb +16 -0
- data/spec/d-parse/parsers/or_spec.rb +26 -0
- data/spec/d-parse/parsers/repeat_spec.rb +40 -0
- data/spec/d-parse/parsers/sequence_spec.rb +52 -0
- data/spec/d-parse/parsers/string_spec.rb +19 -0
- data/spec/d-parse/parsers/succeed_spec.rb +12 -0
- data/spec/d-parse/parsers/whitespace_char_spec.rb +14 -0
- data/spec/spec_helper.rb +97 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2672e347527fd59383d12db21f5a64e1cfe16e5b
|
4
|
+
data.tar.gz: 541544acc6be6004decf009531f9b9b6bdae15b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa5dcb3e12a82314066025d0c0739a64657e29bec485b414bdd705cab39848fcee448c21d811ac046b486a89ab815a958dd5066aa73b3722f2cec22d6050108c
|
7
|
+
data.tar.gz: b6f0b08ce5a15a067e07c98618a8da9c13b3b39828f13af2ab316d37f07be31886e5d275b8a587c1512cb5ea1fa34465ad7bb6a593980a4d161bc6b782c3b928
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
d-parse (0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.3.0)
|
10
|
+
coderay (1.1.1)
|
11
|
+
coveralls (0.8.13)
|
12
|
+
json (~> 1.8)
|
13
|
+
simplecov (~> 0.11.0)
|
14
|
+
term-ansicolor (~> 1.3)
|
15
|
+
thor (~> 0.19.1)
|
16
|
+
tins (~> 1.6.0)
|
17
|
+
diff-lcs (1.2.5)
|
18
|
+
docile (1.1.5)
|
19
|
+
ffi (1.9.10)
|
20
|
+
formatador (0.2.5)
|
21
|
+
guard (2.14.0)
|
22
|
+
formatador (>= 0.2.4)
|
23
|
+
listen (>= 2.7, < 4.0)
|
24
|
+
lumberjack (~> 1.0)
|
25
|
+
nenv (~> 0.1)
|
26
|
+
notiffany (~> 0.0)
|
27
|
+
pry (>= 0.9.12)
|
28
|
+
shellany (~> 0.0)
|
29
|
+
thor (>= 0.18.1)
|
30
|
+
guard-rake (1.0.0)
|
31
|
+
guard
|
32
|
+
rake
|
33
|
+
json (1.8.3)
|
34
|
+
listen (3.1.5)
|
35
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
36
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
37
|
+
ruby_dep (~> 1.2)
|
38
|
+
lumberjack (1.0.10)
|
39
|
+
method_source (0.8.2)
|
40
|
+
nenv (0.3.0)
|
41
|
+
notiffany (0.1.0)
|
42
|
+
nenv (~> 0.1)
|
43
|
+
shellany (~> 0.0)
|
44
|
+
parser (2.3.1.2)
|
45
|
+
ast (~> 2.2)
|
46
|
+
powerpack (0.1.1)
|
47
|
+
pry (0.10.3)
|
48
|
+
coderay (~> 1.1.0)
|
49
|
+
method_source (~> 0.8.1)
|
50
|
+
slop (~> 3.4)
|
51
|
+
rainbow (2.1.0)
|
52
|
+
rake (11.2.2)
|
53
|
+
rb-fsevent (0.9.7)
|
54
|
+
rb-inotify (0.9.7)
|
55
|
+
ffi (>= 0.5.0)
|
56
|
+
rspec (3.5.0)
|
57
|
+
rspec-core (~> 3.5.0)
|
58
|
+
rspec-expectations (~> 3.5.0)
|
59
|
+
rspec-mocks (~> 3.5.0)
|
60
|
+
rspec-core (3.5.0)
|
61
|
+
rspec-support (~> 3.5.0)
|
62
|
+
rspec-expectations (3.5.0)
|
63
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
64
|
+
rspec-support (~> 3.5.0)
|
65
|
+
rspec-mocks (3.5.0)
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
+
rspec-support (~> 3.5.0)
|
68
|
+
rspec-support (3.5.0)
|
69
|
+
rubocop (0.41.1)
|
70
|
+
parser (>= 2.3.1.1, < 3.0)
|
71
|
+
powerpack (~> 0.1)
|
72
|
+
rainbow (>= 1.99.1, < 3.0)
|
73
|
+
ruby-progressbar (~> 1.7)
|
74
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
75
|
+
ruby-progressbar (1.8.1)
|
76
|
+
ruby_dep (1.3.1)
|
77
|
+
shellany (0.0.1)
|
78
|
+
simplecov (0.11.2)
|
79
|
+
docile (~> 1.1.0)
|
80
|
+
json (~> 1.8)
|
81
|
+
simplecov-html (~> 0.10.0)
|
82
|
+
simplecov-html (0.10.0)
|
83
|
+
slop (3.6.0)
|
84
|
+
term-ansicolor (1.3.2)
|
85
|
+
tins (~> 1.0)
|
86
|
+
thor (0.19.1)
|
87
|
+
tins (1.6.0)
|
88
|
+
unicode-display_width (1.1.0)
|
89
|
+
|
90
|
+
PLATFORMS
|
91
|
+
ruby
|
92
|
+
|
93
|
+
DEPENDENCIES
|
94
|
+
bundler (>= 1.11.2, < 2.0)
|
95
|
+
coveralls
|
96
|
+
d-parse!
|
97
|
+
guard
|
98
|
+
guard-rake
|
99
|
+
rake
|
100
|
+
rspec
|
101
|
+
rubocop
|
102
|
+
|
103
|
+
BUNDLED WITH
|
104
|
+
1.12.5
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2016 Denis Defreyne and contributors
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/NEWS.md
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
[](https://travis-ci.org/ddfreyne/d-parse)
|
2
|
+
[](https://codeclimate.com/github/ddfreyne/d-parse)
|
3
|
+
[](https://coveralls.io/r/ddfreyne/d-parse)
|
4
|
+
|
5
|
+
# D★Parse
|
6
|
+
|
7
|
+
_D★Parse_ is a parser combinator library for Ruby.
|
8
|
+
|
9
|
+
**STATUS**: Experimental. Pre-alpha. Use at your own risk.
|
10
|
+
|
11
|
+
## Example
|
12
|
+
|
13
|
+
Here is a parser for a series of numbers:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'd-parse'
|
17
|
+
|
18
|
+
module Grammar
|
19
|
+
extend DParse::DSL
|
20
|
+
|
21
|
+
DIGIT = char_in('0'..'9')
|
22
|
+
|
23
|
+
ROOT =
|
24
|
+
seq(
|
25
|
+
intersperse(
|
26
|
+
repeat(DIGIT).capture.map { |d| d.to_i(10) },
|
27
|
+
char(',').ignore,
|
28
|
+
).compact,
|
29
|
+
eof,
|
30
|
+
).first
|
31
|
+
end
|
32
|
+
|
33
|
+
res = Grammar::ROOT.apply("1,2,100,582048,07,09")
|
34
|
+
case res
|
35
|
+
when DParse::Success
|
36
|
+
p res.data
|
37
|
+
when DParse::Failure
|
38
|
+
$stderr.puts res.pretty_message
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
## Parsers
|
44
|
+
|
45
|
+
* `alt(p1, p2, …)` attempts to apply any of the given parsers.
|
46
|
+
|
47
|
+
* `any` parses any character.
|
48
|
+
|
49
|
+
* `char_in(cs)` parses a character that is in the `cs` collection.
|
50
|
+
|
51
|
+
* `char_not_in(cs)` parses a character that is not in the `cs` collection.
|
52
|
+
|
53
|
+
* `char_not(c)` parses a character that is not `c`.
|
54
|
+
|
55
|
+
* `char(c)` parses the single character `c`.
|
56
|
+
|
57
|
+
* `eof` parses the end of file.
|
58
|
+
|
59
|
+
* `fail` always fails.
|
60
|
+
|
61
|
+
* `describe(p, name)` sets the name of the parser, so that parsing failures of `p` return a failure with message “expected <var>name</var>”.
|
62
|
+
|
63
|
+
* `repeat(p)` tries to apply `p` as many times as possible, and never fails.
|
64
|
+
|
65
|
+
* `seq(p1, p2, …)` tries to apply the given parsers in sequence.
|
66
|
+
|
67
|
+
* `succeed` always succeeds, without advancing the position.
|
68
|
+
|
69
|
+
Special modifiers:
|
70
|
+
|
71
|
+
* `lazy { p }` references the parser `p`, which might not be defined yet. This is useful for recursive definitions.
|
72
|
+
|
73
|
+
* `p.capture` sets the data of the parsing result of `p`, if successful, to the data between the start and the end of the match.
|
74
|
+
|
75
|
+
* `p.ignore` sets the data of the parsing result of `p`, if successful, to `nil`. This is particularly useful in combination with `p.compact`.
|
76
|
+
|
77
|
+
* `p.map { |data| … }` sets the data of the parsing result of `p`, if successful, to the return value of the block. The block gets the data of the success as an argument.
|
78
|
+
|
79
|
+
* `p.first` sets the data of the parsing result of `p`, if successful, to the first element of the data of the success. This only works if the success data is an array.
|
80
|
+
|
81
|
+
* `p.second` sets the data of the parsing result of `p`, if successful, to the second element of the data of the success. This only works if the success data is an array.
|
82
|
+
|
83
|
+
* `p.select_odd` sets the data of the parsing result of `p`, if successful, to each odd element of the data of the success. This only works if the success data is an array.
|
84
|
+
|
85
|
+
* `p.select_even` sets the data of the parsing result of `p`, if successful, to each even element of the data of the success. This only works if the success data is an array.
|
86
|
+
|
87
|
+
* `p.compact` sets the data of the parsing result of `p`, if successful, to each non-nil element of the data of the success. This only works if the success data is an array. This is particularly useful in combination with `p.ignore`.
|
88
|
+
|
89
|
+
## To do
|
90
|
+
|
91
|
+
As mentioned above, this software is in an early state, and still lacks many features. It is not yet a fully functional parser combinator library, but it’ll hopefully get there.
|
92
|
+
|
93
|
+
* Add more combinators (e.g. `repeat1`).
|
94
|
+
|
95
|
+
* Add support for backtracking, so that `seq(repeat(any), string('donkey'))` can parse `superdonkey`.
|
96
|
+
|
97
|
+
* Add failure descriptions to all parsers.
|
98
|
+
|
99
|
+
* Allow renaming failures, so that errors can be easier to understand for hoominz.
|
100
|
+
|
101
|
+
* Add tests for everything.
|
102
|
+
|
103
|
+
* Add documentation.
|
104
|
+
|
105
|
+
* Add support for parsing generic token streams, rather than just characters.
|
106
|
+
|
107
|
+
## Commit message conventions
|
108
|
+
|
109
|
+
As an experiment, I’m going to use commit message conventions slightly adapted from [Angular.js](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md)’s.
|
110
|
+
|
111
|
+
```
|
112
|
+
<type>(<scope>): <subject>
|
113
|
+
<BLANK LINE>
|
114
|
+
<body>
|
115
|
+
```
|
116
|
+
|
117
|
+
The following types are supported:
|
118
|
+
|
119
|
+
* `feat` (new feature)
|
120
|
+
* `fix` (bug fix)
|
121
|
+
* `docs` (documentation)
|
122
|
+
* `style` (formatting, …)
|
123
|
+
* `refactor`
|
124
|
+
* `test` (adding tests)
|
125
|
+
* `chore` (maintenance, such as build infrastructure changes)
|
126
|
+
|
127
|
+
The following scopes are supported:
|
128
|
+
|
129
|
+
* `core`
|
130
|
+
* `parsers`
|
131
|
+
* `samples`
|
132
|
+
|
133
|
+
The following rules apply to the subject:
|
134
|
+
|
135
|
+
* Use the imperative, present tense.
|
136
|
+
* Do not capitalize the first letter.
|
137
|
+
* Do not end the subject with a period.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'rubocop/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
5
|
+
t.rspec_opts = '-r ./spec/spec_helper.rb --color'
|
6
|
+
t.verbose = false
|
7
|
+
end
|
8
|
+
|
9
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
10
|
+
task.options = %w(--display-cop-names --format simple)
|
11
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
task default: [:spec, :rubocop]
|
data/d-parse.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'lib/d-parse/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'd-parse'
|
5
|
+
s.version = DParse::VERSION
|
6
|
+
s.homepage = 'http://rubygems.org/gems/d-parse'
|
7
|
+
s.summary = 'parser combinator library'
|
8
|
+
s.description = 'D★Parse is a library for building parser combinators.'
|
9
|
+
|
10
|
+
s.author = 'Denis Defreyne'
|
11
|
+
s.email = 'denis.defreyne@stoneship.org'
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.files =
|
15
|
+
Dir['[A-Z]*'] +
|
16
|
+
Dir['{lib,spec,samples}/**/*'] +
|
17
|
+
['d-parse.gemspec']
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.rdoc_options = ['--main', 'README.md']
|
21
|
+
s.extra_rdoc_files = ['LICENSE', 'README.md', 'NEWS.md']
|
22
|
+
|
23
|
+
s.required_ruby_version = '>= 2.1.0'
|
24
|
+
|
25
|
+
s.add_development_dependency('bundler', '>= 1.11.2', '< 2.0')
|
26
|
+
end
|
data/lib/d-parse.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module DParse
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative 'd-parse/version.rb'
|
5
|
+
require_relative 'd-parse/position.rb'
|
6
|
+
require_relative 'd-parse/success.rb'
|
7
|
+
require_relative 'd-parse/failure.rb'
|
8
|
+
require_relative 'd-parse/parser.rb'
|
9
|
+
require_relative 'd-parse/parsers.rb'
|
10
|
+
require_relative 'd-parse/dsl.rb'
|
data/lib/d-parse/dsl.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module DParse
|
2
|
+
module DSL
|
3
|
+
def alt(*ps)
|
4
|
+
DParse::Parsers::Alt.new(*ps)
|
5
|
+
end
|
6
|
+
|
7
|
+
def char(c)
|
8
|
+
DParse::Parsers::Char.new(c)
|
9
|
+
end
|
10
|
+
|
11
|
+
def char_in(cs)
|
12
|
+
DParse::Parsers::CharIn.new(cs)
|
13
|
+
end
|
14
|
+
|
15
|
+
def char_not(c)
|
16
|
+
DParse::Parsers::CharNot.new(c)
|
17
|
+
end
|
18
|
+
|
19
|
+
def char_not_in(cs)
|
20
|
+
DParse::Parsers::CharNotIn.new(cs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def eof
|
24
|
+
DParse::Parsers::EOF.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def intersperse(a, b)
|
28
|
+
DParse::Parsers::Intersperse.new(a, b)
|
29
|
+
end
|
30
|
+
|
31
|
+
def except(a, b)
|
32
|
+
DParse::Parsers::Except.new(a, b)
|
33
|
+
end
|
34
|
+
|
35
|
+
def lazy(&block)
|
36
|
+
DParse::Parsers::Lazy.new(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def opt(p)
|
40
|
+
DParse::Parsers::Opt.new(p)
|
41
|
+
end
|
42
|
+
|
43
|
+
def describe(p, name)
|
44
|
+
DParse::Parsers::Describe.new(p, name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def repeat(p)
|
48
|
+
DParse::Parsers::Repeat.new(p)
|
49
|
+
end
|
50
|
+
|
51
|
+
def seq(*ps)
|
52
|
+
DParse::Parsers::Seq.new(*ps)
|
53
|
+
end
|
54
|
+
|
55
|
+
def string(s)
|
56
|
+
DParse::Parsers::String.new(s)
|
57
|
+
end
|
58
|
+
|
59
|
+
def fail
|
60
|
+
DParse::Parsers::Fail.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def succeed
|
64
|
+
DParse::Parsers::Succeed.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def whitespace_char
|
68
|
+
DParse::Parsers::WhitespaceChar.new
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DParse
|
2
|
+
class Failure
|
3
|
+
attr_reader :input
|
4
|
+
attr_reader :pos
|
5
|
+
attr_reader :origin
|
6
|
+
|
7
|
+
def initialize(input, pos, origin: nil)
|
8
|
+
@input = input
|
9
|
+
@pos = pos
|
10
|
+
@origin = origin
|
11
|
+
end
|
12
|
+
|
13
|
+
def map
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
@_message ||= 'expected ' + (@origin ? @origin.expectation_message : '?')
|
19
|
+
end
|
20
|
+
|
21
|
+
def full_message
|
22
|
+
"#{message} at line #{@pos.line + 1}, column #{@pos.column + 1}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def pretty_message
|
26
|
+
line = (input.lines[@pos.line] || '').rstrip
|
27
|
+
fancy_line = line.chars.map.with_index { |c, i| i == @pos.column ? "\e[31m" + c + "\e[0m" : c }.join
|
28
|
+
|
29
|
+
lines = [full_message, '', fancy_line, "\e[31m" + ' ' * @pos.column + '↑' + "\e[0m"]
|
30
|
+
|
31
|
+
lines.join("\n")
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
"Failure(#{@pos}; #{message})"
|
36
|
+
end
|
37
|
+
|
38
|
+
def success?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|