blob: 190abf458aeb572031ec1c0b4172edc76e1dad14 [file] [log] [blame]
# -*- coding: utf-8 -*- #
module Rouge
module Lexers
class Coffeescript < RegexLexer
tag 'coffeescript'
aliases 'coffee', 'coffee-script'
filenames '*.coffee', 'Cakefile'
mimetypes 'text/coffeescript'
title "CoffeeScript"
desc 'The Coffeescript programming language (coffeescript.org)'
def self.analyze_text(text)
return 1 if text.shebang? 'coffee'
end
def self.keywords
@keywords ||= Set.new %w(
for in of while break return continue switch when then if else
throw try catch finally new delete typeof instanceof super
extends this class by
)
end
def self.constants
@constants ||= Set.new %w(
true false yes no on off null NaN Infinity undefined
)
end
def self.builtins
@builtins ||= Set.new %w(
Array Boolean Date Error Function Math netscape Number Object
Packages RegExp String sun decodeURI decodeURIComponent
encodeURI encodeURIComponent eval isFinite isNaN parseFloat
parseInt document window
)
end
id = /[$a-zA-Z_][a-zA-Z0-9_]*/
state :comments_and_whitespace do
rule /\s+/m, Text
rule /###.*?###/m, Comment::Multiline
rule /#.*$/, Comment::Single
end
state :multiline_regex do
# this order is important, so that #{ isn't interpreted
# as a comment
mixin :has_interpolation
mixin :comments_and_whitespace
rule %r(///([gim]+\b|\B)), Str::Regex, :pop!
rule %r(/), Str::Regex
rule %r([^/#]+), Str::Regex
end
state :slash_starts_regex do
mixin :comments_and_whitespace
rule %r(///) do
token Str::Regex
goto :multiline_regex
end
rule %r(
/(\\.|[^\[/\\\n]|\[(\\.|[^\]\\\n])*\])+/ # a regex
([gim]+\b|\B)
)x, Str::Regex, :pop!
rule(//) { pop! }
end
state :root do
rule(%r(^(?=\s|/|<!--))) { push :slash_starts_regex }
mixin :comments_and_whitespace
rule %r(
[+][+]|--|~|&&|\band\b|\bor\b|\bis\b|\bisnt\b|\bnot\b|[?]|:|=|
[|][|]|\\(?=\n)|(<<|>>>?|==?|!=?|[-<>+*`%&|^/])=?
)x, Operator, :slash_starts_regex
rule /[-=]>/, Name::Function
rule /(@)([ \t]*)(#{id})/ do
groups Name::Variable::Instance, Text, Name::Attribute
push :slash_starts_regex
end
rule /([.])([ \t]*)(#{id})/ do
groups Punctuation, Text, Name::Attribute
push :slash_starts_regex
end
rule /#{id}(?=\s*:)/, Name::Attribute, :slash_starts_regex
rule /#{id}/ do |m|
if self.class.keywords.include? m[0]
token Keyword
elsif self.class.constants.include? m[0]
token Name::Constant
elsif self.class.builtins.include? m[0]
token Name::Builtin
else
token Name::Other
end
push :slash_starts_regex
end
rule /[{(\[;,]/, Punctuation, :slash_starts_regex
rule /[})\].]/, Punctuation
rule /\d+[.]\d+([eE]\d+)?[fd]?/, Num::Float
rule /0x[0-9a-fA-F]+/, Num::Hex
rule /\d+/, Num::Integer
rule /"""/, Str, :tdqs
rule /'''/, Str, :tsqs
rule /"/, Str, :dqs
rule /'/, Str, :sqs
end
state :strings do
# all coffeescript strings are multi-line
rule /[^#\\'"]+/m, Str
rule /\\./, Str::Escape
rule /#/, Str
end
state :double_strings do
rule /'/, Str
mixin :has_interpolation
mixin :strings
end
state :single_strings do
rule /"/, Str
mixin :strings
end
state :interpolation do
rule /}/, Str::Interpol, :pop!
mixin :root
end
state :has_interpolation do
rule /[#][{]/, Str::Interpol, :interpolation
end
state :dqs do
rule /"/, Str, :pop!
mixin :double_strings
end
state :tdqs do
rule /"""/, Str, :pop!
rule /"/, Str
mixin :double_strings
end
state :sqs do
rule /'/, Str, :pop!
mixin :single_strings
end
state :tsqs do
rule /'''/, Str, :pop!
rule /'/, Str
mixin :single_strings
end
end
end
end