# -*- coding: utf-8 -*- # # frozen_string_literal: true module Rouge module Lexers module ObjectiveCCommon id = /[a-z$_][a-z0-9$_]*/i def 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 at_builtins @at_builtins ||= %w(true false YES NO) end def builtins @builtins ||= %w(YES NO nil) end def self.extended(base) base.prepend :statements do rule %r/@"/, base::Str, :string rule %r/@'(\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|\\.|[^\\'\n]')/, base::Str::Char rule %r/@(\d+[.]\d*|[.]\d+|\d+)e[+-]?\d+l?/i, base::Num::Float rule %r/@(\d+[.]\d*|[.]\d+|\d+f)f?/i, base::Num::Float rule %r/@0x\h+[lL]?/, base::Num::Hex rule %r/@0[0-7]+l?/i, base::Num::Oct rule %r/@\d+l?/, base::Num::Integer rule %r/\bin\b/, base::Keyword rule %r/@(?:interface|implementation)\b/, base::Keyword, :objc_classname rule %r/@(?:class|protocol)\b/, base::Keyword, :forward_classname rule %r/@([[:alnum:]]+)/ do |m| if base.at_keywords.include? m[1] token base::Keyword elsif base.at_builtins.include? m[1] token base::Name::Builtin else token Error end end rule %r/[?]/, base::Punctuation, :ternary rule %r/\[/, base::Punctuation, :message rule %r/@\[/, base::Punctuation, :array_literal rule %r/@\{/, base::Punctuation, :dictionary_literal end id = /[a-z$_][a-z0-9$_]*/i base.state :ternary do rule %r/:/, base::Punctuation, :pop! mixin :statements end base.state :message_shared do rule %r/\]/, base::Punctuation, :pop! rule %r/\{/, base::Punctuation, :pop! rule %r/;/, base::Error mixin :statements end base.state :message do rule %r/(#{id})(\s*)(:)/ do groups(base::Name::Function, base::Text, base::Punctuation) goto :message_with_args end rule %r/(#{id})(\s*)(\])/ do groups(base::Name::Function, base::Text, base::Punctuation) pop! end mixin :message_shared end base.state :message_with_args do rule %r/\{/, base::Punctuation, :function rule %r/(#{id})(\s*)(:)/ do groups(base::Name::Function, base::Text, base::Punctuation) pop! end mixin :message_shared end base.state :array_literal do rule %r/]/, base::Punctuation, :pop! rule %r/,/, base::Punctuation mixin :statements end base.state :dictionary_literal do rule %r/}/, base::Punctuation, :pop! rule %r/,/, base::Punctuation mixin :statements end base.state :objc_classname do mixin :whitespace rule %r/(#{id})(\s*)(:)(\s*)(#{id})/ do groups(base::Name::Class, base::Text, base::Punctuation, base::Text, base::Name::Class) pop! end rule %r/(#{id})(\s*)([(])(\s*)(#{id})(\s*)([)])/ do groups(base::Name::Class, base::Text, base::Punctuation, base::Text, base::Name::Label, base::Text, base::Punctuation) pop! end rule id, base::Name::Class, :pop! end base.state :forward_classname do mixin :whitespace rule %r/(#{id})(\s*)(,)(\s*)/ do groups(base::Name::Class, base::Text, base::Punctuation, base::Text) push end rule %r/(#{id})(\s*)(;?)/ do groups(base::Name::Class, base::Text, base::Punctuation) pop! end end base.prepend :root do rule %r( ([-+])(\s*) ([(].*?[)])?(\s*) (?=#{id}:?) )ix do |m| token base::Keyword, m[1] token base::Text, m[2] recurse(m[3]) if m[3] token base::Text, m[4] push :method_definition end end base.state :method_definition do rule %r/,/, base::Punctuation rule %r/[.][.][.]/, base::Punctuation rule %r/([(].*?[)])(#{id})/ do |m| recurse m[1]; token base::Name::Variable, m[2] end rule %r/(#{id})(\s*)(:)/m do groups(base::Name::Function, base::Text, base::Punctuation) end rule %r/;/, base::Punctuation, :pop! rule %r/{/ do token base::Punctuation goto :function end mixin :inline_whitespace rule %r(//.*?\n), base::Comment::Single rule %r/\s+/m, base::Text rule(//) { pop! } end end end end end