parslet 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,112 @@
1
+
2
+ require 'stringio'
3
+
4
+ # Wraps the input IO to parslet. The interface defined by this class is
5
+ # smaller than what IO offers, but enhances it with a #column and #line
6
+ # method for the current position.
7
+ #
8
+ class Parslet::Source
9
+ attr_reader :line_ends
10
+
11
+ def initialize(io)
12
+ if io.respond_to? :to_str
13
+ io = StringIO.new(io)
14
+ end
15
+
16
+ @io = io
17
+ warn "Line counting will be off if the IO is not rewound." unless @io.pos==0
18
+
19
+ # Stores line endings as a simple position number. The first line always
20
+ # starts at 0; numbers beyond the biggest entry are on any line > size,
21
+ # but probably make a scan to that position neccessary.
22
+ @line_ends = []
23
+ @line_ends.extend RangeSearch
24
+ @eof_reached_once = false
25
+ end
26
+
27
+ def read(n)
28
+ start_pos = pos
29
+ @io.read(n).tap { |buf| scan_for_line_endings(start_pos, buf) }
30
+ end
31
+
32
+ def eof?
33
+ @io.eof?
34
+ end
35
+
36
+ def pos
37
+ @io.pos
38
+ end
39
+
40
+ # NOTE: If you seek beyond the point that you last read, you will get
41
+ # undefined behaviour. This is by design.
42
+ def pos=(new_pos)
43
+ @io.pos = new_pos
44
+ end
45
+
46
+ def line_and_column(position=nil)
47
+ pos = (position || self.pos)
48
+ eol_idx = @line_ends.lbound(pos)
49
+
50
+ if eol_idx
51
+ # eol_idx points to the offset that ends the current line.
52
+ # Let's try to find the offset that starts it:
53
+ offset = eol_idx>0 && @line_ends[eol_idx-1] || 0
54
+ return [eol_idx+1, pos-offset+1]
55
+ else
56
+ # eol_idx is nil, that means that we're beyond the last line end that
57
+ # we know about. Pretend for now that we're just on the last line.
58
+ offset = @line_ends.last || 0
59
+ return [@line_ends.size+1, pos-offset+1]
60
+ end
61
+ end
62
+
63
+ # Mixin for arrays that implicitly give a number of ranges, where one range
64
+ # begins where the other one ends.
65
+ #
66
+ # Example:
67
+ #
68
+ # [10, 20, 30]
69
+ # # would describe [0, 10], (10, 20], (20, 30]
70
+ #
71
+ module RangeSearch
72
+ # Scans the array for the first number that is > than bound. Returns the
73
+ # index of that number.
74
+ #
75
+ def lbound(bound)
76
+ return nil if empty?
77
+ return nil unless last > bound
78
+
79
+ left = 0
80
+ right = size - 1
81
+
82
+ n = 10
83
+ loop do
84
+ mid = left + (right - left) / 2
85
+
86
+ if self[mid] > bound
87
+ right = mid
88
+ else
89
+ # assert: self[mid] <= bound
90
+ left = mid+1
91
+ end
92
+
93
+ if right <= left
94
+ return right
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def scan_for_line_endings(start_pos, buf)
103
+ # Scan the string for line endings; store the positions of all endings
104
+ # in @line_ends.
105
+ cur = -1
106
+ while buf && cur = buf.index("\n", cur+1)
107
+ @line_ends << (start_pos + cur+1)
108
+ end
109
+
110
+ @eof_reached_once = true
111
+ end
112
+ end
data/lib/parslet.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'stringio'
2
-
3
1
  # A simple parser generator library. Typical usage would look like this:
4
2
  #
5
3
  # require 'parslet'
@@ -229,6 +227,7 @@ module Parslet
229
227
  autoload :Expression, 'parslet/expression'
230
228
  end
231
229
 
230
+ require 'parslet/source'
232
231
  require 'parslet/error_tree'
233
232
  require 'parslet/atoms'
234
233
  require 'parslet/pattern'
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 0
8
7
  - 1
9
- version: 1.0.1
8
+ - 0
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kaspar Schiess
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-17 00:00:00 +01:00
17
+ date: 2011-02-02 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -27,10 +27,8 @@ dependencies:
27
27
  - !ruby/object:Gem::Version
28
28
  segments:
29
29
  - 2
30
- - 1
31
- - 2
32
- - 3
33
- version: 2.1.2.3
30
+ - 0
31
+ version: "2.0"
34
32
  type: :runtime
35
33
  version_requirements: *id001
36
34
  - !ruby/object:Gem::Dependency
@@ -59,6 +57,19 @@ dependencies:
59
57
  version: "0"
60
58
  type: :development
61
59
  version_requirements: *id003
60
+ - !ruby/object:Gem::Dependency
61
+ name: sdoc
62
+ prerelease: false
63
+ requirement: &id004 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :development
72
+ version_requirements: *id004
62
73
  description:
63
74
  email: kaspar.schiess@absurd.li
64
75
  executables: []
@@ -75,6 +86,7 @@ files:
75
86
  - README
76
87
  - lib/parslet/atoms/alternative.rb
77
88
  - lib/parslet/atoms/base.rb
89
+ - lib/parslet/atoms/context.rb
78
90
  - lib/parslet/atoms/entity.rb
79
91
  - lib/parslet/atoms/lookahead.rb
80
92
  - lib/parslet/atoms/named.rb
@@ -82,8 +94,11 @@ files:
82
94
  - lib/parslet/atoms/repetition.rb
83
95
  - lib/parslet/atoms/sequence.rb
84
96
  - lib/parslet/atoms/str.rb
97
+ - lib/parslet/atoms/visitor.rb
85
98
  - lib/parslet/atoms.rb
99
+ - lib/parslet/convenience.rb
86
100
  - lib/parslet/error_tree.rb
101
+ - lib/parslet/export.rb
87
102
  - lib/parslet/expression/treetop.rb
88
103
  - lib/parslet/expression.rb
89
104
  - lib/parslet/parser.rb
@@ -91,11 +106,13 @@ files:
91
106
  - lib/parslet/pattern/context.rb
92
107
  - lib/parslet/pattern.rb
93
108
  - lib/parslet/rig/rspec.rb
109
+ - lib/parslet/source.rb
94
110
  - lib/parslet/transform.rb
95
111
  - lib/parslet.rb
96
112
  - example/documentation.rb
97
113
  - example/email_parser.rb
98
114
  - example/empty.rb
115
+ - example/erb.rb
99
116
  - example/ip_address.rb
100
117
  - example/minilisp.rb
101
118
  - example/parens.rb