Class: SXP::Reader::SPARQL
- Defined in:
- lib/sxp/reader/sparql.rb
Overview
A SPARQL Syntax Expressions (SSE) parser.
Requires [RDF.rb](rdf.rubyforge.org/).
Constant Summary collapse
- A =
Alias for rdf:type
/^a$/- BASE =
Base token, causes next URI to be treated as the
base_urifor further URI expansion /^base$/i- PREFIX =
Prefix token, causes following prefix and URI pairs to be used for transforming PNAME tokens into URIs.
/^prefix$/i- NIL =
/^nil$/i- FALSE =
/^false$/i- TRUE =
/^true$/i- EXPONENT =
/[eE][+-]?[0-9]+/- DECIMAL =
/^[+-]?(\d*)?\.\d*$/- DOUBLE =
/^[+-]?(\d*)?\.\d*#{EXPONENT}$/- BNODE_ID =
BNode with identifier
/^_:([^\s]*)/- BNODE_NEW =
Anonymous BNode
/^_:$/- VAR_ID =
Distinguished variable
/^\?(.*)/- ND_VAR =
Non-distinguished variable
/^\?(:?\?([0-9]+)?|(\.[0-9]+))/- PNAME =
A QName, subject to expansion to URIs using PREFIX
/([^:]*):(.*)/- RDF_TYPE =
(a = RDF.type.dup; a.lexical = 'a'; a).freeze
Constants inherited from Extended
Extended::ATOM, Extended::LPARENS, Extended::RPARENS
Constants inherited from Basic
Basic::ATOM, Basic::INTEGER, Basic::LPARENS, Basic::RATIONAL, Basic::RPARENS
Instance Attribute Summary collapse
-
#base_uri ⇒ Object
Base URI as specified or when parsing parsing a BASE token using the immediately following token, which must be a URI.
-
#prefixes ⇒ Hash{Object => RDF::URI}
Prefixes defined while parsing.
Attributes inherited from SXP::Reader
Instance Method Summary collapse
-
#initialize(input, options = {}, &block) ⇒ SPARQL
constructor
Initializes the reader.
-
#prefix(name, uri = nil) ⇒ RDF::URI
Defines the given named URI prefix for this parser.
-
#read_atom ⇒ Object
Reads an SSE Atom.
-
#read_rdf_literal ⇒ RDF::Literal
Reads literals corresponding to SPARQL/Turtle/Notation-3 syntax.
-
#read_rdf_uri ⇒ RDF::URI
Reads a URI in SPARQL/Turtle/Notation-3 syntax.
-
#read_token ⇒ Object
Reads SSE Tokens, including RDF::Literal, RDF::URI and RDF::Node.
- #skip_comments ⇒ void
-
#variable(id, distinguished = true) ⇒ RDF::Query::Variable
Return variable allocated to an ID.
Methods inherited from Basic
#read_character, #read_literal, #read_string
Methods inherited from SXP::Reader
#each, read, #read, read_all, #read_all, #read_character, read_file, #read_files, #read_integer, #read_list, #read_literal, #read_sharp, #read_string, read_url
Constructor Details
#initialize(input, options = {}, &block) ⇒ SPARQL
Initializes the reader.
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/sxp/reader/sparql.rb', line 70 def initialize(input, = {}, &block) super { @prefixes = {}; @bnodes = {}; @list_depth = 0 } if block_given? case block.arity when 1 then block.call(self) else self.instance_eval(&block) end end end |
Instance Attribute Details
#base_uri ⇒ Object
Base URI as specified or when parsing parsing a BASE token using the immediately following token, which must be a URI.
41 42 43 |
# File 'lib/sxp/reader/sparql.rb', line 41 def base_uri @base_uri end |
#prefixes ⇒ Hash{Object => RDF::URI}
Prefixes defined while parsing
46 47 48 |
# File 'lib/sxp/reader/sparql.rb', line 46 def prefixes @prefixes end |
Instance Method Details
#prefix(name, uri = nil) ⇒ RDF::URI
Defines the given named URI prefix for this parser.
60 61 62 63 |
# File 'lib/sxp/reader/sparql.rb', line 60 def prefix(name, uri = nil) name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym) uri.nil? ? @prefixes[name] : @prefixes[name] = uri end |
#read_atom ⇒ Object
Reads an SSE Atom
Atoms parsed including base, prefix, true, false, numeric, BNodes and variables.
Creates RDF::Literal, RDF::Node, or RDF::Query::Variable instances where appropriate.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/sxp/reader/sparql.rb', line 213 def read_atom case buffer = read_literal when '.' then buffer.to_sym when A then RDF_TYPE when BASE then @parsed_base = true; buffer.to_sym when NIL then nil when FALSE then RDF::Literal(false) when TRUE then RDF::Literal(true) when DOUBLE then RDF::Literal::Double.new(buffer) when DECIMAL then RDF::Literal::Decimal.new(buffer) when INTEGER then RDF::Literal::Integer.new(buffer) when BNODE_ID then @bnodes[$1] ||= RDF::Node($1) when BNODE_NEW then RDF::Node.new when ND_VAR then variable($1, false) when VAR_ID then variable($1, true) else buffer.to_sym end end |
#read_rdf_literal ⇒ RDF::Literal
Reads literals corresponding to SPARQL/Turtle/Notation-3 syntax
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/sxp/reader/sparql.rb', line 150 def read_rdf_literal value = read_string = case peek_char when ?@ skip_char # '@' {language: read_atom.downcase} when ?^ 2.times { skip_char } # '^^' {datatype: read_token.last} else {} end RDF::Literal(value, ) end |
#read_rdf_uri ⇒ RDF::URI
Reads a URI in SPARQL/Turtle/Notation-3 syntax
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/sxp/reader/sparql.rb', line 171 def read_rdf_uri buffer = String.new skip_char # '<' return :< if (char = peek_char).nil? || char.chr !~ ATOM # FIXME: nasty special case for the '< symbol return :<= if peek_char.chr.eql?(?=.chr) && read_char # FIXME: nasty special case for the '<= symbol until peek_char == ?> buffer << read_char # TODO: unescaping end skip_char # '>' # If we have a base URI, use that when constructing a new URI uri = if self.base_uri && RDF::URI(buffer).relative? u = self.base_uri.join(buffer) u.lexical = "<#{buffer}>" unless u.to_s == buffer # So that it can be re-serialized properly u else RDF::URI(buffer) end # If we previously parsed a "BASE" element, then this URI is used to set that value if @parsed_base self.base_uri = uri @parsed_base = nil end # If we previously parsed a "PREFIX" element, associate this URI with the prefix if @parsed_prefix prefix(@parsed_prefix, uri) @parsed_prefix = nil end uri end |
#read_token ⇒ Object
Reads SSE Tokens, including RDF::Literal, RDF::URI and RDF::Node.
Performs forward reference for prefix and base URI representations and saves in #base_uri and #prefixes accessors.
Transforms tokens matching a PNAME pattern into RDF::URI instances if a match is found with a previously identified PREFIX.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/sxp/reader/sparql.rb', line 90 def read_token case peek_char when ?" then [:atom, read_rdf_literal] # " when ?< then [:atom, read_rdf_uri] else tok = super # If we just parsed "PREFIX", and this is an opening list, then # record list depth and process following as token, URI pairs # # Once we've closed the list, go out of prefix mode if tok.is_a?(Array) && tok[0] == :list if '(['.include?(tok[1]) @list_depth += 1 else @list_depth -= 1 @prefix_depth = nil if @prefix_depth && @list_depth < @prefix_depth end end if tok.is_a?(Array) && tok[0] == :atom && tok[1].is_a?(Symbol) value = tok[1].to_s # We previously parsed a PREFIX, this will be the map value @parsed_prefix = value.chop if @prefix_depth && @prefix_depth > 0 # If we just saw PREFIX, then this starts the parsing mode @prefix_depth = @list_depth + 1 if value =~ PREFIX # If the token is of the form 'prefix:suffix', create a URI and give it the # token as a QName if value.to_s =~ PNAME && base = prefix($1) suffix = $2 #STDERR.puts "read_tok lexical: pfx: #{$1.inspect} => #{prefix($1).inspect}, sfx: #{suffix.inspect}" suffix = suffix.sub(/^\#/, "") if base.to_s.index("#") uri = RDF::URI(base.to_s + suffix) #STDERR.puts "read_tok lexical uri: #{uri.inspect}" # Cause URI to be serialized as a lexical uri.lexical = value [:atom, uri] else tok end else tok end end end |
#skip_comments ⇒ void
This method returns an undefined value.
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/sxp/reader/sparql.rb', line 234 def skip_comments until eof? case (char = peek_char).chr when /\s+/ then skip_char when /;/ then skip_line when /#/ then skip_line else break end end end |
#variable(id, distinguished = true) ⇒ RDF::Query::Variable
Return variable allocated to an ID. If no ID is provided, a new variable is allocated. Otherwise, any previous assignment will be used.
The variable has a #distinguished? method applied depending on if this is a disinguished or non-distinguished variable. Non-distinguished variables are effectively the same as BNodes.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/sxp/reader/sparql.rb', line 254 def variable(id, distinguished = true) id = nil if id.to_s.empty? if id @vars ||= {} @vars[id] ||= begin v = RDF::Query::Variable.new(id) v.distinguished = distinguished v end else v = RDF::Query::Variable.new v.distinguished = distinguished v end end |