sexpistol 0.0.2 → 0.0.3
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/VERSION +1 -1
- data/lib/sexpistol/sexpistol.rb +31 -52
- data/sexpistol.gemspec +5 -3
- data/test/performance/benchmark_test.rb +34 -0
- data/test/unit/structure_test.rb +3 -3
- metadata +5 -3
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.3
|
data/lib/sexpistol/sexpistol.rb
CHANGED
|
@@ -3,10 +3,21 @@
|
|
|
3
3
|
# native Ruby representation like:
|
|
4
4
|
# [:def, :something [:lambda, [:a], [:do_something]]]
|
|
5
5
|
class Sexpistol
|
|
6
|
+
|
|
6
7
|
attr_accessor :ruby_keyword_literals
|
|
7
8
|
|
|
8
9
|
def initialize
|
|
9
10
|
@ruby_keyword_literals = false
|
|
11
|
+
|
|
12
|
+
# Setup all of our token patterns as instance variables
|
|
13
|
+
# so they don't have to be re-instantiated for each
|
|
14
|
+
# run & match
|
|
15
|
+
@string_literal_pattern = /"([^"\\]|\\.)*"/
|
|
16
|
+
@integer_literal_pattern = /[\-\+]?[0-9]+/
|
|
17
|
+
@float_literal_pattern = /[\-\+]?[0-9]+\.[0-9]+(e[0-9]+)?/
|
|
18
|
+
@symbol_pattern = /[^\"\'\,\(\)]+/
|
|
19
|
+
|
|
20
|
+
@string_replacement_token = "__++STRING_LITERAL++__"
|
|
10
21
|
end
|
|
11
22
|
|
|
12
23
|
# Parse a string containing an S-Expression into a
|
|
@@ -14,16 +25,7 @@ class Sexpistol
|
|
|
14
25
|
def parse_string( string )
|
|
15
26
|
string_array = split_outside_strings(string)
|
|
16
27
|
tokens = process_tokens( string_array )
|
|
17
|
-
|
|
18
|
-
structure( tokens )
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Check and array of tokens to make sure that the number
|
|
22
|
-
# of open and closing parentheses match
|
|
23
|
-
def check_tokens( tokens )
|
|
24
|
-
unless( (tokens.reject {|x| x == "("}).length == (tokens.reject {|x| x == ")"}).length)
|
|
25
|
-
raise Exception, "Invalid S-Expression. The number of opening and closing parentheses does not match."
|
|
26
|
-
end
|
|
28
|
+
structure( tokens )[1]
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
# Iterate over an array of strings and turn each
|
|
@@ -32,11 +34,11 @@ class Sexpistol
|
|
|
32
34
|
tokens = []
|
|
33
35
|
token_array.each do |t|
|
|
34
36
|
if(@ruby_keyword_literals)
|
|
35
|
-
tokens << nil and next if(
|
|
36
|
-
tokens << true and next if(
|
|
37
|
-
tokens << false and next if(
|
|
37
|
+
tokens << nil and next if(t == "nil")
|
|
38
|
+
tokens << true and next if(t == "true")
|
|
39
|
+
tokens << false and next if(t == "false")
|
|
38
40
|
end
|
|
39
|
-
tokens << t and next if(
|
|
41
|
+
tokens << t and next if(t == "(" || t == ")")
|
|
40
42
|
tokens << t.to_f and next if( is_float?(t))
|
|
41
43
|
tokens << t.to_i and next if( is_integer?(t))
|
|
42
44
|
tokens << t.to_sym and next if( is_symbol?(t))
|
|
@@ -61,30 +63,27 @@ class Sexpistol
|
|
|
61
63
|
end
|
|
62
64
|
offset += 1
|
|
63
65
|
end
|
|
64
|
-
|
|
65
|
-
return [offset, program]
|
|
66
|
-
else
|
|
67
|
-
return program
|
|
68
|
-
end
|
|
66
|
+
return [offset, program]
|
|
69
67
|
end
|
|
70
68
|
|
|
71
69
|
# Split up a string into an array where delimited by whitespace,
|
|
72
70
|
# except inside string literals
|
|
73
71
|
def split_outside_strings( string )
|
|
74
|
-
string_literal_pattern = /"([^"\\]|\\.)*"/
|
|
75
|
-
string_token = "__++STRING_LITERAL++__"
|
|
76
72
|
# Find and extract all the string literals
|
|
77
73
|
string_literals = []
|
|
78
|
-
string.gsub(string_literal_pattern)
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
string = string.gsub(@string_literal_pattern) do |x|
|
|
75
|
+
string_literals << x
|
|
76
|
+
@string_replacement_token
|
|
77
|
+
end
|
|
78
|
+
# Make sure the s-expression is valid
|
|
79
|
+
unless( string.count("(") == string.count(")") )
|
|
80
|
+
raise Exception, "Invalid S-Expression. The number of opening and closing parentheses does not match."
|
|
81
|
+
end
|
|
81
82
|
# Split the string up on whitespace and parentheses
|
|
82
|
-
string.gsub
|
|
83
|
-
string.gsub!(")", " ) ")
|
|
84
|
-
array = string.split(" ")
|
|
83
|
+
array = string.gsub("(", " ( ").gsub(")", " ) ").split(" ")
|
|
85
84
|
# replace the special string token with the original string literals
|
|
86
85
|
array.collect! do |x|
|
|
87
|
-
if( x ==
|
|
86
|
+
if( x == @string_replacement_token)
|
|
88
87
|
string_literals.shift
|
|
89
88
|
else
|
|
90
89
|
x
|
|
@@ -93,44 +92,24 @@ class Sexpistol
|
|
|
93
92
|
return array
|
|
94
93
|
end
|
|
95
94
|
|
|
96
|
-
# Test to see whether or not a string represents the 'nil' literal
|
|
97
|
-
def is_nil?( string )
|
|
98
|
-
true if(string == "nil")
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Test to see whether or not a string represents the 'true' literal
|
|
102
|
-
def is_true?( string )
|
|
103
|
-
true if(string == "true")
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Test to see whether or not a string represents the 'false' literal
|
|
107
|
-
def is_false?( string )
|
|
108
|
-
true if(string == "false")
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Test to see whether a string represents a parentheses
|
|
112
|
-
def is_paren?( string )
|
|
113
|
-
is_match?( string, /[\(\)]+/ )
|
|
114
|
-
end
|
|
115
|
-
|
|
116
95
|
# Test to see whether or not a string represents an integer
|
|
117
96
|
def is_integer?( string )
|
|
118
|
-
is_match?( string,
|
|
97
|
+
is_match?( string, @integer_literal_pattern )
|
|
119
98
|
end
|
|
120
99
|
|
|
121
100
|
# Test to see whether or not a string represents a float
|
|
122
101
|
def is_float?( string )
|
|
123
|
-
is_match?( string,
|
|
102
|
+
is_match?( string, @float_literal_pattern )
|
|
124
103
|
end
|
|
125
104
|
|
|
126
105
|
# Test to see whether or not a string represents a symbol
|
|
127
106
|
def is_symbol?( string )
|
|
128
|
-
is_match?( string,
|
|
107
|
+
is_match?( string, @symbol_pattern )
|
|
129
108
|
end
|
|
130
109
|
|
|
131
110
|
# Test to see whether or not a string represents a string literal
|
|
132
111
|
def is_string_literal?( string )
|
|
133
|
-
is_match?( string,
|
|
112
|
+
is_match?( string, @string_literal_pattern )
|
|
134
113
|
end
|
|
135
114
|
|
|
136
115
|
# Convert a set of nested arrays back into an S-Expression
|
data/sexpistol.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{sexpistol}
|
|
8
|
-
s.version = "0.0.
|
|
8
|
+
s.version = "0.0.3"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Aaron Gough"]
|
|
12
|
-
s.date = %q{2010-10-
|
|
12
|
+
s.date = %q{2010-10-06}
|
|
13
13
|
s.description = %q{Sexpistol is an easy-to-use S-Expression parser for Ruby. It is fast and has no dependencies.}
|
|
14
14
|
s.email = %q{aaron@aarongough.com}
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
"lib/sexpistol.rb",
|
|
26
26
|
"lib/sexpistol/sexpistol.rb",
|
|
27
27
|
"sexpistol.gemspec",
|
|
28
|
+
"test/performance/benchmark_test.rb",
|
|
28
29
|
"test/setup/test_unit_extensions.rb",
|
|
29
30
|
"test/test_helper.rb",
|
|
30
31
|
"test/unit/float_literal_test.rb",
|
|
@@ -41,7 +42,8 @@ Gem::Specification.new do |s|
|
|
|
41
42
|
s.rubygems_version = %q{1.3.7}
|
|
42
43
|
s.summary = %q{An S-Expression Parser Library for Ruby}
|
|
43
44
|
s.test_files = [
|
|
44
|
-
"test/
|
|
45
|
+
"test/performance/benchmark_test.rb",
|
|
46
|
+
"test/setup/test_unit_extensions.rb",
|
|
45
47
|
"test/test_helper.rb",
|
|
46
48
|
"test/unit/float_literal_test.rb",
|
|
47
49
|
"test/unit/integer_literal_test.rb",
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
test "benchmark sexpistol" do
|
|
8
|
+
puts "\nRunning performance test...\n"
|
|
9
|
+
parser = Sexpistol.new
|
|
10
|
+
parser.ruby_keyword_literals = true
|
|
11
|
+
Benchmark.bmbm do |b|
|
|
12
|
+
b.report do
|
|
13
|
+
5000.times do
|
|
14
|
+
parser.parse_string <<-EOD
|
|
15
|
+
|
|
16
|
+
(display "This is a test string!")
|
|
17
|
+
|
|
18
|
+
(define test (lambda () (begin
|
|
19
|
+
(display (== 1 1))
|
|
20
|
+
(display (== true true))
|
|
21
|
+
(display (== false false))
|
|
22
|
+
(display (== nil nil))
|
|
23
|
+
(display (== 2.09 1.08))
|
|
24
|
+
(display (== 2e6 2e12))
|
|
25
|
+
)))
|
|
26
|
+
|
|
27
|
+
EOD
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
puts
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
data/test/unit/structure_test.rb
CHANGED
|
@@ -5,10 +5,10 @@ class RubyKeywordLiteralsTest < Test::Unit::TestCase
|
|
|
5
5
|
def setup
|
|
6
6
|
@parser = Sexpistol.new
|
|
7
7
|
end
|
|
8
|
-
|
|
8
|
+
|
|
9
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
|
|
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
12
|
end
|
|
13
13
|
|
|
14
14
|
test "should create nested set of arrays from s-expression with string literals" do
|
metadata
CHANGED
|
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
7
|
- 0
|
|
8
|
-
-
|
|
9
|
-
version: 0.0.
|
|
8
|
+
- 3
|
|
9
|
+
version: 0.0.3
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Aaron Gough
|
|
@@ -14,7 +14,7 @@ autorequire:
|
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
16
|
|
|
17
|
-
date: 2010-10-
|
|
17
|
+
date: 2010-10-06 00:00:00 -04:00
|
|
18
18
|
default_executable:
|
|
19
19
|
dependencies: []
|
|
20
20
|
|
|
@@ -36,6 +36,7 @@ files:
|
|
|
36
36
|
- lib/sexpistol.rb
|
|
37
37
|
- lib/sexpistol/sexpistol.rb
|
|
38
38
|
- sexpistol.gemspec
|
|
39
|
+
- test/performance/benchmark_test.rb
|
|
39
40
|
- test/setup/test_unit_extensions.rb
|
|
40
41
|
- test/test_helper.rb
|
|
41
42
|
- test/unit/float_literal_test.rb
|
|
@@ -80,6 +81,7 @@ signing_key:
|
|
|
80
81
|
specification_version: 3
|
|
81
82
|
summary: An S-Expression Parser Library for Ruby
|
|
82
83
|
test_files:
|
|
84
|
+
- test/performance/benchmark_test.rb
|
|
83
85
|
- test/setup/test_unit_extensions.rb
|
|
84
86
|
- test/test_helper.rb
|
|
85
87
|
- test/unit/float_literal_test.rb
|