class CodeRay::Scanners::JavaScript

Scanner for JavaScript.

Aliases: ecmascript, ecma_script, javascript

Protected Instance Methods

reset_instance() click to toggle source
# File lib/coderay/scanners/java_script.rb, line 201
def reset_instance
  super
  @xml_scanner.reset if defined? @xml_scanner
end
scan_tokens(encoder, options) click to toggle source
# File lib/coderay/scanners/java_script.rb, line 57
def scan_tokens encoder, options
  
  state = :initial
  string_delimiter = nil
  value_expected = true
  key_expected = false
  function_expected = false
  
  until eos?
    
    case state
      
    when :initial
      
      if match = scan(%r \s+ | \\\n /)
        value_expected = true if !value_expected && match.index(\n\)
        encoder.text_token match, :space
        
      elsif match = scan(%r // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !x)
        value_expected = true
        encoder.text_token match, :comment
        
      elsif check(%r\.?\d/)
        key_expected = value_expected = false
        if match = scan(%r0[xX][0-9A-Fa-f]+/)
          encoder.text_token match, :hex
        elsif match = scan(%r(?>0[0-7]+)(?![89.eEfF])/)
          encoder.text_token match, :octal
        elsif match = scan(%r\d+[fF]|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
          encoder.text_token match, :float
        elsif match = scan(%r\d+/)
          encoder.text_token match, :integer
        end
        
      elsif value_expected && match = scan(%r<([[:alpha:]]\w*) (?: [^\/>]*\/> | .*?<\/\11>>)/im)
        # TODO: scan over nested tags
        xml_scanner.tokenize match, :tokens => encoder
        value_expected = false
        next
        
      elsif match = scan(%r [-+*=<>?:;,!&^|(\[{~%]+ | \.(?!\d) /)
        value_expected = true
        last_operator = match[-1]
        key_expected = (last_operator == {{) || (last_operator == ,,)
        function_expected = false
        encoder.text_token match, :operator
        
      elsif match = scan(%r [)\]}]+ /)
        function_expected = key_expected = value_expected = false
        encoder.text_token match, :operator
        
      elsif match = scan(%r [$a-zA-Z_][A-Za-z_0-9$]* /)
        kind = IDENT_KIND[match]
        value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match]
        # TODO: labels
        if kind == :ident
          if match.index($$)  # $ allowed inside an identifier
            kind = :predefined
          elsif function_expected
            kind = :function
          elsif check(%r\s*[=:]\s*function\b/)
            kind = :function
          elsif key_expected && check(%r\s*:/)
            kind = :key
          end
        end
        function_expected = (kind == :keyword) && (match == 'function')
        key_expected = false
        encoder.text_token match, kind
        
      elsif match = scan(%r["']/)
        if key_expected && check(KEY_CHECK_PATTERN[match])
          state = :key
        else
          state = :string
        end
        encoder.begin_group state
        string_delimiter = match
        encoder.text_token match, :delimiter
        
      elsif value_expected && (match = scan(%r\//))
        encoder.begin_group :regexp
        state = :regexp
        string_delimiter = '/'
        encoder.text_token match, :delimiter
        
      elsif match = scan(%r \/ /)
        value_expected = true
        key_expected = false
        encoder.text_token match, :operator
        
      else
        encoder.text_token getch, :error
        
      end
      
    when :string, :regexp, :key
      if match = scan(STRING_CONTENT_PATTERN[string_delimiter])
        encoder.text_token match, :content
      elsif match = scan(%r["'\/]/)
        encoder.text_token match, :delimiter
        if state == :regexp
          modifiers = scan(%r[gim]+/)
          encoder.text_token modifiers, :modifier if modifiers && !modifiers.empty?
        end
        encoder.end_group state
        string_delimiter = nil
        key_expected = value_expected = false
        state = :initial
      elsif state != :regexp && (match = scan(%r \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /ox))
        if string_delimiter == "'" && !(match == "\\\\" || match == "\\'")
          encoder.text_token match, :content
        else
          encoder.text_token match, :char
        end
      elsif state == :regexp && match = scan(%r \\ (?: #{ESCAPE} | #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /ox)
        encoder.text_token match, :char
      elsif match = scan(%r\\./)
        encoder.text_token match, :content
      elsif match = scan(%r \\ | $ /)
        encoder.end_group state
        encoder.text_token match, :error
        key_expected = value_expected = false
        state = :initial
      else
        raise_inspect "else case \" reached; %p not handled." % peek(1), encoder
      end
      
    else
      raise_inspect 'Unknown state', encoder
      
    end
    
  end
  
  if [:string, :regexp].include? state
    encoder.end_group state
  end
  
  encoder
end
xml_scanner() click to toggle source
# File lib/coderay/scanners/java_script.rb, line 206
def xml_scanner
  @xml_scanner ||= CodeRay.scanner :xml, :tokens => @tokens, :keep_tokens => true, :keep_state => false
end