class Scim2::Filter::Lexer

Implements a SCIM2 compliant lexer for query filters. This class is responsible for producing and emitting tokens for consumption by a parser. It is not intended to use directly.

Attributes

filename[R]
lineno[R]
state[RW]

Public Instance Methods

_next_token() click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 54
def _next_token
  text = @ss.peek(1)
  @lineno  +=  1  if text == "\n"
  token = case @state
    when nil
  case
          when (text = @ss.scan(/\s[eE][qQ]\s/))
             action { [:EQ, :eq] }

          when (text = @ss.scan(/\s[nN][eE]\s/))
             action { [:NE, :ne] }

          when (text = @ss.scan(/\s[gG][tT]\s/))
             action { [:GT, :gt] }

          when (text = @ss.scan(/\s[gG][eE]\s/))
             action { [:GE, :ge] }

          when (text = @ss.scan(/\s[lL][tT]\s/))
             action { [:LT, :lt] }

          when (text = @ss.scan(/\s[lL][eE]\s/))
             action { [:LE, :le] }

          when (text = @ss.scan(/\s[cC][oO]\s/))
             action { [:CO, :co] }

          when (text = @ss.scan(/\s[sS][wW]\s/))
             action { [:SW, :sw] }

          when (text = @ss.scan(/\s[eE][wW]\s/))
             action { [:EW, :ew] }

          when (text = @ss.scan(/\s[pP][rR]/))
             action { [:PR, :pr] }

          when (text = @ss.scan(/\s[aA][nN][dD]\s/))
             action { [:AND, :and] }

          when (text = @ss.scan(/\s[oO][rR]\s/))
             action { [:OR, :or] }

          when (text = @ss.scan(/[nN][oO][tT]\s*/))
             action { [:NOT, :not] }  # NOTE: RFC7644 (Section 3.4.2) seems to specify no space, but the example contradicts it

          when (text = @ss.scan(/\(/))
             action { [:LPAREN, text] }

          when (text = @ss.scan(/\)/))
             action { [:RPAREN, text] }

          when (text = @ss.scan(/\[/))
             action { [:LBRACKET, text] }

          when (text = @ss.scan(/\]/))
             action { [:RBRACKET, text] }

          when (text = @ss.scan(/null/))
             action { [:NULL, nil] }

          when (text = @ss.scan(/(?:true|false)/))
             action { [:BOOLEAN, text == 'true'] }

          when (text = @ss.scan(/\d+/))
             action { [:NUMBER, text.to_i] }

          when (text = @ss.scan(/"(?:[^"\\]|\\.)*"/))
             action { [:STRING, text.undump] }

          when (text = @ss.scan(/([a-zA-Z]+:[a-zA-Z0-9:\._-]+):/))
             action { [:SCHEMA, @ss.captures.first] }

          when (text = @ss.scan(/[a-zA-Z][a-zA-Z0-9_-]*/))
             action { [:ATTRNAME, text.to_sym] }

          when (text = @ss.scan(/\./))
             action { [:DOT, text] }

  
  else
    text = @ss.string[@ss.pos .. -1]
    raise  ScanError, "can not match: '" + text + "'"
  end  # if

else
  raise  ScanError, "undefined state: '" + state.to_s + "'"
end  # case state
  token
end
action() { || ... } click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 23
def action
  yield
end
load_file( filename ) click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 33
def load_file( filename )
  @filename = filename
  File.open(filename, "r") do |f|
    scan_setup(f.read)
  end
end
next_token() click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 46
def next_token
  return if @ss.eos?

  # skips empty actions
  until token = _next_token or @ss.eos?; end
  token
end
scan(str)
Alias for: scan_str
scan_file( filename ) click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 40
def scan_file( filename )
  load_file(filename)
  do_parse
end
scan_setup(str) click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 17
def scan_setup(str)
  @ss = StringScanner.new(str)
  @lineno =  1
  @state  = nil
end
scan_str(str) click to toggle source
# File lib/scim2/filter/lexer.rex.rb, line 27
def scan_str(str)
  scan_setup(str)
  do_parse
end
Also aliased as: scan