mirror of https://github.com/zachjs/sv2v.git
expanded support for macros in preprocessor directives
This commit is contained in:
parent
6f0fa58ace
commit
cf4c2a5491
|
|
@ -32,6 +32,7 @@ module Language.SystemVerilog.Parser.Lex
|
||||||
import System.FilePath (dropFileName)
|
import System.FilePath (dropFileName)
|
||||||
import System.Directory (findFile)
|
import System.Directory (findFile)
|
||||||
import System.IO.Unsafe (unsafePerformIO)
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
import Text.Read (readMaybe)
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Data.List (span, elemIndex, dropWhileEnd)
|
import Data.List (span, elemIndex, dropWhileEnd)
|
||||||
|
|
@ -732,21 +733,31 @@ dropWhitespace = do
|
||||||
else return()
|
else return()
|
||||||
[] -> return ()
|
[] -> return ()
|
||||||
|
|
||||||
-- removes and returns a quoted string such as <foo.bar> or "foo.bar"
|
-- lex the remainder of the current line into tokens and return them, rather
|
||||||
takeQuotedString :: Alex String
|
-- than storing them in the lexer state
|
||||||
takeQuotedString = do
|
tokenizeLine :: Alex [Token]
|
||||||
dropSpaces
|
tokenizeLine = do
|
||||||
ch <- takeChar
|
-- read in the rest of the current line
|
||||||
end <-
|
str <- takeUntilNewline
|
||||||
case ch of
|
dropWhitespace
|
||||||
'"' -> return '"'
|
-- save the current lexer state
|
||||||
'<' -> return '>'
|
currInput <- alexGetInput
|
||||||
_ -> lexicalError $ "bad beginning of include arg: " ++ (show ch)
|
currFile <- getCurrentFile
|
||||||
rest <- takeThrough end
|
currToks <- gets lsToks
|
||||||
let res = ch : rest
|
-- parse the line into tokens (which includes macro processing)
|
||||||
if end == '>'
|
modify $ \s -> s { lsToks = [] }
|
||||||
then lexicalError $ "library includes are not supported: " ++ res
|
let newInput = (alexStartPos, ' ', [], str)
|
||||||
else return res
|
alexSetInput newInput
|
||||||
|
alexMonadScan
|
||||||
|
toks <- gets lsToks
|
||||||
|
-- return to the previous state
|
||||||
|
alexSetInput currInput
|
||||||
|
setCurrentFile currFile
|
||||||
|
modify $ \s -> s { lsToks = currToks }
|
||||||
|
-- remove macro boundary tokens and put the tokens in order
|
||||||
|
let isntMacroBoundary = \(Token t _ _ ) -> t /= MacroBoundary
|
||||||
|
let toks' = filter isntMacroBoundary toks
|
||||||
|
return $ reverse toks'
|
||||||
|
|
||||||
-- removes and returns a decimal number
|
-- removes and returns a decimal number
|
||||||
takeNumber :: Alex Int
|
takeNumber :: Alex Int
|
||||||
|
|
@ -772,9 +783,9 @@ takeNumber = do
|
||||||
peekChar :: Alex Char
|
peekChar :: Alex Char
|
||||||
peekChar = do
|
peekChar = do
|
||||||
(_, _, _, str) <- alexGetInput
|
(_, _, _, str) <- alexGetInput
|
||||||
return $ if null str
|
if null str
|
||||||
then '\n'
|
then lexicalError "unexpected end of input"
|
||||||
else head str
|
else return $head str
|
||||||
|
|
||||||
takeMacroDefinition :: Alex (String, [(String, Maybe String)])
|
takeMacroDefinition :: Alex (String, [(String, Maybe String)])
|
||||||
takeMacroDefinition = do
|
takeMacroDefinition = do
|
||||||
|
|
@ -856,6 +867,7 @@ findUnescapedQuote ('`' : '\\' : '`' : '"' : rest) = ('\\' : '"' : start, end)
|
||||||
findUnescapedQuote ('\\' : '"' : rest) = ('\\' : '"' : start, end)
|
findUnescapedQuote ('\\' : '"' : rest) = ('\\' : '"' : start, end)
|
||||||
where (start, end) = findUnescapedQuote rest
|
where (start, end) = findUnescapedQuote rest
|
||||||
findUnescapedQuote ('"' : rest) = ("\"", rest)
|
findUnescapedQuote ('"' : rest) = ("\"", rest)
|
||||||
|
findUnescapedQuote ('`' : '"' : rest) = ("\"", rest)
|
||||||
findUnescapedQuote (ch : rest) = (ch : start, end)
|
findUnescapedQuote (ch : rest) = (ch : start, end)
|
||||||
where (start, end) = findUnescapedQuote rest
|
where (start, end) = findUnescapedQuote rest
|
||||||
|
|
||||||
|
|
@ -939,7 +951,10 @@ handleDirective (posOrig, _, _, strOrig) len = do
|
||||||
"resetall" -> passThrough
|
"resetall" -> passThrough
|
||||||
|
|
||||||
"begin_keywords" -> do
|
"begin_keywords" -> do
|
||||||
quotedSpec <- takeQuotedString
|
toks <- tokenizeLine
|
||||||
|
quotedSpec <- case toks of
|
||||||
|
[Token Lit_string str _] -> return str
|
||||||
|
_ -> lexicalError $ "unexpected tokens following `begin_keywords: " ++ show toks
|
||||||
let spec = tail $ init quotedSpec
|
let spec = tail $ init quotedSpec
|
||||||
case Map.lookup spec specMap of
|
case Map.lookup spec specMap of
|
||||||
Nothing ->
|
Nothing ->
|
||||||
|
|
@ -973,9 +988,16 @@ handleDirective (posOrig, _, _, strOrig) len = do
|
||||||
alexMonadScan
|
alexMonadScan
|
||||||
|
|
||||||
"line" -> do
|
"line" -> do
|
||||||
lineNumber <- takeNumber
|
toks <- tokenizeLine
|
||||||
quotedFilename <- takeQuotedString
|
(lineNumber, quotedFilename, levelNumber) <-
|
||||||
levelNumber <- takeNumber -- level, ignored
|
case toks of
|
||||||
|
[ Token Lit_number lineStr _,
|
||||||
|
Token Lit_string filename _,
|
||||||
|
Token Lit_number levelStr _] -> do
|
||||||
|
let Just line = readMaybe lineStr :: Maybe Int
|
||||||
|
let Just level = readMaybe levelStr :: Maybe Int
|
||||||
|
return (line, filename, level)
|
||||||
|
_ -> lexicalError $ "unexpected tokens following `begin_keywords: " ++ show toks
|
||||||
let filename = init $ tail quotedFilename
|
let filename = init $ tail quotedFilename
|
||||||
setCurrentFile filename
|
setCurrentFile filename
|
||||||
(AlexPn f _ c, prev, _, str) <- alexGetInput
|
(AlexPn f _ c, prev, _, str) <- alexGetInput
|
||||||
|
|
@ -985,7 +1007,10 @@ handleDirective (posOrig, _, _, strOrig) len = do
|
||||||
else lexicalError "line directive invalid level number"
|
else lexicalError "line directive invalid level number"
|
||||||
|
|
||||||
"include" -> do
|
"include" -> do
|
||||||
quotedFilename <- takeQuotedString
|
toks <- tokenizeLine
|
||||||
|
quotedFilename <- case toks of
|
||||||
|
[Token Lit_string str _] -> return str
|
||||||
|
_ -> lexicalError $ "unexpected tokens following `include: " ++ show toks
|
||||||
inputFollow <- alexGetInput
|
inputFollow <- alexGetInput
|
||||||
fileFollow <- getCurrentFile
|
fileFollow <- getCurrentFile
|
||||||
-- process the included file
|
-- process the included file
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,10 @@ module top;
|
||||||
$display(`__FILE__, `__LINE__);
|
$display(`__FILE__, `__LINE__);
|
||||||
`line 101 "fake.v" 1
|
`line 101 "fake.v" 1
|
||||||
$display(`__FILE__, `__LINE__);
|
$display(`__FILE__, `__LINE__);
|
||||||
|
`define foo(filename) `"filename.vh`"
|
||||||
|
`include `foo(line)
|
||||||
|
`define new_line_num 200
|
||||||
|
`line `new_line_num `foo(line) 1
|
||||||
|
$display(`__FILE__, `__LINE__);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
module top;
|
module top;
|
||||||
initial begin
|
initial begin
|
||||||
$display("line.sv", `__LINE__);
|
$display("line.sv", `__LINE__);
|
||||||
;
|
|
||||||
$display("fake.v", 102);
|
$display("fake.v", 102);
|
||||||
|
$display("via include: ", "./line.vh", 1);
|
||||||
|
$display("line.vh", 201);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
$display("via include: ", `__FILE__, `__LINE__);
|
||||||
Loading…
Reference in New Issue