parslet 1.3.0 → 1.4.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.
Files changed (48) hide show
  1. data/HISTORY.txt +38 -1
  2. data/README +33 -21
  3. data/example/deepest_errors.rb +131 -0
  4. data/example/email_parser.rb +2 -6
  5. data/example/ignore.rb +2 -2
  6. data/example/json.rb +0 -3
  7. data/example/modularity.rb +47 -0
  8. data/example/nested_errors.rb +132 -0
  9. data/example/output/deepest_errors.out +54 -0
  10. data/example/output/modularity.out +0 -0
  11. data/example/output/nested_errors.out +54 -0
  12. data/lib/parslet.rb +65 -51
  13. data/lib/parslet/atoms.rb +1 -1
  14. data/lib/parslet/atoms/alternative.rb +11 -12
  15. data/lib/parslet/atoms/base.rb +57 -99
  16. data/lib/parslet/atoms/can_flatten.rb +9 -4
  17. data/lib/parslet/atoms/context.rb +26 -4
  18. data/lib/parslet/atoms/entity.rb +5 -10
  19. data/lib/parslet/atoms/lookahead.rb +11 -7
  20. data/lib/parslet/atoms/named.rb +8 -12
  21. data/lib/parslet/atoms/re.rb +10 -9
  22. data/lib/parslet/atoms/repetition.rb +23 -24
  23. data/lib/parslet/atoms/sequence.rb +10 -16
  24. data/lib/parslet/atoms/str.rb +11 -13
  25. data/lib/parslet/cause.rb +45 -13
  26. data/lib/parslet/convenience.rb +6 -6
  27. data/lib/parslet/error_reporter.rb +7 -0
  28. data/lib/parslet/error_reporter/deepest.rb +95 -0
  29. data/lib/parslet/error_reporter/tree.rb +57 -0
  30. data/lib/parslet/export.rb +4 -4
  31. data/lib/parslet/expression.rb +0 -2
  32. data/lib/parslet/expression/treetop.rb +2 -2
  33. data/lib/parslet/parser.rb +2 -6
  34. data/lib/parslet/pattern.rb +15 -4
  35. data/lib/parslet/pattern/binding.rb +3 -3
  36. data/lib/parslet/rig/rspec.rb +2 -2
  37. data/lib/parslet/slice.rb +0 -6
  38. data/lib/parslet/source.rb +40 -59
  39. data/lib/parslet/source/line_cache.rb +2 -2
  40. data/lib/parslet/transform.rb +13 -7
  41. data/lib/parslet/transform/context.rb +1 -1
  42. metadata +69 -26
  43. data/example/ignore_whitespace.rb +0 -66
  44. data/lib/parslet/bytecode.rb +0 -6
  45. data/lib/parslet/bytecode/compiler.rb +0 -138
  46. data/lib/parslet/bytecode/instructions.rb +0 -358
  47. data/lib/parslet/bytecode/vm.rb +0 -209
  48. data/lib/parslet/error_tree.rb +0 -50
@@ -3,7 +3,7 @@
3
3
  class Parslet::Source
4
4
  # A cache for line start positions.
5
5
  #
6
- class LineCache # :nodoc:
6
+ class LineCache
7
7
  def initialize
8
8
  # Stores line endings as a simple position number. The first line always
9
9
  # starts at 0; numbers beyond the biggest entry are on any line > size,
@@ -59,7 +59,7 @@ class Parslet::Source
59
59
  # [10, 20, 30]
60
60
  # # would describe [0, 10], (10, 20], (20, 30]
61
61
  #
62
- module RangeSearch # :nodoc:
62
+ module RangeSearch
63
63
  def find_mid(left, right)
64
64
  # NOTE: Jonathan Hinkle reported that when mathn is required, just
65
65
  # dividing and relying on the integer truncation is not enough.
@@ -131,12 +131,12 @@ class Parslet::Transform
131
131
 
132
132
  # Allows accessing the class' rules
133
133
  #
134
- def rules # :nodoc:
134
+ def rules
135
135
  @__transform_rules || []
136
136
  end
137
137
  end
138
138
 
139
- def initialize(&block) # :nodoc:
139
+ def initialize(&block)
140
140
  @rules = []
141
141
 
142
142
  if block
@@ -183,7 +183,6 @@ class Parslet::Transform
183
183
  # arity 1 variant of the block. Alternatively, you can inject a context object
184
184
  # and call methods on it (think :ctx => self).
185
185
  #
186
- # Example:
187
186
  # # the local variable a is simulated
188
187
  # t.call_on_match(:a => :b) { a }
189
188
  # # no change of environment here
@@ -203,11 +202,13 @@ class Parslet::Transform
203
202
  # Allow easy access to all rules, the ones defined in the instance and the
204
203
  # ones predefined in a subclass definition.
205
204
  #
206
- def rules # :nodoc:
205
+ def rules
207
206
  self.class.rules + @rules
208
207
  end
209
208
 
210
- def transform_elt(elt, context) # :nodoc:
209
+ # @api private
210
+ #
211
+ def transform_elt(elt, context)
211
212
  rules.each do |pattern, block|
212
213
  if bindings=pattern.match(elt, context)
213
214
  # Produces transformed value
@@ -218,13 +219,18 @@ class Parslet::Transform
218
219
  # No rule matched - element is not transformed
219
220
  return elt
220
221
  end
221
- def recurse_hash(hsh, ctx) # :nodoc:
222
+
223
+ # @api private
224
+ #
225
+ def recurse_hash(hsh, ctx)
222
226
  hsh.inject({}) do |new_hsh, (k,v)|
223
227
  new_hsh[k] = apply(v, ctx)
224
228
  new_hsh
225
229
  end
226
230
  end
227
- def recurse_array(ary, ctx) # :nodoc:
231
+ # @api private
232
+ #
233
+ def recurse_array(ary, ctx)
228
234
  ary.map { |elt| apply(elt, ctx) }
229
235
  end
230
236
  end
@@ -10,7 +10,7 @@ require 'blankslate'
10
10
  # a # => :b
11
11
  # end
12
12
  #
13
- class Parslet::Transform::Context < BlankSlate # :nodoc:
13
+ class Parslet::Transform::Context < BlankSlate
14
14
  reveal :methods
15
15
  reveal :respond_to?
16
16
  reveal :inspect
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parslet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-05 00:00:00.000000000 Z
12
+ date: 2012-05-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: blankslate
16
- requirement: &70331801365680 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '2.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70331801365680
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rspec
27
- requirement: &70331801365040 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70331801365040
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: flexmock
38
- requirement: &70331802115280 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70331802115280
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rdoc
49
- requirement: &70331802114800 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70331802114800
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: sdoc
60
- requirement: &70331802114300 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70331802114300
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: guard
71
- requirement: &70331802113400 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,10 +101,15 @@ dependencies:
76
101
  version: '0'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70331802113400
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: guard-rspec
82
- requirement: &70331802112700 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
115
  - - ! '>='
@@ -87,10 +117,15 @@ dependencies:
87
117
  version: '0'
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70331802112700
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: growl
93
- requirement: &70331802112180 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
131
  - - ! '>='
@@ -98,7 +133,12 @@ dependencies:
98
133
  version: '0'
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70331802112180
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
102
142
  description:
103
143
  email: kaspar.schiess@absurd.li
104
144
  executables: []
@@ -124,13 +164,11 @@ files:
124
164
  - lib/parslet/atoms/str.rb
125
165
  - lib/parslet/atoms/visitor.rb
126
166
  - lib/parslet/atoms.rb
127
- - lib/parslet/bytecode/compiler.rb
128
- - lib/parslet/bytecode/instructions.rb
129
- - lib/parslet/bytecode/vm.rb
130
- - lib/parslet/bytecode.rb
131
167
  - lib/parslet/cause.rb
132
168
  - lib/parslet/convenience.rb
133
- - lib/parslet/error_tree.rb
169
+ - lib/parslet/error_reporter/deepest.rb
170
+ - lib/parslet/error_reporter/tree.rb
171
+ - lib/parslet/error_reporter.rb
134
172
  - lib/parslet/export.rb
135
173
  - lib/parslet/expression/treetop.rb
136
174
  - lib/parslet/expression.rb
@@ -146,19 +184,22 @@ files:
146
184
  - lib/parslet.rb
147
185
  - example/boolean_algebra.rb
148
186
  - example/comments.rb
187
+ - example/deepest_errors.rb
149
188
  - example/documentation.rb
150
189
  - example/email_parser.rb
151
190
  - example/empty.rb
152
191
  - example/erb.rb
153
192
  - example/ignore.rb
154
- - example/ignore_whitespace.rb
155
193
  - example/ip_address.rb
156
194
  - example/json.rb
157
195
  - example/local.rb
158
196
  - example/mathn.rb
159
197
  - example/minilisp.rb
198
+ - example/modularity.rb
199
+ - example/nested_errors.rb
160
200
  - example/output/boolean_algebra.out
161
201
  - example/output/comments.out
202
+ - example/output/deepest_errors.out
162
203
  - example/output/documentation.err
163
204
  - example/output/documentation.out
164
205
  - example/output/email_parser.out
@@ -171,6 +212,8 @@ files:
171
212
  - example/output/local.out
172
213
  - example/output/mathn.out
173
214
  - example/output/minilisp.out
215
+ - example/output/modularity.out
216
+ - example/output/nested_errors.out
174
217
  - example/output/parens.out
175
218
  - example/output/readme.out
176
219
  - example/output/seasons.out
@@ -201,7 +244,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
244
  version: '0'
202
245
  segments:
203
246
  - 0
204
- hash: 3769329244908936169
247
+ hash: 1524575203779308108
205
248
  required_rubygems_version: !ruby/object:Gem::Requirement
206
249
  none: false
207
250
  requirements:
@@ -210,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
253
  version: '0'
211
254
  requirements: []
212
255
  rubyforge_project:
213
- rubygems_version: 1.8.16
256
+ rubygems_version: 1.8.24
214
257
  signing_key:
215
258
  specification_version: 3
216
259
  summary: Parser construction library with great error reporting in Ruby.
@@ -1,66 +0,0 @@
1
- # An example on how to ignore whitespace. Use the composition, luke.
2
-
3
- $:.unshift File.dirname(__FILE__) + "/../lib"
4
-
5
- require 'pp'
6
- require 'parslet'
7
- require 'parslet/convenience'
8
-
9
- class AParser < Parslet::Parser
10
- root :as
11
-
12
- rule(:as) { a.repeat }
13
- rule(:a) { str('a').as(:a) }
14
- end
15
-
16
- class WsIgnoreSource
17
- def initialize(string)
18
- @io = StringIO.new(string)
19
- @early_eof = nil
20
- end
21
-
22
- def pos
23
- @io.pos
24
- end
25
-
26
- def pos=(n)
27
- @io.pos = n
28
- end
29
-
30
- def gets(buf, n)
31
- return nil if eof?
32
-
33
- return read(n).tap {
34
- @early_eof = pos unless can_read?
35
- }
36
- end
37
-
38
- def eof?
39
- @io.eof? || # the underlying source is EOF
40
- @early_eof && pos >= @early_eof # we have no non-ws chars left
41
- end
42
-
43
- private
44
-
45
- # Reads n chars from @io.
46
- def read(n)
47
- b = ''
48
- while b.size < n && !@io.eof?
49
- c = @io.gets(nil, 1)
50
- b << c unless c == ' '
51
- end
52
- b
53
- end
54
-
55
- # True if there are any chars left in @io.
56
- def can_read?
57
- old_pos = @io.pos
58
- read(1).size == 1
59
- rescue => ex
60
- return false
61
- ensure
62
- @io.pos = old_pos
63
- end
64
- end
65
-
66
- pp AParser.new.parse_with_debug(WsIgnoreSource.new('a a a a '))
@@ -1,6 +0,0 @@
1
- module Parslet::Bytecode
2
- end
3
-
4
- require 'parslet/bytecode/instructions'
5
- require 'parslet/bytecode/compiler'
6
- require 'parslet/bytecode/vm'
@@ -1,138 +0,0 @@
1
- require 'parslet/atoms/visitor'
2
-
3
- module Parslet::Bytecode
4
- class Compiler
5
- def initialize
6
- @buffer = []
7
- @blocks = Hash.new
8
- end
9
-
10
- class Address
11
- attr_reader :address
12
- def initialize(address=nil)
13
- @address = address
14
- end
15
- def resolve(vm)
16
- @address = vm.buffer_pointer
17
- end
18
- def inspect
19
- "@#{@address}"
20
- end
21
- def to_s
22
- "@#{address}"
23
- end
24
- end
25
- class Block
26
- def initialize(name, block, compiler)
27
- @name = name
28
- @block = block
29
- @compiler = compiler
30
- end
31
- def address
32
- return @address if @address
33
-
34
- # Actual compilation:
35
-
36
- # TODO raise not implemented if the block returns nil (see Entity)
37
- @address = @compiler.current_address
38
- atom.accept(@compiler)
39
- @compiler.add Return.new
40
-
41
- return @address
42
- end
43
- def atom
44
- @atom ||= @block.call
45
- end
46
- end
47
-
48
- def compile(atom)
49
- atom.accept(self)
50
- add Stop.new
51
- @buffer
52
- end
53
- def add(instruction)
54
- @buffer << instruction
55
- end
56
-
57
- def fwd_address
58
- Address.new
59
- end
60
- def current_address
61
- Address.new(buffer_pointer)
62
- end
63
- def buffer_pointer
64
- @buffer.size
65
- end
66
-
67
- def visit_str(str)
68
- add Match.new(str)
69
- end
70
- def visit_re(match)
71
- add Re.new(match, 1)
72
- end
73
- def visit_sequence(parslets)
74
- emit_block do
75
- sequence = Parslet::Atoms::Sequence.new(*parslets)
76
- error_msg = "Failed to match sequence (#{sequence.inspect})"
77
-
78
- end_adr = fwd_address
79
- parslets.each_with_index do |atom, idx|
80
- atom.accept(self)
81
- add CheckSequence.new(idx, end_adr, error_msg)
82
- end
83
-
84
- add PackSequence.new(parslets.size)
85
-
86
- end_adr.resolve(self)
87
- end
88
- end
89
- def visit_alternative(alternatives)
90
- emit_block do
91
- adr_end = fwd_address
92
-
93
- add EnterFrame.new
94
- add PushPos.new
95
- alternatives.each_with_index do |alternative, idx|
96
- alternative.accept(self)
97
- add BranchOnSuccess.new(adr_end, idx)
98
- end
99
- add Fail.new(["Expected one of ", alternatives.inspect], alternatives.size)
100
-
101
- adr_end.resolve(self)
102
- end
103
- end
104
- def visit_repetition(tag, min, max, parslet)
105
- add SetupRepeat.new(tag)
106
- start = current_address
107
- parslet.accept(self)
108
- add Repeat.new(min, max, start, parslet)
109
- end
110
- def visit_named(name, parslet)
111
- parslet.accept(self)
112
- add Box.new(name)
113
- end
114
- def visit_lookahead(positive, parslet)
115
- add PushPos.new
116
- parslet.accept(self)
117
- add CheckAndReset.new(positive, parslet)
118
- end
119
- def visit_entity(name, block)
120
- @blocks[name] ||= Block.new(name, block, self)
121
- add CallBlock.new(@blocks[name])
122
- end
123
- def visit_parser(root)
124
- root.accept(self)
125
- end
126
-
127
- def emit_block
128
- end_adr = fwd_address
129
- cache_adr = current_address
130
- add CheckCache.new(end_adr)
131
-
132
- yield
133
-
134
- add StoreResult.new(cache_adr)
135
- end_adr.resolve(self)
136
- end
137
- end
138
- end