bracer 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c8b71bbf9c678ae9d2e8a33ccc8dc54bb0a04683
4
+ data.tar.gz: 2d7f04f3b5cf21afefe7a3ea9855f6be80d28ea2
5
+ SHA512:
6
+ metadata.gz: 58bea8f8543d81af5ecb11f3da3d2ca878ef75e99c3126f47bfaf19a129c7ccbe5c434cf52cca2410fa2de1fc005cccb332827c9c711f8bf034d4b8c2a991467
7
+ data.tar.gz: 749658b045ace5f741332ed8ee5d1f127a1db8e9b1e38a885964a5eeeb6b97909b6564825024526373059a9357512b238d990c13280b9b7a8915c9016d7a137d
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Aaron Gough (http://thingsaaronmade.com/)
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,89 @@
1
+ = Sexpistol
2
+
3
+ Sexpistol is a very fast and easy-to-use library for parsing S-Expressions in Ruby. Sexpistol takes an S-Expression in string form and turns it into a native Ruby data structure made up of nested sets of arrays.
4
+
5
+ === Example
6
+
7
+ (define test (lambda () (
8
+ (print "Hello world!\n")
9
+ (print 1)
10
+ (print 9.01)
11
+ (print 2.0e10)
12
+ (print (+ 10 12 13))
13
+ )))
14
+
15
+ would be parsed by Sexpistol like so:
16
+
17
+ [:define, :test, [:lambda, [], [
18
+ [:print, "Hello world!\n"],
19
+ [:print, 1],
20
+ [:print, 9.01],
21
+ [:print, 2.0e10],
22
+ [:print, [:+, 10, 12, 13]]
23
+ ]]]
24
+
25
+ === Type mappings
26
+
27
+ Sexpistol supports all of the standard datatypes and converts them directly to their Ruby equivalents:
28
+
29
+ * Lists (a b c)
30
+ * Integers (1 2 3)
31
+ * Floats (1.0 2.0 42.9 3e6 1.2e2)
32
+ * Strings ("\t\"Hello world!\"\n")
33
+ * Symbols (symbol Symbol ____symbol____ symbo_l symbol? symbol! + - / ++ a+ e$, etc...)
34
+
35
+ Sexpistol also supports mapping the Ruby keyword literals (nil, true, false) to their native Ruby types, although this is disabled by default for compatibility. To enable it use `@parser.ruby_keyword_literals = true`, eg:
36
+
37
+ @parser = Sexpistol.new
38
+ @parser.parse_string("nil false true")
39
+ #=> [:nil, :false, :true]
40
+
41
+ @parser.ruby_keyword_literals = true
42
+ @parser.parse_string("nil false true")
43
+ #=> [nil, false, true]
44
+
45
+ == Scheme compatibility
46
+
47
+ Above all Sexpistol strives to be compatible with Scheme-style S-Expressions. This means that Sexpistol supports comma quoting, though quasi-quoting is not yet implemented. Sexpistol can also generate Scheme compatible external representations when the 'scheme_compatability' options is set to true:
48
+
49
+ @parser = Sexpistol.new
50
+ @parser.scheme_compatability = true
51
+ @parser.to_sexp([:test, false, true, nil])
52
+ #=> "(test #f #t ())"
53
+
54
+ === Installation
55
+
56
+ For convenience Sexpistol is packaged as a RubyGem, to install it simply enter the following at your command line:
57
+
58
+ gem install sexpistol
59
+
60
+ === Usage
61
+
62
+ # Create a new parser instance
63
+ @parser = Sexpistol.new
64
+
65
+ # Parse a string
66
+ ast = @parser.parse_string("(string (to (parse)))")
67
+ #=> [:string, [:to, [:parse]]]
68
+
69
+ # Change the representation
70
+ ast[1][0] = :is
71
+ ast[1][1][0] = :parsed
72
+ #=> [:string, [:is, [:parsed]]]
73
+
74
+ # Turn the array structure back into an S-Expression
75
+ @parser.to_sexp( ast )
76
+ #=> "( string ( is ( parsed ) ) )"
77
+
78
+ === Performance
79
+
80
+ The core of Sexpistol was recently re-written using StringScanner and the new version is roughly twice as fast as the older ones.
81
+
82
+ Parsing throughput on my test machine (2Ghz Core 2 Duo, 4GB RAM, Ruby 1.9) is approximately 1 Megabytes/sec. This is fairly high given that Sexpistol is pure Ruby. Benchmarking Sexpistol against other popular S-Expression parser gems shows that it is roughly 8x faster than the nearest competitor.
83
+
84
+ === Author & Credits
85
+
86
+ Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
87
+ Contributors:: {Shane Hanna}[http://github.com/shanna]
88
+
89
+ Copyright (c) 2010 {Aaron Gough}[http://thingsaaronmade.com/] ({thingsaaronmade.com}[http://thingsaaronmade.com/]), released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ begin
9
+ require 'jeweler'
10
+ Jeweler::Tasks.new do |gemspec|
11
+ gemspec.name = "sexpistol"
12
+ gemspec.summary = "An S-Expression Parser Library for Ruby"
13
+ gemspec.description = "Sexpistol is an easy-to-use S-Expression parser for Ruby. It is fast and has no dependencies."
14
+ gemspec.email = "aaron@aarongough.com"
15
+ gemspec.homepage = "http://github.com/aarongough/sexpistol"
16
+ gemspec.authors = ["Aaron Gough"]
17
+ gemspec.rdoc_options << '--line-numbers' << '--inline-source'
18
+ gemspec.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE']
19
+ end
20
+ rescue LoadError
21
+ puts "Jeweler not available. Install it with: gem install jeweler"
22
+ end
23
+
24
+
25
+ desc 'Test sexpistol.'
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib/*.rb'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = true
31
+ end
32
+
33
+
34
+ desc 'Generate documentation for sexpistol.'
35
+ Rake::RDocTask.new(:rdoc) do |rdoc|
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = 'Koi'
38
+ rdoc.options << '--line-numbers' << '--inline-source'
39
+ rdoc.rdoc_files.include('README.rdoc')
40
+ rdoc.rdoc_files.include('lib/**/*.rb')
41
+ rdoc.rdoc_files.include('app/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.7
data/lib/sexpistol.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'sexpistol', 'sexpistol_parser.rb'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'sexpistol', 'sexpistol.rb'))
@@ -0,0 +1,76 @@
1
+ # This class contains our logic for parsing
2
+ # S-Expressions. They are turned into a
3
+ # native Ruby representation like:
4
+ # [:def, :something [:lambda, [:a], [:do_something]]]
5
+ class Bracer
6
+
7
+ attr_accessor :ruby_keyword_literals, :scheme_compatability
8
+
9
+ # Parse a string containing an S-Expression into a
10
+ # nested set of Ruby arrays
11
+ def parse_string(string)
12
+ tree = BracerParser.new(string).parse
13
+ return convert_ruby_keyword_literals(tree) if(@ruby_keyword_literals)
14
+ return tree
15
+ end
16
+
17
+ # Convert symbols corresponding to Ruby's keyword literals
18
+ # into their literal forms
19
+ def convert_ruby_keyword_literals(expression)
20
+ return recursive_map(expression) do |x|
21
+ case x
22
+ when :'nil' then nil
23
+ when :'true' then true
24
+ when :'false' then false
25
+ else x
26
+ end
27
+ end
28
+ end
29
+
30
+ # Convert nil, true and false into (), #t and #f for compatability
31
+ # with Scheme
32
+ def convert_scheme_literals(data)
33
+ return recursive_map(data) do |x|
34
+ case x
35
+ when nil then []
36
+ when true then :"#t"
37
+ when false then :"#f"
38
+ else x
39
+ end
40
+ end
41
+ end
42
+
43
+ # Convert a set of nested arrays back into an S-Expression
44
+ def to_sexp(data)
45
+ data = convert_scheme_literals(data) if(@scheme_compatability)
46
+ if( data.is_a?(Array))
47
+ mapped = data.map do |item|
48
+ if( item.is_a?(Array))
49
+ to_sexp(item)
50
+ else
51
+ item.to_s
52
+ end
53
+ end
54
+ "[" + mapped.join(" ") + "]"
55
+ else
56
+ data.to_s
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def recursive_map(data, &block)
63
+ if(data.is_a?(Array))
64
+ return data.map do |x|
65
+ if(x.is_a?(Array))
66
+ recursive_map(x, &block)
67
+ else
68
+ block.call(x)
69
+ end
70
+ end
71
+ else
72
+ block.call(data)
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,64 @@
1
+ require 'strscan'
2
+
3
+ class BracerParser < StringScanner
4
+
5
+ def initialize(string)
6
+ unless(string.count('[') == string.count(']'))
7
+ raise Exception, "Missing closing braces"
8
+ end
9
+ super(string)
10
+ end
11
+
12
+ def parse
13
+ exp = []
14
+ while true
15
+ case fetch_token
16
+ when '['
17
+ exp << parse
18
+ when ']'
19
+ break
20
+ when :"'"
21
+ case fetch_token
22
+ when '[' then exp << [:quote].concat([parse])
23
+ else exp << [:quote, @token]
24
+ end
25
+ when String, Fixnum, Float, Symbol
26
+ exp << @token
27
+ when nil
28
+ break
29
+ end
30
+ end
31
+ exp
32
+ end
33
+
34
+ def fetch_token
35
+ skip(/\s+/)
36
+ return nil if(eos?)
37
+
38
+ @token =
39
+ # Match parentheses
40
+ if scan(/[\[\]]/)
41
+ matched
42
+ # Match a string literal
43
+ elsif scan(/"([^"\\]|\\.)*"/)
44
+ eval(matched)
45
+ # Match a float literal
46
+ elsif scan(/[\-\+]? [0-9]+ ((e[0-9]+) | (\.[0-9]+(e[0-9]+)?))/x)
47
+ matched.to_f
48
+ # Match an integer literal
49
+ elsif scan(/[\-\+]?[0-9]+/)
50
+ matched.to_i
51
+ # Match a comma (for comma quoting)
52
+ elsif scan(/'/)
53
+ matched.to_sym
54
+ # Match a symbol
55
+ elsif scan(/[^\[\]\s]+/)
56
+ matched.to_sym
57
+ # If we've gotten here then we have an invalid token
58
+ else
59
+ near = scan %r{.{0,20}}
60
+ raise "Invalid character at position #{pos} near '#{near}'."
61
+ end
62
+ end
63
+
64
+ end
data/sexpistol.gemspec ADDED
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bracer}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Aaron Gough","The Trung"]
12
+ s.date = %q{2015-02-07}
13
+ s.description = %q{Brace is Sexpistol with braces, an easy-to-use S-Expression parser for Ruby. It is fast and has no dependencies.}
14
+ s.email = %q{aaron@aarongough.com, deulamco@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "MIT-LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "lib/sexpistol.rb",
26
+ "lib/sexpistol/sexpistol.rb",
27
+ "lib/sexpistol/sexpistol_parser.rb",
28
+ "sexpistol.gemspec",
29
+ "test/performance/benchmark_test.rb",
30
+ "test/setup/test_unit_extensions.rb",
31
+ "test/test_helper.rb",
32
+ "test/unit/float_literal_test.rb",
33
+ "test/unit/integer_literal_test.rb",
34
+ "test/unit/ruby_keyword_literals_test.rb",
35
+ "test/unit/scheme_compatability_test.rb",
36
+ "test/unit/string_literal_test.rb",
37
+ "test/unit/structure_test.rb",
38
+ "test/unit/symbol_test.rb",
39
+ "test/unit/to_sexp_test.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/thetrung/sexpistol}
42
+ s.rdoc_options = ["--charset=UTF-8", "--line-numbers", "--inline-source"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.3.7}
45
+ s.summary = %q{An Braces S-Expression with Parser Library for Ruby}
46
+ s.test_files = [
47
+ "test/performance/benchmark_test.rb",
48
+ "test/setup/test_unit_extensions.rb",
49
+ "test/test_helper.rb",
50
+ "test/unit/float_literal_test.rb",
51
+ "test/unit/integer_literal_test.rb",
52
+ "test/unit/ruby_keyword_literals_test.rb",
53
+ "test/unit/scheme_compatability_test.rb",
54
+ "test/unit/string_literal_test.rb",
55
+ "test/unit/structure_test.rb",
56
+ "test/unit/symbol_test.rb",
57
+ "test/unit/to_sexp_test.rb"
58
+ ]
59
+
60
+ if s.respond_to? :specification_version then
61
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
+ else
66
+ end
67
+ else
68
+ end
69
+ end
70
+
@@ -0,0 +1,46 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class BenchmarkTest < Test::Unit::TestCase
4
+
5
+ require 'benchmark'
6
+
7
+ def setup
8
+ @example_sexp = <<-EOD
9
+ [display "This is a test string!"]
10
+
11
+ [define test [lambda [] [begin
12
+ [display [== 1 1]]
13
+ [display [== true true]]
14
+ [display [== false false]]
15
+ [display [== nil nil]]
16
+ [display [== 2.09 1.08]]
17
+ [display [== 2e6 2e12]]
18
+ ]]]
19
+ EOD
20
+ end
21
+
22
+ test "benchmark bracer" do
23
+ puts "\nRunning performance test...\n"
24
+
25
+ parser = Bracer.new
26
+ parser.ruby_keyword_literals = true
27
+
28
+ Benchmark.bmbm do |b|
29
+ b.report("Parse") do
30
+ 5000.times do
31
+ parser.parse_string(@example_sexp)
32
+ end
33
+ end
34
+
35
+ b.report("to_sexp") do
36
+ ast = parser.parse_string(@example_sexp)
37
+ 5000.times do
38
+ parser.to_sexp(ast)
39
+ end
40
+ end
41
+ end
42
+
43
+ puts
44
+ end
45
+
46
+ end
@@ -0,0 +1,21 @@
1
+ module Test::Unit
2
+ # Used to fix a minor minitest/unit incompatibility in flexmock
3
+ AssertionFailedError = Class.new(StandardError)
4
+
5
+ class TestCase
6
+
7
+ def self.test(name, &block)
8
+ test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
9
+ defined = instance_method(test_name) rescue false
10
+ raise "#{test_name} is already defined in #{self}" if defined
11
+ if block_given?
12
+ define_method(test_name, &block)
13
+ else
14
+ define_method(test_name) do
15
+ flunk "No implementation provided for #{name}"
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ require_files = []
5
+ require_files << File.join(File.dirname(__FILE__), '..', 'lib', 'sexpistol.rb')
6
+ require_files.concat Dir[File.join(File.dirname(__FILE__), 'setup', '*.rb')]
7
+
8
+ require_files.each do |file|
9
+ require File.expand_path(file)
10
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class FloatLiteralTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should parse sexp containing an implicitly positive float literal" do
10
+ ast = @parser.parse_string("[10.00]")
11
+ assert_equal [[10.00]], ast
12
+ end
13
+
14
+ test "should parse sexp containing an explicitly positive float literal" do
15
+ ast = @parser.parse_string("[+910.00]")
16
+ assert_equal [[910.00]], ast
17
+ end
18
+
19
+ test "should parse sexp containing an explicitly negative float literal" do
20
+ ast = @parser.parse_string("[-10.00]")
21
+ assert_equal [[-10.00]], ast
22
+ end
23
+
24
+ test "should parse sexp containing a large float literal" do
25
+ ast = @parser.parse_string("[1.0000127829]")
26
+ assert_equal [[1.0000127829]], ast
27
+ end
28
+
29
+ test "should parse sexp containing a float defined in scientific notation" do
30
+ ast = @parser.parse_string("[1.0e6]")
31
+ assert_equal [[1.0e6]], ast
32
+ end
33
+
34
+ test "should parse sexp containing a float defined in scientific notation with no decimal place" do
35
+ ast = @parser.parse_string("[10e2]")
36
+ assert_equal [[10e2]], ast
37
+ end
38
+
39
+
40
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class IntegerLiteralTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should parse sexp containing an implicitly positive integer literal" do
10
+ ast = @parser.parse_string("[10]")
11
+ assert_equal [[10]], ast
12
+ end
13
+
14
+ test "should parse sexp containing an explicitly positive integer literal" do
15
+ ast = @parser.parse_string("[+910]")
16
+ assert_equal [[910]], ast
17
+ end
18
+
19
+ test "should parse sexp containing an explicitly negative integer literal" do
20
+ ast = @parser.parse_string("[-10]")
21
+ assert_equal [[-10]], ast
22
+ end
23
+
24
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class RubyKeywordLiteralsTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should parse nil as literal" do
10
+ @parser.ruby_keyword_literals = true
11
+ ast = @parser.parse_string("[nil]")
12
+ assert_equal [[nil]], ast
13
+ end
14
+
15
+ test "should not parse nil as literal" do
16
+ @parser.ruby_keyword_literals = false
17
+ ast = @parser.parse_string("[nil]")
18
+ assert_equal [[:nil]], ast
19
+ end
20
+
21
+ test "should parse true as literal" do
22
+ @parser.ruby_keyword_literals = true
23
+ ast = @parser.parse_string("[true]")
24
+ assert_equal [[true]], ast
25
+ end
26
+
27
+ test "should not parse true as literal" do
28
+ @parser.ruby_keyword_literals = false
29
+ ast = @parser.parse_string("[true]")
30
+ assert_equal [[:true]], ast
31
+ end
32
+
33
+ test "should parse false as literal" do
34
+ @parser.ruby_keyword_literals = true
35
+ ast = @parser.parse_string("[false]")
36
+ assert_equal [[false]], ast
37
+ end
38
+
39
+ test "should notparse false as literal" do
40
+ @parser.ruby_keyword_literals = false
41
+ ast = @parser.parse_string("[false]")
42
+ assert_equal [[:false]], ast
43
+ end
44
+
45
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class SchemeCompatabilityTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ @parser.scheme_compatability = true
8
+ end
9
+
10
+ test "should parse #t as symbol" do
11
+ ast = @parser.parse_string('[#t]')
12
+ assert_equal [[:"#t"]], ast
13
+ end
14
+
15
+ test "should parse #f as symbol" do
16
+ ast = @parser.parse_string('[#f]')
17
+ assert_equal [[:"#f"]], ast
18
+ end
19
+
20
+ test "should allow comma quoting" do
21
+ ast = @parser.parse_string("[this is '[ a test] too foo][foo]")
22
+ assert_equal [[:this, :is, [:quote, [:a, :test]], :too, :foo ],[:foo]], ast
23
+ end
24
+
25
+ test "should allow complicated comma quoting" do
26
+ ast = @parser.parse_string("[this is '[ a test] [also]]")
27
+ assert_equal [[:this, :is, [:quote, [:a, :test]], [:also]]], ast
28
+ end
29
+
30
+ test "should allow comma quoting of integer literal" do
31
+ ast = @parser.parse_string("[this is '1 [also]]")
32
+ assert_equal [[:this, :is, [:quote, 1], [:also]]], ast
33
+ end
34
+
35
+ test "should allow comma quoting of string literal" do
36
+ ast = @parser.parse_string("[this is '\"test\" [also]]")
37
+ assert_equal [[:this, :is, [:quote, "test"], [:also]]], ast
38
+ end
39
+
40
+ test "should return scheme compatible external representation" do
41
+ ast = [true, false, nil]
42
+ string = @parser.to_sexp(ast)
43
+ assert_equal "[#t #f []]", string
44
+ end
45
+
46
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class StringLiteralTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should parse empty string literal" do
10
+ ast = @parser.parse_string('[""]')
11
+ assert_equal [[""]], ast
12
+ end
13
+
14
+ test "should parse string literal" do
15
+ ast = @parser.parse_string('["test"]')
16
+ assert_equal [["test"]], ast
17
+ end
18
+
19
+ test "should parse string literal containing escaped quotes" do
20
+ ast = @parser.parse_string('["te\"st"]')
21
+ assert_equal [["te\"st"]], ast
22
+ end
23
+
24
+ test "should parse string literal containing escaped characters" do
25
+ ast = @parser.parse_string('["\n\t\r"]')
26
+ assert_equal [["\n\t\r"]], ast
27
+ end
28
+
29
+ test "should parse string literal containing spaces" do
30
+ ast = @parser.parse_string('["blah foo"]')
31
+ assert_equal [["blah foo"]], ast
32
+ end
33
+
34
+ test "should parse string literal containing newlines" do
35
+ ast = @parser.parse_string('["blah' + "\n" + 'foo"]')
36
+ assert_equal [["blah\nfoo"]], ast
37
+ end
38
+
39
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class StructureTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should create nested set of arrays from s-expression" do
10
+ ast = @parser.parse_string('[this [is [an [s_expression] [also] blah] foo] [test]]')
11
+ assert_equal [[:this, [:is, [:an, [:s_expression], [:also], :blah], :foo], [:test]]], ast
12
+ end
13
+
14
+ test "should create nested set of arrays from s-expression with string literals" do
15
+ ast = @parser.parse_string('[this [is [an ["s_expression"]]]]')
16
+ assert_equal [[:this, [:is, [:an, ["s_expression"]]]]], ast
17
+ end
18
+
19
+ test "should raise error on broken s-expression" do
20
+ assert_raises Exception do
21
+ ast = @parser.parse_string('[this [is [an [s_expression] too]')
22
+ end
23
+ end
24
+
25
+ test "should parser [] as empty list" do
26
+ ast = @parser.parse_string('[]')
27
+ assert_equal [[]], ast
28
+ end
29
+
30
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class SymbolTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should parse simple symbol" do
10
+ ast = @parser.parse_string("[test]")
11
+ assert_equal [[:test]], ast
12
+ end
13
+
14
+ test "should parse symbol with trailing exclamation mark" do
15
+ ast = @parser.parse_string("[test!]")
16
+ assert_equal [[:test!]], ast
17
+ end
18
+
19
+ test "should parse symbol with trailing question mark" do
20
+ ast = @parser.parse_string("[test?]")
21
+ assert_equal [[:test?]], ast
22
+ end
23
+
24
+ test "should parse symbol containing underscores" do
25
+ ast = @parser.parse_string("[te__st]")
26
+ assert_equal [[:te__st]], ast
27
+ end
28
+
29
+ test "should parse symbol with leading underscores" do
30
+ ast = @parser.parse_string("[__test]")
31
+ assert_equal [[:__test]], ast
32
+ end
33
+
34
+ test "should parse symbol with trailing underscores" do
35
+ ast = @parser.parse_string("[test__]")
36
+ assert_equal [[:test__]], ast
37
+ end
38
+
39
+ test "should parse CamelCase symbol" do
40
+ ast = @parser.parse_string("[TestSymbol]")
41
+ assert_equal [[:TestSymbol]], ast
42
+ end
43
+
44
+ test "should parse complex symbol" do
45
+ ast = @parser.parse_string("[__TestSymbol_TEST__?]")
46
+ assert_equal [[:__TestSymbol_TEST__?]], ast
47
+ end
48
+
49
+ test "should parse symbol containing addition operators" do
50
+ ast = @parser.parse_string("[+]")
51
+ assert_equal [[:+]], ast
52
+ end
53
+
54
+ test "should parse symbol containing multiplication operators" do
55
+ ast = @parser.parse_string("[*]")
56
+ assert_equal [[:*]], ast
57
+ end
58
+
59
+ test "should parse symbol containing subtraction operators" do
60
+ ast = @parser.parse_string("[-]")
61
+ assert_equal [[:-]], ast
62
+ end
63
+
64
+ test "should parse symbol containing division operators" do
65
+ ast = @parser.parse_string("[/]")
66
+ assert_equal [[:"/"]], ast
67
+ end
68
+
69
+ test "should parse symbol containing any character except single and double quotes, backquote, parentheses and comma" do
70
+ ast = @parser.parse_string("[~1!2@3#4$%5^6&7*890-_+=|)}({poiuytrewqasdfghjklmnbvcxzZXCVBNMLKJHGFDSAQWERTYUIOP:;/?><]")
71
+ assert_equal [[:"~1!2@3#4$%5^6&7*890-_+=|\)}({poiuytrewqasdfghjklmnbvcxzZXCVBNMLKJHGFDSAQWERTYUIOP:;/?><"]], ast
72
+ end
73
+
74
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper.rb'))
2
+
3
+ class ToSexpTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @parser = Bracer.new
7
+ end
8
+
9
+ test "should convert nested arrays back into an S-Expression" do
10
+ ast = [:string, [:is, [:parsed]]]
11
+ sexp = @parser.to_sexp(ast)
12
+ assert_equal "[string [is [parsed]]]", sexp
13
+ end
14
+
15
+ test "should structure containing integers and strings back into an S-Expression" do
16
+ ast = ["String!", [1, [2, "Other string."]]]
17
+ sexp = @parser.to_sexp(ast)
18
+ assert_equal "[String! [1 [2 Other string.]]]", sexp
19
+ end
20
+
21
+ test "should not output true and false using scheme notation when scheme compat is off" do
22
+ ast = [true, [false, [true, false]]]
23
+ sexp = @parser.to_sexp(ast)
24
+ assert_equal "[true [false [true false]]]", sexp
25
+ end
26
+
27
+ test "when not passed array to_sexp should print value [integer]" do
28
+ ast = 1
29
+ sexp = @parser.to_sexp(ast)
30
+ assert_equal "1", sexp
31
+ end
32
+
33
+ test "when not passed array to_sexp should print value [string]" do
34
+ ast = "test"
35
+ sexp = @parser.to_sexp(ast)
36
+ assert_equal "test", sexp
37
+ end
38
+
39
+ test "when not passed array to_sexp should print value [symbol]" do
40
+ ast = :test
41
+ sexp = @parser.to_sexp(ast)
42
+ assert_equal "test", sexp
43
+ end
44
+
45
+ test "lists passed to to_sexp should have not extraneous spaces" do
46
+ ast = [1, 2, 3]
47
+ sexp = @parser.to_sexp(ast)
48
+ assert_equal "[1 2 3]", sexp
49
+ end
50
+
51
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bracer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Gough
8
+ - The Trung
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-02-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Brace is Sexpistol with braces, an easy-to-use S-Expression parser for
15
+ Ruby. It is fast and has no dependencies.
16
+ email: aaron@aarongough.com, deulamco@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - MIT-LICENSE
21
+ - README.rdoc
22
+ files:
23
+ - ".gitignore"
24
+ - MIT-LICENSE
25
+ - README.rdoc
26
+ - Rakefile
27
+ - VERSION
28
+ - lib/sexpistol.rb
29
+ - lib/sexpistol/sexpistol.rb
30
+ - lib/sexpistol/sexpistol_parser.rb
31
+ - sexpistol.gemspec
32
+ - test/performance/benchmark_test.rb
33
+ - test/setup/test_unit_extensions.rb
34
+ - test/test_helper.rb
35
+ - test/unit/float_literal_test.rb
36
+ - test/unit/integer_literal_test.rb
37
+ - test/unit/ruby_keyword_literals_test.rb
38
+ - test/unit/scheme_compatability_test.rb
39
+ - test/unit/string_literal_test.rb
40
+ - test/unit/structure_test.rb
41
+ - test/unit/symbol_test.rb
42
+ - test/unit/to_sexp_test.rb
43
+ homepage: http://github.com/thetrung/sexpistol
44
+ licenses: []
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options:
48
+ - "--charset=UTF-8"
49
+ - "--line-numbers"
50
+ - "--inline-source"
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.4.5
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: An Braces S-Expression with Parser Library for Ruby
69
+ test_files:
70
+ - test/performance/benchmark_test.rb
71
+ - test/setup/test_unit_extensions.rb
72
+ - test/test_helper.rb
73
+ - test/unit/float_literal_test.rb
74
+ - test/unit/integer_literal_test.rb
75
+ - test/unit/ruby_keyword_literals_test.rb
76
+ - test/unit/scheme_compatability_test.rb
77
+ - test/unit/string_literal_test.rb
78
+ - test/unit/structure_test.rb
79
+ - test/unit/symbol_test.rb
80
+ - test/unit/to_sexp_test.rb
81
+ has_rdoc: