module Text.Highlighting.Kate.Syntax.Verilog
(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 Data.Map (fromList)
import Control.Monad.State
import Data.Char (isSpace)
import Data.Maybe (fromMaybe)
import qualified Data.Set as Set
syntaxName :: String
syntaxName = "Verilog"
syntaxExtensions :: String
syntaxExtensions = "*.v;*.V;*.vl"
highlight :: String -> [SourceLine]
highlight input = evalState (mapM parseSourceLine $ lines input) startingState
parseSourceLine :: String -> State SyntaxState SourceLine
parseSourceLine = mkParseSourceLine parseExpressionInternal pEndLine
parseExpression :: KateParser Token
parseExpression = do
st <- getState
let oldLang = synStLanguage st
setState $ st { synStLanguage = "Verilog" }
context <- currentContext <|> (pushContext "Normal" >> currentContext)
result <- parseRules context
optional $ eof >> pEndLine
updateState $ \st -> st { synStLanguage = oldLang }
return result
startingState = SyntaxState {synStContexts = fromList [("Verilog",["Normal"])], synStLanguage = "Verilog", synStLineNumber = 0, synStPrevChar = '\n', synStPrevNonspace = False, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}
pEndLine = do
updateState $ \st -> st{ synStPrevNonspace = False }
context <- currentContext
case context of
"Normal" -> return ()
"String" -> (popContext) >> pEndLine
"Commentar 1" -> (popContext) >> pEndLine
"Commentar 2" -> return ()
"Preprocessor" -> (popContext) >> pEndLine
"Commentar/Preprocessor" -> return ()
"Some Context" -> (popContext) >> pEndLine
"Some Context2" -> return ()
"Block name" -> (popContext) >> pEndLine
"Port" -> return ()
_ -> 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)
parseExpressionInternal = do
context <- currentContext
parseRules context <|> (pDefault >>= withAttribute (fromMaybe NormalTok $ lookup context defaultAttributes))
list_keywords = Set.fromList $ words $ "macromodule table endtable specify specparam endspecify defparam default if ifnone else forever while for wait repeat disable assign deassign force release always initial edge posedge negedge config endconfig library design liblist cell use instance"
list_beginwords = Set.fromList $ words $ "begin fork module case casex casez task function generate"
list_endwords = Set.fromList $ words $ "end join endmodule endcase endtask endfunction endgenerate"
list_strength = Set.fromList $ words $ "strong0 strong1 pull0 pull1 weak0 weak1 highz0 highz1 small medium large"
list_gates = Set.fromList $ words $ "pullup pulldown cmos rcmos nmos pmos rnmos rpmos and nand or nor xor xnor not buf tran rtran tranif0 tranif1 rtranif0 rtranif1 bufif0 bufif1 notif0 notif1"
list_types = Set.fromList $ words $ "input output inout wire tri tri0 tri1 wand wor triand trior supply0 supply1 reg integer real realtime time vectored scalared trireg parameter event signed automatic genvar localparam"
regex_begin'5c_'2a'3a = compileRegex "begin\\ *:"
regex_fork'5c_'2a'3a = compileRegex "fork\\ *:"
regex_'5b'5cd'5f'5d'2a'27d'5b'5cd'5f'5d'2b = compileRegex "[\\d_]*'d[\\d_]+"
regex_'5b'5cd'5f'5d'2a'27o'5b0'2d7xXzZ'5f'5d'2b = compileRegex "[\\d_]*'o[0-7xXzZ_]+"
regex_'5b'5cd'5f'5d'2a'27h'5b'5cda'2dfA'2dFxXzZ'5f'5d'2b = compileRegex "[\\d_]*'h[\\da-fA-FxXzZ_]+"
regex_'5b'5cd'5f'5d'2a'27b'5b01'5fzZxX'5d'2b = compileRegex "[\\d_]*'b[01_zZxX]+"
regex_'5ba'2dzA'2dZ0'2d9'5f'2c_'5ct'5d'2b'5cs'2a'3a = compileRegex "[a-zA-Z0-9_, \\t]+\\s*:"
regex_'5c'60'5ba'2dzA'2dZ'5f'5d'2b'5cw'2a = compileRegex "\\`[a-zA-Z_]+\\w*"
regex_'5c'24'5ba'2dzA'2dZ'5f'5d'2b'5cw'2a = compileRegex "\\$[a-zA-Z_]+\\w*"
regex_'23'5b'5cd'5f'5d'2b = compileRegex "#[\\d_]+"
defaultAttributes = [("Normal",NormalTok),("String",StringTok),("Commentar 1",CommentTok),("Commentar 2",CommentTok),("Preprocessor",OtherTok),("Commentar/Preprocessor",CommentTok),("Some Context",NormalTok),("Some Context2",CommentTok),("Block name",DataTypeTok),("Port",NormalTok)]
parseRules "Normal" =
(((pDetectSpaces >>= withAttribute NormalTok))
<|>
((pRegExpr regex_begin'5c_'2a'3a >>= withAttribute KeywordTok) >>~ pushContext "Block name")
<|>
((pRegExpr regex_fork'5c_'2a'3a >>= withAttribute KeywordTok) >>~ pushContext "Block name")
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_beginwords >>= withAttribute KeywordTok))
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_endwords >>= withAttribute KeywordTok))
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_keywords >>= withAttribute KeywordTok))
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_types >>= withAttribute DataTypeTok))
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_strength >>= withAttribute BaseNTok))
<|>
((pKeyword " \n\t.():!+,-<=>%&*/;?[]^{|}~\\" list_gates >>= withAttribute DataTypeTok))
<|>
((pRegExpr regex_'5b'5cd'5f'5d'2a'27d'5b'5cd'5f'5d'2b >>= withAttribute BaseNTok))
<|>
((pRegExpr regex_'5b'5cd'5f'5d'2a'27o'5b0'2d7xXzZ'5f'5d'2b >>= withAttribute BaseNTok))
<|>
((pRegExpr regex_'5b'5cd'5f'5d'2a'27h'5b'5cda'2dfA'2dFxXzZ'5f'5d'2b >>= withAttribute BaseNTok))
<|>
((pRegExpr regex_'5b'5cd'5f'5d'2a'27b'5b01'5fzZxX'5d'2b >>= withAttribute BaseNTok))
<|>
((pFloat >>= withAttribute FloatTok))
<|>
((pInt >>= withAttribute DecValTok))
<|>
((pFirstNonSpace >> pRegExpr regex_'5ba'2dzA'2dZ0'2d9'5f'2c_'5ct'5d'2b'5cs'2a'3a >>= withAttribute DecValTok))
<|>
((pDetectChar False '"' >>= withAttribute StringTok) >>~ pushContext "String")
<|>
((pDetect2Chars False '/' '/' >>= withAttribute CommentTok) >>~ pushContext "Commentar 1")
<|>
((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext "Commentar 2")
<|>
((pAnyChar "!%&()+,-<=+/:;>?[]^{|}~@" >>= withAttribute NormalTok))
<|>
((pColumn 0 >> pDetectChar False '`' >>= withAttribute OtherTok) >>~ pushContext "Preprocessor")
<|>
((pRegExpr regex_'5c'60'5ba'2dzA'2dZ'5f'5d'2b'5cw'2a >>= withAttribute OtherTok))
<|>
((pRegExpr regex_'5c'24'5ba'2dzA'2dZ'5f'5d'2b'5cw'2a >>= withAttribute DataTypeTok))
<|>
((pRegExpr regex_'23'5b'5cd'5f'5d'2b >>= withAttribute BaseNTok)))
parseRules "String" =
(((pLineContinue >>= withAttribute StringTok) >>~ pushContext "Some Context")
<|>
((pHlCStringChar >>= withAttribute CharTok))
<|>
((pDetectChar False '"' >>= withAttribute StringTok) >>~ (popContext)))
parseRules "Commentar 1" =
((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute CommentTok) . snd)))
parseRules "Commentar 2" =
(((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute CommentTok) . snd)))
<|>
((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext)))
parseRules "Preprocessor" =
(((pLineContinue >>= withAttribute OtherTok) >>~ pushContext "Some Context")
<|>
((pRangeDetect '"' '"' >>= withAttribute FloatTok))
<|>
((pRangeDetect '<' '>' >>= withAttribute FloatTok))
<|>
((pDetect2Chars False '/' '/' >>= withAttribute CommentTok) >>~ pushContext "Commentar 1")
<|>
((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext "Commentar/Preprocessor"))
parseRules "Commentar/Preprocessor" =
((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext))
parseRules "Some Context" =
pzero
parseRules "Some Context2" =
(((Text.Highlighting.Kate.Syntax.Alert.parseExpression >>= ((withAttribute CommentTok) . snd)))
<|>
((pFirstNonSpace >> pString False "#endif" >>= withAttribute CommentTok) >>~ (popContext)))
parseRules "Block name" =
((pDetectIdentifier >>= withAttribute DataTypeTok) >>~ (popContext))
parseRules "Port" =
((pDetectIdentifier >>= withAttribute NormalTok) >>~ (popContext))
parseRules "" = parseRules "Normal"
parseRules x = fail $ "Unknown context" ++ x