mirror of https://github.com/zachjs/sv2v.git
fix handling of comments, quotes, and trailing whitespace in macro arguments
This commit is contained in:
parent
4c7e9d0353
commit
9aa8b7033e
|
|
@ -16,7 +16,7 @@ module Language.SystemVerilog.Parser.Preprocess
|
|||
import Control.Monad.Except
|
||||
import Control.Monad.State.Strict
|
||||
import Data.Char (ord)
|
||||
import Data.List (dropWhileEnd, tails, isPrefixOf, findIndex, intercalate)
|
||||
import Data.List (tails, isPrefixOf, findIndex, intercalate)
|
||||
import Data.Maybe (isJust, fromJust)
|
||||
import System.Directory (findFile)
|
||||
import System.FilePath (dropFileName)
|
||||
|
|
@ -397,34 +397,59 @@ takeMacroArguments = do
|
|||
argLoop :: PPS [String]
|
||||
argLoop = do
|
||||
dropWhitespace
|
||||
(arg, isEnd) <- loop "" []
|
||||
let arg' = dropWhileEnd isWhitespaceChar arg
|
||||
(argRev, isEnd) <- loop "" []
|
||||
let arg = trimAndRev argRev
|
||||
if isEnd
|
||||
then return [arg']
|
||||
then return [arg]
|
||||
else do
|
||||
rest <- argLoop
|
||||
return $ arg' : rest
|
||||
return $ arg : rest
|
||||
loop :: String -> [Char] -> PPS (String, Bool)
|
||||
loop curr stack = do
|
||||
ch <- takeChar
|
||||
case (stack, ch) of
|
||||
( s,'\\') -> do
|
||||
ch2 <- takeChar
|
||||
loop (curr ++ [ch, ch2]) s
|
||||
([ ], ',') -> return (curr, False)
|
||||
([ ], ')') -> return (curr, True)
|
||||
|
||||
('"' : s, '"') -> loop (curr ++ [ch]) s
|
||||
( s, '"') -> loop (curr ++ [ch]) ('"' : s)
|
||||
('[' : s, ']') -> loop (curr ++ [ch]) s
|
||||
( s, '[') -> loop (curr ++ [ch]) ('[' : s)
|
||||
('(' : s, ')') -> loop (curr ++ [ch]) s
|
||||
( s, '(') -> loop (curr ++ [ch]) ('(' : s)
|
||||
('{' : s, '}') -> loop (curr ++ [ch]) s
|
||||
( s, '{') -> loop (curr ++ [ch]) ('{' : s)
|
||||
-- simple quoted strings, allowing escaped quotes
|
||||
('\\': s, _ ) -> loop (ch : curr) s
|
||||
('"' : s, '"') -> loop (ch : curr) s
|
||||
('"' : _,'\\') -> loop (ch : curr) ('\\': stack)
|
||||
('"' : _, _ ) -> loop (ch : curr) stack
|
||||
( _, '"') -> loop (ch : curr) ('"' : stack)
|
||||
|
||||
( s,'\n') -> loop (curr ++ [' ']) s
|
||||
( s, _ ) -> loop (curr ++ [ch ]) s
|
||||
('[' : s, ']') -> loop (ch : curr) s
|
||||
( s, '[') -> loop (ch : curr) ('[' : s)
|
||||
('(' : s, ')') -> loop (ch : curr) s
|
||||
( s, '(') -> loop (ch : curr) ('(' : s)
|
||||
('{' : s, '}') -> loop (ch : curr) s
|
||||
( s, '{') -> loop (ch : curr) ('{' : s)
|
||||
|
||||
( s, '/') -> do
|
||||
next <- peekChar
|
||||
case next of
|
||||
'/' -> takeChar >> dropLineComment >> loop curr s
|
||||
'*' -> takeChar >> dropBlockComment >> loop curr s
|
||||
_ -> loop ('/' : curr) s
|
||||
|
||||
( s,'\n') -> loop (' ' : curr) s
|
||||
( s, _ ) -> loop (ch : curr) s
|
||||
|
||||
trimAndRev = -- drop surrounding whitespace and reverse string
|
||||
dropWhile isWhitespaceChar . reverse . dropWhile isWhitespaceChar
|
||||
|
||||
dropLineComment :: PPS ()
|
||||
dropLineComment = do
|
||||
ch <- takeChar
|
||||
when (ch /= '\n') dropLineComment
|
||||
|
||||
dropBlockComment :: PPS ()
|
||||
dropBlockComment = do
|
||||
ch1 <- takeChar
|
||||
ch2 <- peekChar
|
||||
if ch1 == '*' && ch2 == '/'
|
||||
then takeChar >> return ()
|
||||
else dropBlockComment
|
||||
|
||||
defaultMacroArgs :: [Maybe String] -> [String] -> PPS [String]
|
||||
defaultMacroArgs [] [] = return []
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
`define MACRO_A(
|
||||
// comment
|
||||
/* intentional tab */
|
||||
/* comment */ x /* comment */
|
||||
/* intentional tab */
|
||||
// comment
|
||||
,
|
||||
// comment
|
||||
/* intentional tab */
|
||||
/* comment */ y /* comment */
|
||||
/* intentional tab */
|
||||
// comment
|
||||
) \
|
||||
initial begin \
|
||||
$display(`"x %b`", x); \
|
||||
$display(`"y %b`", y); \
|
||||
end
|
||||
|
||||
`define MACRO_B(x, y, z) initial $display(x, y, z);
|
||||
|
||||
module top;
|
||||
`MACRO_A(
|
||||
// comment
|
||||
/* intentional tab */
|
||||
/* comment */ 1 + 2 /* comment */
|
||||
/* intentional tab */
|
||||
// comment
|
||||
,
|
||||
/* intentional tab */
|
||||
/* comment */ 1'b1 & 1 /* comment */
|
||||
/* intentional tab */
|
||||
// comment
|
||||
)
|
||||
`MACRO_B(
|
||||
"/* not a block comment */",
|
||||
"// not a line comment",
|
||||
"cool \046 \" ( } { beans\\"
|
||||
)
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
`define MACRO_A(x, y) \
|
||||
initial begin \
|
||||
$display(`"x %b`", x); \
|
||||
$display(`"y %b`", y); \
|
||||
end
|
||||
|
||||
`define MACRO_B(x, y, z) initial $display(x, y, z);
|
||||
|
||||
module top;
|
||||
`MACRO_A(1 + 2, 1'b1 & 1)
|
||||
`MACRO_B(
|
||||
"/* not a block comment */",
|
||||
"// not a line comment",
|
||||
"cool \046 \042 ( } { beans\\"
|
||||
)
|
||||
endmodule
|
||||
Loading…
Reference in New Issue