sexpistol 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +71 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/lib/sexpistol/sexpistol.rb +137 -0
- data/lib/sexpistol.rb +1 -0
- data/test/setup/test_unit_extensions.rb +21 -0
- data/test/test_helper.rb +10 -0
- data/test/unit/float_literal_test.rb +30 -0
- data/test/unit/integer_literal_test.rb +24 -0
- data/test/unit/ruby_keyword_literals_test.rb +45 -0
- data/test/unit/string_literal_test.rb +29 -0
- data/test/unit/structure_test.rb +20 -0
- data/test/unit/symbol_test.rb +49 -0
- data/test/unit/to_sexp_test.rb +15 -0
- metadata +89 -0
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,71 @@
|
|
1
|
+
= Sexpistol
|
2
|
+
|
3
|
+
Sexpistol is a simple library for parsing S-Expressions in Ruby. Sexpistol takes an S-Expression 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 "blah")
|
9
|
+
(print 1)
|
10
|
+
(print 9.01)
|
11
|
+
(print (+ 10 12 13))
|
12
|
+
)))
|
13
|
+
|
14
|
+
would be parsed by Sexpistol like so:
|
15
|
+
|
16
|
+
[:define, :test, [:lambda, [], [
|
17
|
+
[:print, "blah"],
|
18
|
+
[:print, 1],
|
19
|
+
[:print, 9.01],
|
20
|
+
[:print, [:"+", 10, 12, 13]]
|
21
|
+
]]]
|
22
|
+
|
23
|
+
=== Type mappings
|
24
|
+
|
25
|
+
Sexpistol supports all of the standard datatypes and converts them directly to their Ruby equivalents:
|
26
|
+
|
27
|
+
* Lists (a b c)
|
28
|
+
* Integers (1 2 3)
|
29
|
+
* Floats (1.0 2.0 42.9)
|
30
|
+
* Strings ("\t\"Hello world!\"\n")
|
31
|
+
* Symbols (symbol Symbol __symbol__ symbo_l symbol? symbol!)
|
32
|
+
|
33
|
+
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:
|
34
|
+
|
35
|
+
@parser = Sexpistol.new
|
36
|
+
@parser.parse_string("nil false true")
|
37
|
+
#=> [:nil, :false, :true]
|
38
|
+
|
39
|
+
@parser.ruby_keyword_literals = true
|
40
|
+
@parser.parse_string("nil false true")
|
41
|
+
#=> [nil, false, true]
|
42
|
+
|
43
|
+
=== Installation
|
44
|
+
|
45
|
+
For convenience Sexpistol is packaged as a RubyGem, to install it simply enter the following at your command line:
|
46
|
+
|
47
|
+
gem install sexpistol
|
48
|
+
|
49
|
+
=== Usage
|
50
|
+
|
51
|
+
# Create a new parser instance
|
52
|
+
@parser = Sexpistol.new
|
53
|
+
|
54
|
+
# Parse a string
|
55
|
+
ast = @parser.parse_string("(string (to (parse)))")
|
56
|
+
#=> [:string, [:to, [:parse]]]
|
57
|
+
|
58
|
+
# Change the representation
|
59
|
+
ast[1][0] = :is
|
60
|
+
ast[1][1][0] = :parsed
|
61
|
+
#=> [:string, [:is, [:parsed]]]
|
62
|
+
|
63
|
+
# Turn the array structure back into an S-Expression
|
64
|
+
@parser.to_sexp( ast )
|
65
|
+
#=> "( string ( is ( parsed ) ) )"
|
66
|
+
|
67
|
+
=== Author & Credits
|
68
|
+
|
69
|
+
Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
|
70
|
+
|
71
|
+
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 'rake/rdoctask'
|
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.1
|
@@ -0,0 +1,137 @@
|
|
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 Sexpistol
|
6
|
+
attr_accessor :ruby_keyword_literals
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@ruby_keyword_literals = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# Parse a string containing an S-Expression into a
|
13
|
+
# nested set of Ruby arrays
|
14
|
+
def parse_string( string )
|
15
|
+
string.gsub!("(", " ( ")
|
16
|
+
string.gsub!(")", " ) ")
|
17
|
+
string_array = string.split
|
18
|
+
tokens = process_tokens( string_array )
|
19
|
+
check_tokens( tokens )
|
20
|
+
structure( tokens )
|
21
|
+
end
|
22
|
+
|
23
|
+
# Check and array of tokens to make sure that the number
|
24
|
+
# of open and closing parentheses match
|
25
|
+
def check_tokens( tokens )
|
26
|
+
unless( (tokens.reject {|x| x == "("}).length == (tokens.reject {|x| x == ")"}).length)
|
27
|
+
raise Exception, "Invalid S-Expression. The number of opening and closing parentheses do not match."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Iterate over an array of strings and turn each
|
32
|
+
# item into it's relevant token. ie: "string" -> :string, "1" -> 1
|
33
|
+
def process_tokens( token_array )
|
34
|
+
tokens = []
|
35
|
+
token_array.each do |t|
|
36
|
+
if(@ruby_keyword_literals)
|
37
|
+
tokens << nil and next if(is_nil?(t))
|
38
|
+
tokens << true and next if(is_true?(t))
|
39
|
+
tokens << false and next if(is_false?(t))
|
40
|
+
end
|
41
|
+
tokens << t and next if(is_paren?(t))
|
42
|
+
tokens << t.to_f and next if( is_float?(t))
|
43
|
+
tokens << t.to_i and next if( is_integer?(t))
|
44
|
+
tokens << t.to_sym and next if( is_identifier?(t) || is_symbol?(t))
|
45
|
+
tokens << eval(t) and next if( is_string_literal?(t))
|
46
|
+
raise "\nUnrecognized token: #{t}\n"
|
47
|
+
end
|
48
|
+
return tokens
|
49
|
+
end
|
50
|
+
|
51
|
+
# Iterate over a flat array of tokens and turn it
|
52
|
+
# a nested set of arrays by detecting '(' and ')'
|
53
|
+
def structure( token_array, offset = 0, internal = false )
|
54
|
+
program = []
|
55
|
+
while(offset < token_array.length)
|
56
|
+
if( token_array[offset] == "(" )
|
57
|
+
offset, array = structure( token_array, offset + 1, true )
|
58
|
+
program << array
|
59
|
+
elsif( token_array[offset] == ")" )
|
60
|
+
break
|
61
|
+
else
|
62
|
+
program << token_array[offset]
|
63
|
+
end
|
64
|
+
offset += 1
|
65
|
+
end
|
66
|
+
if(internal)
|
67
|
+
return [offset, program]
|
68
|
+
else
|
69
|
+
return program
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Test to see whether or not a string represents the 'nil' literal
|
74
|
+
def is_nil?( string )
|
75
|
+
true if(string == "nil")
|
76
|
+
end
|
77
|
+
|
78
|
+
# Test to see whether or not a string represents the 'true' literal
|
79
|
+
def is_true?( string )
|
80
|
+
true if(string == "true")
|
81
|
+
end
|
82
|
+
|
83
|
+
# Test to see whether or not a string represents the 'false' literal
|
84
|
+
def is_false?( string )
|
85
|
+
true if(string == "false")
|
86
|
+
end
|
87
|
+
|
88
|
+
# Test to see whether a string represents a parentheses
|
89
|
+
def is_paren?( string )
|
90
|
+
is_match?( string, /[\(\)]+/ )
|
91
|
+
end
|
92
|
+
|
93
|
+
# Test to see whether or not a string represents an integer
|
94
|
+
def is_integer?( string )
|
95
|
+
is_match?( string, /[\-\+]?[0-9]+/ )
|
96
|
+
end
|
97
|
+
|
98
|
+
# Test to see whether or not a string represents a float
|
99
|
+
def is_float?( string )
|
100
|
+
is_match?( string, /[\-\+]?[0-9]+\.[0-9]+/ )
|
101
|
+
end
|
102
|
+
|
103
|
+
# Test to see whether or not a string represents an identifier
|
104
|
+
def is_identifier?( string )
|
105
|
+
is_match?( string, /_*[a-zA-Z]+[a-zA-Z0-9_]*\??\!?/ )
|
106
|
+
end
|
107
|
+
|
108
|
+
# Test to see whether or not a string represents a string literal
|
109
|
+
def is_string_literal?( string )
|
110
|
+
is_match?( string, /".*"/)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Test to see whether or not a string represents a symbol
|
114
|
+
def is_symbol?( string )
|
115
|
+
is_match?( string, /[\!\*\^=\/\+\-]+/ )
|
116
|
+
end
|
117
|
+
|
118
|
+
# Convert a set of nested arrays back into an S-Expression
|
119
|
+
def to_sexp( data )
|
120
|
+
mapped = data.map do |item|
|
121
|
+
if( item.is_a?(Array))
|
122
|
+
to_sexp(item)
|
123
|
+
else
|
124
|
+
item.to_s
|
125
|
+
end
|
126
|
+
end
|
127
|
+
"( " + mapped.join(" ") + " )"
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def is_match?( string, pattern )
|
133
|
+
match = string.match(pattern)
|
134
|
+
return false unless match
|
135
|
+
match[0].length == string.length
|
136
|
+
end
|
137
|
+
end
|
data/lib/sexpistol.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'sexpistol', 'sexpistol.rb'))
|
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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,30 @@
|
|
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 = Sexpistol.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
|
+
|
30
|
+
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 = Sexpistol.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 = Sexpistol.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,29 @@
|
|
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 = Sexpistol.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
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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 = Sexpistol.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))))')
|
11
|
+
assert_equal [[:this, [:is, [:an, [:s_expression]]]]], ast
|
12
|
+
end
|
13
|
+
|
14
|
+
test "should raise error on broken s-expression" do
|
15
|
+
assert_raises Exception do
|
16
|
+
ast = @parser.parse_string('(this (is (an (s_expression) too)')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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 = Sexpistol.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
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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 = Sexpistol.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
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sexpistol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Aaron Gough
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-02 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Sexpistol is an easy-to-use S-Expression parser for Ruby. It is fast and has no dependencies.
|
22
|
+
email: aaron@aarongough.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- MIT-LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- MIT-LICENSE
|
32
|
+
- README.rdoc
|
33
|
+
- Rakefile
|
34
|
+
- VERSION
|
35
|
+
- lib/sexpistol.rb
|
36
|
+
- lib/sexpistol/sexpistol.rb
|
37
|
+
- test/setup/test_unit_extensions.rb
|
38
|
+
- test/test_helper.rb
|
39
|
+
- test/unit/float_literal_test.rb
|
40
|
+
- test/unit/integer_literal_test.rb
|
41
|
+
- test/unit/ruby_keyword_literals_test.rb
|
42
|
+
- test/unit/string_literal_test.rb
|
43
|
+
- test/unit/structure_test.rb
|
44
|
+
- test/unit/symbol_test.rb
|
45
|
+
- test/unit/to_sexp_test.rb
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/aarongough/sexpistol
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --charset=UTF-8
|
53
|
+
- --line-numbers
|
54
|
+
- --inline-source
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: An S-Expression Parser Library for Ruby
|
80
|
+
test_files:
|
81
|
+
- test/setup/test_unit_extensions.rb
|
82
|
+
- test/test_helper.rb
|
83
|
+
- test/unit/float_literal_test.rb
|
84
|
+
- test/unit/integer_literal_test.rb
|
85
|
+
- test/unit/ruby_keyword_literals_test.rb
|
86
|
+
- test/unit/string_literal_test.rb
|
87
|
+
- test/unit/structure_test.rb
|
88
|
+
- test/unit/symbol_test.rb
|
89
|
+
- test/unit/to_sexp_test.rb
|