class CodeRay::Scanners::SQL

by Josh Goebel

Constants

COMMANDS
DIRECTIVES
ESCAPE
IDENT_KIND
KEYWORDS
OBJECTS
PREDEFINED_CONSTANTS
PREDEFINED_FUNCTIONS
PREDEFINED_TYPES
STRING_PREFIXES
UNICODE_ESCAPE

Public Instance Methods

scan_tokens(encoder, options) click to toggle source
# File lib/coderay/scanners/sql.rb, line 59
def scan_tokens encoder, options
  
  state = :initial
  string_type = nil
  string_content = ''
  name_expected = false
  
  until eos?
    
    if state == :initial
      
      if match = scan(%r \s+ | \\\n /)
        encoder.text_token match, :space
      
      elsif match = scan(%r(?:--\s?|#).*/)
        encoder.text_token match, :comment
        
      elsif match = scan(%r( /\* (!)? (?: .*? \*/ | .* ) )x)
        encoder.text_token match, self[1] ? :directive : :comment
        
      elsif match = scan(%r [*\/=<>:;,!&^|()\[\]{}~%] | [-+\.](?!\d) /)
        name_expected = true if match == '.' && check(%r[A-Za-z_]/)
        encoder.text_token match, :operator
        
      elsif match = scan(%r(#{STRING_PREFIXES})?([`"'])/)
        prefix = self[1]
        string_type = self[2]
        encoder.begin_group :string
        encoder.text_token prefix, :modifier if prefix
        match = string_type
        state = :string
        encoder.text_token match, :delimiter
        
      elsif match = scan(%r @? [A-Za-z_][A-Za-z_0-9]* /)
        encoder.text_token match, name_expected ? :ident : (match[0] == @@ ? :variable : IDENT_KIND[match])
        name_expected = false
        
      elsif match = scan(%r0[xX][0-9A-Fa-f]+/)
        encoder.text_token match, :hex
        
      elsif match = scan(%r0[0-7]+(?![89.eEfF])/)
        encoder.text_token match, :octal
        
      elsif match = scan(%r[-+]?(?>\d+)(?![.eEfF])/)
        encoder.text_token match, :integer
        
      elsif match = scan(%r[-+]?(?:\d[fF]|\d*\.\d+(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)/)
        encoder.text_token match, :float
      
      elsif match = scan(%r\\N/)
        encoder.text_token match, :predefined_constant
        
      else
        encoder.text_token getch, :error
        
      end
      
    elsif state == :string
      if match = scan(%r[^\\"'`]+/)
        string_content << match
        next
      elsif match = scan(%r["'`]/)
        if string_type == match
          if peek(1) == string_type  # doubling means escape
            string_content << string_type << getch
            next
          end
          unless string_content.empty?
            encoder.text_token string_content, :content
            string_content = ''
          end
          encoder.text_token match, :delimiter
          encoder.end_group :string
          state = :initial
          string_type = nil
        else
          string_content << match
        end
      elsif match = scan(%r \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /ox)
        unless string_content.empty?
          encoder.text_token string_content, :content
          string_content = ''
        end
        encoder.text_token match, :char
      elsif match = scan(%r \\ . /ox)
        string_content << match
        next
      elsif match = scan(%r \\ | $ /)
        unless string_content.empty?
          encoder.text_token string_content, :content
          string_content = ''
        end
        encoder.text_token match, :error
        state = :initial
      else
        raise "else case \" reached; %p not handled." % peek(1), encoder
      end
      
    else
      raise 'else-case reached', encoder
      
    end
    
  end
  
  if state == :string
    encoder.end_group state
  end
  
  encoder
  
end