class Graphlyte::Schema::Lexer

Constants

SIMPLE_EXPRESSION
SPECIAL_ARG_REGEX
START_MAP

Attributes

scanner[R]
stack[R]

Public Class Methods

new(gql, scanner: StringScanner.new(gql)) click to toggle source
# File lib/graphlyte/schema/parser.rb, line 265
def initialize(gql, scanner: StringScanner.new(gql))
  @original_string = gql
  @scanner = scanner
  @tokens = []
end

Public Instance Methods

tokenize() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 279
def tokenize
  until scanner.eos?
    case state
    when :default
      if scanner.scan /^query (\w+)/
        @tokens << [:START_QUERY, scanner[1]]
        push_state :query
      elsif scanner.scan /^mutation (\w+)/
        @tokens << [:START_MUTATION, scanner[1]]
        push_state :mutation
      elsif scanner.scan /\s*fragment\s*(\w+)\s*on\s*(\w+)/
        @tokens << [:START_FRAGMENT, scanner[1], scanner[2]]
        push_state :fragment
      elsif scanner.scan /\s*{\s*/
        @tokens << [:START_FIELD]
        push_state :field
      elsif scanner.scan /\s*}\s*/
        @tokens << [:END_EXPRESSION_SHOULDNT_GET_THIS]
      else
        advance
      end
    when :fragment
      if scanner.scan /\s*\}\s*/
        @tokens << [:END_FRAGMENT]
        pop_state
        pop_context
      elsif scanner.check /^\s*\{\s*/
        if get_context == :field
          push_state :field
          push_context :field
        else
          scanner.scan /^\s*\{\s*/
          push_context :field
        end
      else
        handle_field
      end
    when :mutation
      if scanner.scan /\}/
        @tokens << [:END_MUTATION]
        pop_state
        pop_context
      elsif scanner.check /^\s*\{\s*$/
        if get_context == :field
          push_state :field
        else
          scanner.scan /^\s*\{\s*$/
          push_context :field
        end
      else
        handle_field
      end
    when :query
      if scanner.scan /\s*\}\s*/
        @tokens << [:END_QUERY]
        pop_state
        pop_context
      elsif scanner.check /^\s*\{\s*/
        if get_context == :field
          push_state :field
          push_context :field
        else
          scanner.scan /^\s*\{\s*/
          push_context :field
        end
      else
        handle_field
      end
    when :field
      if scanner.check /\s*\}\s*/
        if get_context == :field
          scanner.scan /\s*\}\s*/
          @tokens << [:END_FIELD]
          pop_state
        else
          pop_state
        end
      else
        handle_field
      end
    when :hash_arguments
      handle_hash_arguments
    when :array_arguments
      handle_array_arguments
    when :arguments
      if scanner.scan /\s*\)\s*/
        @tokens << [:END_ARGS]
        pop_state
      elsif scanner.scan /\=/
        @tokens << [:START_DEFAULT_VALUE]
        push_state :argument_defaults
      elsif scanner.scan /,/
        #
      else
        handle_shared_arguments
      end
    when :argument_defaults
      if @stack.reverse.take(2).eql?([:argument_defaults, :argument_defaults])
        @tokens << [:END_DEFAULT_VALUE]
        pop_state
        pop_state
      else
        push_state :argument_defaults
        handle_shared_arguments
      end
    when :special_args
      handle_special_args
    end
  end
  @tokens
end

Private Instance Methods

advance() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 500
def advance
  scanner.pos = scanner.pos + 1
end
env() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 480
def env
  @ctx ||= []
end
get_context() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 484
def get_context
  env.last || :default
end
handle_array_arguments() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 471
def handle_array_arguments
  if scanner.scan /\s*\]\s*/
    @tokens << [:ARG_ARRAY_END]   
    pop_state   
  else
    handle_shared_arguments
  end
end
handle_field() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 393
def handle_field
  if scanner.scan /\s*\{\s*/
    @context = :field
    @tokens << [:START_FIELD]
    push_state :field
  elsif scanner.check /\.{3}(\w+)\s*\}/
    scanner.scan /\.{3}(\w+)/
    @tokens << [:FRAGMENT_REF, scanner[1]]
    pop_context
    # we need to pop state if we are nested in a field, and not in the query context
    pop_state if get_context == :field
  elsif scanner.scan /\.{3}(\w+)/
    @tokens << [:FRAGMENT_REF, scanner[1]]
  elsif scanner.scan /\s*(\w+):\s*/
    @tokens << [:ALIAS, scanner[1]]
  elsif scanner.check /\s*(\w+)\s*\}/
    scanner.scan /\s*(\w+)\s*/
    @tokens << [:FIELD_NAME, scanner[1]]
    pop_context
    # we need to pop state if we are nested in a field, and not in the query context
    pop_state if get_context == :field
  elsif scanner.scan /\s*(\w+)\s*/
    @tokens << [:FIELD_NAME, scanner[1]]
  elsif scanner.scan /^\s*\(/
    @tokens << [:START_ARGS]
    push_state :arguments
  else
    advance
  end
end
handle_hash_arguments() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 462
def handle_hash_arguments
  if scanner.scan /\}/
    @tokens << [:ARG_HASH_END]
    pop_state
  else
    handle_shared_arguments
  end
end
handle_shared_arguments() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 424
def handle_shared_arguments
  if scanner.scan /^(\w+):/
    @tokens << [:ARG_KEY, scanner[1]]
  elsif scanner.scan /^\s*\{\s*?/
    @tokens << [:ARG_HASH_START]
    push_state :hash_arguments
  elsif scanner.scan /\s*\[\s*/
    @tokens << [:ARG_ARRAY_START]
    push_state :array_arguments
  elsif scanner.scan /\s?\"([\w\s]+)\"/
    @tokens << [:ARG_STRING_VALUE, scanner[1]]
  elsif scanner.scan /\s?(\d+\.\d+)/
    @tokens << [:ARG_FLOAT_VALUE, scanner[1].to_f]
  elsif scanner.scan /\s?(\d+)/
    @tokens << [:ARG_NUM_VALUE, scanner[1].to_i]
  elsif scanner.scan /\s?(true|false)\s?/
    bool = scanner[1] == "true"
    @tokens << [:ARG_BOOL_VALUE, bool]
  elsif scanner.scan /\$(\w+):/
    @tokens << [:SPECIAL_ARG_KEY, scanner[1]]
    push_state :special_args
  elsif scanner.scan /\$(\w+)/
    @tokens << [:SPECIAL_ARG_REF, scanner[1]]
  else
    advance
  end
end
handle_special_args() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 452
def handle_special_args
  if scanner.check SPECIAL_ARG_REGEX
    scanner.scan SPECIAL_ARG_REGEX
    @tokens << [:SPECIAL_ARG_VAL, scanner[1]]
    pop_state
  else
    pop_state
  end
end
pop_context() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 492
def pop_context
  env.pop
end
pop_state() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 516
def pop_state
  stack.pop
end
push_context(context) click to toggle source
# File lib/graphlyte/schema/parser.rb, line 488
def push_context(context)
  env << context
end
push_state(state) click to toggle source
# File lib/graphlyte/schema/parser.rb, line 512
def push_state(state)
  stack << state
end
rewind() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 496
def rewind
  scanner.pos = scanner.pos - 1
end
state() click to toggle source
# File lib/graphlyte/schema/parser.rb, line 508
def state
  stack.last || :default
end