parslet 1.3.0 → 1.4.0

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