sparse 0.0.1
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/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/sparse/sparse.rb +116 -0
- data/lib/sparse.rb +1 -0
- data/spec/complete_code_spec.rb +150 -0
- data/spec/empty_lists_spec.rb +40 -0
- data/spec/invalid_syntax_spec.rb +34 -0
- data/spec/nested_lists_spec.rb +22 -0
- data/spec/quote_spec.rb +46 -0
- data/spec/spec_helper.rb +12 -0
- metadata +112 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.4)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.9.2)
|
11
|
+
rspec (2.6.0)
|
12
|
+
rspec-core (~> 2.6.0)
|
13
|
+
rspec-expectations (~> 2.6.0)
|
14
|
+
rspec-mocks (~> 2.6.0)
|
15
|
+
rspec-core (2.6.4)
|
16
|
+
rspec-expectations (2.6.0)
|
17
|
+
diff-lcs (~> 1.1.2)
|
18
|
+
rspec-mocks (2.6.0)
|
19
|
+
simplecov (0.4.2)
|
20
|
+
simplecov-html (~> 0.4.4)
|
21
|
+
simplecov-html (0.4.5)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
x86-mingw32
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler (~> 1.0.0)
|
28
|
+
jeweler (~> 1.6.4)
|
29
|
+
rspec (~> 2.6.0)
|
30
|
+
simplecov
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Plinio Balduino
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= sparse
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to sparse
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Plinio Balduino. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "sparse"
|
18
|
+
gem.homepage = "http://github.com/pbalduino/sparse"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Fast and light S-Expression parser}
|
21
|
+
gem.description = %Q{Fast and light S-Expression parser}
|
22
|
+
gem.email = "pbalduino+github@gmail.com"
|
23
|
+
gem.authors = ["Plinio Balduino"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "sparse #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
class Sparse
|
4
|
+
def parse(text)
|
5
|
+
@scanner = StringScanner.new(text)
|
6
|
+
@line = 1
|
7
|
+
@column = 1
|
8
|
+
|
9
|
+
result = []
|
10
|
+
until @scanner.eos?
|
11
|
+
case
|
12
|
+
when open_parenthesis
|
13
|
+
result << strip
|
14
|
+
when quote
|
15
|
+
result << :quote
|
16
|
+
unless open_parenthesis
|
17
|
+
blowup 'Expected list'
|
18
|
+
end
|
19
|
+
@scanner.unscan
|
20
|
+
when whitespace || comment
|
21
|
+
#do nothing
|
22
|
+
else
|
23
|
+
blowup
|
24
|
+
end
|
25
|
+
|
26
|
+
# puts "parse rest: ->#{@scanner.rest.bytes.to_a.map{|b| b < 32 ? b : b.chr}}"
|
27
|
+
end
|
28
|
+
|
29
|
+
result
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def format_text(text)
|
35
|
+
text.size < 10 ? text : "#{text[0..7]}..."
|
36
|
+
end
|
37
|
+
|
38
|
+
def blowup(message = "Unexpected token #{format(@scanner.rest)}")
|
39
|
+
raise SyntaxError.new "#{message} in position #{@scanner.pos + 1}, line #{@line}, column #{@scanner.pos - @column + 1}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def strip
|
43
|
+
current = []
|
44
|
+
until close_parenthesis
|
45
|
+
start_rest = @scanner.rest
|
46
|
+
whitespace
|
47
|
+
|
48
|
+
case
|
49
|
+
when whitespace
|
50
|
+
# nothing, as usual
|
51
|
+
when open_parenthesis
|
52
|
+
current << strip
|
53
|
+
when quote
|
54
|
+
current << :quote
|
55
|
+
unless open_parenthesis || symbol || number # || string
|
56
|
+
p @scanner.rest
|
57
|
+
blowup 'Expected a list, symbol or number'
|
58
|
+
end
|
59
|
+
@scanner.unscan
|
60
|
+
when symbol
|
61
|
+
sym = @scanner.matched
|
62
|
+
current << (sym == '- ' ? '-' : sym).to_sym
|
63
|
+
when number
|
64
|
+
current << eval(@scanner.matched)
|
65
|
+
end
|
66
|
+
|
67
|
+
# puts "strip rest: #{@scanner.rest.bytes.to_a.map{|b| b < 32 ? b : b.chr}}"
|
68
|
+
|
69
|
+
if start_rest == @scanner.rest
|
70
|
+
p @scanner.rest
|
71
|
+
blowup 'Unbalanced brackets'
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
current
|
78
|
+
end
|
79
|
+
|
80
|
+
# singular: parenthesis
|
81
|
+
# plural : parentheses
|
82
|
+
def open_parenthesis
|
83
|
+
@scanner.scan(/[(]/)
|
84
|
+
end
|
85
|
+
|
86
|
+
def close_parenthesis
|
87
|
+
@scanner.scan(/[)]/)
|
88
|
+
end
|
89
|
+
|
90
|
+
def whitespace
|
91
|
+
ret = @scanner.scan(/[ \t\n\r]/)
|
92
|
+
if ret == "\n"
|
93
|
+
@line += 1
|
94
|
+
@column = @scanner.pos
|
95
|
+
end
|
96
|
+
|
97
|
+
ret
|
98
|
+
end
|
99
|
+
|
100
|
+
def quote
|
101
|
+
@scanner.scan(/[']/)
|
102
|
+
end
|
103
|
+
|
104
|
+
def symbol
|
105
|
+
@scanner.scan(/([-][^0-9]|[+*\/]|[a-zA-Z\$][a-zA-Z0-9\-\$]*)/)
|
106
|
+
end
|
107
|
+
|
108
|
+
def number
|
109
|
+
@scanner.scan(/[-]?[0-9]+([.][0-9]+)?/)
|
110
|
+
end
|
111
|
+
|
112
|
+
def comment
|
113
|
+
@scanner.scan(/^;.*$/)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
data/lib/sparse.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sparse/sparse'
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sparse do
|
4
|
+
context "Complete source code" do
|
5
|
+
before :each do
|
6
|
+
@parser = Sparse.new
|
7
|
+
end
|
8
|
+
|
9
|
+
# http://www.csc.villanova.edu/~dmatusze/resources/lisp/lisp-example.html
|
10
|
+
it "copied from villanova" do
|
11
|
+
code = <<lisp
|
12
|
+
; Try to apply each rule in turn to the expression. SIMPLIFY picks
|
13
|
+
; up the rules and gives them, along with the expression, to SIMPLIFY-2.
|
14
|
+
; SIMPLIFY-2 picks off one rule and applies it by calling APPLY-RULE,
|
15
|
+
; then recurs with the remaining rules. APPLY-RULE breaks the rule up
|
16
|
+
; into pattern and replacement parts and gives these, along with the
|
17
|
+
; expression, to SUBSTITUTE.
|
18
|
+
|
19
|
+
(defun simplify (expression)
|
20
|
+
(simplify-2 (rules) expression) )
|
21
|
+
|
22
|
+
(defun simplify-2 (rules expression)
|
23
|
+
(cond
|
24
|
+
((null rules) expression)
|
25
|
+
(T (simplify-2 (cdr rules) (apply-rule (car rules) expression))) ) )
|
26
|
+
|
27
|
+
(defun apply-rule (rule expression)
|
28
|
+
(substitute (car rule) (cadr rule) expression) )
|
29
|
+
|
30
|
+
|
31
|
+
; Try to match the pattern to the expression. If it matches, replace
|
32
|
+
; the part matched with the replacement, and return the result.
|
33
|
+
; If the pattern doesn't apply, the result is the original expression.
|
34
|
+
; Example: (substitute '(1 + $) '($ + 1) '(A + 1 + B + C)) returns
|
35
|
+
;(A + B + 1 + C)
|
36
|
+
|
37
|
+
(defun substitute (pattern replacement expression)
|
38
|
+
(cond
|
39
|
+
((null expression) ())
|
40
|
+
((occurs-at-front pattern expression)
|
41
|
+
(substitute-at-front pattern replacement expression) )
|
42
|
+
(T (cons (car expression)
|
43
|
+
(substitute pattern replacement (cdr expression)) )) ) )
|
44
|
+
|
45
|
+
|
46
|
+
; Test whether the pattern occurs at the very front of the expression.
|
47
|
+
; This function uses MATCHES to test individual components of the pattern.
|
48
|
+
; Example: (occurs-at-front '($ + 0) '(A + 0 + B)) returns T
|
49
|
+
|
50
|
+
(defun occurs-at-front (pattern expression)
|
51
|
+
(cond
|
52
|
+
((null pattern) T)
|
53
|
+
((null expression) nil)
|
54
|
+
((matches (car pattern) (car expression))
|
55
|
+
(occurs-at-front (cdr pattern) (cdr expression)) )
|
56
|
+
(T nil) ) )
|
57
|
+
|
58
|
+
|
59
|
+
; Test whether the first component of the pattern matches the
|
60
|
+
; first component of the expression. A match occurs if:
|
61
|
+
; 1. The pattern component is '$
|
62
|
+
; 2. They are identical atoms
|
63
|
+
|
64
|
+
(defun matches (pattern-part expression-part)
|
65
|
+
(cond
|
66
|
+
((eq pattern-part '$) T)
|
67
|
+
(T (eq pattern-part expression-part)) ) )
|
68
|
+
|
69
|
+
|
70
|
+
; This function should be called only when we know that the pattern
|
71
|
+
; matches the front of the expression.
|
72
|
+
; If the pattern contains a $, find and return the corresponding
|
73
|
+
; component (atom or list) of the expression. If the pattern
|
74
|
+
; does not contain a $, return NIL.
|
75
|
+
; (Note: this means you can't replace $ with NIL, but for this
|
76
|
+
; example, using arithmetic expressions, you shouldn't ever want to.)
|
77
|
+
; Example: (get-$-match '(0 + $) '(0 + A + B)) returns A
|
78
|
+
|
79
|
+
(defun get-$-match (pattern expression)
|
80
|
+
(cond
|
81
|
+
((null expression) nil)
|
82
|
+
((eq (car pattern) '$) (car expression))
|
83
|
+
(T (get-$-match (cdr pattern) (cdr expression))) ) )
|
84
|
+
|
85
|
+
|
86
|
+
; In the replacement, substitute the value we found for the $ for
|
87
|
+
; the $ itself. If $-value is NIL, that means the pattern did not
|
88
|
+
; contain a $, and the replacement shouldn't have one, either.
|
89
|
+
; Example: (substitute-in-replacement 'A '($ + 0)) returns (A + 0).
|
90
|
+
|
91
|
+
(defun substitute-in-replacement ($-value replacement)
|
92
|
+
(cond
|
93
|
+
((null $-value) replacement)
|
94
|
+
((null replacement) ())
|
95
|
+
((eq (car replacement) '$) (cons $-value (cdr replacement)))
|
96
|
+
(T (cons (car replacement)
|
97
|
+
(substitute-in-replacement $-value (cdr replacement)) )) ) )
|
98
|
+
|
99
|
+
|
100
|
+
; This function is called when we know the pattern matches the very
|
101
|
+
; first part of the expression. If the pattern contains a $, that
|
102
|
+
; could match anything, and the thing it matches should be put in
|
103
|
+
; place of the $ the replacement. If the pattern does not contain
|
104
|
+
; a $, then the replacement can be used as is.
|
105
|
+
; Example: (substitute-at-front '(0 * $) '(0) '(0 * A + B)) returns (0 + B).
|
106
|
+
|
107
|
+
(defun substitute-at-front (pattern replacement expression)
|
108
|
+
(final-replace
|
109
|
+
pattern
|
110
|
+
(substitute-in-replacement (get-$-match pattern expression) replacement)
|
111
|
+
expression ) )
|
112
|
+
|
113
|
+
|
114
|
+
; This function is called when (1) the pattern has been matched at the
|
115
|
+
; very front of the expression, and (2) the replacement has been suitably
|
116
|
+
; modified. We step through and discard one component of the expression
|
117
|
+
; for every component of the pattern, then append the replacement to
|
118
|
+
; whatever is left of the expression.
|
119
|
+
; Example: (substitute-at-front '($ + 0) '($) '(A + 0 + B)) returns (A + B)
|
120
|
+
|
121
|
+
(defun final-replace (pattern replacement expression)
|
122
|
+
(cond
|
123
|
+
((null pattern) (append replacement expression))
|
124
|
+
(T (final-replace (cdr pattern) replacement (cdr expression))) ) )
|
125
|
+
|
126
|
+
|
127
|
+
; Define the rules
|
128
|
+
|
129
|
+
(defun rules ()
|
130
|
+
'( (($ + 0) ($))
|
131
|
+
((0 + $) ($))
|
132
|
+
((1 * $) ($))
|
133
|
+
((0 * $) (0))
|
134
|
+
(($ * 0) (0))
|
135
|
+
((1 + 1) (2))
|
136
|
+
(($ * 2 * 2) (4 * $)) ) )
|
137
|
+
|
138
|
+
(+ 1 1)(+ 1.1 1)(+ -1 -1)(+ -1 -1.1)
|
139
|
+
(* 1 1)(* 1.1 1)(* -1 -1)(* -1 -1.1)
|
140
|
+
(- 1 1)(- 1.1 1)(- -1 -1)(- -1 -1.1)
|
141
|
+
(/ 1 1)(/ 1.1 1)(/ -1 -1)(/ -1 -1.1)
|
142
|
+
|
143
|
+
lisp
|
144
|
+
@parser.parse code
|
145
|
+
end
|
146
|
+
|
147
|
+
# http://www.lispworks.com/documentation/lcl50/ug/ug-22.html#HEADING22-0
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sparse do
|
4
|
+
context "An empty list" do
|
5
|
+
before :each do
|
6
|
+
@parser = Sparse.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should work with an empty string' do
|
10
|
+
@parser.parse('').should be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'could start with a parenthesis' do
|
14
|
+
@parser.parse('()').should == [[]]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'could start with a parenthesis and contains a space' do
|
18
|
+
@parser.parse('( )').should == [[]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'could start with tab and contains space' do
|
22
|
+
@parser.parse("\t( )").should == [[]]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'could start with space and contains space' do
|
26
|
+
@parser.parse(" ( )").should == [[]]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'could start with linebreak and contains space' do
|
30
|
+
@parser.parse(<<lisp
|
31
|
+
|
32
|
+
( )
|
33
|
+
|
34
|
+
lisp
|
35
|
+
).should == [[]]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sparse do
|
4
|
+
context 'Is an invalid syntax when it' do
|
5
|
+
before :each do
|
6
|
+
@parser = Sparse.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'starts with a number' do
|
10
|
+
lambda {@parser.parse '9'}.should raise_error SyntaxError
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'starts with two quotes' do
|
14
|
+
lambda {@parser.parse "''()"}.should raise_error SyntaxError
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has only a quote' do
|
18
|
+
lambda {@parser.parse "'"}.should raise_error SyntaxError
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has one open bracket and zero close brackets' do
|
22
|
+
lambda {@parser.parse "("}.should raise_error SyntaxError
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'only close brackets' do
|
26
|
+
lambda {@parser.parse ')'}.should raise_error SyntaxError
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has unbalanced number of open and close brackets' do
|
30
|
+
lambda {@parser.parse '(()'}.should raise_error SyntaxError
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sparse do
|
4
|
+
context 'Special use of lists' do
|
5
|
+
before :each do
|
6
|
+
@parser = Sparse.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'like nested lists should just work' do
|
10
|
+
@parser.parse('(())').should == [[[]]]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'like sister lists should just work too' do
|
14
|
+
@parser.parse('()()').should == [[], []]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'like nested sister lists should just work also' do
|
18
|
+
@parser.parse('(()())').should == [[[], []]]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/spec/quote_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sparse do
|
4
|
+
context 'Quotes' do
|
5
|
+
before :each do
|
6
|
+
@parser = Sparse.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should be before a first level list' do
|
10
|
+
@parser.parse("'()").should == [:quote, []]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be before a first level list, in any position' do
|
14
|
+
@parser.parse("()'()").should == [[], :quote, []]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be before a nested list' do
|
18
|
+
@parser.parse("('())").should == [[:quote, []]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be before symbols' do
|
22
|
+
@parser.parse("('a 'b 'c)").should == [[:quote, :a, :quote, :b, :quote, :c]]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should be before symbols with more than one character' do
|
26
|
+
@parser.parse("('abc 'def 'ghi)").should == [[:quote, :abc, :quote, :def, :quote, :ghi]]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be before numbers' do
|
30
|
+
@parser.parse("('1 '2 '3)").should == [[:quote, 1, :quote, 2, :quote, 3]]
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should be before negative numbers' do
|
34
|
+
@parser.parse("('-1 '-2 '-3)").should == [[:quote, -1, :quote, -2, :quote, -3]]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should be before positive and negative decimal numbers' do
|
38
|
+
@parser.parse("('-1.1 '2.2 '3.14159)").should == [[:quote, -1.1, :quote, 2.2, :quote, 3.14159]]
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should be before nested lists' do
|
42
|
+
@parser.parse("(1 2 '(foo))").should == [[1, 2, :quote, [:foo]]]
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'sparse'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sparse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Plinio Balduino
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-16 00:00:00.000000000 -03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: &11380380 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.6.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *11380380
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: &11379948 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *11379948
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: jeweler
|
39
|
+
requirement: &11379612 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.6.4
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *11379612
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: simplecov
|
50
|
+
requirement: &11379216 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *11379216
|
59
|
+
description: Fast and light S-Expression parser
|
60
|
+
email: pbalduino+github@gmail.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files:
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.rdoc
|
66
|
+
files:
|
67
|
+
- .document
|
68
|
+
- .rspec
|
69
|
+
- Gemfile
|
70
|
+
- Gemfile.lock
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.rdoc
|
73
|
+
- Rakefile
|
74
|
+
- VERSION
|
75
|
+
- lib/sparse.rb
|
76
|
+
- lib/sparse/sparse.rb
|
77
|
+
- spec/complete_code_spec.rb
|
78
|
+
- spec/empty_lists_spec.rb
|
79
|
+
- spec/invalid_syntax_spec.rb
|
80
|
+
- spec/nested_lists_spec.rb
|
81
|
+
- spec/quote_spec.rb
|
82
|
+
- spec/spec_helper.rb
|
83
|
+
has_rdoc: true
|
84
|
+
homepage: http://github.com/pbalduino/sparse
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
hash: -540899953
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.5.2
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: Fast and light S-Expression parser
|
112
|
+
test_files: []
|