Commit 9aa8b703 by Zachary Snow

fix handling of comments, quotes, and trailing whitespace in macro arguments

parent 4c7e9d03
...@@ -16,7 +16,7 @@ module Language.SystemVerilog.Parser.Preprocess ...@@ -16,7 +16,7 @@ module Language.SystemVerilog.Parser.Preprocess
import Control.Monad.Except import Control.Monad.Except
import Control.Monad.State.Strict import Control.Monad.State.Strict
import Data.Char (ord) 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 Data.Maybe (isJust, fromJust)
import System.Directory (findFile) import System.Directory (findFile)
import System.FilePath (dropFileName) import System.FilePath (dropFileName)
...@@ -397,34 +397,59 @@ takeMacroArguments = do ...@@ -397,34 +397,59 @@ takeMacroArguments = do
argLoop :: PPS [String] argLoop :: PPS [String]
argLoop = do argLoop = do
dropWhitespace dropWhitespace
(arg, isEnd) <- loop "" [] (argRev, isEnd) <- loop "" []
let arg' = dropWhileEnd isWhitespaceChar arg let arg = trimAndRev argRev
if isEnd if isEnd
then return [arg'] then return [arg]
else do else do
rest <- argLoop rest <- argLoop
return $ arg' : rest return $ arg : rest
loop :: String -> [Char] -> PPS (String, Bool) loop :: String -> [Char] -> PPS (String, Bool)
loop curr stack = do loop curr stack = do
ch <- takeChar ch <- takeChar
case (stack, ch) of case (stack, ch) of
( s,'\\') -> do
ch2 <- takeChar
loop (curr ++ [ch, ch2]) s
([ ], ',') -> return (curr, False) ([ ], ',') -> return (curr, False)
([ ], ')') -> return (curr, True) ([ ], ')') -> return (curr, True)
('"' : s, '"') -> loop (curr ++ [ch]) s -- simple quoted strings, allowing escaped quotes
( s, '"') -> loop (curr ++ [ch]) ('"' : s) ('\\': s, _ ) -> loop (ch : curr) s
('[' : s, ']') -> loop (curr ++ [ch]) s ('"' : s, '"') -> loop (ch : curr) s
( s, '[') -> loop (curr ++ [ch]) ('[' : s) ('"' : _,'\\') -> loop (ch : curr) ('\\': stack)
('(' : s, ')') -> loop (curr ++ [ch]) s ('"' : _, _ ) -> loop (ch : curr) stack
( s, '(') -> loop (curr ++ [ch]) ('(' : s) ( _, '"') -> loop (ch : curr) ('"' : stack)
('{' : s, '}') -> loop (curr ++ [ch]) s
( s, '{') -> loop (curr ++ [ch]) ('{' : s) ('[' : s, ']') -> loop (ch : curr) s
( s, '[') -> loop (ch : curr) ('[' : s)
( s,'\n') -> loop (curr ++ [' ']) s ('(' : s, ')') -> loop (ch : curr) s
( s, _ ) -> loop (curr ++ [ch ]) 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 :: [Maybe String] -> [String] -> PPS [String]
defaultMacroArgs [] [] = return [] defaultMacroArgs [] [] = return []
......
`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
`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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment