{- This module was generated from data in the Kate syntax highlighting file javascript.xml, version 1.11,
   by  Anders Lund (anders@alweb.dk), Joseph Wenninger (jowenn@kde.org), Whitehawk Stormchaser (zerokode@gmx.net) -}

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

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

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

-- | 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 = "JavaScript" }
  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 [("JavaScript",["Normal"])], synStLanguage = "JavaScript", synStCurrentLine = "", synStCharsParsedInLine = 0, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}

parseSourceLine = manyTill parseExpressionInternal pEndLine

pEndLine = do
  newline <|> (eof >> return '\n')
  context <- currentContext
  case context of
    "Normal" -> return ()
    "String" -> (popContext >> return ())
    "String 1" -> (popContext >> return ())
    "Comment" -> (popContext >> return ())
    "Multi/inline Comment" -> return ()
    "Regular Expression" -> return ()
    "(Internal regex catch)" -> return ()
    "Regular Expression Character Class" -> return ()
    "(regex caret first check)" -> (popContext >> return ())
    "(charclass caret first check)" -> (popContext >> return ())
    "region_marker" -> (popContext >> 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"),("Function","Function"),("Objects","Keyword"),("Math","Keyword"),("Events","Keyword"),("Data Type","DataType"),("Decimal","DecVal"),("Float","Float"),("Char","Char"),("String","String"),("String Char","Char"),("Comment","Comment"),("Symbol","Normal"),("Regular Expression","Others"),("Pattern Internal Operator","Float"),("Pattern Character Class","BaseN"),("Region Marker","RegionMarker")]

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

defaultAttributes = [("Normal","Normal Text"),("String","String"),("String 1","String Char"),("Comment","Comment"),("Multi/inline Comment","Comment"),("Regular Expression","Regular Expression"),("(Internal regex catch)","Normal Text"),("Regular Expression Character Class","Pattern Character Class"),("(regex caret first check)","Pattern Internal Operator"),("(charclass caret first check)","Pattern Internal Operator"),("region_marker","Region Marker")]

parseRules "Normal" = 
  do (attr, result) <- (((pDetectSpaces >>= withAttribute "Normal Text"))
                        <|>
                        ((pString False "//BEGIN" >>= withAttribute "Region Marker") >>~ pushContext "region_marker")
                        <|>
                        ((pRegExpr (compileRegex "//END") >>= withAttribute "Region Marker") >>~ pushContext "region_marker")
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["if","else","for","in","while","do","continue","break","with","try","catch","finally","switch","case","new","var","function","return","delete","true","false","void","throw","typeof","const","default"] >>= withAttribute "Keyword"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["escape","isFinite","isNaN","Number","parseFloat","parseInt","reload","taint","unescape","untaint","write"] >>= withAttribute "Function"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["Anchor","Applet","Area","Array","Boolean","Button","Checkbox","Date","document","window","Image","FileUpload","Form","Frame","Function","Hidden","Link","MimeType","Math","Max","Min","Layer","navigator","Object","Password","Plugin","Radio","RegExp","Reset","Screen","Select","String","Text","Textarea","this","Window"] >>= withAttribute "Objects"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["abs","acos","asin","atan","atan2","ceil","cos","ctg","E","exp","floor","LN2","LN10","log","LOG2E","LOG10E","PI","pow","round","sin","sqrt","SQRT1_2","SQRT2","tan"] >>= withAttribute "Math"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["onAbort","onBlur","onChange","onClick","onError","onFocus","onLoad","onMouseOut","onMouseOver","onReset","onSelect","onSubmit","onUnload"] >>= withAttribute "Events"))
                        <|>
                        ((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" ["above","action","alinkColor","alert","anchor","anchors","appCodeName","applets","apply","appName","appVersion","argument","arguments","arity","availHeight","availWidth","back","background","below","bgColor","border","big","blink","blur","bold","border","call","caller","charAt","charCodeAt","checked","clearInterval","clearTimeout","click","clip","close","closed","colorDepth","complete","compile","constructor","confirm","cookie","current","cursor","data","defaultChecked","defaultSelected","defaultStatus","defaultValue","description","disableExternalCapture","domain","elements","embeds","enabledPlugin","enableExternalCapture","encoding","eval","exec","fgColor","filename","find","fixed","focus","fontcolor","fontsize","form","forms","formName","forward","frames","fromCharCode","getDate","getDay","getHours","getMiliseconds","getMinutes","getMonth","getSeconds","getSelection","getTime","getTimezoneOffset","getUTCDate","getUTCDay","getUTCFullYear","getUTCHours","getUTCMilliseconds","getUTCMinutes","getUTCMonth","getUTCSeconds","getYear","global","go","hash","height","history","home","host","hostname","href","hspace","ignoreCase","images","index","indexOf","innerHeight","innerWidth","input","italics","javaEnabled","join","language","lastIndex","lastIndexOf","lastModified","lastParen","layers","layerX","layerY","left","leftContext","length","link","linkColor","links","location","locationbar","load","lowsrc","match","MAX_VALUE","menubar","method","mimeTypes","MIN_VALUE","modifiers","moveAbove","moveBelow","moveBy","moveTo","moveToAbsolute","multiline","name","NaN","NEGATIVE_INFINITY","negative_infinity","next","open","opener","options","outerHeight","outerWidth","pageX","pageY","pageXoffset","pageYoffset","parent","parse","pathname","personalbar","pixelDepth","platform","plugins","pop","port","POSITIVE_INFINITY","positive_infinity","preference","previous","print","prompt","protocol","prototype","push","referrer","refresh","releaseEvents","reload","replace","reset","resizeBy","resizeTo","reverse","rightContext","screenX","screenY","scroll","scrollbar","scrollBy","scrollTo","search","select","selected","selectedIndex","self","setDate","setHours","setMinutes","setMonth","setSeconds","setTime","setTimeout","setUTCDate","setUTCDay","setUTCFullYear","setUTCHours","setUTCMilliseconds","setUTCMinutes","setUTCMonth","setUTCSeconds","setYear","shift","siblingAbove","siblingBelow","small","sort","source","splice","split","src","status","statusbar","strike","sub","submit","substr","substring","suffixes","sup","taintEnabled","target","test","text","title","toGMTString","toLocaleString","toLowerCase","toolbar","toSource","toString","top","toUpperCase","toUTCString","type","URL","unshift","unwatch","userAgent","UTC","value","valueOf","visibility","vlinkColor","vspace","width","watch","which","width","write","writeln","x","y","zIndex"] >>= withAttribute "Data Type"))
                        <|>
                        ((pDetectIdentifier >>= withAttribute "Normal Text"))
                        <|>
                        ((pFloat >>= withAttribute "Float"))
                        <|>
                        ((pInt >>= withAttribute "Decimal"))
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "String") >>~ pushContext "String")
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "String") >>~ pushContext "String 1")
                        <|>
                        ((pDetect2Chars False '/' '/' >>= withAttribute "Comment") >>~ pushContext "Comment")
                        <|>
                        ((pDetect2Chars False '/' '*' >>= withAttribute "Comment") >>~ pushContext "Multi/inline Comment")
                        <|>
                        ((pRegExpr (compileRegex "[=?:]") >>= withAttribute "Normal Text") >>~ pushContext "(Internal regex catch)")
                        <|>
                        ((pRegExpr (compileRegex "\\(") >>= withAttribute "Normal Text") >>~ pushContext "(Internal regex catch)")
                        <|>
                        ((pDetectChar False '{' >>= withAttribute "Symbol"))
                        <|>
                        ((pDetectChar False '}' >>= withAttribute "Symbol"))
                        <|>
                        ((pAnyChar ":!%&+,-/.*<=>?[]|~^;" >>= withAttribute "Symbol")))
     return (attr, result)

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

parseRules "String 1" = 
  do (attr, result) <- (((pDetectIdentifier >>= withAttribute "String Char"))
                        <|>
                        ((pDetectChar False '"' >>= withAttribute "String") >>~ pushContext "String")
                        <|>
                        ((pDetectChar False '\'' >>= withAttribute "String Char") >>~ (popContext >> return ())))
     return (attr, result)

parseRules "Comment" = 
  do (attr, result) <- (((pDetectSpaces >>= withAttribute "Comment"))
                        <|>
                        ((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute "") . snd)))
                        <|>
                        ((pDetectIdentifier >>= withAttribute "Comment")))
     return (attr, result)

parseRules "Multi/inline Comment" = 
  do (attr, result) <- (((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute "") . snd)))
                        <|>
                        ((pDetect2Chars False '*' '/' >>= withAttribute "Comment") >>~ (popContext >> return ())))
     return (attr, result)

parseRules "Regular Expression" = 
  do (attr, result) <- (((pRegExpr (compileRegex "/[ig]{0,2}") >>= withAttribute "Regular Expression") >>~ (popContext >> popContext >> popContext >> return ()))
                        <|>
                        ((pRegExpr (compileRegex "\\{[\\d, ]+\\}") >>= withAttribute "Pattern Internal Operator"))
                        <|>
                        ((pRegExpr (compileRegex "\\\\[bB]") >>= withAttribute "Pattern Internal Operator"))
                        <|>
                        ((pRegExpr (compileRegex "\\\\[nrtvfDdSsWw]") >>= withAttribute "Pattern Character Class"))
                        <|>
                        ((pDetectChar False '[' >>= withAttribute "Pattern Character Class") >>~ pushContext "(charclass caret first check)")
                        <|>
                        ((pRegExpr (compileRegex "\\\\.") >>= withAttribute "Pattern Internal Operator"))
                        <|>
                        ((pRegExpr (compileRegex "\\$(?=/)") >>= withAttribute "Pattern Internal Operator"))
                        <|>
                        ((pAnyChar "?+*()|" >>= withAttribute "Pattern Internal Operator")))
     return (attr, result)

parseRules "(Internal regex catch)" = 
  do (attr, result) <- (((pDetectSpaces >>= withAttribute "Normal Text"))
                        <|>
                        ((pRegExpr (compileRegex "//(?=;)") >>= withAttribute "Regular Expression") >>~ (popContext >> return ()))
                        <|>
                        ((pDetect2Chars False '/' '/' >>= withAttribute "Comment") >>~ pushContext "Comment")
                        <|>
                        ((pDetect2Chars False '/' '*' >>= withAttribute "Comment") >>~ pushContext "Multi/inline Comment")
                        <|>
                        ((pDetectChar False '/' >>= withAttribute "Regular Expression") >>~ pushContext "(regex caret first check)")
                        <|>
                        ((popContext >> return ()) >> return ([], "")))
     return (attr, result)

parseRules "Regular Expression Character Class" = 
  do (attr, result) <- (((pRegExpr (compileRegex "\\\\[\\[\\]]") >>= withAttribute "Pattern Character Class"))
                        <|>
                        ((pDetectChar False ']' >>= withAttribute "Pattern Character Class") >>~ (popContext >> popContext >> return ())))
     return (attr, result)

parseRules "(regex caret first check)" = 
  do (attr, result) <- (((pDetectChar False '^' >>= withAttribute "Pattern Internal Operator") >>~ pushContext "Regular Expression")
                        <|>
                        (pushContext "Regular Expression" >> return ([], "")))
     return (attr, result)

parseRules "(charclass caret first check)" = 
  do (attr, result) <- (((pDetectChar False '^' >>= withAttribute "Pattern Internal Operator") >>~ pushContext "Regular Expression Character Class")
                        <|>
                        (pushContext "Regular Expression Character Class" >> return ([], "")))
     return (attr, result)

parseRules "region_marker" = 
  do (attr, result) <- (((pDetectIdentifier >>= withAttribute "Region Marker"))
                        <|>
                        ((pDetectSpaces >>= withAttribute "Region Marker")))
     return (attr, result)

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