sxp 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,38 +1,27 @@
1
- SXP.rb: SXP for Ruby
2
- ====================
1
+ SXP.rb: S-Expressions for Ruby
2
+ ==============================
3
3
 
4
- This is the Ruby reference implementation of the SXP data interchange
5
- format.
4
+ This is a Ruby implementation of a universal [S-expression][] parser.
6
5
 
7
6
  * <http://sxp.rubyforge.org/>
8
7
  * <http://github.com/bendiken/sxp-ruby>
9
8
 
10
- ### About SXP
11
-
12
- SXP is a data interchange format based on S-expressions, the simplest and
13
- most versatile known means of representing complex data structures such as
14
- lists, trees and graphs.
15
-
16
- * <http://sxp.cc/>
17
- * <http://en.wikipedia.org/wiki/S-expression>
18
-
19
9
  Features
20
10
  --------
21
11
 
22
- * Parses S-expressions in SXP format.
12
+ * Parses S-expressions in universal, [Scheme][], [Common Lisp][], or
13
+ [SPARQL][] syntax.
23
14
  * Adds a `#to_sxp` method to Ruby objects.
15
+ * Compatible with Ruby 1.8.7+, Ruby 1.9.x, and JRuby 1.4/1.5.
24
16
 
25
17
  Examples
26
18
  --------
27
19
 
28
20
  require 'sxp'
29
21
 
30
- ### Parsing S-expressions
31
-
32
- SXP.read "(+ 1 2)"
33
-
34
- => [:+, 1, 2]
22
+ ### Parsing S-expressions using universal syntax
35
23
 
24
+ SXP.read "(* 6 7)" #=> [:*, 6, 7]
36
25
 
37
26
  SXP.read <<-EOF
38
27
  (define (fact n)
@@ -41,16 +30,43 @@ Examples
41
30
  (* n (fact (- n 1)))))
42
31
  EOF
43
32
 
44
- => [:define, [:fact, :n],
45
- [:if, [:"=", :n, 0],
46
- 1,
47
- [:*, :n, [:fact, [:-, :n, 1]]]]]
33
+ #=> [:define, [:fact, :n],
34
+ [:if, [:"=", :n, 0],
35
+ 1,
36
+ [:*, :n, [:fact, [:-, :n, 1]]]]]
37
+
38
+ ### Parsing S-expressions using Scheme syntax
39
+
40
+ SXP::Reader::Scheme.read %q((and #t #f)) #=> [:and, true, false]
41
+
42
+ ### Parsing S-expressions using Common Lisp syntax
43
+
44
+ SXP::Reader::CommonLisp.read %q((or t nil)) #=> [:or, true, nil]
45
+
46
+ ### Parsing S-expressions using SPARQL syntax
47
+
48
+ SXP::Reader::SPARQL.read %q((base <http://ar.to/>)) #=> [:base, RDF::URI('http://ar.to/')]
48
49
 
49
50
  Documentation
50
51
  -------------
51
52
 
52
53
  * <http://sxp.rubyforge.org/>
53
54
 
55
+ Dependencies
56
+ ------------
57
+
58
+ * [Ruby](http://ruby-lang.org/) (>= 1.8.7) or (>= 1.8.1 with [Backports][])
59
+ * [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.2.0), only needed for SPARQL
60
+ S-expressions
61
+
62
+ Installation
63
+ ------------
64
+
65
+ The recommended installation method is via [RubyGems](http://rubygems.org/).
66
+ To install the latest official release of the SXP.rb gem, do:
67
+
68
+ % [sudo] gem install sxp
69
+
54
70
  Download
55
71
  --------
56
72
 
@@ -63,21 +79,13 @@ as follows:
63
79
 
64
80
  % wget http://github.com/bendiken/sxp-ruby/tarball/master
65
81
 
66
- Installation
67
- ------------
68
-
69
- The recommended installation method is via RubyGems. To install the latest
70
- official release from Gemcutter, do:
71
-
72
- % [sudo] gem install sxp
73
-
74
82
  Resources
75
83
  ---------
76
84
 
77
85
  * <http://sxp.rubyforge.org/>
78
86
  * <http://github.com/bendiken/sxp>
79
87
  * <http://github.com/bendiken/sxp-ruby>
80
- * <http://gemcutter.org/gems/sxp>
88
+ * <http://rubygems.org/gems/sxp>
81
89
  * <http://rubyforge.org/projects/sxp/>
82
90
  * <http://raa.ruby-lang.org/project/sxp>
83
91
 
@@ -91,3 +99,9 @@ License
91
99
 
92
100
  SXP.rb is free and unencumbered public domain software. For more
93
101
  information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
102
+
103
+ [S-expression]: http://en.wikipedia.org/wiki/S-expression
104
+ [Scheme]: http://scheme.info/
105
+ [Common Lisp]: http://en.wikipedia.org/wiki/Common_Lisp
106
+ [SPARQL]: http://openjena.org/wiki/SSE
107
+ [Backports]: http://rubygems.org/gems/backports
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
@@ -14,7 +14,7 @@ module SXP; class Reader
14
14
  def read_token
15
15
  case peek_char
16
16
  when ?(, ?) then [:list, read_char]
17
- when ?" then [:atom, read_string]
17
+ when ?" then [:atom, read_string] #"
18
18
  else super
19
19
  end
20
20
  end
@@ -36,7 +36,7 @@ module SXP; class Reader
36
36
  def read_string
37
37
  buffer = String.new
38
38
  skip_char # '"'
39
- until peek_char == ?"
39
+ until peek_char == ?" #"
40
40
  buffer <<
41
41
  case char = read_char
42
42
  when ?\\ then read_character
@@ -58,7 +58,7 @@ module SXP; class Reader
58
58
  when ?t then ?\t
59
59
  when ?u then read_chars(4).to_i(16).chr
60
60
  when ?U then read_chars(8).to_i(16).chr
61
- when ?" then char
61
+ when ?" then char #"
62
62
  when ?\\ then char
63
63
  else char
64
64
  end
@@ -72,5 +72,5 @@ module SXP; class Reader
72
72
  buffer << read_char while !eof? && peek_char.chr =~ grammar
73
73
  buffer
74
74
  end
75
- end # class Reader
75
+ end # class Basic
76
76
  end; end # class SXP::Reader
@@ -0,0 +1,127 @@
1
+ module SXP; class Reader
2
+ ##
3
+ # A Common Lisp S-expressions parser.
4
+ #
5
+ # @see http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node14.html
6
+ class CommonLisp < Basic
7
+ OPTIONS = {:nil => nil, :t => true, :quote => :quote, :function => :function}
8
+
9
+ DECIMAL = /^[+-]?(\d*)?\.\d*$/
10
+ INTEGER_BASE_2 = /^[+-]?[01]+$/
11
+ INTEGER_BASE_8 = /^[+-]?[0-7]+$/
12
+ INTEGER_BASE_10 = /^[+-]?\d+$/
13
+ INTEGER_BASE_16 = /^[+-]?[\da-z]+$/i
14
+ RATIONAL = /^([+-]?\d+)\/(\d+)$/
15
+
16
+ # @see http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node22.html
17
+ CHARACTERS = {
18
+ 'newline' => "\n",
19
+ 'space' => " ",
20
+ 'backspace' => "\b", # \010 BS
21
+ 'tab' => "\t", # \011 HT
22
+ 'linefeed' => "\n", # \012 LF
23
+ 'page' => "\f", # \014 FF
24
+ 'return' => "\r", # \015 CR
25
+ 'rubout' => "\x7F", # \177 DEL
26
+ }
27
+
28
+ ##
29
+ # Initializes the reader.
30
+ #
31
+ # @param [IO, StringIO, String] input
32
+ # @param [Hash{Symbol => Object}] options
33
+ # @option options [Object] :nil (nil)
34
+ # @option options [Object] :t (true)
35
+ # @option options [Object] :quote (:quote)
36
+ # @option options [Object] :function (:function)
37
+ def initialize(input, options = {}, &block)
38
+ super(input, OPTIONS.merge(options), &block)
39
+ end
40
+
41
+ ##
42
+ # @return [Object]
43
+ def read_token
44
+ case peek_char
45
+ when ?# then [:atom, read_sharp]
46
+ when ?| then [:atom, read_symbol(?|)]
47
+ when ?' then [:atom, read_quote]
48
+ else super
49
+ end
50
+ end
51
+
52
+ ##
53
+ # @return [Object]
54
+ def read_sharp
55
+ skip_char # '#'
56
+ case char = read_char
57
+ when ?b, ?B then read_integer(2)
58
+ when ?o, ?O then read_integer(8)
59
+ when ?x, ?X then read_integer(16)
60
+ when ?\\ then read_character
61
+ when ?( then read_vector
62
+ when ?' then read_function
63
+ else raise Error, "invalid sharp-sign read syntax: ##{char.chr}"
64
+ end
65
+ end
66
+
67
+ ##
68
+ # @return [Symbol]
69
+ def read_symbol(delimiter = nil)
70
+ buffer = String.new
71
+ skip_char # '|'
72
+ until delimiter === peek_char
73
+ buffer <<
74
+ case char = read_char
75
+ when ?\\ then read_character
76
+ else char
77
+ end
78
+ end
79
+ skip_char # '|'
80
+ buffer.to_sym
81
+ end
82
+
83
+ ##
84
+ # Reads `#(1 2 3)` forms.
85
+ #
86
+ # @return [Array]
87
+ def read_vector
88
+ raise NotImplementedError, "#{self.class}#read_vector" # TODO
89
+ end
90
+
91
+ ##
92
+ # Reads `'foobar` forms.
93
+ #
94
+ # @return [Array]
95
+ def read_quote
96
+ skip_char # "'"
97
+ [options[:quote] || :quote, read]
98
+ end
99
+
100
+ ##
101
+ # Reads `#'mapcar` forms.
102
+ #
103
+ # @return [Array]
104
+ def read_function
105
+ [options[:function] || :function, read]
106
+ end
107
+
108
+ ##
109
+ # @return [String]
110
+ # @see http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node22.html
111
+ def read_character
112
+ super
113
+ end
114
+
115
+ ##
116
+ # @return [void]
117
+ def skip_comments
118
+ until eof?
119
+ case (char = peek_char).chr
120
+ when /\s+/ then skip_char
121
+ when /;/ then skip_line
122
+ else break
123
+ end
124
+ end
125
+ end
126
+ end # class CommonLisp
127
+ end; end # class SXP::Reader
@@ -26,5 +26,5 @@ module SXP; class Reader
26
26
  end
27
27
  end
28
28
  end
29
- end # class Reader
29
+ end # class Extended
30
30
  end; end # class SXP::Reader
@@ -1,6 +1,8 @@
1
1
  module SXP; class Reader
2
2
  ##
3
- # A Scheme-like S-expression parser.
3
+ # A Scheme R4RS S-expressions parser.
4
+ #
5
+ # @see http://people.csail.mit.edu/jaffer/r4rs_9.html#SEC65
4
6
  class Scheme < Extended
5
7
  DECIMAL = /^[+-]?(\d*)?\.\d*$/.freeze
6
8
  INTEGER_BASE_2 = /^[+-]?[01]+$/.freeze
@@ -9,6 +11,16 @@ module SXP; class Reader
9
11
  INTEGER_BASE_16 = /^[+-]?[\da-z]+$/i.freeze
10
12
  RATIONAL = /^([+-]?\d+)\/(\d+)$/.freeze
11
13
 
14
+ ##
15
+ # Initializes the reader.
16
+ #
17
+ # @param [IO, StringIO, String] input
18
+ # @param [Hash{Symbol => Object}] options
19
+ # @option options [Symbol] :version (:r4rs)
20
+ def initialize(input, options = {}, &block)
21
+ super(input, {:version => :r4rs}.merge(options), &block)
22
+ end
23
+
12
24
  ##
13
25
  # @return [Object]
14
26
  def read_token
@@ -35,18 +47,18 @@ module SXP; class Reader
35
47
  def read_sharp
36
48
  skip_char # '#'
37
49
  case char = read_char
38
- when ?n then nil # not in Scheme
39
- when ?f then false
40
- when ?t then true
41
- when ?b then read_integer(2)
42
- when ?o then read_integer(8)
43
- when ?d then read_integer(10)
44
- when ?x then read_integer(16)
45
- when ?\\ then read_character
46
- when ?; then skip; read
47
- when ?! then skip_line; read # shebang
50
+ when ?n, ?N then nil # not in Scheme per se
51
+ when ?f, ?F then false
52
+ when ?t, ?T then true
53
+ when ?b, ?B then read_integer(2)
54
+ when ?o, ?O then read_integer(8)
55
+ when ?d, ?D then read_integer(10)
56
+ when ?x, ?X then read_integer(16)
57
+ when ?\\ then read_character
58
+ when ?; then skip; read
59
+ when ?! then skip_line; read # shebang
48
60
  else raise Error, "invalid sharp-sign read syntax: ##{char.chr}"
49
61
  end
50
62
  end
51
- end # class Reader
63
+ end # class Scheme
52
64
  end; end # class SXP::Reader
@@ -0,0 +1,80 @@
1
+ require 'rdf' # @see http://rubygems.org/gems/rdf
2
+
3
+ module SXP; class Reader
4
+ ##
5
+ # A SPARQL Syntax Expressions (SSE) parser.
6
+ #
7
+ # Requires [RDF.rb](http://rdf.rubyforge.org/).
8
+ #
9
+ # @see http://openjena.org/wiki/SSE
10
+ class SPARQL < Extended
11
+ BNODE_ID = /^_:([A-Za-z][A-Za-z0-9]*)/.freeze # FIXME
12
+ BNODE_NEW = /^_:$/.freeze
13
+ VARIABLE = /^\?([A-Za-z][A-Za-z0-9]*)/.freeze # FIXME
14
+ URIREF = /^<([^>]+)>/.freeze
15
+
16
+ ##
17
+ # @return [Object]
18
+ def read_token
19
+ case peek_char
20
+ when ?" then [:atom, read_rdf_literal] # "
21
+ when ?< then [:atom, read_rdf_uri]
22
+ else super
23
+ end
24
+ end
25
+
26
+ ##
27
+ # @return [RDF::Literal]
28
+ def read_rdf_literal
29
+ value = read_string
30
+ options = case peek_char
31
+ when ?@
32
+ skip_char # '@'
33
+ {:language => read_atom}
34
+ when ?^
35
+ 2.times { skip_char } # '^^'
36
+ {:datatype => read_rdf_uri} # TODO: support prefixed names
37
+ else {}
38
+ end
39
+ RDF::Literal.new(value, options)
40
+ end
41
+
42
+ ##
43
+ # @return [RDF::URI]
44
+ def read_rdf_uri
45
+ buffer = String.new
46
+ skip_char # '<'
47
+ until peek_char == ?>
48
+ buffer << read_char # TODO: unescaping
49
+ end
50
+ skip_char # '>'
51
+ RDF::URI.new(buffer)
52
+ end
53
+
54
+ ##
55
+ # @return [Object]
56
+ def read_atom
57
+ case buffer = read_literal
58
+ when '.' then buffer.to_sym
59
+ when INTEGER then RDF::Literal.new(Integer(buffer))
60
+ when BNODE_ID then RDF::Node.new($1)
61
+ when BNODE_NEW then RDF::Node.new
62
+ when VARIABLE then RDF::Query::Variable.new($1)
63
+ else buffer.to_sym
64
+ end
65
+ end
66
+
67
+ ##
68
+ # @return [void]
69
+ def skip_comments
70
+ until eof?
71
+ case (char = peek_char).chr
72
+ when /\s+/ then skip_char
73
+ when /;/ then skip_line
74
+ when /#/ then skip_line
75
+ else break
76
+ end
77
+ end
78
+ end
79
+ end # class SPARQL
80
+ end; end # class SXP::Reader
data/lib/sxp/reader.rb CHANGED
@@ -2,22 +2,73 @@ module SXP
2
2
  ##
3
3
  # The base class for S-expression parsers.
4
4
  class Reader
5
- autoload :Basic, 'sxp/reader/basic'
6
- autoload :Extended, 'sxp/reader/extended'
7
- autoload :Scheme, 'sxp/reader/scheme'
5
+ autoload :Basic, 'sxp/reader/basic'
6
+ autoload :Extended, 'sxp/reader/extended'
7
+ autoload :Scheme, 'sxp/reader/scheme'
8
+ autoload :CommonLisp, 'sxp/reader/common_lisp'
9
+ autoload :SPARQL, 'sxp/reader/sparql'
8
10
 
9
11
  class Error < StandardError; end
10
12
  class EOF < Error; end
11
13
 
12
14
  include Enumerable
13
15
 
14
- # @return [Object]
15
- attr_reader :input
16
+ ##
17
+ # Reads all S-expressions from a given input URL using the HTTP or FTP
18
+ # protocols.
19
+ #
20
+ # @param [String, #to_s] url
21
+ # @param [Hash{Symbol => Object}] options
22
+ # @return [Enumerable<Object>]
23
+ def self.read_url(url, options = {})
24
+ require 'open-uri'
25
+ open(url.to_s, 'rb', nil, options) { |io| read_all(io, options) }
26
+ end
16
27
 
17
- # @return [Hash{Symbol => Object}]
18
- attr_reader :options
28
+ ##
29
+ # Reads all S-expressions from the given input files.
30
+ #
31
+ # @param [Enumerable<String>] filenames
32
+ # @param [Hash{Symbol => Object}] options
33
+ # @return [Enumerable<Object>]
34
+ def self.read_files(*filenames)
35
+ options = filenames.last.is_a?(Hash) ? filenames.pop : {}
36
+ filenames.map { |filename| read_file(filename, options) }.inject { |sxps, sxp| sxps + sxp }
37
+ end
38
+
39
+ ##
40
+ # Reads all S-expressions from a given input file.
41
+ #
42
+ # @param [String, #to_s] filename
43
+ # @param [Hash{Symbol => Object}] options
44
+ # @return [Enumerable<Object>]
45
+ def self.read_file(filename, options = {})
46
+ File.open(filename.to_s, 'rb') { |io| read_all(io, options) }
47
+ end
48
+
49
+ ##
50
+ # Reads all S-expressions from the given input stream.
51
+ #
52
+ # @param [IO, StringIO, String] input
53
+ # @param [Hash{Symbol => Object}] options
54
+ # @return [Enumerable<Object>]
55
+ def self.read_all(input, options = {})
56
+ self.new(input, options).read_all
57
+ end
19
58
 
20
59
  ##
60
+ # Reads one S-expression from the given input stream.
61
+ #
62
+ # @param [IO, StringIO, String] input
63
+ # @param [Hash{Symbol => Object}] options
64
+ # @return [Object]
65
+ def self.read(input, options = {})
66
+ self.new(input, options).read
67
+ end
68
+
69
+ ##
70
+ # Initializes the reader.
71
+ #
21
72
  # @param [IO, StringIO, String] input
22
73
  # @param [Hash{Symbol => Object}] options
23
74
  def initialize(input, options = {}, &block)
@@ -28,7 +79,8 @@ module SXP
28
79
  @input = input
29
80
  when input.respond_to?(:to_str)
30
81
  require 'stringio' unless defined?(StringIO)
31
- @input = StringIO.new(input.to_str)
82
+ # NOTE: StringIO#ungetc mutates the string, so we use #dup to take a copy.
83
+ @input = StringIO.new(input.to_str.dup)
32
84
  else
33
85
  raise ArgumentError, "expected an IO or String input stream, but got #{input.inspect}"
34
86
  end
@@ -41,16 +93,22 @@ module SXP
41
93
  end
42
94
  end
43
95
 
96
+ # @return [Object]
97
+ attr_reader :input
98
+
99
+ # @return [Hash]
100
+ attr_reader :options
101
+
44
102
  ##
45
103
  # @yield [object]
46
104
  # @yieldparam [Object] object
47
105
  # @return [Enumerator]
48
106
  def each(&block)
49
- #block_given? ?
50
- # to_enum
51
- #else
52
- # block.call(read)
53
- #end
107
+ unless block_given?
108
+ to_enum
109
+ else
110
+ read_all.each(&block) # TODO: lazy reading
111
+ end
54
112
  end
55
113
 
56
114
  ##
data/lib/sxp/version.rb CHANGED
@@ -2,7 +2,7 @@ module SXP
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 5
5
+ TINY = 6
6
6
  EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
data/lib/sxp.rb CHANGED
@@ -26,15 +26,14 @@ module SXP
26
26
  autoload :Reader, 'sxp/reader'
27
27
 
28
28
  ##
29
- # Reads all S-expressions from a given input URI using the HTTP or FTP
29
+ # Reads all S-expressions from a given input URL using the HTTP or FTP
30
30
  # protocols.
31
31
  #
32
32
  # @param [String, #to_s] url
33
33
  # @param [Hash{Symbol => Object}] options
34
34
  # @return [Enumerable<Object>]
35
35
  def self.read_url(url, options = {})
36
- require 'open-uri'
37
- open(url.to_s, 'rb', nil, options) { |io| read_all(io, options) }
36
+ Reader::Scheme.read_url(url, options)
38
37
  end
39
38
 
40
39
  ##
@@ -44,8 +43,7 @@ module SXP
44
43
  # @param [Hash{Symbol => Object}] options
45
44
  # @return [Enumerable<Object>]
46
45
  def self.read_files(*filenames)
47
- options = filenames.last.is_a?(Hash) ? filenames.pop : {}
48
- filenames.map { |filename| read_file(filename, options) }.inject { |sxps, sxp| sxps + sxp }
46
+ Reader::Scheme.read_files(*filenames)
49
47
  end
50
48
 
51
49
  ##
@@ -55,7 +53,7 @@ module SXP
55
53
  # @param [Hash{Symbol => Object}] options
56
54
  # @return [Enumerable<Object>]
57
55
  def self.read_file(filename, options = {})
58
- File.open(filename.to_s, 'rb') { |io| read_all(io, options) }
56
+ Reader::Scheme.read_file(filename, options)
59
57
  end
60
58
 
61
59
  ##
@@ -65,7 +63,7 @@ module SXP
65
63
  # @param [Hash{Symbol => Object}] options
66
64
  # @return [Enumerable<Object>]
67
65
  def self.read_all(input, options = {})
68
- Reader::Scheme.new(input, options).read_all
66
+ Reader::Scheme.read_all(input, options)
69
67
  end
70
68
 
71
69
  ##
@@ -75,7 +73,7 @@ module SXP
75
73
  # @param [Hash{Symbol => Object}] options
76
74
  # @return [Object]
77
75
  def self.read(input, options = {})
78
- Reader::Scheme.new(input, options).read
76
+ Reader::Scheme.read(input, options)
79
77
  end
80
78
 
81
79
  class << self
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 5
9
- version: 0.0.5
8
+ - 6
9
+ version: 0.0.6
10
10
  platform: ruby
11
11
  authors:
12
12
  - Arto Bendiken
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-23 00:00:00 +02:00
17
+ date: 2010-08-25 00:00:00 +02:00
18
18
  default_executable: sxp2rdf
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -45,7 +45,7 @@ dependencies:
45
45
  version: 1.3.0
46
46
  type: :development
47
47
  version_requirements: *id002
48
- description: " SXP is a data interchange format based on S-expressions, the simplest and\n most versatile known means of representing complex data structures such as\n lists, trees and graphs.\n"
48
+ description: A pure-Ruby implementation of a universal S-expression parser.
49
49
  email: arto.bendiken@gmail.com
50
50
  executables:
51
51
  - sxp2rdf
@@ -66,8 +66,10 @@ files:
66
66
  - lib/sxp/list.rb
67
67
  - lib/sxp/pair.rb
68
68
  - lib/sxp/reader/basic.rb
69
+ - lib/sxp/reader/common_lisp.rb
69
70
  - lib/sxp/reader/extended.rb
70
71
  - lib/sxp/reader/scheme.rb
72
+ - lib/sxp/reader/sparql.rb
71
73
  - lib/sxp/reader.rb
72
74
  - lib/sxp/version.rb
73
75
  - lib/sxp/writer.rb
@@ -103,6 +105,6 @@ rubyforge_project: sxp
103
105
  rubygems_version: 1.3.6
104
106
  signing_key:
105
107
  specification_version: 3
106
- summary: A pure-Ruby implementation of the SXP data interchange format.
108
+ summary: A pure-Ruby implementation of a universal S-expression parser.
107
109
  test_files: []
108
110