cljdotrb 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 ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,48 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ .DS_Store
31
+
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+
41
+ # For vim:
42
+ #*.swp
43
+
44
+ # For redcar:
45
+ #.redcar
46
+
47
+ # For rubinius:
48
+ #*.rbc
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.2@cljdotrb
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cljdotrb (0.0.1)
5
+ citrus
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ citrus (2.4.1)
11
+ coderay (0.9.8)
12
+ diff-lcs (1.1.3)
13
+ guard (0.8.8)
14
+ thor (~> 0.14.6)
15
+ guard-rspec (0.5.8)
16
+ guard (>= 0.8.4)
17
+ method_source (0.6.7)
18
+ ruby_parser (>= 2.3.1)
19
+ multi_json (1.0.3)
20
+ pry (0.9.7.4)
21
+ coderay (~> 0.9.8)
22
+ method_source (~> 0.6.7)
23
+ ruby_parser (>= 2.3.1)
24
+ slop (~> 2.1.0)
25
+ rspec (2.7.0)
26
+ rspec-core (~> 2.7.0)
27
+ rspec-expectations (~> 2.7.0)
28
+ rspec-mocks (~> 2.7.0)
29
+ rspec-core (2.7.1)
30
+ rspec-expectations (2.7.0)
31
+ diff-lcs (~> 1.1.2)
32
+ rspec-mocks (2.7.0)
33
+ ruby_parser (2.3.1)
34
+ sexp_processor (~> 3.0)
35
+ sexp_processor (3.0.8)
36
+ simplecov (0.5.4)
37
+ multi_json (~> 1.0.3)
38
+ simplecov-html (~> 0.5.3)
39
+ simplecov-html (0.5.3)
40
+ slop (2.1.0)
41
+ thor (0.14.6)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ cljdotrb!
48
+ guard-rspec
49
+ pry
50
+ rspec
51
+ simplecov
data/README.markdown ADDED
@@ -0,0 +1,13 @@
1
+ # clj.rb
2
+
3
+ A [Clojure](http://clojure.org) data reader and supporting classes for Ruby
4
+
5
+ ## Usage
6
+
7
+ Don't. Yet.
8
+
9
+
10
+ ## Copyright
11
+
12
+ Copyright (c) 2012 fogus. License info forthcoming.
13
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require "rspec/core/rake_task"
4
+ require 'rake'
5
+
6
+ desc "Run all specs"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.pattern = "spec/**/*_spec.rb"
9
+ t.ruby_opts = '-Ilib -Ispec -I.'
10
+ t.rspec_opts = '--color'
11
+ end
12
+
13
+ task :default => :spec
data/cljdotrb.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cljdotrb/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cljdotrb"
7
+ s.version = Clojure::VERSION
8
+ s.authors = ["Michael Fogus", "Alex Redington"]
9
+ s.email = ["fogus@thinkrelevance.com", "alex.redington@thinkrelevance.com"]
10
+ s.homepage = "http://github.com/fogus/clj.rb"
11
+ s.summary = %q{A reader for Clojure strings.}
12
+ s.description = %q{clj.rb parses Clojure data into its Ruby equivalents.}
13
+
14
+ s.rubyforge_project = "clj.rb"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency 'pry'
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'guard-rspec'
25
+ s.add_development_dependency 'simplecov'
26
+ s.add_runtime_dependency 'citrus'
27
+ end
data/lib/cljdotrb.rb ADDED
@@ -0,0 +1,156 @@
1
+ require 'cljdotrb/number'
2
+ require 'cljdotrb/collections'
3
+ require 'cljdotrb/boolean'
4
+ require 'cljdotrb/nil'
5
+ require 'cljdotrb/symbolic'
6
+ require 'cljdotrb/string'
7
+ require 'cljdotrb/reader'
8
+
9
+ module Metadata
10
+ def meta
11
+ @meta
12
+ end
13
+
14
+ def with_meta m
15
+ @meta = m
16
+ self
17
+ end
18
+ end
19
+
20
+ require 'delegate'
21
+
22
+ module Clojure
23
+ module Types
24
+ class Sym < Delegator
25
+ include Metadata
26
+
27
+ def initialize n
28
+ super
29
+ @name = n
30
+ end
31
+
32
+ def __getobj__
33
+ @name
34
+ end
35
+
36
+ def __setobj__ obj
37
+ @name = obj
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ require 'strscan'
44
+ require 'str_parse'
45
+
46
+ module Clojure
47
+ class Parser < StringScanner
48
+ include Clojure::StringParser # parsing unicode strings is dirty business
49
+
50
+ INTEGER = /([-+]?0)|([-+]?[1-9]\d*)(N)?/
51
+ HEX = /([-+]?)0[xX]([0-9A-Fa-f]+)(N)?/
52
+ OCTAL = /([-+]?)0([0-7]+)(N)?/
53
+ RADIX = /([-+]?)([1-9][0-9]?)[rR]([0-9A-Za-z]+)/
54
+ RATIO = /([-+]?[0-9]+)\/([0-9]+)/
55
+ FLOAT = /([-+]?[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?/
56
+ SYMBOLIC = /([:]?)(([\D].*)(\/))?([\D][^\/]*)/
57
+ TRUE = /true/
58
+ FALSE = /false/
59
+ NIL = /nil/
60
+ MAPO = /\{/
61
+ MAPC = /\}/
62
+ VECO = /\[/
63
+ VECC = /\]/
64
+ LISTO = /\(/
65
+ LISTC = /\)/
66
+ SET_START = /#/
67
+ IGNORE = /(?:[ \t\r\n,]+)/mx
68
+
69
+ def initialize src, opts = {}
70
+ opts ||= {}
71
+ super src
72
+
73
+ @int_ctor = opts[:int_ctor] || lambda { |repr, radix| repr.to_i(radix) }
74
+ @bint_ctor = opts[:bint_ctor] || @int_ctor
75
+ @ratio_ctor = opts[:ratio_ctor] || lambda { |n,d| Rational(n.to_i, d.to_i) }
76
+ @float_ctor = opts[:float_ctor] || lambda { |repr| repr.to_f }
77
+ @bigdec_ctor = opts[:bigdec_ctor] || @float_ctor
78
+ @kw_ctor = opts[:kw_ctor] || lambda { |prefix, name| "#{prefix ? prefix + '/' : prefix}#{name}".to_sym }
79
+ @sym_ctor = opts[:sym_ctor] || lambda { |prefix, name| Clojure::Types::Sym.new(@kw_ctor.call(prefix, name)) }
80
+ end
81
+
82
+ def parse_scalar
83
+ case
84
+ when scan(RATIO)
85
+ parse_ratio
86
+ when scan(HEX)
87
+ parse_hex
88
+ when scan(OCTAL)
89
+ parse_octal
90
+ when scan(RADIX)
91
+ parse_radix
92
+ when scan(FLOAT)
93
+ parse_float
94
+ when scan(INTEGER)
95
+ parse_int
96
+ when scan(TRUE)
97
+ true
98
+ when scan(FALSE)
99
+ false
100
+ when scan(NIL)
101
+ nil
102
+ when (str = parse_string) != :no_string
103
+ str
104
+ when scan(SYMBOLIC)
105
+ parse_symbolic
106
+ else
107
+ throw "unparseable"
108
+ end
109
+ end
110
+
111
+ def parse_symbolic
112
+ is_kw = !self[1].empty?
113
+ prefix = self[4] ? self[3] : nil
114
+ name = self[5]
115
+
116
+ if is_kw
117
+ @kw_ctor.call prefix, name
118
+ else
119
+ @sym_ctor.call prefix, name
120
+ end
121
+ end
122
+
123
+ def parse_hex
124
+ ctor = self[3] ? @bint_ctor : @int_ctor
125
+ ctor.call "#{self[1]}" + self[2], 16
126
+ end
127
+
128
+ def parse_octal
129
+ ctor = self[3] ? @bint_ctor : @int_ctor
130
+ ctor.call "#{self[1]}" + self[2], 8
131
+ end
132
+
133
+ def parse_radix
134
+ @int_ctor.call "#{self[1]}" + self[3], self[2].to_i
135
+ end
136
+
137
+ def parse_float
138
+ ctor = self[4] ? @bigdec_ctor : @float_ctor
139
+ ctor.call self[1]
140
+ end
141
+
142
+ def parse_int
143
+ ctor = self[3] ? @bint_ctor : @int_ctor
144
+
145
+ if self[1]
146
+ ctor.call self[1], 10
147
+ else
148
+ ctor.call self[2], 10
149
+ end
150
+ end
151
+
152
+ def parse_ratio
153
+ @ratio_ctor.call self[1], self[2]
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,7 @@
1
+ module Clojure
2
+ module Boolean
3
+ def to_ruby
4
+ to_s == "true"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module Clojure
2
+ module List
3
+ def to_ruby
4
+ captures[:form].map(&:to_ruby)
5
+ end
6
+ end
7
+
8
+ Vector = List
9
+
10
+ module Map
11
+ def to_ruby
12
+ ruby_val = {}
13
+ captures[:form].each_slice(2) do |slice|
14
+ key,value = slice
15
+ ruby_val[key.to_ruby] = value.to_ruby
16
+ end
17
+ ruby_val
18
+ end
19
+ end
20
+
21
+ module Set
22
+ def to_ruby
23
+ ::Set.new(captures[:form].map(&:to_ruby))
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+ module Clojure
2
+ module Nil
3
+ def to_ruby
4
+ nil
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ module Clojure
2
+ module Integer
3
+ def to_ruby
4
+ to_i
5
+ end
6
+ end
7
+
8
+ module HexInteger
9
+ def to_ruby
10
+ to_i 16
11
+ end
12
+ end
13
+
14
+ module OctalInteger
15
+ def to_ruby
16
+ to_i 8
17
+ end
18
+ end
19
+
20
+ module RadixInteger
21
+ def to_ruby
22
+ a = to_a
23
+ (a[1]+a[4]).to_i a[2].to_i
24
+ end
25
+ end
26
+
27
+ module Ratio
28
+ def to_ruby
29
+ a = to_a
30
+ Rational(a[1].to_i, a[3].to_i)
31
+ end
32
+ end
33
+
34
+ module Float
35
+ def to_ruby
36
+ to_f
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,98 @@
1
+ grammar Clojure::Reader
2
+
3
+ rule form
4
+ (collection | literal)
5
+ end
6
+
7
+ rule collection
8
+ (vector | list | map | set)
9
+ end
10
+
11
+ rule set
12
+ ("#" "{" (whitespace* form whitespace*)* "}") <Clojure::Set>
13
+ end
14
+
15
+ rule map
16
+ ("{" (whitespace* form whitespace+ form whitespace*)+ "}") <Clojure::Map>
17
+ end
18
+
19
+ rule list
20
+ ("(" (whitespace* form whitespace*)* ")") <Clojure::List>
21
+ end
22
+
23
+ rule vector
24
+ ("[" (whitespace* form whitespace*)* "]") <Clojure::Vector>
25
+ end
26
+
27
+ rule whitespace
28
+ " "
29
+ end
30
+
31
+ rule literal
32
+ (string | nil | boolean | number | symbolic)
33
+ end
34
+
35
+ rule nil
36
+ "nil" <Clojure::Nil>
37
+ end
38
+
39
+ rule boolean
40
+ ("true" | "false") <Clojure::Boolean>
41
+ end
42
+
43
+ rule number
44
+ rational | integral
45
+ end
46
+
47
+ rule integral
48
+ (radix_integer | octal_integer | hex_integer | integer)
49
+ end
50
+
51
+ rule rational
52
+ (ratio | float)
53
+ end
54
+
55
+ rule string
56
+ ("\"" content:string_content* "\"") <Clojure::String>
57
+ end
58
+
59
+ rule string_content
60
+ (/[^"\\]/ | /\\./)
61
+ end
62
+
63
+ rule symbolic
64
+ (colon:":"? (prefix:symbolic_token sep:"/")? symbol:symbolic_token) <Clojure::Symbolic>
65
+ end
66
+
67
+ rule symbolic_token
68
+ /[a-zA-Z\?\+!_-][a-zA-Z0-9\?\+!_-]*/
69
+ end
70
+
71
+ rule integer
72
+ /([-+]?0)|([-+]?[1-9]\d*)(N)?/ <Clojure::Integer>
73
+ end
74
+
75
+ rule hex_integer
76
+ /([-+]?)0[xX]([0-9A-Fa-f]+)(N)?/ <Clojure::HexInteger>
77
+ end
78
+
79
+ rule octal_integer
80
+ /([-+]?)0([0-7]+)(N)?/ <Clojure::OctalInteger>
81
+ end
82
+
83
+ rule radix_integer
84
+ (sign:/[-+]?/ radix:/[1-9][0-9]?/ delimeter:/[rR]/ number:/[0-9A-Za-z]+/) <Clojure::RadixInteger>
85
+ end
86
+
87
+ rule ratio
88
+ (numerator:/[-+]?[0-9]+/ "/" denominator:/[0-9]+/) <Clojure::Ratio>
89
+ end
90
+
91
+ rule float
92
+ #/([-+]?[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)(M)?/
93
+ ((number:/[-+]?[0-9]+\.[0-9]*(?:[eE][-+]?[0-9]+)?/ marker:"M"?)
94
+ | (number:/[-+]?[0-9]+M/)
95
+ | (number:/[-+]?[0-9][eE][-+]?[0-9]+M?/)) <Clojure::Float>
96
+ end
97
+
98
+ end
@@ -0,0 +1,13 @@
1
+ require 'citrus'
2
+
3
+ module Clojure
4
+ Citrus.load('lib/cljdotrb/reader', :force => true)
5
+ end
6
+
7
+ module Clojure
8
+ module Reader
9
+ def self.read(string)
10
+ parse(string).to_ruby
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module Clojure
2
+ module String
3
+ def to_ruby
4
+ captures[:content].first.gsub(/\\\"/,"\"")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Clojure
2
+
3
+ module Symbolic
4
+ def to_ruby
5
+ captures[:colon].first.empty? ? to_clojure_symbol : to_keyword
6
+ end
7
+
8
+ def to_clojure_symbol
9
+ Clojure::Types::Sym.new to_keyword
10
+ end
11
+
12
+ def to_keyword
13
+ to_a[2..3].reject(&:empty?).join.to_sym
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Clojure
2
+ VERSION = "0.0.1"
3
+ end
data/lib/str_parse.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'iconv'
2
+
3
+ module Clojure
4
+ # Taken from the JSON parser at http://flori.github.com/json/
5
+ module StringParser
6
+ STRING = /" ((?:[^\x0-\x1f"\\] |
7
+ # escaped special characters:
8
+ \\["\\\/bfnrt] |
9
+ \\u[0-9a-fA-F]{4} |
10
+ # match all but escaped special characters:
11
+ \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
12
+ "/nx
13
+
14
+ def parse_string
15
+ if scan(STRING)
16
+ return '' if self[1].empty?
17
+
18
+ string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
19
+ if u = UNESCAPE_MAP[$&[1]]
20
+ u
21
+ else # \uXXXX
22
+ bytes = EMPTY_8BIT_STRING.dup
23
+ i = 0
24
+ while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
25
+ bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
26
+ i += 1
27
+ end
28
+
29
+ Iconv.iconv('utf-8', 'utf-16be', bytes)
30
+ end
31
+ end
32
+
33
+ if string.respond_to?(:force_encoding)
34
+ string.force_encoding(::Encoding::UTF_8)
35
+ end
36
+
37
+ string
38
+ else
39
+ :no_string
40
+ end
41
+ rescue => e
42
+ raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
43
+ end
44
+
45
+ EMPTY_8BIT_STRING = ''
46
+ if ::String.method_defined?(:encode)
47
+ EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
48
+ end
49
+
50
+ UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
51
+ UNESCAPE_MAP.update({
52
+ ?" => '"',
53
+ ?\\ => '\\',
54
+ ?/ => '/',
55
+ ?b => "\b",
56
+ ?f => "\f",
57
+ ?n => "\n",
58
+ ?r => "\r",
59
+ ?t => "\t",
60
+ ?u => nil,
61
+ })
62
+ end
63
+ end
@@ -0,0 +1,133 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. spec_helper.rb])
2
+ require 'pry'
3
+ require 'set'
4
+
5
+ def read(string)
6
+ Clojure::Reader.read(string)
7
+ end
8
+
9
+ describe Clojure::Reader do
10
+ it 'parses positive integers' do
11
+ read("+42").should == 42
12
+ read("-42").should == -42
13
+ read("42").should == 42
14
+ read("-42").should == -42
15
+ read("-0").should == 0
16
+ read("+0").should == 0
17
+ read("-42N").should == -42
18
+ read("42N").should == 42
19
+ read("+42N").should == 42
20
+ end
21
+
22
+ it "should recognize and parse hex integers" do
23
+ read("0xF").should == 15
24
+ read("+0xF").should == 15
25
+ read("-0xF").should == -15
26
+ read("0xFN").should == 15
27
+ read("-0xFN").should == -15
28
+ read("+0xFN").should == 15
29
+ end
30
+
31
+ it "should recognize and parse octal integers" do
32
+ read("07").should == 7
33
+ read("+07").should == 7
34
+ read("-07").should == -7
35
+ read("07N").should == 7
36
+ read("-07N").should == -7
37
+ read("+07N").should == 7
38
+ end
39
+
40
+ it "should recognize and parse radix integers" do
41
+ read("2r111").should == 7
42
+ read("+2r111").should == 7
43
+ read("-2r111").should == -7
44
+ read("32r1").should == 1
45
+ read("27rmj").should == 613
46
+ end
47
+
48
+ it "should recognize and parse ratios" do
49
+ read("22/7").should == Rational(22,7)
50
+ read("+22/7").should == Rational(22,7)
51
+ read("-22/7").should == Rational(-22,7)
52
+ end
53
+
54
+ it "should recognize and parse floating point numbers" do
55
+ read("1.1").should == 1.1
56
+ read("1.1M").should == 1.1
57
+ read("-1.1").should == -1.1
58
+ read("-1.1M").should == -1.1
59
+ read("-1.21e10").should == -12_100_000_000.0
60
+ read("+1.21e10").should == 12_100_000_000.0
61
+ read("-1.21e10M").should == -12_100_000_000.0
62
+ read("+1.21e10M").should == 12_100_000_000.0
63
+ read("1M").should == 1.0
64
+ read("1e4").should == 10_000
65
+ end
66
+
67
+ it "should recognize and parse true and false" do
68
+ read("true").should == true
69
+ read("false").should == false
70
+ end
71
+
72
+ it "should recognize and parse nil" do
73
+ read("nil").should == nil
74
+ end
75
+
76
+ it "should recognize and parse symbols" do
77
+ read("a").should == :a
78
+ read("a").class.should == Clojure::Types::Sym
79
+ read("a/b").should == :"a/b"
80
+ read("a/b").class.should == Clojure::Types::Sym
81
+ read("a").with_meta({:a => 1}).meta.should include(:a => 1)
82
+ read("a").with_meta({:a => 1}).should == :a
83
+ end
84
+
85
+
86
+ it 'parses keywords' do
87
+ read(":keyword").should == :keyword
88
+ end
89
+
90
+ it 'parses vectors of single elements' do
91
+ read("[42]").should == [42]
92
+ end
93
+
94
+ it 'ignores whitespace' do
95
+ read("[ 42 ]").should == [42]
96
+ end
97
+
98
+ it 'parses vectors of multiple elements' do
99
+ read("[42 -1]").should == [42, -1]
100
+ end
101
+
102
+ it 'parses lists' do
103
+ read("(42 -1)").should == [42, -1]
104
+ end
105
+
106
+ it 'parses maps' do
107
+ read("{:a 7 :b 6}").should == {:a => 7, :b => 6}
108
+ end
109
+
110
+ it 'parses sets' do
111
+ read("\#{:a :a :b :c :a :d :b :c :b :a}").should == Set.new([:a, :b, :c, :d])
112
+ end
113
+
114
+ it 'parses nested collections' do
115
+ read("[[1 2] 3 4]").should == [[1, 2], 3, 4]
116
+ end
117
+
118
+ it 'has no problem with maps of vectors' do
119
+ read("{:a [1 2] :b [3 4]}").should == {:a => [1, 2], :b => [3, 4]}
120
+ end
121
+
122
+ it 'reads strings' do
123
+ read('"a string by any other name is just as tangly"').should == 'a string by any other name is just as tangly'
124
+ end
125
+
126
+ it 'reads strings with escaped quotes' do
127
+ read('"a string with an \"escaped quote\""').should == 'a string with an "escaped quote"'
128
+ end
129
+
130
+ it 'preserves other escaped characters' do
131
+ read('"a string with a\nnewline"').should == 'a string with a\nnewline'
132
+ end
133
+ end
@@ -0,0 +1,104 @@
1
+ require 'rspec'
2
+ require 'cljdotrb'
3
+
4
+ describe Metadata do
5
+ class A
6
+ include Metadata
7
+ end
8
+
9
+ it "should store metadata via mixin" do
10
+ a = A.new
11
+
12
+ a.should respond_to :with_meta
13
+
14
+ a.meta.should == nil
15
+ a.with_meta({:a => 1}).meta.should include(:a => 1)
16
+ end
17
+ end
18
+
19
+ def scalarize str
20
+ Clojure::Parser.new(str).parse_scalar
21
+ end
22
+
23
+ describe Clojure::Parser do
24
+ context "when parsing scalar values" do
25
+ it "should recognize and parse integers" do
26
+ scalarize("+42").should == 42
27
+ scalarize("-42").should == -42
28
+ scalarize("42").should == 42
29
+ scalarize("-42").should == -42
30
+ scalarize("-0").should == 0
31
+ scalarize("+0").should == 0
32
+ scalarize("-42N").should == -42
33
+ scalarize("42N").should == 42
34
+ scalarize("+42N").should == 42
35
+ end
36
+
37
+ it "should recognize and parse hex integers" do
38
+ scalarize("0xF").should == 15
39
+ scalarize("+0xF").should == 15
40
+ scalarize("-0xF").should == -15
41
+ scalarize("0xFN").should == 15
42
+ scalarize("-0xFN").should == -15
43
+ scalarize("+0xFN").should == 15
44
+ end
45
+
46
+ it "should recognize and parse octal integers" do
47
+ scalarize("07").should == 7
48
+ scalarize("+07").should == 7
49
+ scalarize("-07").should == -7
50
+ scalarize("07N").should == 7
51
+ scalarize("-07N").should == -7
52
+ scalarize("+07N").should == 7
53
+ end
54
+
55
+ it "should recognize and parse radix integers" do
56
+ scalarize("2r111").should == 7
57
+ scalarize("+2r111").should == 7
58
+ scalarize("-2r111").should == -7
59
+ scalarize("32r1").should == 1
60
+ scalarize("27rmj").should == 613
61
+ end
62
+
63
+ it "should recognize and parse ratios" do
64
+ scalarize("22/7").should == Rational(22,7)
65
+ scalarize("+22/7").should == Rational(22,7)
66
+ scalarize("-22/7").should == Rational(-22,7)
67
+ end
68
+
69
+ it "should recognize and parse floating point numbers" do
70
+ scalarize("1.1").should == 1.1
71
+ scalarize("1.1M").should == 1.1
72
+ scalarize("-1.1").should == -1.1
73
+ scalarize("-1.1M").should == -1.1
74
+ scalarize("-1.21e10").should == -12100000000.0
75
+ scalarize("+1.21e10").should == 12100000000.0
76
+ scalarize("-1.21e10M").should == -12100000000.0
77
+ scalarize("+1.21e10M").should == 12100000000.0
78
+ end
79
+
80
+ it "should recognize and parse true and false" do
81
+ scalarize("true").should == true
82
+ scalarize("false").should == false
83
+ end
84
+
85
+ it "should recognize and parse nil" do
86
+ scalarize("nil").should == nil
87
+ end
88
+
89
+ it "should recognize and parse strings" do
90
+ scalarize('""').should == ""
91
+ scalarize('"this is a string"').should == "this is a string"
92
+ scalarize('"this is \n string"').should == "this is \n string"
93
+ end
94
+
95
+ it "should recognize and parse symbols" do
96
+ scalarize("a").should == :a
97
+ scalarize("a").class.should == Clojure::Types::Sym
98
+ scalarize("a/b").should == :"a/b"
99
+ scalarize("a/b").class.should == Clojure::Types::Sym
100
+ scalarize("a").with_meta({:a => 1}).meta.should include(:a => 1)
101
+ scalarize("a").with_meta({:a => 1}).should == :a
102
+ end
103
+ end
104
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib cljdotrb])
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cljdotrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Fogus
9
+ - Alex Redington
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-06-13 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: pry
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard-rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: simplecov
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: citrus
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ description: clj.rb parses Clojure data into its Ruby equivalents.
96
+ email:
97
+ - fogus@thinkrelevance.com
98
+ - alex.redington@thinkrelevance.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - .document
104
+ - .gitignore
105
+ - .rvmrc
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - README.markdown
109
+ - Rakefile
110
+ - cljdotrb.gemspec
111
+ - lib/cljdotrb.rb
112
+ - lib/cljdotrb/boolean.rb
113
+ - lib/cljdotrb/collections.rb
114
+ - lib/cljdotrb/nil.rb
115
+ - lib/cljdotrb/number.rb
116
+ - lib/cljdotrb/reader.citrus
117
+ - lib/cljdotrb/reader.rb
118
+ - lib/cljdotrb/string.rb
119
+ - lib/cljdotrb/symbolic.rb
120
+ - lib/cljdotrb/version.rb
121
+ - lib/str_parse.rb
122
+ - spec/cljdotrb/reader_spec.rb
123
+ - spec/cljdotrb_spec.rb
124
+ - spec/spec_helper.rb
125
+ homepage: http://github.com/fogus/clj.rb
126
+ licenses: []
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project: clj.rb
145
+ rubygems_version: 1.8.22
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: A reader for Clojure strings.
149
+ test_files:
150
+ - spec/cljdotrb/reader_spec.rb
151
+ - spec/cljdotrb_spec.rb
152
+ - spec/spec_helper.rb