{- This module was generated from data in the Kate syntax
   highlighting file erlang.xml, version 1.03, by Bill Ross (bill@emailme.net.au) -}

module Text.Highlighting.Kate.Syntax.Erlang
          (highlight, parseExpression, syntaxName, syntaxExtensions)
where
import Text.Highlighting.Kate.Types
import Text.Highlighting.Kate.Common
import qualified Text.Highlighting.Kate.Syntax.Alert
import Text.ParserCombinators.Parsec hiding (State)
import Control.Monad.State
import Data.Char (isSpace)
import qualified Data.Set as Set

-- | Full name of language.
syntaxName :: String
syntaxName = "Erlang"

-- | Filename extensions for this language.
syntaxExtensions :: String
syntaxExtensions = "*.erl"

-- | Highlight source code using this syntax definition.
highlight :: String -> [SourceLine]
highlight input = evalState (mapM parseSourceLine $ lines input) startingState

parseSourceLine :: String -> State SyntaxState SourceLine
parseSourceLine = mkParseSourceLine (parseExpression Nothing)

-- | Parse an expression using appropriate local context.
parseExpression :: Maybe (String,String)
                -> KateParser Token
parseExpression mbcontext = do
  (lang,cont) <- maybe currentContext return mbcontext
  result <- parseRules (lang,cont)
  optional $ do eof
                updateState $ \st -> st{ synStPrevChar = '\n' }
                pEndLine
  return result

startingState = SyntaxState {synStContexts = [("Erlang","Normal Text")], synStLineNumber = 0, synStPrevChar = '\n', synStPrevNonspace = False, synStContinuation = False, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}

pEndLine = do
  updateState $ \st -> st{ synStPrevNonspace = False }
  context <- currentContext
  contexts <- synStContexts `fmap` getState
  st <- getState
  if length contexts >= 2
    then case context of
      _ | synStContinuation st -> updateState $ \st -> st{ synStContinuation = False }
      ("Erlang","Normal Text") -> return ()
      ("Erlang","isfunction") -> (popContext) >> pEndLine
      ("Erlang","atomquote") -> (popContext) >> pEndLine
      ("Erlang","stringquote") -> (popContext) >> pEndLine
      ("Erlang","comment") -> (popContext) >> pEndLine
      _ -> return ()
    else return ()

withAttribute attr txt = do
  when (null txt) $ fail "Parser matched no text"
  updateState $ \st -> st { synStPrevChar = last txt
                          , synStPrevNonspace = synStPrevNonspace st || not (all isSpace txt) }
  return (attr, txt)

list_keywords = Set.fromList $ words $ "after begin case catch cond end fun if let of query receive all_true some_true"
list_operators = Set.fromList $ words $ "div rem or xor bor bxor bsl bsr and band not bnot"
list_functions = Set.fromList $ words $ "abs accept alarm apply atom_to_list binary_to_list binary_to_term check_process_code concat_binary date delete_module disconnect_node element erase exit float float_to_list garbage_collect get get_keys group_leader halt hd integer_to_list is_alive is_atom is_binary is_boolean is_float is_function is_integer is_list is_number is_pid is_port is_process_alive is_record is_reference is_tuple length link list_to_atom list_to_binary list_to_float list_to_integer list_to_pid list_to_tuple load_module loaded localtime make_ref module_loaded node nodes now open_port pid_to_list port_close port_command port_connect port_control ports pre_loaded process_flag process_info processes purge_module put register registered round self setelement size spawn spawn_link spawn_opt split_binary statistics term_to_binary throw time tl trunc tuple_to_list unlink unregister whereis"

regex_'28'3f'3a'2dmodule'7c'2dexport'7c'2ddefine'7c'2dundef'7c'2difdef'7c'2difndef'7c'2delse'7c'2dendif'7c'2dinclude'7c'2dinclude'5flib'29 = compileRegex True "(?:-module|-export|-define|-undef|-ifdef|-ifndef|-else|-endif|-include|-include_lib)"
regex_'28'3f'3a'5c'2b'7c'2d'7c'5c'2a'7c'5c'2f'7c'3d'3d'7c'5c'2f'3d'7c'3d'3a'3d'7c'3d'5c'2f'3d'7c'3c'7c'3d'3c'7c'3e'7c'3e'3d'7c'5c'2b'5c'2b'7c'2d'2d'7c'3d'7c'21'7c'3c'2d'29 = compileRegex True "(?:\\+|-|\\*|\\/|==|\\/=|=:=|=\\/=|<|=<|>|>=|\\+\\+|--|=|!|<-)"
regex_'28'3f'3a'5c'28'7c'5c'29'7c'5c'7b'7c'5c'7d'7c'5c'5b'7c'5c'5d'7c'5c'2e'7c'5c'3a'7c'5c'7c'7c'5c'7c'5c'7c'7c'3b'7c'5c'2c'7c'5c'3f'7c'2d'3e'7c'5c'23'29 = compileRegex True "(?:\\(|\\)|\\{|\\}|\\[|\\]|\\.|\\:|\\||\\|\\||;|\\,|\\?|->|\\#)"
regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29'3a'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 = compileRegex True "\\b[a-z][_a-z@-Z0-9]*(?:(?=[^_a-z@-Z0-9])|$):\\b[a-z][_a-z@-Z0-9]*(?:(?=[^_a-z@-Z0-9])|$)"
regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29'5c'28 = compileRegex True "\\b[a-z][_a-z@-Z0-9]*(?:(?=[^_a-z@-Z0-9])|$)\\("
regex_'5cb'5b'5fA'2dZ'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 = compileRegex True "\\b[_A-Z][_a-z@-Z0-9]*(?:(?=[^_a-z@-Z0-9])|$)"
regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 = compileRegex True "\\b[a-z][_a-z@-Z0-9]*(?:(?=[^_a-z@-Z0-9])|$)"
regex_'5b0'2d9'5d'2b'5c'2e'5b0'2d9'5d'2b'28'3f'3a'5beE'5d'5b'2b'2d'5d'3f'5b0'2d9'5d'2b'29'3f = compileRegex True "[0-9]+\\.[0-9]+(?:[eE][+-]?[0-9]+)?"
regex_'5cd'2b'23'5ba'2dzA'2dZ0'2d9'5d'2b = compileRegex True "\\d+#[a-zA-Z0-9]+"
regex_'5c'24'5cS = compileRegex True "\\$\\S"
regex_'5b0'2d9'5d'2b = compileRegex True "[0-9]+"
regex_'28'3f'3a'28'3f'3a'5c'5c'27'29'3f'5b'5e'27'5d'2a'29'2a'27 = compileRegex True "(?:(?:\\\\')?[^']*)*'"
regex_'28'3f'3a'28'3f'3a'5c'5c'22'29'3f'5b'5e'22'5d'2a'29'2a'22 = compileRegex True "(?:(?:\\\\\")?[^\"]*)*\""

parseRules ("Erlang","Normal Text") =
  (((pColumn 0 >> pRegExpr regex_'28'3f'3a'2dmodule'7c'2dexport'7c'2ddefine'7c'2dundef'7c'2difdef'7c'2difndef'7c'2delse'7c'2dendif'7c'2dinclude'7c'2dinclude'5flib'29 >>= withAttribute KeywordTok))
   <|>
   ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_keywords >>= withAttribute KeywordTok))
   <|>
   ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_operators >>= withAttribute KeywordTok))
   <|>
   ((pRegExpr regex_'28'3f'3a'5c'2b'7c'2d'7c'5c'2a'7c'5c'2f'7c'3d'3d'7c'5c'2f'3d'7c'3d'3a'3d'7c'3d'5c'2f'3d'7c'3c'7c'3d'3c'7c'3e'7c'3e'3d'7c'5c'2b'5c'2b'7c'2d'2d'7c'3d'7c'21'7c'3c'2d'29 >>= withAttribute KeywordTok))
   <|>
   ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_functions >>= withAttribute FunctionTok))
   <|>
   ((pRegExpr regex_'28'3f'3a'5c'28'7c'5c'29'7c'5c'7b'7c'5c'7d'7c'5c'5b'7c'5c'5d'7c'5c'2e'7c'5c'3a'7c'5c'7c'7c'5c'7c'5c'7c'7c'3b'7c'5c'2c'7c'5c'3f'7c'2d'3e'7c'5c'23'29 >>= withAttribute FunctionTok))
   <|>
   ((pDetectSpaces >>= withAttribute NormalTok))
   <|>
   ((pDetectChar False '%' >>= withAttribute CommentTok) >>~ pushContext ("Erlang","comment"))
   <|>
   ((pRegExpr regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29'3a'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 >>= withAttribute FunctionTok))
   <|>
   ((lookAhead (pRegExpr regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29'5c'28) >> pushContext ("Erlang","isfunction") >> currentContext >>= parseRules))
   <|>
   ((pRegExpr regex_'5cb'5b'5fA'2dZ'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 >>= withAttribute DataTypeTok))
   <|>
   ((pDetectChar False '\'' >>= withAttribute CharTok) >>~ pushContext ("Erlang","atomquote"))
   <|>
   ((pRegExpr regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 >>= withAttribute CharTok))
   <|>
   ((pDetectChar False '"' >>= withAttribute StringTok) >>~ pushContext ("Erlang","stringquote"))
   <|>
   ((pRegExpr regex_'5b0'2d9'5d'2b'5c'2e'5b0'2d9'5d'2b'28'3f'3a'5beE'5d'5b'2b'2d'5d'3f'5b0'2d9'5d'2b'29'3f >>= withAttribute FloatTok))
   <|>
   ((pRegExpr regex_'5cd'2b'23'5ba'2dzA'2dZ0'2d9'5d'2b >>= withAttribute BaseNTok))
   <|>
   ((pRegExpr regex_'5c'24'5cS >>= withAttribute DecValTok))
   <|>
   ((pRegExpr regex_'5b0'2d9'5d'2b >>= withAttribute DecValTok))
   <|>
   (currentContext >>= \x -> guard (x == ("Erlang","Normal Text")) >> pDefault >>= withAttribute NormalTok))

parseRules ("Erlang","isfunction") =
  (((pRegExpr regex_'5cb'5ba'2dz'5d'5b'5fa'2dz'40'2dZ0'2d9'5d'2a'28'3f'3a'28'3f'3d'5b'5e'5fa'2dz'40'2dZ0'2d9'5d'29'7c'24'29 >>= withAttribute FunctionTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("Erlang","isfunction")) >> pDefault >>= withAttribute FunctionTok))

parseRules ("Erlang","atomquote") =
  (((pRegExpr regex_'28'3f'3a'28'3f'3a'5c'5c'27'29'3f'5b'5e'27'5d'2a'29'2a'27 >>= withAttribute CharTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("Erlang","atomquote")) >> pDefault >>= withAttribute CharTok))

parseRules ("Erlang","stringquote") =
  (((pRegExpr regex_'28'3f'3a'28'3f'3a'5c'5c'22'29'3f'5b'5e'22'5d'2a'29'2a'22 >>= withAttribute StringTok) >>~ (popContext))
   <|>
   (currentContext >>= \x -> guard (x == ("Erlang","stringquote")) >> pDefault >>= withAttribute StringTok))

parseRules ("Erlang","comment") =
  (((pDetectSpaces >>= withAttribute CommentTok))
   <|>
   ((Text.Highlighting.Kate.Syntax.Alert.parseExpression (Just ("Alerts","")) >>= ((withAttribute CommentTok) . snd)))
   <|>
   ((pDetectIdentifier >>= withAttribute CommentTok))
   <|>
   (currentContext >>= \x -> guard (x == ("Erlang","comment")) >> pDefault >>= withAttribute CommentTok))

parseRules ("Alerts", _) = Text.Highlighting.Kate.Syntax.Alert.parseExpression Nothing

parseRules x = parseRules ("Erlang","Normal Text") <|> fail ("Unknown context" ++ show x)
