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 Control.Monad.State
import Data.Char (isSpace)
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 (parseExpression Nothing)
parseExpression :: Maybe (String,String)
-> KateParser Token
parseExpression mbcontext = do
(lang,cont) <- maybe currentContext return mbcontext
result <- parseRules (lang,cont)
optional $ do eof
updateState $ \st -> st{ synStPrevChar = '\n' }
pEndLine
return result
startingState = SyntaxState {synStContexts = [("Verilog","Normal")], synStLineNumber = 0, synStPrevChar = '\n', synStPrevNonspace = False, synStCaseSensitive = True, synStKeywordCaseSensitive = True, synStCaptures = []}
pEndLine = do
updateState $ \st -> st{ synStPrevNonspace = False }
context <- currentContext
contexts <- synStContexts `fmap` getState
if length contexts >= 2
then case context of
("Verilog","Normal") -> return ()
("Verilog","String") -> (popContext) >> pEndLine
("Verilog","Commentar 1") -> (popContext) >> pEndLine
("Verilog","Commentar 2") -> return ()
("Verilog","Preprocessor") -> (popContext) >> pEndLine
("Verilog","Commentar/Preprocessor") -> return ()
("Verilog","Some Context") -> (popContext) >> pEndLine
("Verilog","Some Context2") -> return ()
("Verilog","Block name") -> (popContext) >> pEndLine
("Verilog","Port") -> return ()
_ -> return ()
else 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)
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_]+"
parseRules ("Verilog","Normal") =
(((pDetectSpaces >>= withAttribute NormalTok))
<|>
((pRegExpr regex_begin'5c_'2a'3a >>= withAttribute KeywordTok) >>~ pushContext ("Verilog","Block name"))
<|>
((pRegExpr regex_fork'5c_'2a'3a >>= withAttribute KeywordTok) >>~ pushContext ("Verilog","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 ("Verilog","String"))
<|>
((pDetect2Chars False '/' '/' >>= withAttribute CommentTok) >>~ pushContext ("Verilog","Commentar 1"))
<|>
((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext ("Verilog","Commentar 2"))
<|>
((pAnyChar "!%&()+,-<=+/:;>?[]^{|}~@" >>= withAttribute NormalTok))
<|>
((pColumn 0 >> pDetectChar False '`' >>= withAttribute OtherTok) >>~ pushContext ("Verilog","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))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Normal")) >> pDefault >>= withAttribute NormalTok))
parseRules ("Verilog","String") =
(((pLineContinue >>= withAttribute StringTok) >>~ pushContext ("Verilog","Some Context"))
<|>
((pHlCStringChar >>= withAttribute CharTok))
<|>
((pDetectChar False '"' >>= withAttribute StringTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","String")) >> pDefault >>= withAttribute StringTok))
parseRules ("Verilog","Commentar 1") =
(((Text.Highlighting.Kate.Syntax.Alert.parseExpression (Just ("Alerts","")) >>= ((withAttribute CommentTok) . snd)))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Commentar 1")) >> pDefault >>= withAttribute CommentTok))
parseRules ("Verilog","Commentar 2") =
(((Text.Highlighting.Kate.Syntax.Alert.parseExpression (Just ("Alerts","")) >>= ((withAttribute CommentTok) . snd)))
<|>
((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Commentar 2")) >> pDefault >>= withAttribute CommentTok))
parseRules ("Verilog","Preprocessor") =
(((pLineContinue >>= withAttribute OtherTok) >>~ pushContext ("Verilog","Some Context"))
<|>
((pRangeDetect '"' '"' >>= withAttribute FloatTok))
<|>
((pRangeDetect '<' '>' >>= withAttribute FloatTok))
<|>
((pDetect2Chars False '/' '/' >>= withAttribute CommentTok) >>~ pushContext ("Verilog","Commentar 1"))
<|>
((pDetect2Chars False '/' '*' >>= withAttribute CommentTok) >>~ pushContext ("Verilog","Commentar/Preprocessor"))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Preprocessor")) >> pDefault >>= withAttribute OtherTok))
parseRules ("Verilog","Commentar/Preprocessor") =
(((pDetect2Chars False '*' '/' >>= withAttribute CommentTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Commentar/Preprocessor")) >> pDefault >>= withAttribute CommentTok))
parseRules ("Verilog","Some Context") =
(currentContext >>= \x -> guard (x == ("Verilog","Some Context")) >> pDefault >>= withAttribute NormalTok)
parseRules ("Verilog","Some Context2") =
(((Text.Highlighting.Kate.Syntax.Alert.parseExpression (Just ("Alerts","")) >>= ((withAttribute CommentTok) . snd)))
<|>
((pFirstNonSpace >> pString False "#endif" >>= withAttribute CommentTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Some Context2")) >> pDefault >>= withAttribute CommentTok))
parseRules ("Verilog","Block name") =
(((pDetectIdentifier >>= withAttribute DataTypeTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Block name")) >> pDefault >>= withAttribute DataTypeTok))
parseRules ("Verilog","Port") =
(((pDetectIdentifier >>= withAttribute NormalTok) >>~ (popContext))
<|>
(currentContext >>= \x -> guard (x == ("Verilog","Port")) >> pDefault >>= withAttribute NormalTok))
parseRules ("Alerts", _) = Text.Highlighting.Kate.Syntax.Alert.parseExpression Nothing
parseRules x = parseRules ("Verilog","Normal") <|> fail ("Unknown context" ++ show x)