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