bracer 0.0.1

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