sparse 0.0.1 → 0.0.2
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/VERSION +1 -1
- data/lib/sparse/sparse.rb +23 -19
- data/lib/sparse.rb +1 -0
- data/sparse.gemspec +65 -0
- data/spec/complete_code_spec.rb +128 -0
- metadata +11 -10
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/sparse/sparse.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
|
3
1
|
class Sparse
|
4
2
|
def parse(text)
|
5
3
|
@scanner = StringScanner.new(text)
|
@@ -9,6 +7,8 @@ class Sparse
|
|
9
7
|
result = []
|
10
8
|
until @scanner.eos?
|
11
9
|
case
|
10
|
+
when whitespace || comment
|
11
|
+
# do nothing
|
12
12
|
when open_parenthesis
|
13
13
|
result << strip
|
14
14
|
when quote
|
@@ -17,13 +17,10 @@ class Sparse
|
|
17
17
|
blowup 'Expected list'
|
18
18
|
end
|
19
19
|
@scanner.unscan
|
20
|
-
when whitespace || comment
|
21
|
-
#do nothing
|
22
20
|
else
|
23
21
|
blowup
|
24
22
|
end
|
25
23
|
|
26
|
-
# puts "parse rest: ->#{@scanner.rest.bytes.to_a.map{|b| b < 32 ? b : b.chr}}"
|
27
24
|
end
|
28
25
|
|
29
26
|
result
|
@@ -31,11 +28,7 @@ class Sparse
|
|
31
28
|
end
|
32
29
|
|
33
30
|
private
|
34
|
-
def
|
35
|
-
text.size < 10 ? text : "#{text[0..7]}..."
|
36
|
-
end
|
37
|
-
|
38
|
-
def blowup(message = "Unexpected token #{format(@scanner.rest)}")
|
31
|
+
def blowup(message = "Unexpected token #{@scanner.rest}")
|
39
32
|
raise SyntaxError.new "#{message} in position #{@scanner.pos + 1}, line #{@line}, column #{@scanner.pos - @column + 1}"
|
40
33
|
end
|
41
34
|
|
@@ -43,31 +36,34 @@ class Sparse
|
|
43
36
|
current = []
|
44
37
|
until close_parenthesis
|
45
38
|
start_rest = @scanner.rest
|
46
|
-
whitespace
|
47
39
|
|
48
40
|
case
|
49
|
-
when whitespace
|
50
|
-
# nothing
|
41
|
+
when whitespace || comment
|
42
|
+
# do nothing
|
51
43
|
when open_parenthesis
|
52
44
|
current << strip
|
53
45
|
when quote
|
54
46
|
current << :quote
|
55
|
-
unless open_parenthesis || symbol || number
|
56
|
-
p @scanner.rest
|
47
|
+
unless open_parenthesis || symbol || number
|
57
48
|
blowup 'Expected a list, symbol or number'
|
58
49
|
end
|
59
50
|
@scanner.unscan
|
51
|
+
when fn
|
52
|
+
current << :fn
|
53
|
+
unless open_parenthesis
|
54
|
+
blowup 'Expected a list'
|
55
|
+
end
|
56
|
+
@scanner.unscan
|
60
57
|
when symbol
|
61
58
|
sym = @scanner.matched
|
62
59
|
current << (sym == '- ' ? '-' : sym).to_sym
|
60
|
+
when string
|
61
|
+
current << @scanner.matched
|
63
62
|
when number
|
64
63
|
current << eval(@scanner.matched)
|
65
64
|
end
|
66
65
|
|
67
|
-
# puts "strip rest: #{@scanner.rest.bytes.to_a.map{|b| b < 32 ? b : b.chr}}"
|
68
|
-
|
69
66
|
if start_rest == @scanner.rest
|
70
|
-
p @scanner.rest
|
71
67
|
blowup 'Unbalanced brackets'
|
72
68
|
|
73
69
|
end
|
@@ -101,8 +97,12 @@ class Sparse
|
|
101
97
|
@scanner.scan(/[']/)
|
102
98
|
end
|
103
99
|
|
100
|
+
def fn
|
101
|
+
@scanner.scan(/[#]/)
|
102
|
+
end
|
103
|
+
|
104
104
|
def symbol
|
105
|
-
@scanner.scan(/([-][^0-9]|[
|
105
|
+
@scanner.scan(/([-][^0-9]|[&+*\/:]|[a-zA-Z\$][a-zA-Z0-9\-\$]*[?]?)/)
|
106
106
|
end
|
107
107
|
|
108
108
|
def number
|
@@ -113,4 +113,8 @@ class Sparse
|
|
113
113
|
@scanner.scan(/^;.*$/)
|
114
114
|
end
|
115
115
|
|
116
|
+
def string
|
117
|
+
@scanner.scan(/"[^"]*"/)
|
118
|
+
end
|
119
|
+
|
116
120
|
end
|
data/lib/sparse.rb
CHANGED
data/sparse.gemspec
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sparse}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Plinio Balduino"]
|
12
|
+
s.date = %q{2011-07-16}
|
13
|
+
s.description = %q{Fast and light S-Expression parser}
|
14
|
+
s.email = %q{pbalduino+github@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"lib/sparse.rb",
|
29
|
+
"lib/sparse/sparse.rb",
|
30
|
+
"sparse.gemspec",
|
31
|
+
"spec/complete_code_spec.rb",
|
32
|
+
"spec/empty_lists_spec.rb",
|
33
|
+
"spec/invalid_syntax_spec.rb",
|
34
|
+
"spec/nested_lists_spec.rb",
|
35
|
+
"spec/quote_spec.rb",
|
36
|
+
"spec/spec_helper.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/pbalduino/sparse}
|
39
|
+
s.licenses = ["MIT"]
|
40
|
+
s.require_paths = ["lib"]
|
41
|
+
s.rubygems_version = %q{1.5.2}
|
42
|
+
s.summary = %q{Fast and light S-Expression parser}
|
43
|
+
|
44
|
+
if s.respond_to? :specification_version then
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
49
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
50
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
51
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
54
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
56
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
60
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
61
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
62
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
data/spec/complete_code_spec.rb
CHANGED
@@ -145,6 +145,134 @@ lisp
|
|
145
145
|
end
|
146
146
|
|
147
147
|
# http://www.lispworks.com/documentation/lcl50/ug/ug-22.html#HEADING22-0
|
148
|
+
it "copied from lispworks" do
|
149
|
+
code = <<lisp
|
150
|
+
;; Declare the correct package for this application;
|
151
|
+
;; for this example, use the "user" package.
|
152
|
+
(in-package "USER")
|
153
|
+
|
154
|
+
;; Define a default size for the queue.
|
155
|
+
(defconstant default-queue-size 100 "Default size of a queue")
|
156
|
+
|
157
|
+
|
158
|
+
;;; The following structure encapsulates a queue. It contains a
|
159
|
+
;;; simple vector to hold the elements and a pair of pointers to
|
160
|
+
;;; index into the vector. One is a "put pointer" that indicates
|
161
|
+
;;; where the next element is stored into the queue. The other is
|
162
|
+
;;; a "get pointer" that indicates the place from which the next
|
163
|
+
;;; element is retrieved.
|
164
|
+
;;;
|
165
|
+
;;; When put-ptr = get-ptr, the queue is empty.
|
166
|
+
;;; When put-ptr + 1 = get-ptr, the queue is full.
|
167
|
+
(defstruct (queue (:constructor create-queue)
|
168
|
+
(:print-function queue-print-function))
|
169
|
+
(elements #() :type simple-vector)
|
170
|
+
; simple vector of elements
|
171
|
+
(put-ptr 0 :type fixnum) ; next place to put an element
|
172
|
+
(get-ptr 0 :type fixnum) ; next place to take an element
|
173
|
+
)
|
174
|
+
|
175
|
+
|
176
|
+
;; To make QUEUE-NEXT efficient, give the Compiler some hints.
|
177
|
+
(eval-when (compile eval)
|
178
|
+
(proclaim '(inline queue-next))
|
179
|
+
(proclaim '(function queue-next (queue fixnum) fixnum))
|
180
|
+
)
|
181
|
+
|
182
|
+
|
183
|
+
(defun queue-next (queue ptr)
|
184
|
+
"Increment a queue pointer by 1 and wrap around if needed."
|
185
|
+
(let ((length (length (queue-elements queue)))
|
186
|
+
(try (the fixnum (1+ ptr))))
|
187
|
+
(if (eql? try length) 0 try)))
|
188
|
+
|
189
|
+
|
190
|
+
(defun queue-get (queue &optional (default nil))
|
191
|
+
; return DEFAULT if the queue is empty."
|
192
|
+
"Get an element from QUEUE"
|
193
|
+
(check-type queue queue)
|
194
|
+
(let ((get (queue-get-ptr queue))
|
195
|
+
(put (queue-put-ptr queue)))
|
196
|
+
(if (eql? get put)
|
197
|
+
;; Queue is empty.
|
198
|
+
default
|
199
|
+
;; Get the element and update the get-ptr.
|
200
|
+
(prog1
|
201
|
+
(svref (queue-elements queue) get)
|
202
|
+
(setf (queue-get-ptr queue) (queue-next queue get))))))
|
203
|
+
|
204
|
+
|
205
|
+
;; Define a function to put an element into the queue. If the
|
206
|
+
;; queue is already full, QUEUE-PUT returns NIL. If the queue
|
207
|
+
;; isn't full, QUEUE-PUT stores the element and returns T.
|
208
|
+
(defun queue-put (queue element)
|
209
|
+
"Store ELEMENT in the QUEUE and return T on success or NIL on failure."
|
210
|
+
(check-type queue queue)
|
211
|
+
(let* ((get (queue-get-ptr queue))
|
212
|
+
(put (queue-put-ptr queue))
|
213
|
+
(next (queue-next queue put)))
|
214
|
+
(unless (eql? get next)
|
215
|
+
;; store element
|
216
|
+
(setf (svref (queue-elements queue) put) element)
|
217
|
+
(setf (queue-put-ptr queue) next) ; update put-ptr
|
218
|
+
t))) ; indicate success
|
219
|
+
|
220
|
+
|
221
|
+
;; Define a SETF method.
|
222
|
+
(defsetf queue-get queue-put)
|
223
|
+
|
224
|
+
|
225
|
+
(defun queue-print-function (queue stream depth)
|
226
|
+
"This is the function used to print queue structures."
|
227
|
+
(declare (ignore depth))
|
228
|
+
(multiple-value-bind (current-size max-size)
|
229
|
+
(queue-length queue)
|
230
|
+
(format stream "#<Queue ~A/~A ~X>"
|
231
|
+
current-size
|
232
|
+
max-size
|
233
|
+
(liquid pointer queue))))
|
234
|
+
|
235
|
+
|
236
|
+
(defun queue-length (queue)
|
237
|
+
"Returns as two values the number of elements in the queue
|
238
|
+
and the maximum number of elements the queue can hold."
|
239
|
+
(check-type queue queue)
|
240
|
+
(let ((length (length (queue-elements queue)))
|
241
|
+
(delta (the fixnum (- (queue-put-ptr queue)
|
242
|
+
(queue-get-ptr queue)))))
|
243
|
+
(declare (fixnum length delta))
|
244
|
+
;; The maximum number of elements the queue can hold is
|
245
|
+
;; (1- LENGTH) because a queue is empty when put-ptr =
|
246
|
+
;; get-ptr.
|
247
|
+
(values (mod delta length) (the fixnum (1- length)))))
|
248
|
+
|
249
|
+
|
250
|
+
(defun queue-empty-p (queue)
|
251
|
+
"Return T if QUEUE is empty."
|
252
|
+
(check-type queue queue)
|
253
|
+
(eql? (queue-put-ptr queue) (queue-get-ptr queue)))
|
254
|
+
|
255
|
+
|
256
|
+
(defun queue-full-p (queue)
|
257
|
+
"Return T if QUEUE is full."
|
258
|
+
(check-type queue queue)
|
259
|
+
(eql? (queue-get-ptr queue)
|
260
|
+
(queue-next queue (queue-put-ptr queue))))
|
261
|
+
|
262
|
+
|
263
|
+
;; Create a queue. The :ELEMENTS keyword specifies a simple
|
264
|
+
;; vector to hold the elements of the queue. Note that the
|
265
|
+
;; maximum number of elements the queue can hold is one less than
|
266
|
+
;; the length of the vector.
|
267
|
+
(defun make-queue (&key (elements (make-array (1+ default-queue-size))))
|
268
|
+
"Create a queue."
|
269
|
+
(check-type elements simple-vector)
|
270
|
+
(create-queue :elements elements))
|
271
|
+
|
272
|
+
lisp
|
273
|
+
|
274
|
+
@parser.parse code
|
275
|
+
end
|
148
276
|
|
149
277
|
end
|
150
278
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ default_executable:
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
17
|
-
requirement: &
|
17
|
+
requirement: &11262144 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 2.6.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *11262144
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: bundler
|
28
|
-
requirement: &
|
28
|
+
requirement: &11261844 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *11261844
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: jeweler
|
39
|
-
requirement: &
|
39
|
+
requirement: &11261400 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: 1.6.4
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *11261400
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: simplecov
|
50
|
-
requirement: &
|
50
|
+
requirement: &11260932 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *11260932
|
59
59
|
description: Fast and light S-Expression parser
|
60
60
|
email: pbalduino+github@gmail.com
|
61
61
|
executables: []
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- VERSION
|
75
75
|
- lib/sparse.rb
|
76
76
|
- lib/sparse/sparse.rb
|
77
|
+
- sparse.gemspec
|
77
78
|
- spec/complete_code_spec.rb
|
78
79
|
- spec/empty_lists_spec.rb
|
79
80
|
- spec/invalid_syntax_spec.rb
|
@@ -96,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
97
|
version: '0'
|
97
98
|
segments:
|
98
99
|
- 0
|
99
|
-
hash:
|
100
|
+
hash: 503240909
|
100
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
102
|
none: false
|
102
103
|
requirements:
|