module Rouge module Lexers class SML < RegexLexer desc 'Standard ML' tag 'sml' aliases 'ml' filenames '*.sml', '*.sig', '*.fun' mimetypes 'text/x-standardml', 'application/x-standardml' def self.keywords @keywords ||= Set.new %w( abstype and andalso as case datatype do else end exception fn fun handle if in infix infixr let local nonfix of op open orelse raise rec then type val with withtype while eqtype functor include sharing sig signature struct structure where ) end id = /[a-z][\w']*/i symbol = %r([!%&$#/:<=>?@\\~`^|*+-]+) def self.analyze_text(text) return 0 end state :whitespace do rule /\s+/m, Text rule /[(][*]/, Comment, :comment end state :delimiters do rule /[(\[{]/, Punctuation, :main rule /[)\]}]/, Punctuation, :pop! rule /\b(let|if|local)\b(?!')/, Keyword::Reserved do push; push end rule /\b(struct|sig|while)\b(?!')/ do token Keyword::Reserved push end rule /\b(do|else|end|in|then)\b(?!')/, Keyword::Reserved, :pop! end def token_for_id_with_dot(id) if self.class.keywords.include? id Error else Name::Namespace end end def token_for_final_id(id) if self.class.keywords.include? id or self.class.symbolic_reserved.include? id Error else Name end end def token_for_id(id) if self.class.keywords.include? id Keyword::Reserved elsif self.class.symbolic_reserved.include? id Punctuation else Name end end state :core do rule /[()\[\]{},;_]|[.][.][.]/, Punctuation rule /#"/, Str::Char, :char rule /~?0x[0-9a-fA-F]+/, Num::Hex rule /0wx[0-9a-fA-F]+/, Num::Hex rule /0w\d+/, Num::Integer rule /~?\d+[.]\d+[eE]~?\d+/, Num::Float rule /~?\d+[.]\d+/, Num::Float rule /~?\d+/, Num::Integer rule /#\s*[1-9][0-9]*/, Name::Label rule /#\s*#{id}/, Name::Label rule /#\s+#{symbol}/, Name::Label rule /\b(datatype|abstype)\b(?!')/, Keyword::Reserved, :dname rule(/(?=\bexception\b(?!'))/) { push :ename } rule /\b(functor|include|open|signature|structure)\b(?!')/, Keyword::Reserved, :sname rule /\b(type|eqtype)\b(?!')/, Keyword::Reserved, :tname rule /'#{id}/, Name::Decorator rule /(#{id})([.])/ do |m| groups(token_for_id_with_dot(m[1]), Punctuation) push :dotted end state :dotted do rule /(#{id})([.])/ do |m| groups(token_for_id_with_dot(m[1]), Punctuation) end end end state :root do rule /#!.*?\n/, Comment::Preproc rule(//) { push :main } end end end end