From 12c57ecc2469561d436019293c2c2797614c83ab Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Thu, 6 May 2021 16:14:41 -0400 Subject: [PATCH] preprocessor cleanup and extended test coverage --- .../SystemVerilog/Parser/Preprocess.hs | 70 ++++++++----------- test/error/block_comment_eof.sv | 2 + test/error/double_backtick.sv | 4 ++ test/error/include_filename_eof.sv | 2 + test/error/macro_arg_bad_eq.sv | 2 + test/error/macro_arg_bad_name.sv | 2 + test/error/macro_args_empty.sv | 2 + test/error/macro_illegal_name.sv | 2 + test/error/macro_overapplied.sv | 3 + test/error/macro_unapplied.sv | 3 + test/error/macro_unapplied_eof.sv | 3 + test/error/macro_underapplied.sv | 3 + test/error/string_directive.sv | 2 + test/error/string_literal_backtick_eof.sv | 2 + test/error/string_literal_eof.sv | 2 + test/error/unmatched_else.sv | 2 + test/error/unmatched_elsif.sv | 2 + test/lex/macro_arg_escape.sv | 5 ++ test/lex/undefineall.sv | 7 ++ test/lex/undefineall.v | 3 + 20 files changed, 83 insertions(+), 40 deletions(-) create mode 100644 test/error/block_comment_eof.sv create mode 100644 test/error/double_backtick.sv create mode 100644 test/error/include_filename_eof.sv create mode 100644 test/error/macro_arg_bad_eq.sv create mode 100644 test/error/macro_arg_bad_name.sv create mode 100644 test/error/macro_args_empty.sv create mode 100644 test/error/macro_illegal_name.sv create mode 100644 test/error/macro_overapplied.sv create mode 100644 test/error/macro_unapplied.sv create mode 100644 test/error/macro_unapplied_eof.sv create mode 100644 test/error/macro_underapplied.sv create mode 100644 test/error/string_directive.sv create mode 100644 test/error/string_literal_backtick_eof.sv create mode 100644 test/error/string_literal_eof.sv create mode 100644 test/error/unmatched_else.sv create mode 100644 test/error/unmatched_elsif.sv create mode 100644 test/lex/macro_arg_escape.sv create mode 100644 test/lex/undefineall.sv create mode 100644 test/lex/undefineall.v diff --git a/src/Language/SystemVerilog/Parser/Preprocess.hs b/src/Language/SystemVerilog/Parser/Preprocess.hs index 4943467..293f842 100644 --- a/src/Language/SystemVerilog/Parser/Preprocess.hs +++ b/src/Language/SystemVerilog/Parser/Preprocess.hs @@ -38,14 +38,14 @@ data PP = PP , ppIncludePaths :: [FilePath] -- folders to search for includes , ppMacroStack :: [[(String, String)]] -- arguments for in-progress macro expansions , ppIncludeStack :: [(FilePath, Env)] -- in-progress includes for loop detection - } deriving (Eq, Show) + } -- keeps track of the state of an if-else cascade level data Cond = CurrentlyTrue -- an active if/elsif/else branch (condition is met) | PreviouslyTrue -- an inactive else/elsif block due to an earlier if/elsif | NeverTrue -- an inactive if/elsif block; a subsequent else will be met - deriving (Eq, Show) + deriving Eq -- update a Cond for an `else block, where this block is active if and only if -- no previous block was active @@ -288,8 +288,7 @@ takeThrough :: Char -> PPS String takeThrough goal = do str <- getInput if null str - then lexicalError $ - "unexpected end of input, looking for " ++ (show goal) + then lexicalError $ "unexpected end of input, looking for " ++ show goal else do ch <- takeChar if ch == goal @@ -366,24 +365,23 @@ takeMacroDefinition = do dropSpaces body <- takeUntilNewline argsWithDefaults <- mapM splitArg args - if null args - then lexicalError "macros cannot have 0 args" - else return (body, argsWithDefaults) + return (body, argsWithDefaults) where splitArg :: String -> PPS (String, Maybe String) - splitArg [] = lexicalError "macro defn. empty argument" - splitArg str = do - let (name, rest) = span isIdentChar str - if null name || not (all isIdentChar name) then - lexicalError $ "invalid macro arg name: " ++ show name + splitArg [] = lexicalError "macro definition missing argument name" + splitArg str = + if null name then + lexicalError $ "invalid macro definition argument: " ++ show str else if null rest then return (name, Nothing) - else do - let leadCh : after = dropWhile isWhitespaceChar rest - let value = dropWhile isWhitespaceChar after - if leadCh /= '=' - then lexicalError $ "bad char after arg name: " ++ (show leadCh) - else return (name, Just value) + else if leadCh /= '=' then + lexicalError $ "bad char after argument name: " ++ show leadCh + else + return (name, Just value) + where + (name, rest) = span isIdentChar str + leadCh : after = dropWhile isWhitespaceChar rest + value = dropWhile isWhitespaceChar after -- commas and right parens are forbidden outside matched pairs of: (), [], {}, -- "", except to delimit arguments or end the list of arguments; see 22.5.1 @@ -393,7 +391,7 @@ takeMacroArguments = do leadCh <- takeChar if leadCh == '(' then argLoop >>= mapM preprocessString - else lexicalError $ "expected begining of macro arguments, but found " + else lexicalError $ "expected beginning of macro arguments, but found " ++ show leadCh where argLoop :: PPS [String] @@ -466,12 +464,10 @@ dropWhitespace = do str <- getInput case str of ch : chs -> - if isWhitespaceChar ch - then do - advancePosition ch - setInput chs - dropWhitespace - else return () + when (isWhitespaceChar ch) $ do + advancePosition ch + setInput chs + dropWhitespace [] -> return () -- directives that must always be processed even if the current code block is @@ -617,7 +613,7 @@ handleString = do [] -> lexicalError "unterminated string literal" -- preprocess a "backtick string", which begins and ends with a backtick --- followed by a slash (`"), and withing which macros can be invoked as normal; +-- followed by a slash (`"), and within which macros can be invoked as normal; -- otherwise, normal string literal rules apply, except that unescaped quotes -- are forbidden, and backticks must be escaped using a backslash to avoid being -- interpreted as a macro or marking the end of a string @@ -733,9 +729,8 @@ handleDirective macrosOnly = do setFilePath filename let newPos = Position filename lineNumber 0 setPosition newPos - if 0 <= levelNumber && levelNumber <= 2 - then return () - else lexicalError "line directive invalid level number" + when (levelNumber < 0 || 2 < levelNumber) $ + lexicalError "line directive invalid level number" "include" -> do lineLookahead @@ -884,9 +879,7 @@ advancePosition _ = do -- advances position for multiple characters advancePositions :: String -> PPS () -advancePositions str = do - _ <- mapM advancePosition str - return () +advancePositions = mapM_ advancePosition -- update the given position based on the movement of the given character advance :: Position -> Char -> Position @@ -897,16 +890,13 @@ advance (Position f l c) _ = Position f l (c + 1) pushChar :: Char -> Position -> PPS () pushChar c p = do condStack <- getCondStack - if any (/= CurrentlyTrue) condStack - then return () - else do - output <- getOutput - setOutput $ (c, p) : output + when (all (== CurrentlyTrue) condStack) $ do + output <- getOutput + setOutput $ (c, p) : output + -- adds a sequence of characters all at the same given position pushChars :: String -> Position -> PPS () -pushChars s p = do - _ <- mapM (flip pushChar p) s - return () +pushChars s p = mapM_ (flip pushChar p) s -- search for a pattern in the input and remove remove characters up to and -- including the first occurrence of the pattern diff --git a/test/error/block_comment_eof.sv b/test/error/block_comment_eof.sv new file mode 100644 index 0000000..661162f --- /dev/null +++ b/test/error/block_comment_eof.sv @@ -0,0 +1,2 @@ +// pattern: Reached EOF while looking for: "\*/" +/* diff --git a/test/error/double_backtick.sv b/test/error/double_backtick.sv new file mode 100644 index 0000000..0a0718b --- /dev/null +++ b/test/error/double_backtick.sv @@ -0,0 +1,4 @@ +// pattern: Parse error: unexpected token '`' +module top; + `` +endmodule diff --git a/test/error/include_filename_eof.sv b/test/error/include_filename_eof.sv new file mode 100644 index 0000000..d9354a7 --- /dev/null +++ b/test/error/include_filename_eof.sv @@ -0,0 +1,2 @@ +// pattern: unexpected end of input, looking for '>' +`include