{- This module was generated from data in the Kate syntax highlighting file python.xml, version 2.09,
   by  Michael Bueker -}

module Text.Highlighting.Kate.Syntax.Python ( highlight, parseExpression, syntaxName, syntaxExtensions ) where
import Text.Highlighting.Kate.Definitions
import Text.Highlighting.Kate.Common
import qualified Text.Highlighting.Kate.Syntax.Alert_indent
import Text.ParserCombinators.Parsec
import Control.Monad (when)
import Data.Map (fromList)
import Data.Maybe (fromMaybe, maybeToList)

import qualified Data.Set as Set
-- | Full name of language.
syntaxName :: String
syntaxName = "Python"

-- | Filename extensions for this language.
syntaxExtensions :: String
syntaxExtensions = "*.py;*.pyw"

-- | Highlight source code using this syntax definition.
highlight :: String -> Either String [SourceLine]
highlight input =
  case runParser parseSource startingState "source" input of
    Left err     -> Left $ show err
    Right result -> Right result

-- | Parse an expression using appropriate local context.
parseExpression :: GenParser Char SyntaxState LabeledSource
parseExpression = do
  st <- getState
  let oldLang = synStLanguage st
  setState $ st { synStLanguage = "Python" }
  context <- currentContext <|> (pushContext "Normal" >> currentContext)
  result <- parseRules context
  updateState $ \st -> st { synStLanguage = oldLang }
  return result

parseSource = do 
  lineContents <- lookAhead wholeLine
  updateState $ \st -> st { synStCurrentLine = lineContents }
  result <- manyTill parseSourceLine eof
  return $ map normalizeHighlighting result

startingState = SyntaxState {synStContexts = fromList [("Python",["Normal"])], synStLanguage = "Python", synStCurrentLine = "", synStCharsParsedInLine = 0, synStPrevChar = '\n', synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}

parseSourceLine = manyTill parseExpressionInternal pEndLine

pEndLine = do
  lookAhead $ newline <|> (eof >> return '\n')
  context <- currentContext
  case context of
    "Normal" -> return () >> pHandleEndLine
    "parenthesised" -> return () >> pHandleEndLine
    "Hash comment" -> (popContext) >> pEndLine
    "Tripple A-comment" -> return () >> pHandleEndLine
    "Tripple Q-comment" -> return () >> pHandleEndLine
    "Single A-comment" -> return () >> pHandleEndLine
    "Single Q-comment" -> return () >> pHandleEndLine
    "stringformat" -> return () >> pHandleEndLine
    "Tripple A-string" -> return () >> pHandleEndLine
    "Raw Tripple A-string" -> return () >> pHandleEndLine
    "Tripple Q-string" -> return () >> pHandleEndLine
    "Raw Tripple Q-string" -> return () >> pHandleEndLine
    "Single A-string" -> return () >> pHandleEndLine
    "Single Q-string" -> return () >> pHandleEndLine
    "Raw A-string" -> return () >> pHandleEndLine
    "Raw Q-string" -> return () >> pHandleEndLine
    _ -> pHandleEndLine

withAttribute attr txt = do
  when (null txt) $ fail "Parser matched no text"
  let labs = attr : maybeToList (lookup attr styles)
  st <- getState
  let oldCharsParsed = synStCharsParsedInLine st
  let prevchar = if null txt then '\n' else last txt
  updateState $ \st -> st { synStCharsParsedInLine = oldCharsParsed + length txt, synStPrevChar = prevchar } 
  return (labs, txt)

styles = [("Definition Keyword","kw"),("String Substitution","ot"),("Command Keyword","kw"),("Flow Control Keyword","kw"),("Builtin Function","dt"),("Special Variable","ot"),("Extensions","ot"),("Exceptions","ot"),("Overloaders","ot"),("Preprocessor","ch"),("String Char","ch"),("Float","fl"),("Int","dv"),("Hex","bn"),("Octal","bn"),("Complex","ot"),("Comment","co"),("String","st"),("Raw String","st"),("Decorator","ot")]

parseExpressionInternal = do
  context <- currentContext
  parseRules context <|> (pDefault >>= withAttribute (fromMaybe "" $ lookup context defaultAttributes))

list_prep = Set.fromList $ words $ "import from as"
list_defs = Set.fromList $ words $ "class def del global lambda nonlocal"
list_operators = Set.fromList $ words $ "and in is not or"
list_commands = Set.fromList $ words $ "exec print"
list_flow = Set.fromList $ words $ "assert break continue elif else except finally for if pass raise return try while with yield"
list_builtinfuncs = Set.fromList $ words $ "__future__ __import__ __name__ abs all any apply basestring bin bool buffer callable chr classmethod cmp coerce compile complex delattr dict dir divmod enumerate eval execfile file filter float format frozenset getattr globals hasattr hash help hex id input int intern isinstance issubclass iter len list locals long map max min next object oct open ord pow property range raw_input reduce reload repr reversed round set setattr slice sorted staticmethod str sum super tuple type unichr unicode vars xrange zip"
list_specialvars = Set.fromList $ words $ "None self True False NotImplemented Ellipsis __debug__ __file__"
list_bindings = Set.fromList $ words $ "SIGNAL SLOT connect"
list_overloaders = Set.fromList $ words $ "__new__ __init__ __del__ __repr__ __str__ __lt__ __le__ __eq__ __ne__ __gt__ __ge__ __cmp__ __rcmp__ __hash__ __nonzero__ __unicode__ __getattr__ __setattr__ __delattr__ __getattribute__ __get__ __set__ __delete__ __call__ __len__ __getitem__ __setitem__ __delitem__ __iter__ __reversed__ __contains__ __getslice__ __setslice__ __delslice__ __add__ __sub__ __mul__ __floordiv__ __mod__ __divmod__ __pow__ __lshift__ __rshift__ __and__ __xor__ __or__ __div__ __truediv__ __radd__ __rsub__ __rmul__ __rdiv__ __rtruediv__ __rfloordiv__ __rmod__ __rdivmod__ __rpow__ __rlshift__ __rrshift__ __rand__ __rxor__ __ror__ __iadd__ __isub__ __imul__ __idiv__ __itruediv__ __ifloordiv__ __imod__ __ipow__ __ilshift__ __irshift__ __iand__ __ixor__ __ior__ __neg__ __pos__ __abs__ __invert__ __complex__ __int__ __long__ __float__ __oct__ __hex__ __index__ __coerce__ __enter__ __exit__"
list_exceptions = Set.fromList $ words $ "ArithmeticError AssertionError AttributeError BaseException DeprecationWarning EnvironmentError EOFError Exception FloatingPointError FutureWarning GeneratorExit IOError ImportError ImportWarning IndexError KeyError KeyboardInterrupt LookupError MemoryError NameError NotImplementedError OSError OverflowError PendingDeprecationWarning ReferenceError RuntimeError RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning SystemError SystemExit TypeError UnboundLocalError UserWarning UnicodeError UnicodeWarning UnicodeEncodeError UnicodeDecodeError UnicodeTranslateError ValueError Warning WindowsError ZeroDivisionError"

regex_'5ba'2dzA'2dZ'5f'5d'5ba'2dzA'2dZ'5f0'2d9'5d'2b = compileRegex "[a-zA-Z_][a-zA-Z_0-9]+"
regex__'28'28'28'5b0'2d9'5d'2a'5c'2e'5b0'2d9'5d'2b'7c'5b0'2d9'5d'2b'5c'2e'29'7c'28'5b0'2d9'5d'2b'7c'28'5b0'2d9'5d'2a'5c'2e'5b0'2d9'5d'2b'7c'5b0'2d9'5d'2b'5c'2e'29'29'5beE'5d'28'5c'2b'7c'2d'29'3f'5b0'2d9'5d'2b'29'7c'5b0'2d9'5d'2b'29'5bjJ'5d = compileRegex " ((([0-9]*\\.[0-9]+|[0-9]+\\.)|([0-9]+|([0-9]*\\.[0-9]+|[0-9]+\\.))[eE](\\+|-)?[0-9]+)|[0-9]+)[jJ]"
regex_u'3f'27'27'27 = compileRegex "u?'''"
regex_u'3f'22'22'22 = compileRegex "u?\"\"\""
regex_'40'5b'5fa'2dzA'2dZ'5d'5b'5c'2e'5fa'2dzA'2dZ0'2d9'5d'2a = compileRegex "@[_a-zA-Z][\\._a-zA-Z0-9]*"
regex_'25'28'28'5c'28'5ba'2dzA'2dZ0'2d9'5f'5d'2b'5c'29'29'3f'5b'230'5c'2d_'2b'5d'3f'28'5b1'2d9'5d'5b0'2d9'5d'2a'7c'5c'2a'29'3f'28'5c'2e'28'5b1'2d9'5d'5b0'2d9'5d'2a'7c'5c'2a'29'29'3f'5bhlL'5d'3f'5bcrsdiouxXeEfFgG'25'5d'7cprog'7cdefault'29 = compileRegex "%((\\([a-zA-Z0-9_]+\\))?[#0\\- +]?([1-9][0-9]*|\\*)?(\\.([1-9][0-9]*|\\*))?[hlL]?[crsdiouxXeEfFgG%]|prog|default)"

defaultAttributes = [("Normal","Normal Text"),("parenthesised","Normal Text"),("Hash comment","Comment"),("Tripple A-comment","Comment"),("Tripple Q-comment","Comment"),("Single A-comment","Comment"),("Single Q-comment","Comment"),("stringformat","String Substitution"),("Tripple A-string","String"),("Raw Tripple A-string","Raw String"),("Tripple Q-string","String"),("Raw Tripple Q-string","Raw String"),("Single A-string","String"),("Single Q-string","String"),("Raw A-string","Raw String"),("Raw Q-string","Raw String")]

parseRules "Normal" = 
  do (attr, result) <- (((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_prep >>= withAttribute "Preprocessor"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_defs >>= withAttribute "Definition Keyword"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_operators >>= withAttribute "Operator"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_commands >>= withAttribute "Command Keyword"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_flow >>= withAttribute "Flow Control Keyword"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_builtinfuncs >>= withAttribute "Builtin Function"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_specialvars >>= withAttribute "Special Variable"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_bindings >>= withAttribute "Extensions"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_exceptions >>= withAttribute "Exceptions"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\#'" list_overloaders >>= withAttribute "Overloaders"))
                        <|>
                        ((pRegExpr regex_'5ba'2dzA'2dZ'5f'5d'5ba'2dzA'2dZ'5f0'2d9'5d'2b >>= withAttribute "Normal"))
                        <|>
                        ((pRegExpr regex__'28'28'28'5b0'2d9'5d'2a'5c'2e'5b0'2d9'5d'2b'7c'5b0'2d9'5d'2b'5c'2e'29'7c'28'5b0'2d9'5d'2b'7c'28'5b0'2d9'5d'2a'5c'2e'5b0'2d9'5d'2b'7c'5b0'2d9'5d'2b'5c'2e'29'29'5beE'5d'28'5c'2b'7c'2d'29'3f'5b0'2d9'5d'2b'29'7c'5b0'2d9'5d'2b'29'5bjJ'5d >>= withAttribute "Complex"))
                        <|>
                        ((pFloat >>= withAttribute "Float"))
                        <|>
                        ((pHlCHex >>= withAttribute "Hex"))
                        <|>
                        ((pHlCOct >>= withAttribute "Octal"))
                        <|>
                        (withChildren (pInt >>= withAttribute "Int") ((pString False "L" >>= withAttribute "Int")))
                        <|>
                        ((pString False "r'''" >>= withAttribute "Raw String") >>~ pushContext "Raw Tripple A-string")
                        <|>
                        ((pString False "r\"\"\"" >>= withAttribute "Raw String") >>~ pushContext "Raw Tripple Q-string")
                        <|>
                        ((pString False "r'" >>= withAttribute "Raw String") >>~ pushContext "Raw A-string")
                        <|>
                        ((pString False "r\"" >>= withAttribute "Raw String") >>~ pushContext "Raw Q-string")
                        <|>
                        ((pDetectChar False '#' >>= withAttribute "Comment") >>~ pushContext "Hash comment")
                        <|>
                        ((pFirstNonSpace >> pRegExpr regex_u'3f'27'27'27 >>= withAttribute "Comment") >>~ pushContext "Tripple A-comment")
                        <|>
                        ((pFirstNonSpace >> pRegExpr regex_u'3f'22'22'22 >>= withAttribute "Comment") >>~ pushContext "Tripple Q-comment")
                        <|>
                        ((pString False "'''" >>= withAttribute "String") >>~ pushContext "Tripple A-string")
                        <|>
                        ((pString False "u'''" >>= withAttribute "String") >>~ pushContext "Tripple A-string")
                        <|>
                        ((pString False "\"\"\"" >>= withAttribute "String") >>~ pushContext "Tripple Q-string")
                        <|>
                        ((pString False "u\"\"\"" >>= withAttribute "String") >>~ pushContext "Tripple Q-string")
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "String") >>~ pushContext "Single A-string")
                        <|>
                        ((pDetect2Chars False 'u' '\'' >>= withAttribute "String") >>~ pushContext "Single A-string")
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "String") >>~ pushContext "Single Q-string")
                        <|>
                        ((pDetect2Chars False 'u' '"' >>= withAttribute "String") >>~ pushContext "Single Q-string")
                        <|>
                        ((pDetectChar False '(' >>= withAttribute "Normal") >>~ pushContext "parenthesised")
                        <|>
                        ((pDetectChar False ')' >>= withAttribute "Normal") >>~ (popContext))
                        <|>
                        ((pAnyChar "+*/%\\|=;\\!<>!^&~-" >>= withAttribute "Operator"))
                        <|>
                        ((pFirstNonSpace >> pRegExpr regex_'40'5b'5fa'2dzA'2dZ'5d'5b'5c'2e'5fa'2dzA'2dZ0'2d9'5d'2a >>= withAttribute "Decorator")))
     return (attr, result)

parseRules "parenthesised" = 
  do (attr, result) <- ((parseRules "Normal"))
     return (attr, result)

parseRules "Hash comment" = 
  do (attr, result) <- ((Text.Highlighting.Kate.Syntax.Alert_indent.parseExpression))
     return (attr, result)

parseRules "Tripple A-comment" = 
  do (attr, result) <- (((pString False "'''" >>= withAttribute "Comment") >>~ (popContext))
                        <|>
                        ((Text.Highlighting.Kate.Syntax.Alert_indent.parseExpression)))
     return (attr, result)

parseRules "Tripple Q-comment" = 
  do (attr, result) <- (((pHlCChar >>= withAttribute "Comment"))
                        <|>
                        ((pString False "\"\"\"" >>= withAttribute "Comment") >>~ (popContext))
                        <|>
                        ((Text.Highlighting.Kate.Syntax.Alert_indent.parseExpression)))
     return (attr, result)

parseRules "Single A-comment" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Comment"))
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "Comment") >>~ (popContext))
                        <|>
                        ((Text.Highlighting.Kate.Syntax.Alert_indent.parseExpression)))
     return (attr, result)

parseRules "Single Q-comment" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Comment"))
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "Comment") >>~ (popContext))
                        <|>
                        ((Text.Highlighting.Kate.Syntax.Alert_indent.parseExpression)))
     return (attr, result)

parseRules "stringformat" = 
  do (attr, result) <- ((pRegExpr regex_'25'28'28'5c'28'5ba'2dzA'2dZ0'2d9'5f'5d'2b'5c'29'29'3f'5b'230'5c'2d_'2b'5d'3f'28'5b1'2d9'5d'5b0'2d9'5d'2a'7c'5c'2a'29'3f'28'5c'2e'28'5b1'2d9'5d'5b0'2d9'5d'2a'7c'5c'2a'29'29'3f'5bhlL'5d'3f'5bcrsdiouxXeEfFgG'25'5d'7cprog'7cdefault'29 >>= withAttribute "String Substitution"))
     return (attr, result)

parseRules "Tripple A-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "String Char"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pString False "'''" >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Raw Tripple A-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Raw String"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pString False "'''" >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Tripple Q-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "String Char"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pString False "\"\"\"" >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Raw Tripple Q-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Raw String"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pString False "\"\"\"" >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Single A-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "String Char"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Single Q-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "String Char"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "String") >>~ (popContext)))
     return (attr, result)

parseRules "Raw A-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Raw String"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "Raw String") >>~ (popContext)))
     return (attr, result)

parseRules "Raw Q-string" = 
  do (attr, result) <- (((pHlCStringChar >>= withAttribute "Raw String"))
                        <|>
                        ((parseRules "stringformat"))
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "Raw String") >>~ (popContext)))
     return (attr, result)

parseRules x = fail $ "Unknown context" ++ x