    {- This module was generated from data in the Kate syntax highlighting file fortran.xml, version 1.11,
       by  Franchin Matteo (fnch@libero.it) -}

    module Text.Highlighting.Kate.Syntax.Fortran ( highlight, parseExpression, syntaxName, syntaxExtensions ) where
    import Text.Highlighting.Kate.Definitions
    import Text.Highlighting.Kate.Common
    import Text.ParserCombinators.Parsec
    import Data.List (nub)
    import Data.Map (fromList)
    import Data.Maybe (fromMaybe)

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

    -- | Filename extensions for this language.
    syntaxExtensions :: String
    syntaxExtensions = "*.f;*.F;*.for;*.FOR;*.f90;*.F90;*.fpp;*.FPP;*.f95;*.F95;"

    -- | 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 = "Fortran" }
      context <- currentContext <|> (pushContext "default" >> 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 [("Fortran",["default"])], synStLanguage = "Fortran", synStCurrentLine = "", synStCharsParsedInLine = 0, synStCaseSensitive = False, synStKeywordCaseSensitive = False, synStCaptures = []}

    parseSourceLine = manyTill parseExpressionInternal pEndLine

    pEndLine = do
      newline <|> (eof >> return '\n')
      context <- currentContext
      case context of
        "default" -> return ()
        "find_preprocessor" -> return ()
        "find_op_and_log" -> return ()
        "find_comments" -> return ()
        "find_symbols" -> return ()
        "inside_func_paren" -> return ()
        "find_io_stmnts" -> return ()
        "find_io_paren" -> return ()
        "format_stmnt" -> return ()
        "find_begin_stmnts" -> return ()
        "find_end_stmnts" -> return ()
        "find_decls" -> return ()
        "find_paren" -> (popContext >> return ())
        "find_intrinsics" -> return ()
        "find_numbers" -> return ()
        "find_strings" -> return ()
        "string_1" -> return ()
        "string_2" -> return ()
        "end_of_string" -> return ()
        _ -> return ()
      lineContents <- lookAhead wholeLine
      updateState $ \st -> st { synStCurrentLine = lineContents, synStCharsParsedInLine = 0 }

    withAttribute attr txt = do
      if null txt
         then fail "Parser matched no text"
         else return ()
      let style = fromMaybe "" $ lookup attr styles
      st <- getState
      let oldCharsParsed = synStCharsParsedInLine st
      updateState $ \st -> st { synStCharsParsedInLine = oldCharsParsed + length txt }
      return (nub [style, attr], txt)

    styles = [("Normal Text","Normal"),("Keyword","Keyword"),("Data Type","DataType"),("Decimal","DecVal"),("Float","Float"),("String","String"),("Comment","Comment"),("Symbol","Normal"),("Preprocessor","Others"),("Operator","Keyword"),("Logical","Others"),("IO Function","Function"),("Elemental Procedure","Keyword"),("Inquiry Function","Function"),("Transformational Function","Function"),("Non elemental subroutine","Keyword")]

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

    defaultAttributes = [("default","Normal Text"),("find_preprocessor","Normal Text"),("find_op_and_log","Normal Text"),("find_comments","Normal Text"),("find_symbols","Normal Text"),("inside_func_paren","Normal Text"),("find_io_stmnts","Normal Text"),("find_io_paren","Normal Text"),("format_stmnt","Normal Text"),("find_begin_stmnts","Normal Text"),("find_end_stmnts","Normal Text"),("find_decls","Normal Text"),("find_paren","Data Type"),("find_intrinsics","Normal Text"),("find_numbers","Normal Text"),("find_strings","String"),("string_1","String"),("string_2","String"),("end_of_string","String")]

    parseRules "default" =
      do (attr, result) <- (((parseRules "find_strings"))
                            <|>
                            ((parseRules "find_decls"))
                            <|>
                            ((parseRules "find_intrinsics"))
                            <|>
                            ((parseRules "find_io_stmnts"))
                            <|>
                            ((parseRules "find_op_and_log"))
                            <|>
                            ((parseRules "find_numbers"))
                            <|>
                            ((parseRules "find_preprocessor"))
                            <|>
                            ((parseRules "find_comments"))
                            <|>
                            ((parseRules "find_symbols"))
                            <|>
                            ((parseRules "find_end_stmnts"))
                            <|>
                            ((parseRules "find_begin_stmnts")))
         return (attr, result)

    parseRules "find_preprocessor" =
      do (attr, result) <- ((pColumn 0 >> pRegExpr (compileRegex "(#|cDEC\\$|CDEC\\$).*$") >>= withAttribute "Preprocessor"))
         return (attr, result)

    parseRules "find_op_and_log" =
      do (attr, result) <- (((pRegExpr (compileRegex "\\.(true|false)\\.") >>= withAttribute "Logical"))
                            <|>
                            ((pRegExpr (compileRegex "\\.[A-Za-z]+\\.") >>= withAttribute "Operator"))
                            <|>
                            ((pRegExpr (compileRegex "(==|/=|<|<=|>|>=)") >>= withAttribute "Operator")))
         return (attr, result)

    parseRules "find_comments" =
      do (attr, result) <- (((pColumn 0 >> pRegExpr (compileRegex "[cC\\*].*$") >>= withAttribute "Comment"))
                            <|>
                            ((pRegExpr (compileRegex "!.*$") >>= withAttribute "Comment")))
         return (attr, result)

    parseRules "find_symbols" =
      do (attr, result) <- (((pDetect2Chars False '*' '*' >>= withAttribute "Keyword"))
                            <|>
                            ((pDetect2Chars False '(' '/' >>= withAttribute "Keyword"))
                            <|>
                            ((pDetect2Chars False '/' ')' >>= withAttribute "Keyword"))
                            <|>
                            ((pAnyChar "&+-*/=?[]^{|}~" >>= withAttribute "Keyword"))
                            <|>
                            ((pAnyChar "()," >>= withAttribute "Symbol")))
         return (attr, result)

    parseRules "inside_func_paren" =
      do (attr, result) <- (((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "inside_func_paren")
                            <|>
                            ((pDetectChar False ')' >>= withAttribute "Normal Text") >>~ (popContext >> return ()))
                            <|>
                            ((parseRules "find_strings"))
                            <|>
                            ((parseRules "find_intrinsics"))
                            <|>
                            ((parseRules "find_numbers")))
         return (attr, result)

    parseRules "find_io_stmnts" =
      do (attr, result) <- (((pRegExpr (compileRegex "\\b(read|write|backspace|rewind|end\\s*file|close)\\s*[(]") >>= withAttribute "IO Function") >>~ pushContext "find_io_paren")
                            <|>
                            ((pRegExpr (compileRegex "\\bopen\\s*[(]") >>= withAttribute "IO Function") >>~ pushContext "find_io_paren")
                            <|>
                            ((pRegExpr (compileRegex "\\binquire\\s*[(]") >>= withAttribute "IO Function") >>~ pushContext "find_io_paren")
                            <|>
                            ((pRegExpr (compileRegex "\\bformat\\s*[(]") >>= withAttribute "IO Function") >>~ pushContext "format_stmnt")
                            <|>
                            ((pRegExpr (compileRegex "\\bend\\s*file\\b") >>= withAttribute "IO Function"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["access","backspace","close","inquire","open","print","read","rewind","write","format"] >>= withAttribute "IO Function")))
         return (attr, result)

    parseRules "find_io_paren" =
      do (attr, result) <- (((pDetectChar False '*' >>= withAttribute "IO Function"))
                            <|>
                            ((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "inside_func_paren")
                            <|>
                            ((pDetectChar False ')' >>= withAttribute "IO Function") >>~ (popContext >> return ()))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["unit","end","err","fmt","iostat","status","advance","size","eor"] >>= withAttribute "IO Function"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["unit","iostat","err","file","exist","opened","number","named","name","access","sequential","direct","form","formatted","unformatted","recl","nextrec","blank","position","action","read","write","readwrite","delim","pad"] >>= withAttribute "IO Function"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["unit","iostat","err","file","status","access","form","recl","blank","position","action","delim","pad"] >>= withAttribute "IO Function"))
                            <|>
                            ((parseRules "find_strings"))
                            <|>
                            ((parseRules "find_intrinsics"))
                            <|>
                            ((parseRules "find_numbers"))
                            <|>
                            ((parseRules "find_symbols")))
         return (attr, result)

    parseRules "format_stmnt" =
      do (attr, result) <- (((pDetectChar False '(' >>= withAttribute "IO Function") >>~ pushContext "format_stmnt")
                            <|>
                            ((pDetectChar False ')' >>= withAttribute "IO Function") >>~ (popContext >> return ()))
                            <|>
                            ((pRegExpr (compileRegex "[0-9]*/") >>= withAttribute "IO Function"))
                            <|>
                            ((pAnyChar ":" >>= withAttribute "IO Function"))
                            <|>
                            ((parseRules "find_strings"))
                            <|>
                            ((parseRules "find_symbols")))
         return (attr, result)

    parseRules "find_begin_stmnts" =
      do (attr, result) <- (((pRegExpr (compileRegex "\\bmodule\\s+procedure\\b") >>= withAttribute "Keyword"))
                            <|>
                            ((pRegExpr (compileRegex "\\b(program|subroutine|function|module|block\\s*data)\\b") >>= withAttribute "Keyword")))
         return (attr, result)

    parseRules "find_end_stmnts" =
      do (attr, result) <- (((pRegExpr (compileRegex "\\bend\\s*(program|subroutine|function|module|block\\s*data)\\b") >>= withAttribute "Keyword"))
                            <|>
                            ((pRegExpr (compileRegex "\\bend\\s*(do|if|select|where|forall|interface)\\b") >>= withAttribute "Keyword"))
                            <|>
                            ((pRegExpr (compileRegex "\\bend\\b") >>= withAttribute "Keyword")))
         return (attr, result)

    parseRules "find_decls" =
      do (attr, result) <- (((pRegExpr (compileRegex "\\binteger[\\*]\\d{1,2}") >>= withAttribute "Data Type"))
                            <|>
                            ((pRegExpr (compileRegex "\\breal[\\*]\\d{1,2}") >>= withAttribute "Data Type"))
                            <|>
                            ((pRegExpr (compileRegex "\\bcomplex[\\*]\\d{1,2}") >>= withAttribute "Data Type"))
                            <|>
                            ((pRegExpr (compileRegex "\\bend\\s*type\\b") >>= withAttribute "Data Type"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["double","precision","parameter","save","pointer","public","private","target","allocatable","optional","sequence"] >>= withAttribute "Data Type"))
                            <|>
                            ((pColumn 0 >> pRegExpr (compileRegex "\\s*data\\b") >>= withAttribute "Data Type"))
                            <|>
                            ((pColumn 0 >> pRegExpr (compileRegex "\\s*real\\s*[(]") >>= withAttribute "Data Type") >>~ pushContext "find_paren")
                            <|>
                            ((pColumn 0 >> pRegExpr (compileRegex "\\s*real(?![\\w\\*])") >>= withAttribute "Data Type"))
                            <|>
                            ((pRegExpr (compileRegex "\\bcharacter[*][0-9]+\\b") >>= withAttribute "Data Type"))
                            <|>
                            ((pRegExpr (compileRegex "\\b(type|integer|complex|character|logical|intent|dimension)\\b\\s*[(]") >>= withAttribute "Data Type") >>~ pushContext "find_paren")
                            <|>
                            ((pRegExpr (compileRegex "\\b(type|integer|complex|character|logical|intent|dimension)\\b") >>= withAttribute "Data Type"))
                            <|>
                            ((pDetect2Chars False ':' ':' >>= withAttribute "Data Type")))
         return (attr, result)

    parseRules "find_paren" =
      do (attr, result) <- (((pDetectChar False '(' >>= withAttribute "Data Type") >>~ pushContext "find_paren")
                            <|>
                            ((pDetectChar False ')' >>= withAttribute "Data Type") >>~ (popContext >> return ())))
         return (attr, result)

    parseRules "find_intrinsics" =
      do (attr, result) <- (((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["allocate","break","call","case","common","contains","continue","cycle","deallocate","default","do","forall","where","elsewhere","elseif","else","equivalence","exit","external","for","go","goto","if","implicit","include","interface","intrinsic","namelist","none","nullify","operator","assignment","pause","procedure","pure","elemental","record","recursive","result","return","select","selectcase","stop","then","to","use","only","entry","while"] >>= withAttribute "Keyword"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["abs","cabs","dabs","iabs","aimag","aint","dint","anint","dnint","ceiling","cmplx","dcmplx","dimag","floor","nint","idnint","int","idint","ifix","real","float","sngl","dble","dreal","aprime","dconjg","dfloat","ddmim","rand","modulo","conjg","dprod","dim","ddim","idim","max","amax0","amax1","max0","max1","dmax1","min","amin0","amin1","min0","min1","dmin1","mod","amod","dmod","sign","dsign","isign","acos","dacos","asin","dasin","atan","datan","atan2","datan2","cos","ccos","dcos","cosh","dcosh","exp","cexp","dexp","log","alog","dlog","clog","log10","alog10","dlog10","sin","csin","dsin","sinh","dsinh","sqrt","csqrt","dsqrt","tan","dtan","tanh","dtanh","achar","char","iachar","ichar","lge","lgt","lle","llt","adjustl","adjustr","index","len_trim","scan","verify","logical","exponent","fraction","nearest","rrspacing","scale","set_exponent","spacing","btest","iand","ibclr","ibits","ibset","ieor","ior","ishft","ishftc","not","mvbits","merge"] >>= withAttribute "Elemental Procedure"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["associated","present","kind","len","digits","epsilon","huge","maxexponent","minexponent","precision","radix","range","tiny","bit_size","allocated","lbound","ubound","shape","size"] >>= withAttribute "Inquiry Function"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["repeat","trim","selected_int_kind","selected_real_kind","transfer","dot_product","matmul","all","any","count","maxval","minval","product","sum","pack","unpack","reshape","spread","cshift","eoshift","transpose","maxloc","minloc"] >>= withAttribute "Transformational Function"))
                            <|>
                            ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["date_and_time","system_clock","random_number","random_seed"] >>= withAttribute "Non elemental subroutine")))
         return (attr, result)

    parseRules "find_numbers" =
      do (attr, result) <- (((pRegExpr (compileRegex "[0-9]*\\.[0-9]+([de][+-]?[0-9]+)?([_]([0-9]+|[a-z][\\w_]*))?") >>= withAttribute "Float"))
                            <|>
                            ((pRegExpr (compileRegex "\\b[0-9]+\\.[0-9]*([de][+-]?[0-9]+)?([_]([0-9]+|[a-z][\\w_]*))?(?![a-z])") >>= withAttribute "Float"))
                            <|>
                            ((pRegExpr (compileRegex "\\b[0-9]+[de][+-]?[0-9]+([_]([0-9]+|[a-z][\\w_]*))?") >>= withAttribute "Float"))
                            <|>
                            ((pRegExpr (compileRegex "\\b[0-9]+([_]([0-9]+|[a-zA-Z][\\w_]*))?") >>= withAttribute "Decimal"))
                            <|>
                            ((pRegExpr (compileRegex "\\b[bozx](['][0-9a-f]+[']|[\"][0-9a-f]+[\"])") >>= withAttribute "Decimal")))
         return (attr, result)

    parseRules "find_strings" =
      do (attr, result) <- (((pDetectChar False '\'' >>= withAttribute "String") >>~ pushContext "string_1")
                            <|>
                            ((pDetectChar False '"' >>= withAttribute "String") >>~ pushContext "string_2"))
         return (attr, result)

    parseRules "string_1" =
      do (attr, result) <- (((pRegExpr (compileRegex "[^']*'") >>= withAttribute "String") >>~ (popContext >> return ()))
                            <|>
                            ((pRegExpr (compileRegex "&\\s*$") >>= withAttribute "Keyword") >>~ pushContext "end_of_string")
                            <|>
                            ((pRegExpr (compileRegex ".*(?=&\\s*$)") >>= withAttribute "String") >>~ pushContext "end_of_string")
                            <|>
                            ((popContext >> return ()) >> return ([], "")))
         return (attr, result)

    parseRules "string_2" =
      do (attr, result) <- (((pRegExpr (compileRegex "[^\"]*\"") >>= withAttribute "String") >>~ (popContext >> return ()))
                            <|>
                            ((pRegExpr (compileRegex "&\\s*$") >>= withAttribute "Keyword") >>~ pushContext "end_of_string")
                            <|>
                            ((pRegExpr (compileRegex ".*(?=&\\s*$)") >>= withAttribute "String") >>~ pushContext "end_of_string")
                            <|>
                            ((popContext >> return ()) >> return ([], "")))
         return (attr, result)

    parseRules "end_of_string" =
      do (attr, result) <- (((pDetectSpaces >>= withAttribute "String"))
                            <|>
                            ((pRegExpr (compileRegex "&\\s*$") >>= withAttribute "Keyword"))
                            <|>
                            ((pFirstNonSpace >> pDetectChar False '&' >>= withAttribute "Keyword") >>~ (popContext >> return ()))
                            <|>
                            ((pFirstNonSpace >> pRegExpr (compileRegex "(!.*)?$") >>= withAttribute "Comment"))
                            <|>
                            ((popContext >> popContext >> return ()) >> return ([], "")))
         return (attr, result)

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