module Rouge module Lexers load_const :C, 'c.rb' class ObjectiveC < C tag 'objective_c' desc 'an extension of C commonly used to write Apple software' aliases 'objc' filenames '*.m', '*.h' mimetypes 'text/x-objective_c', 'application/x-objective_c' def self.at_keywords @at_keywords ||= %w( selector private protected public encode synchronized try throw catch finally end property synthesize dynamic optional interface implementation ) end def self.at_builtins @at_builtins ||= %w(true false YES NO) end def self.builtins @builtins ||= %w(YES NO nil) end def self.analyze_text(text) return 1 if text =~ /@(end|implementation|protocol|property)\b/ id = /[a-z$_][a-z0-9$_]*/i return 0.4 if text =~ %r( \[ \s* #{id} \s+ (?: #{id} \s* \] | #{id}? : ) )x return 0.4 if text.include? '@"' end id = /[a-z$_][a-z0-9$_]*/i prepend :statements do rule /@"/, Str, :string rule /@'(\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|\\.|[^\\'\n]')/ Str::Char rule /@(\d+[.]\d*|[.]\d+|\d+)e[+-]?\d+l?/i, Num::Float rule /@(\d+[.]\d*|[.]\d+|\d+f)f?/i, Num::Float rule /@0x\h+[lL]?/, Num::Hex rule /@0[0-7]+l?/i, Num::Oct rule /@\d+l?/, Num::Integer rule /\bin\b/, Keyword rule /@(?:interface|implementation)\b/ do token Keyword goto :classname end rule /@(?:class|protocol)\b/ do token Keyword goto :forward_classname end rule /@([[:alnum:]]+)/ do |m| if self.class.at_keywords.include? m[1] token Keyword elsif self.class.at_builtins.include? m[1] token Name::Builtin else token Error end end rule /[?]/, Punctuation, :ternary rule /\[/, Punctuation, :message end state :ternary do rule /:/, Punctuation, :pop! mixin :statements end state :message_shared do rule /\]/, Punctuation, :pop! rule /;/, Error mixin :statement end state :message do rule /(#{id})(\s*)(:)/ do groups(Name::Function, Text, Punctuation) goto :message_with_args end rule /(#{id})(\s*)(\])/ do groups(Name::Function, Text, Punctuation) pop! end mixin :message_shared end state :message_with_args do rule /(#{id})(\s*)(:)/ do groups(Name::Function, Text, Punctuation) end mixin :message_shared end state :classname do mixin :whitespace rule /(#{id})(\s*)(:)(\s*)(#{id})/ do groups(Name::Class, Text, Punctuation, Text, Name::Class) pop! end rule /(#{id})(\s*)([(])(\s*)(#{id})(\s*)([)])/ do groups(Name::Class, Text, Punctuation, Text, Name::Label, Text, Punctuation) end rule id, Name::Class, :pop! end state :forward_classname do mixin :whitespace rule /(#{id})(\s*)(,)(\s*)/ do groups(Name::Class, Text, Punctuation, Text) push end rule /(#{id})(\s*)(;?)/ do groups(Name::Class, Text, Punctuation) pop! end end prepend :root do rule %r( ([-+])(\s*) ([(].*?[)])?(\s*) (?=#{id}:?) )ix do |m| token Keyword, m[1]; token Text, m[2] recurse m[3]; token Text, m[4] push :method_definition end end state :method_definition do rule /,/, Punctuation rule /[.][.][.]/, Punctuation rule /([(].*?[)])(#{id})/ do |m| recurse m[1]; token Name::Variable, m[2] end rule /(#{id})(\s*)(:)/m do groups(Name::Function, Text, Punctuation) end rule /;/, Punctuation, :pop! rule /{/ do token Punctuation goto :function end mixin :inline_whitespace rule %r(//.*?\n), Comment::Single rule /\s+/m, Text rule(//) { pop! } end end end end