# -*- coding: utf-8 -*- # # frozen_string_literal: true module Rouge module Lexers load_lexer 'c.rb' class ObjectiveC < C tag 'objective_c' title "Objective-C" desc 'an extension of C commonly used to write Apple software' aliases 'objc', 'obj-c', 'obj_c', 'objectivec' 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 import ) end def self.at_builtins @at_builtins ||= %w(true false YES NO) end def self.builtins @builtins ||= %w(YES NO nil) end id = /[a-z$_][a-z0-9$_]*/i prepend :statements do rule %r/@"/, Str, :string rule %r/@'(\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|\\.|[^\\'\n]')/, Str::Char rule %r/@(\d+[.]\d*|[.]\d+|\d+)e[+-]?\d+l?/i, Num::Float rule %r/@(\d+[.]\d*|[.]\d+|\d+f)f?/i, Num::Float rule %r/@0x\h+[lL]?/, Num::Hex rule %r/@0[0-7]+l?/i, Num::Oct rule %r/@\d+l?/, Num::Integer rule %r/\bin\b/, Keyword rule %r/@(?:interface|implementation)\b/, Keyword, :classname rule %r/@(?:class|protocol)\b/, Keyword, :forward_classname rule %r/@([[: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 %r/[?]/, Punctuation, :ternary rule %r/\[/, Punctuation, :message rule %r/@\[/, Punctuation, :array_literal rule %r/@\{/, Punctuation, :dictionary_literal end state :ternary do rule %r/:/, Punctuation, :pop! mixin :statements end state :message_shared do rule %r/\]/, Punctuation, :pop! rule %r/\{/, Punctuation, :pop! rule %r/;/, Error mixin :statements end state :message do rule %r/(#{id})(\s*)(:)/ do groups(Name::Function, Text, Punctuation) goto :message_with_args end rule %r/(#{id})(\s*)(\])/ do groups(Name::Function, Text, Punctuation) pop! end mixin :message_shared end state :message_with_args do rule %r/\{/, Punctuation, :function rule %r/(#{id})(\s*)(:)/ do groups(Name::Function, Text, Punctuation) pop! end mixin :message_shared end state :array_literal do rule %r/]/, Punctuation, :pop! rule %r/,/, Punctuation mixin :statements end state :dictionary_literal do rule %r/}/, Punctuation, :pop! rule %r/,/, Punctuation mixin :statements end state :classname do mixin :whitespace rule %r/(#{id})(\s*)(:)(\s*)(#{id})/ do groups(Name::Class, Text, Punctuation, Text, Name::Class) pop! end rule %r/(#{id})(\s*)([(])(\s*)(#{id})(\s*)([)])/ do groups(Name::Class, Text, Punctuation, Text, Name::Label, Text, Punctuation) pop! end rule id, Name::Class, :pop! end state :forward_classname do mixin :whitespace rule %r/(#{id})(\s*)(,)(\s*)/ do groups(Name::Class, Text, Punctuation, Text) push end rule %r/(#{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]) if m[3] token Text, m[4] push :method_definition end end state :method_definition do rule %r/,/, Punctuation rule %r/[.][.][.]/, Punctuation rule %r/([(].*?[)])(#{id})/ do |m| recurse m[1]; token Name::Variable, m[2] end rule %r/(#{id})(\s*)(:)/m do groups(Name::Function, Text, Punctuation) end rule %r/;/, Punctuation, :pop! rule %r/{/ do token Punctuation goto :function end mixin :inline_whitespace rule %r(//.*?\n), Comment::Single rule %r/\s+/m, Text rule(//) { pop! } end end end end