module Text.Highlighting.Kate.Syntax.Bash ( 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)
syntaxName :: String
syntaxName = "Bash"
syntaxExtensions :: String
syntaxExtensions = "*.sh;*.bash;*.ebuild;*.eclass;.bashrc;.bash_profile;.bash_login;.profile"
highlight :: String -> Either String [SourceLine]
highlight input =
case runParser parseSource startingState "source" input of
Left err -> Left $ show err
Right result -> Right result
parseExpression :: GenParser Char SyntaxState LabeledSource
parseExpression = do
st <- getState
let oldLang = synStLanguage st
setState $ st { synStLanguage = "Bash" }
context <- currentContext <|> (pushContext "Start" >> 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 [("Bash",["Start"])], synStLanguage = "Bash", synStCurrentLine = "", synStCharsParsedInLine = 0, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}
parseSourceLine = manyTill parseExpressionInternal pEndLine
pEndLine = do
newline <|> (eof >> return '\n')
context <- currentContext
case context of
"Start" -> return ()
"FindAll" -> return ()
"FindMost" -> return ()
"FindComments" -> (popContext >> return ())
"Comment" -> (popContext >> return ())
"FindCommentsParen" -> (popContext >> return ())
"CommentParen" -> (popContext >> return ())
"FindCommentsBackq" -> (popContext >> return ())
"CommentBackq" -> (popContext >> return ())
"FindCommands" -> return ()
"FindOthers" -> return ()
"FindStrings" -> return ()
"FindSubstitutions" -> return ()
"FindTests" -> return ()
"ExprDblParen" -> return ()
"ExprDblParenSubst" -> return ()
"ExprSubParen" -> return ()
"ExprBracket" -> return ()
"ExprDblBracket" -> return ()
"Group" -> return ()
"SubShell" -> return ()
"Assign" -> (popContext >> return ())
"AssignArray" -> (popContext >> return ())
"AssignSubscr" -> (popContext >> return ())
"Subscript" -> return ()
"FunctionDef" -> (popContext >> return ())
"VarName" -> (popContext >> return ())
"ProcessSubst" -> return ()
"StringSQ" -> return ()
"StringDQ" -> return ()
"StringEsc" -> return ()
"VarBrace" -> return ()
"VarAlt" -> return ()
"VarSubst" -> return ()
"VarSubst2" -> return ()
"VarSub" -> return ()
"VarSub2" -> return ()
"SubstFile" -> return ()
"SubstCommand" -> return ()
"SubstBackq" -> return ()
"Case" -> return ()
"CaseIn" -> return ()
"CaseExpr" -> return ()
"HereDoc" -> return ()
"HereDocRemainder" -> (popContext >> return ())
"HereDocQ" -> return ()
"HereDocNQ" -> return ()
"HereDocIQ" -> return ()
"HereDocINQ" -> 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"),("Comment","Comment"),("Keyword","Keyword"),("Control","Keyword"),("Builtin","Keyword"),("Command","Keyword"),("Redirection","Keyword"),("Escape","DataType"),("String SingleQ","String"),("String DoubleQ","String"),("Backquote","Keyword"),("String Transl.","String"),("String Escape","DataType"),("Variable","Others"),("Expression","Others"),("Function","Function"),("Path","Normal"),("Option","Normal"),("Error","Error")]
parseExpressionInternal = do
context <- currentContext
parseRules context <|> (pDefault >>= withAttribute (fromMaybe "" $ lookup context defaultAttributes))
defaultAttributes = [("Start","Normal Text"),("FindAll","Normal Text"),("FindMost","Normal Text"),("FindComments","Normal Text"),("Comment","Comment"),("FindCommentsParen","Normal Text"),("CommentParen","Comment"),("FindCommentsBackq","Normal Text"),("CommentBackq","Comment"),("FindCommands","Normal Text"),("FindOthers","Normal Text"),("FindStrings","Normal Text"),("FindSubstitutions","Normal Text"),("FindTests","Normal Text"),("ExprDblParen","Normal Text"),("ExprDblParenSubst","Normal Text"),("ExprSubParen","Normal Text"),("ExprBracket","Normal Text"),("ExprDblBracket","Normal Text"),("Group","Normal Text"),("SubShell","Normal Text"),("Assign","Normal Text"),("AssignArray","Normal Text"),("AssignSubscr","Normal Text"),("Subscript","Variable"),("FunctionDef","Function"),("VarName","Normal Text"),("ProcessSubst","Normal Text"),("StringSQ","String SingleQ"),("StringDQ","String DoubleQ"),("StringEsc","String SingleQ"),("VarBrace","Error"),("VarAlt","Normal Text"),("VarSubst","Normal Text"),("VarSubst2","Normal Text"),("VarSub","Error"),("VarSub2","Error"),("SubstFile","Normal Text"),("SubstCommand","Normal Text"),("SubstBackq","Normal Text"),("Case","Normal Text"),("CaseIn","Normal Text"),("CaseExpr","Normal Text"),("HereDoc","Normal Text"),("HereDocRemainder","Normal Text"),("HereDocQ","Normal Text"),("HereDocNQ","Normal Text"),("HereDocIQ","Normal Text"),("HereDocINQ","Normal Text")]
parseRules "Start" =
do (attr, result) <- ((parseRules "FindAll"))
return (attr, result)
parseRules "FindAll" =
do (attr, result) <- (((parseRules "FindComments"))
<|>
((parseRules "FindCommands"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "FindMost" =
do (attr, result) <- (((parseRules "FindComments"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "FindComments" =
do (attr, result) <- (((pFirstNonSpace >> pDetectChar False '#' >>= withAttribute "Comment") >>~ pushContext "Comment")
<|>
((pRegExpr (compileRegex "[\\s;](?=#)") >>= withAttribute "Normal Text") >>~ pushContext "Comment"))
return (attr, result)
parseRules "Comment" =
do (attr, result) <- ((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute "") . snd)))
return (attr, result)
parseRules "FindCommentsParen" =
do (attr, result) <- (((pFirstNonSpace >> pDetectChar False '#' >>= withAttribute "Comment") >>~ pushContext "CommentParen")
<|>
((pRegExpr (compileRegex "[\\s;](?=#)") >>= withAttribute "Normal Text") >>~ pushContext "CommentParen"))
return (attr, result)
parseRules "CommentParen" =
do (attr, result) <- (((pRegExpr (compileRegex "[^)](?=\\))") >>= withAttribute "Comment") >>~ (popContext >> return ()))
<|>
((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute "") . snd))))
return (attr, result)
parseRules "FindCommentsBackq" =
do (attr, result) <- (((pFirstNonSpace >> pDetectChar False '#' >>= withAttribute "Comment") >>~ pushContext "CommentBackq")
<|>
((pRegExpr (compileRegex "[\\s;](?=#)") >>= withAttribute "Normal Text") >>~ pushContext "CommentBackq"))
return (attr, result)
parseRules "CommentBackq" =
do (attr, result) <- (((pRegExpr (compileRegex "[^`](?=`)") >>= withAttribute "Comment") >>~ (popContext >> return ()))
<|>
((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute "") . snd))))
return (attr, result)
parseRules "FindCommands" =
do (attr, result) <- (((pDetect2Chars False '(' '(' >>= withAttribute "Keyword") >>~ pushContext "ExprDblParen")
<|>
((pColumn 0 >> pRegExpr (compileRegex "\\[\\[(?=($|\\s))") >>= withAttribute "Keyword") >>~ pushContext "ExprDblBracket")
<|>
((pRegExpr (compileRegex "\\s\\[\\[(?=($|\\s))") >>= withAttribute "Keyword") >>~ pushContext "ExprDblBracket")
<|>
((pColumn 0 >> pRegExpr (compileRegex "\\[(?=($|\\s))") >>= withAttribute "Builtin") >>~ pushContext "ExprBracket")
<|>
((pRegExpr (compileRegex "\\s\\[(?=($|\\s))") >>= withAttribute "Builtin") >>~ pushContext "ExprBracket")
<|>
((pRegExpr (compileRegex "\\{(?=($|\\s))") >>= withAttribute "Keyword") >>~ pushContext "Group")
<|>
((pDetectChar False '(' >>= withAttribute "Keyword") >>~ pushContext "SubShell")
<|>
((pRegExpr (compileRegex "\\bdo(?![\\w$+-])") >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\bdone(?![\\w$+-])") >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\bif(?![\\w$+-])") >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\bfi(?![\\w$+-])") >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\bcase(?![\\w$+-])") >>= withAttribute "Keyword") >>~ pushContext "Case")
<|>
((pRegExpr (compileRegex "-[A-Za-z0-9][A-Za-z0-9_]*") >>= withAttribute "Option"))
<|>
((pRegExpr (compileRegex "--[a-z][A-Za-z0-9_-]*") >>= withAttribute "Option"))
<|>
((pRegExpr (compileRegex "\\b[A-Za-z_][A-Za-z0-9_]*\\+?=") >>= withAttribute "Variable") >>~ pushContext "Assign")
<|>
((pRegExpr (compileRegex "\\b[A-Za-z_][A-Za-z0-9_]*(?=\\[.+\\]\\+?=)") >>= withAttribute "Variable") >>~ pushContext "AssignSubscr")
<|>
((pString False ":()" >>= withAttribute "Function"))
<|>
((pRegExpr (compileRegex "\\bfunction\\b") >>= withAttribute "Keyword") >>~ pushContext "FunctionDef")
<|>
((pKeyword " \n\t()!+,<=>&*;?|~\\`" ["else","for","function","in","select","until","while","elif","then","set"] >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\.(?=\\s)") >>= withAttribute "Builtin"))
<|>
((pKeyword " \n\t()!+,<=>&*;?|~\\`" [":","source","alias","bg","bind","break","builtin","cd","caller","command","compgen","complete","continue","dirs","disown","echo","enable","eval","exec","exit","fc","fg","getopts","hash","help","history","jobs","kill","let","logout","popd","printf","pushd","pwd","return","set","shift","shopt","suspend","test","time","times","trap","type","ulimit","umask","unalias","wait"] >>= withAttribute "Builtin"))
<|>
((pKeyword " \n\t()!+,<=>&*;?|~\\`" ["arch","awk","bash","bunzip2","bzcat","bzcmp","bzdiff","bzegrep","bzfgrep","bzgrep","bzip2","bzip2recover","bzless","bzmore","cat","chattr","chgrp","chmod","chown","chvt","cp","date","dd","deallocvt","df","dir","dircolors","dmesg","dnsdomainname","domainname","du","dumpkeys","echo","ed","egrep","false","fgconsole","fgrep","fuser","gawk","getkeycodes","gocr","grep","groff","groups","gunzip","gzexe","gzip","hostname","igawk","install","kbd_mode","kbdrate","killall","last","lastb","link","ln","loadkeys","loadunimap","login","ls","lsattr","lsmod","lsmod.old","mapscrn","mesg","mkdir","mkfifo","mknod","mktemp","more","mount","mv","nano","netstat","nisdomainname","nroff","openvt","pgawk","pidof","ping","ps","pstree","pwd","rbash","readlink","red","resizecons","rm","rmdir","run-parts","sash","sed","setfont","setkeycodes","setleds","setmetamode","setserial","sh","showkey","shred","sleep","ssed","stat","stty","su","sync","tar","tempfile","touch","troff","true","umount","uname","unicode_start","unicode_stop","unlink","utmpdump","uuidgen","vdir","wall","wc","ypdomainname","zcat","zcmp","zdiff","zegrep","zfgrep","zforce","zgrep","zless","zmore","znew","zsh","aclocal","aconnect","aplay","apm","apmsleep","apropos","ar","arecord","as","as86","autoconf","autoheader","automake","awk","basename","bc","bison","c++","cal","cat","cc","cdda2wav","cdparanoia","cdrdao","cd-read","cdrecord","chfn","chgrp","chmod","chown","chroot","chsh","clear","cmp","co","col","comm","cp","cpio","cpp","cut","dc","dd","df","diff","diff3","dir","dircolors","directomatic","dirname","du","env","expr","fbset","file","find","flex","flex++","fmt","free","ftp","funzip","fuser","g++","gawk","gc","gcc","gdb","getent","getopt","gettext","gettextize","gimp","gimp-remote","gimptool","gmake","gs","head","hexdump","id","install","join","kill","killall","ld","ld86","ldd","less","lex","ln","locate","lockfile","logname","lp","lpr","ls","lynx","m4","make","man","mkdir","mknod","msgfmt","mv","namei","nasm","nawk","nice","nl","nm","nm86","nmap","nohup","nop","od","passwd","patch","pcregrep","pcretest","perl","perror","pidof","pr","printf","procmail","prune","ps2ascii","ps2epsi","ps2frag","ps2pdf","ps2ps","psbook","psmerge","psnup","psresize","psselect","pstops","rcs","rev","rm","scp","sed","seq","setterm","shred","size","size86","skill","slogin","snice","sort","sox","split","ssh","ssh-add","ssh-agent","ssh-keygen","ssh-keyscan","stat","strings","strip","sudo","suidperl","sum","tac","tail","tee","test","tr","uniq","unlink","unzip","updatedb","updmap","uptime","users","vmstat","w","wc","wget","whatis","whereis","which","who","whoami","write","xargs","yacc","yes","zip","zsoelim","dcop","kdialog","kfile","xhost","xmodmap","xset"] >>= withAttribute "Command"))
<|>
((pKeyword " \n\t()!+,<=>&*;?|~\\`" ["export","unset","declare","typeset","local","read","readonly"] >>= withAttribute "Builtin") >>~ pushContext "VarName")
<|>
((pRegExpr (compileRegex "\\d*<<<") >>= withAttribute "Redirection"))
<|>
((pString False "<<" >>= withAttribute "Redirection") >>~ pushContext "HereDoc")
<|>
((pRegExpr (compileRegex "[<>]\\(") >>= withAttribute "Redirection") >>~ pushContext "ProcessSubst")
<|>
((pRegExpr (compileRegex "([0-9]*(>{1,2}|<)(&[0-9]+-?)?|&>|>&|[0-9]*<>)") >>= withAttribute "Redirection"))
<|>
((pRegExpr (compileRegex "([|&])\\1?") >>= withAttribute "Control"))
<|>
((pRegExpr (compileRegex "[A-Za-z_:][A-Za-z0-9_:#%@-]*\\s*\\(\\)") >>= withAttribute "Function")))
return (attr, result)
parseRules "FindOthers" =
do (attr, result) <- (((pRegExpr (compileRegex "\\\\[][;\\\\$`{}()|&<>* ]") >>= withAttribute "Escape"))
<|>
((pRegExpr (compileRegex "\\\\$") >>= withAttribute "Keyword"))
<|>
((pRegExpr (compileRegex "\\{(?!(\\s|$))\\S*\\}") >>= withAttribute "Escape"))
<|>
((pRegExpr (compileRegex "([\\w_@.%*?+-]|\\\\ )*(?=/)") >>= withAttribute "Path"))
<|>
((pRegExpr (compileRegex "~\\w*") >>= withAttribute "Path"))
<|>
((pRegExpr (compileRegex "/([\\w_@.%*?+-]|\\\\ )*(?=([\\s/):;$`'\"]|$))") >>= withAttribute "Path")))
return (attr, result)
parseRules "FindStrings" =
do (attr, result) <- (((pDetect2Chars False '\\' '\'' >>= withAttribute "Escape"))
<|>
((pDetect2Chars False '\\' '"' >>= withAttribute "Escape"))
<|>
((pDetectChar False '\'' >>= withAttribute "String SingleQ") >>~ pushContext "StringSQ")
<|>
((pDetectChar False '"' >>= withAttribute "String DoubleQ") >>~ pushContext "StringDQ")
<|>
((pDetect2Chars False '$' '\'' >>= withAttribute "String SingleQ") >>~ pushContext "StringEsc")
<|>
((pDetect2Chars False '$' '"' >>= withAttribute "String Transl.") >>~ pushContext "StringDQ"))
return (attr, result)
parseRules "FindSubstitutions" =
do (attr, result) <- (((pRegExpr (compileRegex "\\$[A-Za-z_][A-Za-z0-9_]*\\[") >>= withAttribute "Variable") >>~ pushContext "Subscript")
<|>
((pRegExpr (compileRegex "\\$[A-Za-z_][A-Za-z0-9_]*") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "\\$[*@#?$!_0-9-]") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "\\$\\{[*@#?$!_0-9-]\\}") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "\\$\\{#[A-Za-z_][A-Za-z0-9_]*(\\[[*@]\\])?\\}") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "\\$\\{![A-Za-z_][A-Za-z0-9_]*(\\[[*@]\\]|[*@])?\\}") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "\\$\\{[A-Za-z_][A-Za-z0-9_]*") >>= withAttribute "Variable") >>~ pushContext "VarBrace")
<|>
((pRegExpr (compileRegex "\\$\\{[*@#?$!_0-9-](?=[:#%/=?+-])") >>= withAttribute "Variable") >>~ pushContext "VarBrace")
<|>
((pString False "$((" >>= withAttribute "Variable") >>~ pushContext "ExprDblParenSubst")
<|>
((pString False "$(<" >>= withAttribute "Redirection") >>~ pushContext "SubstFile")
<|>
((pString False "$(" >>= withAttribute "Variable") >>~ pushContext "SubstCommand")
<|>
((pDetectChar False '`' >>= withAttribute "Backquote") >>~ pushContext "SubstBackq")
<|>
((pRegExpr (compileRegex "\\\\[`$\\\\]") >>= withAttribute "Escape")))
return (attr, result)
parseRules "FindTests" =
do (attr, result) <- (((pRegExpr (compileRegex "-[abcdefghkprstuwxOGLSNozn](?=\\s)") >>= withAttribute "Expression"))
<|>
((pRegExpr (compileRegex "-([no]t|ef)(?=\\s)") >>= withAttribute "Expression"))
<|>
((pRegExpr (compileRegex "([!=]=?|[><])(?=\\s)") >>= withAttribute "Expression"))
<|>
((pRegExpr (compileRegex "-(eq|ne|[gl][te])(?=\\s)") >>= withAttribute "Expression")))
return (attr, result)
parseRules "ExprDblParen" =
do (attr, result) <- (((pDetect2Chars False ')' ')' >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "ExprSubParen")
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "ExprDblParenSubst" =
do (attr, result) <- (((pDetect2Chars False ')' ')' >>= withAttribute "Variable") >>~ (popContext >> return ()))
<|>
((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "ExprSubParen")
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "ExprSubParen" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Normal Text") >>~ (popContext >> return ()))
<|>
((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "ExprSubParen")
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "ExprBracket" =
do (attr, result) <- (((pRegExpr (compileRegex "\\s\\](?=($|[\\s;|&]))") >>= withAttribute "Builtin") >>~ (popContext >> return ()))
<|>
((pColumn 0 >> pRegExpr (compileRegex "\\](?=($|[\\s;|&]))") >>= withAttribute "Builtin") >>~ (popContext >> return ()))
<|>
((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "ExprSubParen")
<|>
((parseRules "FindTests"))
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "ExprDblBracket" =
do (attr, result) <- (((pRegExpr (compileRegex "\\s\\]\\](?=($|[\\s;|&]))") >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((pColumn 0 >> pRegExpr (compileRegex "\\]\\](?=($|[\\s;|&]))") >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((pDetectChar False '(' >>= withAttribute "Normal Text") >>~ pushContext "ExprSubParen")
<|>
((parseRules "FindTests"))
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "Group" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((parseRules "FindAll")))
return (attr, result)
parseRules "SubShell" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((parseRules "FindAll")))
return (attr, result)
parseRules "Assign" =
do (attr, result) <- (((pDetectChar False '(' >>= withAttribute "Variable") >>~ pushContext "AssignArray")
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers"))
<|>
((pRegExpr (compileRegex "[\\w:,+_./-]") >>= withAttribute "Normal Text"))
<|>
((popContext >> return ()) >> return ([], "")))
return (attr, result)
parseRules "AssignArray" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Variable") >>~ (popContext >> return ()))
<|>
((pDetectChar False '[' >>= withAttribute "Variable") >>~ pushContext "Subscript")
<|>
((pDetectChar False '=' >>= withAttribute "Variable") >>~ pushContext "Assign")
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "AssignSubscr" =
do (attr, result) <- (((pDetectChar False '[' >>= withAttribute "Variable") >>~ pushContext "Subscript")
<|>
((pDetect2Chars False '+' '=' >>= withAttribute "Variable") >>~ pushContext "Assign")
<|>
((pDetectChar False '=' >>= withAttribute "Variable") >>~ pushContext "Assign")
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers"))
<|>
((popContext >> return ()) >> return ([], "")))
return (attr, result)
parseRules "Subscript" =
do (attr, result) <- (((pDetectChar False ']' >>= withAttribute "Variable") >>~ (popContext >> return ()))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "FunctionDef" =
do (attr, result) <- (((pRegExpr (compileRegex "\\s+[A-Za-z_:][A-Za-z0-9_:#%@-]*(\\s*\\(\\))?") >>= withAttribute "Function") >>~ (popContext >> return ()))
<|>
((popContext >> return ()) >> return ([], "")))
return (attr, result)
parseRules "VarName" =
do (attr, result) <- (((pRegExpr (compileRegex "-[A-Za-z0-9]+") >>= withAttribute "Option"))
<|>
((pRegExpr (compileRegex "--[a-z][A-Za-z0-9_-]*") >>= withAttribute "Option"))
<|>
((pRegExpr (compileRegex "\\b[A-Za-z_][A-Za-z0-9_]*") >>= withAttribute "Variable"))
<|>
((pDetectChar False '[' >>= withAttribute "Variable") >>~ pushContext "Subscript")
<|>
((pDetectChar False '=' >>= withAttribute "Variable") >>~ pushContext "Assign")
<|>
((parseRules "FindMost"))
<|>
((pRegExpr (compileRegex "[^]})|;`&><]") >>= withAttribute "Normal Text"))
<|>
((popContext >> return ()) >> return ([], "")))
return (attr, result)
parseRules "ProcessSubst" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Redirection") >>~ (popContext >> return ()))
<|>
((parseRules "FindCommentsParen"))
<|>
((parseRules "FindCommands"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "StringSQ" =
do (attr, result) <- ((pDetectChar False '\'' >>= withAttribute "String SingleQ") >>~ (popContext >> return ()))
return (attr, result)
parseRules "StringDQ" =
do (attr, result) <- (((pDetectChar False '"' >>= withAttribute "String DoubleQ") >>~ (popContext >> return ()))
<|>
((pRegExpr (compileRegex "\\\\[`\"\\\\$\\n]") >>= withAttribute "String Escape"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "StringEsc" =
do (attr, result) <- (((pDetectChar False '\'' >>= withAttribute "String SingleQ") >>~ (popContext >> return ()))
<|>
((pRegExpr (compileRegex "\\\\[abefnrtv\\\\']") >>= withAttribute "String Escape"))
<|>
((pRegExpr (compileRegex "\\\\([0-7]{1,3}|x[A-Fa-f0-9]{1,2}|c.)") >>= withAttribute "String Escape")))
return (attr, result)
parseRules "VarBrace" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> return ()))
<|>
((pDetectChar False '[' >>= withAttribute "Variable") >>~ pushContext "Subscript")
<|>
((pRegExpr (compileRegex "(:?[-=?+]|##?|%%?)") >>= withAttribute "Variable") >>~ pushContext "VarAlt")
<|>
((pRegExpr (compileRegex "//?") >>= withAttribute "Variable") >>~ pushContext "VarSubst")
<|>
((pDetectChar False ':' >>= withAttribute "Variable") >>~ pushContext "VarSub"))
return (attr, result)
parseRules "VarAlt" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> popContext >> return ()))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "VarSubst" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> popContext >> return ()))
<|>
((pDetectChar False '/' >>= withAttribute "Variable") >>~ pushContext "VarSubst2")
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "VarSubst2" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> popContext >> popContext >> return ()))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "VarSub" =
do (attr, result) <- (((pDetectChar False ':' >>= withAttribute "Variable") >>~ pushContext "VarSub2")
<|>
((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> popContext >> return ()))
<|>
((pRegExpr (compileRegex "[A-Za-z_][A-Za-z0-9_]*") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "[0-9]+(?=[:}])") >>= withAttribute "Variable"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "VarSub2" =
do (attr, result) <- (((pDetectChar False '}' >>= withAttribute "Variable") >>~ (popContext >> popContext >> popContext >> return ()))
<|>
((pRegExpr (compileRegex "[A-Za-z_][A-Za-z0-9_]*") >>= withAttribute "Variable"))
<|>
((pRegExpr (compileRegex "[0-9](?=[:}])") >>= withAttribute "Variable"))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "SubstFile" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Redirection") >>~ (popContext >> return ()))
<|>
((parseRules "FindCommentsParen"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "SubstCommand" =
do (attr, result) <- (((pDetectChar False ')' >>= withAttribute "Variable") >>~ (popContext >> return ()))
<|>
((parseRules "FindCommentsParen"))
<|>
((parseRules "FindCommands"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "SubstBackq" =
do (attr, result) <- (((pDetectChar False '`' >>= withAttribute "Backquote") >>~ (popContext >> return ()))
<|>
((parseRules "FindCommentsBackq"))
<|>
((parseRules "FindCommands"))
<|>
((parseRules "FindStrings"))
<|>
((parseRules "FindSubstitutions"))
<|>
((parseRules "FindOthers")))
return (attr, result)
parseRules "Case" =
do (attr, result) <- (((pRegExpr (compileRegex "\\sin\\b") >>= withAttribute "Keyword") >>~ pushContext "CaseIn")
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "CaseIn" =
do (attr, result) <- (((pRegExpr (compileRegex "\\besac(?=$|[\\s;)])") >>= withAttribute "Keyword") >>~ (popContext >> popContext >> return ()))
<|>
((pDetectChar False ')' >>= withAttribute "Keyword") >>~ pushContext "CaseExpr")
<|>
((pAnyChar "(|" >>= withAttribute "Keyword"))
<|>
((parseRules "FindMost")))
return (attr, result)
parseRules "CaseExpr" =
do (attr, result) <- (((pDetect2Chars False ';' ';' >>= withAttribute "Keyword") >>~ (popContext >> return ()))
<|>
((parseRules "FindAll")))
return (attr, result)
parseRules "HereDoc" =
do (attr, result) <- (((pRegExpr (compileRegex "(<<-\\s*\"([^|&;()<>\\s]+)\")") >>= withAttribute "Redirection") >>~ pushContext "HereDocIQ")
<|>
((pRegExpr (compileRegex "(<<-\\s*'([^|&;()<>\\s]+)')") >>= withAttribute "Redirection") >>~ pushContext "HereDocIQ")
<|>
((pRegExpr (compileRegex "(<<-\\s*\\\\([^|&;()<>\\s]+))") >>= withAttribute "Redirection") >>~ pushContext "HereDocIQ")
<|>
((pRegExpr (compileRegex "(<<-\\s*([^|&;()<>\\s]+))") >>= withAttribute "Redirection") >>~ pushContext "HereDocINQ")
<|>
((pRegExpr (compileRegex "(<<\\s*\"([^|&;()<>\\s]+)\")") >>= withAttribute "Redirection") >>~ pushContext "HereDocQ")
<|>
((pRegExpr (compileRegex "(<<\\s*'([^|&;()<>\\s]+)')") >>= withAttribute "Redirection") >>~ pushContext "HereDocQ")
<|>
((pRegExpr (compileRegex "(<<\\s*\\\\([^|&;()<>\\s]+))") >>= withAttribute "Redirection") >>~ pushContext "HereDocQ")
<|>
((pRegExpr (compileRegex "(<<\\s*([^|&;()<>\\s]+))") >>= withAttribute "Redirection") >>~ pushContext "HereDocNQ")
<|>
((pString False "<<" >>= withAttribute "Redirection") >>~ (popContext >> return ())))
return (attr, result)
parseRules "HereDocRemainder" =
do (attr, result) <- ((parseRules "FindAll"))
return (attr, result)
parseRules "HereDocQ" =
do (attr, result) <- (((pRegExprDynamic "%1" >>= withAttribute "Redirection") >>~ pushContext "HereDocRemainder")
<|>
((pColumn 0 >> pRegExprDynamic "%2\\b" >>= withAttribute "Redirection") >>~ (popContext >> popContext >> return ())))
return (attr, result)
parseRules "HereDocNQ" =
do (attr, result) <- (((pRegExprDynamic "%1" >>= withAttribute "Redirection") >>~ pushContext "HereDocRemainder")
<|>
((pColumn 0 >> pRegExprDynamic "%2\\b" >>= withAttribute "Redirection") >>~ (popContext >> popContext >> return ()))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules "HereDocIQ" =
do (attr, result) <- (((pRegExprDynamic "%1" >>= withAttribute "Redirection") >>~ pushContext "HereDocRemainder")
<|>
((pColumn 0 >> pRegExprDynamic "\\t*%2\\b" >>= withAttribute "Redirection") >>~ (popContext >> popContext >> return ())))
return (attr, result)
parseRules "HereDocINQ" =
do (attr, result) <- (((pRegExprDynamic "%1" >>= withAttribute "Redirection") >>~ pushContext "HereDocRemainder")
<|>
((pColumn 0 >> pRegExprDynamic "\\t*%2\\b" >>= withAttribute "Redirection") >>~ (popContext >> popContext >> return ()))
<|>
((parseRules "FindSubstitutions")))
return (attr, result)
parseRules x = fail $ "Unknown context" ++ x