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
syntaxName :: String
syntaxName = "Erlang"
syntaxExtensions :: String
syntaxExtensions = "*.erl"
highlight :: String -> [SourceLine]
highlight input = evalState (mapM parseSourceLine $ lines input) startingState
parseSourceLine :: String -> State SyntaxState SourceLine
parseSourceLine = mkParseSourceLine parseExpression
parseExpression :: KateParser Token
parseExpression = do
(lang,cont) <- currentContext
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, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}
pEndLine = do
updateState $ \st -> st{ synStPrevNonspace = False }
context <- currentContext
contexts <- synStContexts `fmap` getState
if length contexts >= 2
then case context of
("Erlang","Normal Text") -> (popContext) >> pEndLine
("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 "(?:-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 "(?:\\+|-|\\*|\\/|==|\\/=|=:=|=\\/=|<|=<|>|>=|\\+\\+|--|=|!|<-)"
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 "(?:\\(|\\)|\\{|\\}|\\[|\\]|\\.|\\:|\\||\\|\\||;|\\,|\\?|->|\\#)"
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 "\\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 "\\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 "\\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 "\\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 "[0-9]+\\.[0-9]+(?:[eE][+-]?[0-9]+)?"
regex_'5cd'2b'23'5ba'2dzA'2dZ0'2d9'5d'2b = compileRegex "\\d+#[a-zA-Z0-9]+"
regex_'5c'24'5cS = compileRegex "\\$\\S"
regex_'5b0'2d9'5d'2b = compileRegex "[0-9]+"
regex_'28'3f'3a'28'3f'3a'5c'5c'27'29'3f'5b'5e'27'5d'2a'29'2a'27 = compileRegex "(?:(?:\\\\')?[^']*)*'"
regex_'28'3f'3a'28'3f'3a'5c'5c'22'29'3f'5b'5e'22'5d'2a'29'2a'22 = compileRegex "(?:(?:\\\\\")?[^\"]*)*\""
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) >>~ (popContext))
<|>
((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) >>~ (popContext))
<|>
((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) >>~ (popContext))
<|>
((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) >>~ (popContext))
<|>
((pRegExpr regex_'5cd'2b'23'5ba'2dzA'2dZ0'2d9'5d'2b >>= withAttribute BaseNTok) >>~ (popContext))
<|>
((pRegExpr regex_'5c'24'5cS >>= withAttribute DecValTok) >>~ (popContext))
<|>
((pRegExpr regex_'5b0'2d9'5d'2b >>= withAttribute DecValTok) >>~ (popContext))
<|>
(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 >>= ((withAttribute CommentTok) . snd)))
<|>
((pDetectIdentifier >>= withAttribute CommentTok))
<|>
(currentContext >>= \x -> guard (x == ("Erlang","comment")) >> pDefault >>= withAttribute CommentTok))
parseRules ("Alerts", _) = Text.Highlighting.Kate.Syntax.Alert.parseExpression
parseRules x = parseRules ("Erlang","Normal Text") <|> fail ("Unknown context" ++ show x)