obsolete.ChilliProject/vendor/plugins/coderay-0.7.6.227/lib/coderay/scanners/javascript.rb

176 lines
4.2 KiB
Ruby
Raw Normal View History

# http://pastie.textmate.org/50774/
module CodeRay module Scanners
class JavaScript < Scanner
register_for :javascript
RESERVED_WORDS = [
'asm', 'break', 'case', 'continue', 'default', 'do', 'else',
'for', 'goto', 'if', 'return', 'switch', 'while',
# 'struct', 'union', 'enum', 'typedef',
# 'static', 'register', 'auto', 'extern',
# 'sizeof',
'typeof',
# 'volatile', 'const', # C89
# 'inline', 'restrict', # C99
'var', 'function','try','new','in',
'instanceof','throw','catch'
]
PREDEFINED_CONSTANTS = [
'void', 'null', 'this',
'true', 'false','undefined',
]
IDENT_KIND = WordList.new(:ident).
add(RESERVED_WORDS, :reserved).
add(PREDEFINED_CONSTANTS, :pre_constant)
ESCAPE = / [rbfnrtv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x
UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
def scan_tokens tokens, options
state = :initial
string_type = nil
regexp_allowed = true
until eos?
kind = :error
match = nil
if state == :initial
if scan(/ \s+ | \\\n /x)
kind = :space
elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
kind = :comment
regexp_allowed = false
elsif match = scan(/ \# \s* if \s* 0 /x)
match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
kind = :comment
regexp_allowed = false
elsif regexp_allowed and scan(/\//)
tokens << [:open, :regexp]
state = :regex
kind = :delimiter
elsif scan(/ [-+*\/=<>?:;,!&^|()\[\]{}~%] | \.(?!\d) /x)
kind = :operator
regexp_allowed=true
elsif match = scan(/ [$A-Za-z_][A-Za-z_0-9]* /x)
kind = IDENT_KIND[match]
# if kind == :ident and check(/:(?!:)/)
# match << scan(/:/)
# kind = :label
# end
regexp_allowed=false
elsif match = scan(/["']/)
tokens << [:open, :string]
string_type = matched
state = :string
kind = :delimiter
# elsif scan(/#\s*(\w*)/)
# kind = :preprocessor # FIXME multiline preprocs
# state = :include_expected if self[1] == 'include'
#
# elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
# kind = :char
elsif scan(/0[xX][0-9A-Fa-f]+/)
kind = :hex
regexp_allowed=false
elsif scan(/(?:0[0-7]+)(?![89.eEfF])/)
kind = :oct
regexp_allowed=false
elsif scan(/(?:\d+)(?![.eEfF])/)
kind = :integer
regexp_allowed=false
elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
kind = :float
regexp_allowed=false
else
getch
end
elsif state == :regex
if scan(/[^\\\/]+/)
kind = :content
elsif scan(/\\\/|\\\\/)
kind = :content
elsif scan(/\//)
tokens << [matched, :delimiter]
tokens << [:close, :regexp]
state = :initial
next
else
getch
kind = :content
end
elsif state == :string
if scan(/[^\\"']+/)
kind = :content
elsif scan(/["']/)
if string_type==matched
tokens << [matched, :delimiter]
tokens << [:close, :string]
state = :initial
string_type=nil
next
else
kind = :content
end
elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
kind = :char
elsif scan(/ \\ | $ /x)
kind = :error
state = :initial
else
raise "else case \" reached; %p not handled." % peek(1), tokens
end
# elsif state == :include_expected
# if scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
# kind = :include
# state = :initial
#
# elsif match = scan(/\s+/)
# kind = :space
# state = :initial if match.index ?\n
#
# else
# getch
#
# end
#
else
raise 'else-case reached', tokens
end
match ||= matched
# raise [match, kind], tokens if kind == :error
tokens << [match, kind]
end
tokens
end
end
end end