Class: SPARQL::Grammar::Parser

Inherits:
Object
  • Object
show all
Includes:
Meta
Defined in:
lib/sparql/grammar/parser.rb

Overview

A parser for the SPARQL 1.0 grammar.

See Also:

Defined Under Namespace

Classes: Error

Constant Summary

START =
SPARQL_GRAMMAR.Query
RDF_TYPE =
(a = RDF.type.dup; a.lexical = 'a'; a).freeze

Constants included from Meta

BRANCHES

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (SPARQL::Grammar::Parser) initialize(input = nil, options = {})

Initializes a new parser instance.

Parameters:

  • (String, #to_s) input (defaults to: nil)
  • (Hash{Symbol => Object}) options (defaults to: {})

Options Hash (options):

  • (Hash) :prefixes — default: Hash.new

    the prefix mappings to use (for acessing intermediate parser productions)

  • (#to_s) :base_uri — default: nil

    the base URI to use when resolving relative URIs (for acessing intermediate parser productions)

  • (#to_s) :anon_base — default: "b0"

    Basis for generating anonymous Nodes

  • (Boolean) :resolve_uris — default: false

    Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE as S-Expressions, use the original prefixed and relative URIs along with `base` and `prefix` definitions.

  • (Boolean) :validate — default: false

    whether to validate the parsed statements and values

  • (Boolean) :progress

    Show progress of parser productions

  • (Boolean) :debug

    Detailed debug output



37
38
39
40
41
42
43
# File 'lib/sparql/grammar/parser.rb', line 37

def initialize(input = nil, options = {})
  @options = {:anon_base => "b0", :validate => false}.merge(options)
  self.input = input if input
  @productions = []
  @vars = {}
  @nd_var_gen = "0"
end

Instance Attribute Details

- (String) input

The current input string being processed.

Returns:

  • (String)


55
56
57
# File 'lib/sparql/grammar/parser.rb', line 55

def input
  @input
end

- (Hash) options (readonly)

Any additional options for the parser.

Returns:

  • (Hash)


49
50
51
# File 'lib/sparql/grammar/parser.rb', line 49

def options
  @options
end

- (Array) result

The internal representation of the result using hierarch of RDF objects and SPARQL::Algebra::Operator objects.

Returns:

  • (Array)

See Also:



68
69
70
# File 'lib/sparql/grammar/parser.rb', line 68

def result
  @result
end

- (Array<Token>) tokens (readonly)

The current input tokens being processed.

Returns:

  • (Array<Token>)


61
62
63
# File 'lib/sparql/grammar/parser.rb', line 61

def tokens
  @tokens
end

Instance Method Details

- (HRDF::URI) base_uri

Returns the Base URI defined for the parser, as specified or when parsing a BASE prologue element.

Examples:

parser.base  #=> RDF::URI('http://example.com/')

Returns:

  • (HRDF::URI)


256
257
258
# File 'lib/sparql/grammar/parser.rb', line 256

def base_uri
  @options[:base_uri]
end

- (RDF::URI) base_uri=(uri)

Set the Base URI to use for this parser.

Examples:

parser.base_uri = RDF::URI('http://purl.org/dc/terms/')

Parameters:

  • (RDF::URI, #to_s) uri

Returns:

  • (RDF::URI)


269
270
271
# File 'lib/sparql/grammar/parser.rb', line 269

def base_uri=(uri)
  @options[:base_uri] = RDF::URI(uri)
end

- (Array) parse(prod = START)

Parse query

The result is a SPARQL Algebra S-List. Productions return an array such as the following:

  (prefix ((: <http://example/>))
    (union
      (bgp (triple ?s ?p ?o))
      (graph ?g
        (bgp (triple ?s ?p ?o)))))

Algebra is based on the SPARQL Algebra notes

Parameters:

  • (Symbol, #to_s) prod (defaults to: START)

    The starting production for the parser. It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.

Returns:

  • (Array)

See Also:



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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
# File 'lib/sparql/grammar/parser.rb', line 120

def parse(prod = START)
  @prod_data = [{}]
  prod = prod.to_s.split("#").last.to_sym unless prod.is_a?(Symbol)
  todo_stack = [{:prod => prod, :terms => nil}]

  while !todo_stack.empty?
    pushed = false
    if todo_stack.last[:terms].nil?
      todo_stack.last[:terms] = []
      token = tokens.first
      @lineno = token.lineno if token
      debug("parse(token)", "#{token.inspect}, prod #{todo_stack.last[:prod]}, depth #{todo_stack.length}")
      
      # Got an opened production
      onStart(abbr(todo_stack.last[:prod]))
      break if token.nil?
      
      cur_prod = todo_stack.last[:prod]
      prod_branch = BRANCHES[cur_prod.to_sym]
      error("parse", "No branches found for '#{abbr(cur_prod)}'",
        :production => cur_prod, :token => token) if prod_branch.nil?
      sequence = prod_branch[token.representation]
      debug("parse(production)", "cur_prod #{cur_prod}, token #{token.representation.inspect} prod_branch #{prod_branch.keys.inspect}, sequence #{sequence.inspect}")
      if sequence.nil?
        expected = prod_branch.values.uniq.map {|u| u.map {|v| abbr(v).inspect}.join(",")}
        error("parse", "Found '#{token.inspect}' when parsing a #{abbr(cur_prod)}. expected #{expected.join(' | ')}",
          :production => cur_prod, :token => token)
      end
      todo_stack.last[:terms] += sequence
    end
    
    debug("parse(terms)", "stack #{todo_stack.last.inspect}, depth #{todo_stack.length}")
    while !todo_stack.last[:terms].to_a.empty?
      term = todo_stack.last[:terms].shift
      debug("parse tokens(#{term})", tokens.inspect)
      if tokens.map(&:representation).include?(term)
        token = accept(term)
        @lineno = token.lineno if token
        debug("parse", "term(#{token.inspect}): #{term}")
        if token
          onToken(abbr(term), token.value)
        else
          error("parse", "Found '#{word}...'; #{term} expected",
            :production => todo_stack.last[:prod], :token => tokens.first)
        end
      else
        todo_stack << {:prod => term, :terms => nil}
        debug("parse(push)", "stack #{term}, depth #{todo_stack.length}")
        pushed = true
        break
      end
    end
    
    while !pushed && !todo_stack.empty? && todo_stack.last[:terms].to_a.empty?
      debug("parse(pop)", "stack #{todo_stack.last.inspect}, depth #{todo_stack.length}")
      todo_stack.pop
      onFinish
    end
  end
  while !todo_stack.empty?
    debug("parse(pop)", "stack #{todo_stack.last.inspect}, depth #{todo_stack.length}")
    todo_stack.pop
    onFinish
  end
  
  # The last thing on the @prod_data stack is the result
  @result = case
  when !prod_data.is_a?(Hash)
    prod_data
  when prod_data.empty?
    nil
  when prod_data[:query]
    prod_data[:query].to_a.length == 1 ? prod_data[:query].first : prod_data[:query]
  else
    key = prod_data.keys.first
    [key] + prod_data[key]  # Creates [:key, [:triple], ...]
  end
end

- (Object) prefix(name, uri) - (Object) prefix(name)

Defines the given named URI prefix for this parser.

Examples:

Defining a URI prefix

parser.prefix :dc, RDF::URI('http://purl.org/dc/terms/')

Returning a URI prefix

parser.prefix(:dc)    #=> RDF::URI('http://purl.org/dc/terms/')

Overloads:

  • - (Object) prefix(name, uri)

    Parameters:

    • (Symbol, #to_s) name
    • (RDF::URI, #to_s) uri
  • - (Object) prefix(name)

    Parameters:

    • (Symbol, #to_s) name

Returns:

  • (RDF::URI)


243
244
245
246
# File 'lib/sparql/grammar/parser.rb', line 243

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

- (Hash{Symbol => RDF::URI}) prefixes

Returns the URI prefixes currently defined for this parser.

Examples:

parser.prefixes[:dc]  #=> RDF::URI('http://purl.org/dc/terms/')

Returns:

  • (Hash{Symbol => RDF::URI})

Since:

  • 0.3.0



207
208
209
# File 'lib/sparql/grammar/parser.rb', line 207

def prefixes
  @options[:prefixes] ||= {}
end

- (Hash{Symbol => RDF::URI}) prefixes=(prefixes)

Defines the given URI prefixes for this parser.

Examples:

parser.prefixes = {
  :dc => RDF::URI('http://purl.org/dc/terms/'),
}

Parameters:

  • (Hash{Symbol => RDF::URI}) prefixes

Returns:

  • (Hash{Symbol => RDF::URI})

Since:

  • 0.3.0



222
223
224
# File 'lib/sparql/grammar/parser.rb', line 222

def prefixes=(prefixes)
  @options[:prefixes] = prefixes
end

- (Object) to_s



100
101
102
# File 'lib/sparql/grammar/parser.rb', line 100

def to_s
  @result.to_sxp
end

- (String) to_sse

Returns:

  • (String)


96
97
98
# File 'lib/sparql/grammar/parser.rb', line 96

def to_sse
  @result
end

- (Boolean) valid?

Returns `true` if the input string is syntactically valid.

Returns:

  • (Boolean)


89
90
91
92
93
# File 'lib/sparql/grammar/parser.rb', line 89

def valid?
  parse
rescue Error
  false
end

- (Boolean) validate?

Returns `true` if parsed statements and values should be validated.

Returns:

  • (Boolean)

    `true` or `false`

Since:

  • 0.3.0



278
279
280
# File 'lib/sparql/grammar/parser.rb', line 278

def validate?
  @options[:validate]
end