better support for macros with arguments

This commit is contained in:
Zachary Snow 2019-03-29 18:55:45 -04:00
parent e49cb3536e
commit c4449fd9ca
2 changed files with 49 additions and 10 deletions

View File

@ -25,7 +25,6 @@ import System.Directory (findFile)
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.List (findIndex, isPrefixOf) import Data.List (findIndex, isPrefixOf)
import Data.List.Split (splitOn)
import Language.SystemVerilog.Parser.Tokens import Language.SystemVerilog.Parser.Tokens
} }
@ -511,18 +510,60 @@ takeMacroDefinition = do
then lexicalError "macros cannot have 0 args" then lexicalError "macros cannot have 0 args"
else return (body, args) else return (body, args)
-- TODO FIXME XXX: This currently assumes that macro arguments contain no commas -- commas and right parens are forbidden outside matched pairs of: (), [], {},
-- or parentheses, which obviously isn't valid. See 22.5.1 of the spec for -- "", except to delimit arguments or end the list of arguments; see 22.5.1
-- details on how to deal with macros with arguments.
takeMacroArguments :: Alex [String] takeMacroArguments :: Alex [String]
takeMacroArguments = do takeMacroArguments = do
dropSpaces dropSpaces
str <- takeThrough ')' '(' <- takeChar
return $ splitOn "," str loop "" []
where
loop :: String -> [Char] -> Alex [String]
loop curr stack = do
ch <- takeChar
case (stack, ch) of
( s,'\\') -> do
ch2 <- takeChar
loop (curr ++ [ch, ch2]) s
([ ], ',') -> do
rest <- loop "" stack
return $ curr : rest
([ ], ')') -> return [curr]
-- TODO FIXME XXX: This doens't handle escape sequences in macros. ('"' : 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)
( s,'\n') -> loop (curr ++ [' ']) s
( s, _ ) -> loop (curr ++ [ch ]) s
findUnescapedQuote :: String -> (String, String)
findUnescapedQuote [] = ([], [])
findUnescapedQuote ('`' : '\\' : '`' : '"' : rest) = ('\\' : '"' : start, end)
where (start, end) = findUnescapedQuote rest
findUnescapedQuote ('\\' : '"' : rest) = ('\\' : '"' : start, end)
where (start, end) = findUnescapedQuote rest
findUnescapedQuote ('"' : rest) = ("\"", rest)
findUnescapedQuote (ch : rest) = (ch : start, end)
where (start, end) = findUnescapedQuote rest
-- substitute in the arguments for a macro expension
substituteArgs :: String -> [String] -> [String] -> String substituteArgs :: String -> [String] -> [String] -> String
substituteArgs "" _ _ = "" substituteArgs "" _ _ = ""
substituteArgs ('`' : '`' : body) names args =
substituteArgs body names args
substituteArgs ('"' : body) names args =
'"' : start ++ substituteArgs rest names args
where (start, rest) = findUnescapedQuote body
substituteArgs ('`' : '"' : body) names args =
'"' : substituteArgs (init start) names args
++ '"' : substituteArgs rest names args
where (start, rest) = findUnescapedQuote body
substituteArgs body names args = substituteArgs body names args =
case findIndex isPresent names of case findIndex isPresent names of
Nothing -> head body : substituteArgs (tail body) names args Nothing -> head body : substituteArgs (tail body) names args
@ -628,7 +669,6 @@ handleDirective (posOrig, _, _, strOrig) len = do
alexMonadScan alexMonadScan
"define" -> do "define" -> do
-- TODO: We don't yet support macros with arguments!
dropSpaces dropSpaces
name <- takeString name <- takeString
defn <- takeMacroDefinition defn <- takeMacroDefinition

View File

@ -29,8 +29,7 @@ executable sv2v
containers, containers,
directory, directory,
filepath, filepath,
mtl, mtl
split
other-modules: other-modules:
-- SystemVerilog modules -- SystemVerilog modules
Language.SystemVerilog Language.SystemVerilog