david-mccullars/scim2-filter

View on GitHub
lib/scim2/filter/lexer.rex

Summary

Maintainability
Test Coverage
class Scim2::Filter::Lexer

macro
  EQ                [eE][qQ]
  NE                [nN][eE]
  GT                [gG][tT]
  GE                [gG][eE]
  LT                [lL][tT]
  LE                [lL][eE]
  CO                [cC][oO]
  SW                [sS][wW]
  EW                [eE][wW]
  PR                [pP][rR]

  AND               [aA][nN][dD]
  OR                [oO][rR]
  NOT               [nN][oO][tT]

  LPAREN            \(
  RPAREN            \)
  LBRACKET          \[
  RBRACKET          \]
  COLON             :
  DOT               \.

  DIGIT             \d
  ALPHA             [a-zA-Z]
  NAMECHAR          [a-zA-Z0-9_-]
  SCHEMACHAR        [a-zA-Z0-9:\._-]
  ESCAPEDSTR        "(?:[^"\\]|\\.)*"

rule
  # Attribute Operators
  \s{EQ}\s          { [:EQ, :eq] }
  \s{NE}\s          { [:NE, :ne] }
  \s{GT}\s          { [:GT, :gt] }
  \s{GE}\s          { [:GE, :ge] }
  \s{LT}\s          { [:LT, :lt] }
  \s{LE}\s          { [:LE, :le] }
  \s{CO}\s          { [:CO, :co] }
  \s{SW}\s          { [:SW, :sw] }
  \s{EW}\s          { [:EW, :ew] }
  \s{PR}            { [:PR, :pr] }

  # Logical Operators
  \s{AND}\s         { [:AND, :and] }
  \s{OR}\s          { [:OR, :or] }
  {NOT}\s*          { [:NOT, :not] }  # NOTE: RFC7644 (Section 3.4.2) seems to specify no space, but the example contradicts it

  # Grouping Operators
  {LPAREN}          { [:LPAREN, text] }
  {RPAREN}          { [:RPAREN, text] }
  {LBRACKET}        { [:LBRACKET, text] }
  {RBRACKET}        { [:RBRACKET, text] }

  # Other
  null                                  { [:NULL, nil] }
  (?:true|false)                        { [:BOOLEAN, text == 'true'] }
  {DIGIT}+                              { [:NUMBER, text.to_i] }
  {ESCAPEDSTR}                          { [:STRING, text.undump] }
  ({ALPHA}+{COLON}{SCHEMACHAR}+){COLON} { [:SCHEMA, @ss.captures.first] }
  {ALPHA}{NAMECHAR}*                    { [:ATTRNAME, text.to_sym] }
  {DOT}                                 { [:DOT, text] }

end