Class: SpectatorSport::SearchQuery::Parser

Inherits:
Object
  • Object
show all
Defined in:
app/models/spectator_sport/search_query/parser.rb

Overview

Recursive-descent parser. AND binds tighter than OR, whether AND is written explicitly or implied by juxtaposition:

query      := or_expr(:and)
or_expr(d) := and_expr(d) ( "OR" and_expr(d) )*
and_expr(d) := factor ( "AND" factor | factor )*   # a bare (no keyword)
                                                  # factor combines via `d`
factor     := "-"* primary                         # each "-" toggles negation
primary    := "(" or_expr(:and) ")"                 # AND-group
          | "{" or_expr(:or) "}"                  # OR-group
          | LABEL
          | DATE_FILTER                           # created:2026-01-31, updated:>=2026-01-31, etc

d (the default) only matters for juxtaposition with no keyword: at the top level and inside "(...)" it's AND, inside "..." it's OR. Explicit "AND"/"OR" keywords always mean what they say regardless of d.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tokens) ⇒ Parser

Returns a new instance of Parser.



24
25
26
27
# File 'app/models/spectator_sport/search_query/parser.rb', line 24

def initialize(tokens)
  @tokens = tokens
  @position = 0
end

Class Method Details

.parse(input) ⇒ Object



20
21
22
# File 'app/models/spectator_sport/search_query/parser.rb', line 20

def self.parse(input)
  new(Lexer.tokenize(input)).parse
end

Instance Method Details

#parseObject

Raises:



29
30
31
32
33
34
35
36
# File 'app/models/spectator_sport/search_query/parser.rb', line 29

def parse
  raise SyntaxError, "Query is blank" if @tokens.empty?

  node = parse_or(:and)
  raise SyntaxError, "Unexpected trailing input after #{describe(peek(-1))}" unless at_end?

  node
end