javascript.rb
175 lines
| 4.2 KiB
| text/x-ruby
|
RubyLexer
|
r2965 | # 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 |