From 1930e7686025601e22de49aa4d4dbeed8311caa0 Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Sun, 31 Mar 2019 21:54:20 +0100 Subject: Rewrite the parser with real lexer --- src/VeriFuzz/AST.hs | 3 + src/VeriFuzz/CodeGen.hs | 45 +++-- src/VeriFuzz/Lexer.hs | 321 ------------------------------------ src/VeriFuzz/Parser.hs | 239 +-------------------------- src/VeriFuzz/Parser/Lex.x | 187 +++++++++++++++++++++ src/VeriFuzz/Parser/Parser.hs | 329 +++++++++++++++++++++++++++++++++++++ src/VeriFuzz/Parser/Preprocess.hs | 88 ++++++++++ src/VeriFuzz/Parser/Token.hs | 337 ++++++++++++++++++++++++++++++++++++++ verifuzz.cabal | 9 +- 9 files changed, 977 insertions(+), 581 deletions(-) delete mode 100644 src/VeriFuzz/Lexer.hs create mode 100644 src/VeriFuzz/Parser/Lex.x create mode 100644 src/VeriFuzz/Parser/Parser.hs create mode 100644 src/VeriFuzz/Parser/Preprocess.hs create mode 100644 src/VeriFuzz/Parser/Token.hs diff --git a/src/VeriFuzz/AST.hs b/src/VeriFuzz/AST.hs index 15e8d0b..d8420d2 100644 --- a/src/VeriFuzz/AST.hs +++ b/src/VeriFuzz/AST.hs @@ -94,6 +94,9 @@ module VeriFuzz.AST , stmntCA , stmntTask , stmntSysTask + , stmntCondExpr + , stmntCondTrue + , stmntCondFalse -- * Module , ModDecl(..) , modId diff --git a/src/VeriFuzz/CodeGen.hs b/src/VeriFuzz/CodeGen.hs index 8f205f8..bd6372a 100644 --- a/src/VeriFuzz/CodeGen.hs +++ b/src/VeriFuzz/CodeGen.hs @@ -72,17 +72,17 @@ moduleDecl m = -- | Conversts 'Port' to 'Text' for the module list, which means it only -- generates a list of identifiers. modPort :: Port -> Text -modPort port = port ^. portName . getIdentifier +modPort p = p ^. portName . getIdentifier -- | Generate the 'Port' description. port :: Port -> Text -port port = t <> sign <> size <> name +port p = t <> sign <> size <> name where - t = flip mappend " " . portType $ port ^. portType - size | port ^. portSize > 1 = "[" <> showT (port ^. portSize - 1) <> ":0] " + t = flip mappend " " . pType $ p ^. portType + size | p ^. portSize > 1 = "[" <> showT (p ^. portSize - 1) <> ":0] " | otherwise = "" - name = port ^. portName . getIdentifier - sign = signed $ port ^. portSigned + name = p ^. portName . getIdentifier + sign = signed $ p ^. portSigned signed :: Bool -> Text signed True = "signed " @@ -98,23 +98,20 @@ portDir PortInOut = "inout" moduleItem :: ModItem -> Text moduleItem (ModCA ca) = contAssign ca moduleItem (ModInst (Identifier i) (Identifier name) conn) = - i <> " " <> name <> "(" <> comma (modConn <$> conn) <> ")" <> ";\n" + i <> " " <> name <> "(" <> comma (mConn <$> conn) <> ")" <> ";\n" moduleItem (Initial stat ) = "initial " <> statement stat moduleItem (Always stat ) = "always " <> statement stat -moduleItem (Decl dir port) = maybe "" makePort dir <> port port <> ";\n" +moduleItem (Decl dir p) = maybe "" makePort dir <> port p <> ";\n" where makePort = (<> " ") . portDir -modConn :: ModConn -> Text -modConn (ModConn c) = expr c -modConn (ModConnNamed n c) = +mConn :: ModConn -> Text +mConn (ModConn c) = expr c +mConn (ModConnNamed n c) = "." <> n ^. getIdentifier <> "(" <> expr c <> ")" -- | Generate continuous assignment contAssign :: ContAssign -> Text -contAssign (ContAssign val e) = "assign " <> name <> " = " <> expr <> ";\n" - where - name = val ^. getIdentifier - expr = expr e +contAssign (ContAssign val e) = "assign " <> val ^. getIdentifier <> " = " <> expr e <> ";\n" -- | Generate 'Function' to 'Text' func :: Function -> Text @@ -183,7 +180,7 @@ unaryOp UnNxorInv = "^~" -- | Generate verilog code for an 'Event'. event :: Event -> Text event (EId i ) = "@(" <> i ^. getIdentifier <> ")" -event (EExpr expr) = "@(" <> expr expr <> ")" +event (EExpr e) = "@(" <> expr e <> ")" event EAll = "@*" event (EPosEdge i) = "@(posedge " <> i ^. getIdentifier <> ")" event (ENegEdge i) = "@(negedge " <> i ^. getIdentifier <> ")" @@ -195,7 +192,7 @@ delay (Delay i) = "#" <> showT i -- | Generate the verilog code for an 'LVal'. lVal :: LVal -> Text lVal (RegId i ) = i ^. getIdentifier -lVal (RegExpr i expr) = i ^. getIdentifier <> " [" <> expr expr <> "]" +lVal (RegExpr i e) = i ^. getIdentifier <> " [" <> expr e <> "]" lVal (RegSize i msb lsb) = i ^. getIdentifier @@ -209,9 +206,9 @@ lVal (RegConcat e) = "{" <> comma (expr <$> e) <> "}" constExpr :: ConstExpr -> Text constExpr (ConstExpr num) = showT num -portType :: PortType -> Text -portType Wire = "wire" -portType Reg = "reg" +pType :: PortType -> Text +pType Wire = "wire" +pType Reg = "reg" genAssign :: Text -> Assign -> Text genAssign op (Assign r d e) = @@ -230,9 +227,9 @@ statement (CondStmnt e t Nothing) = "if(" <> expr e <> ")" <> defMap t statement (CondStmnt e t f) = "if(" <> expr e <> ") " <> defMap t <> "else " <> defMap f task :: Task -> Text -task (Task name expr) - | null expr = i - | otherwise = i <> "(" <> comma (expr <$> expr) <> ")" +task (Task name e) + | null e = i + | otherwise = i <> "(" <> comma (expr <$> e) <> ")" where i = name ^. getIdentifier -- | Render the 'Text' to 'IO'. This is equivalent to 'putStrLn'. @@ -251,7 +248,7 @@ instance Source Statement where genSource = statement instance Source PortType where - genSource = portType + genSource = pType instance Source ConstExpr where genSource = constExpr diff --git a/src/VeriFuzz/Lexer.hs b/src/VeriFuzz/Lexer.hs deleted file mode 100644 index 02e1ebf..0000000 --- a/src/VeriFuzz/Lexer.hs +++ /dev/null @@ -1,321 +0,0 @@ -{-| -Module : VeriFuzz.Lexer -Description : Lexer for Verilog. -Copyright : (c) 2019, Yann Herklotz -License : GPL-3 -Maintainer : ymherklotz [at] gmail [dot] com -Stability : experimental -Portability : POSIX - -Lexer for Verilog. --} - -module VeriFuzz.Lexer - ( lexer - , identifier - , reserved - , operator - , reservedOp - , charLiteral - , stringLiteral - , natural - , integer - , float - , naturalOrFloat - , decimal - , hexadecimal - , octal - , symbol - , lexeme - , whiteSpace - , parens - , braces - , angles - , brackets - , squares - , comma - , colon - , dot - , semiSep - , semiSep1 - , commaSep - , commaSep1 - ) -where - -import Data.Char (digitToInt) -import Text.Parsec -import qualified Text.Parsec.Token as P - -type VerilogDef = P.LanguageDef () - -type Lexer = P.TokenParser () - -type Parser = Parsec String () - -verilogDef :: VerilogDef -verilogDef = P.LanguageDef "/*" - "*/" - "//" - False - letter - (alphaNum <|> char '_') - (oneOf ":!#%&*+./<=>?@\\^|-~") - (oneOf ":!#%&*+./<=>?@\\^|-~") - reserved' - reservedOp' - True - -lexer :: Lexer -lexer = P.makeTokenParser verilogDef - -identifier :: Parser String -identifier = P.identifier lexer - -reserved :: String -> Parser () -reserved = P.reserved lexer - -operator :: Parser String -operator = P.operator lexer - -reservedOp :: String -> Parser () -reservedOp = P.reservedOp lexer - -charLiteral :: Parser Char -charLiteral = P.charLiteral lexer - -stringLiteral :: Parser String -stringLiteral = P.stringLiteral lexer - -natural :: Parser Integer -natural = P.natural lexer - -integer :: Parser Integer -integer = P.integer lexer - -float :: Parser Double -float = P.float lexer - -naturalOrFloat :: Parser (Either Integer Double) -naturalOrFloat = P.naturalOrFloat lexer - -decimal :: Parser Integer -decimal = P.decimal lexer - -number :: Integer -> Parser Char -> Parser Integer -number base baseDigit = do - digits <- many1 baseDigit - let n = foldl (\x d -> base * x + toInteger (digitToInt d)) 0 digits - seq n (return n) - -hexadecimal :: Parser Integer -hexadecimal = number 16 hexDigit - -octal :: Parser Integer -octal = number 8 octDigit - -symbol :: String -> Parser String -symbol = P.symbol lexer - -lexeme :: Parser a -> Parser a -lexeme = P.lexeme lexer - -whiteSpace :: Parser () -whiteSpace = P.whiteSpace lexer - -parens :: Parser a -> Parser a -parens = P.parens lexer - -braces :: Parser a -> Parser a -braces = P.braces lexer - -angles :: Parser a -> Parser a -angles = P.angles lexer - -brackets :: Parser a -> Parser a -brackets = P.brackets lexer - -squares :: Parser a -> Parser a -squares = P.squares lexer - -comma :: Parser String -comma = P.comma lexer - -colon :: Parser String -colon = P.colon lexer - -dot :: Parser String -dot = P.dot lexer - -semiSep :: Parser a -> Parser [a] -semiSep = P.semiSep lexer - -semiSep1 :: Parser a -> Parser [a] -semiSep1 = P.semiSep1 lexer - -commaSep :: Parser a -> Parser [a] -commaSep = P.commaSep lexer - -commaSep1 :: Parser a -> Parser [a] -commaSep1 = P.commaSep1 lexer - -reservedOp' :: [String] -reservedOp' = - [ "!" - , "~" - , "~&" - , "~|" - , "+" - , "-" - , "*" - , "/" - , "%" - , "==" - , "!=" - , "===" - , "!==" - , "&&" - , "||" - , "<" - , "<=" - , ">" - , ">=" - , "&" - , "|" - , "^" - , "^~" - , "~^" - , "**" - , "<<" - , ">>" - , "<<<" - , ">>>" - ] - -reserved' :: [String] -reserved' = - [ "always" - , "and" - , "assign" - , "automatic" - , "begin" - , "buf" - , "bufif0" - , "bufif1" - , "case" - , "casex" - , "casez" - , "cell" - , "cmos" - , "config" - , "deassign" - , "default" - , "defparam" - , "design" - , "disable" - , "edge" - , "else" - , "end" - , "endcase" - , "endconfig" - , "endfunction" - , "endgenerate" - , "endmodule" - , "endprimitive" - , "endspecify" - , "endtable" - , "endtask" - , "event" - , "for" - , "force" - , "forever" - , "fork" - , "function" - , "generate" - , "genvar" - , "highz0" - , "highz1" - , "if" - , "ifnone" - , "incdir" - , "include" - , "initial" - , "inout" - , "input" - , "instance" - , "integer" - , "join" - , "large" - , "liblist" - , "library" - , "localparam" - , "macromodule" - , "medium" - , "module" - , "nand" - , "negedge" - , "nmos" - , "nor" - , "noshowcancelled" - , "not" - , "notif0" - , "notif1" - , "or" - , "output" - , "parameter" - , "pmos" - , "posedge" - , "primitive" - , "pull0" - , "pull1" - , "pulldown" - , "pullup" - , "pulsestyle_onevent" - , "pulsestyle_ondetect" - , "remos" - , "real" - , "realtime" - , "reg" - , "release" - , "repeat" - , "rnmos" - , "rpmos" - , "rtran" - , "rtranif0" - , "rtranif1" - , "scalared" - , "showcancelled" - , "signed" - , "small" - , "specify" - , "specparam" - , "strong0" - , "strong1" - , "supply0" - , "supply1" - , "table" - , "task" - , "time" - , "tran" - , "tranif0" - , "tranif1" - , "tri" - , "tri0" - , "tri1" - , "triand" - , "trior" - , "trireg" - , "unsigned" - , "use" - , "vectored" - , "wait" - , "wand" - , "weak0" - , "weak1" - , "while" - , "wire" - , "wor" - , "xnor" - , "xor" - ] - diff --git a/src/VeriFuzz/Parser.hs b/src/VeriFuzz/Parser.hs index 2c26b56..66608f4 100644 --- a/src/VeriFuzz/Parser.hs +++ b/src/VeriFuzz/Parser.hs @@ -1,247 +1,18 @@ {-| Module : VeriFuzz.Parser -Description : Minimal Verilog parser to reconstruct the AST. -Copyright : (c) 2019, Yann Herklotz +Description : Parser module for Verilog. +Copyright : (c) 2019, Yann Herklotz Grave License : GPL-3 Maintainer : ymherklotz [at] gmail [dot] com Stability : experimental Portability : POSIX -Minimal Verilog parser to reconstruct the AST. This parser does not support the -whole Verilog syntax, as the AST does not support it either. +Parser module for Verilog. -} module VeriFuzz.Parser - ( -- * Parsers - parseVerilog - , parseVerilogSrc - , parseDescription - , parseModDecl - , parseContAssign - , parseExpr + ( module VeriFuzz.Parser.Parser ) where -import Control.Lens -import Data.Functor (($>)) -import Data.Functor.Identity (Identity) -import qualified Data.Text as T -import Text.Parsec -import Text.Parsec.Expr -import VeriFuzz.AST ---import VeriFuzz.CodeGen -import VeriFuzz.Internal -import VeriFuzz.Lexer - -type Parser = Parsec String () - -type ParseOperator = Operator String () Identity - -sBinOp :: BinaryOperator -> Expr -> Expr -> Expr -sBinOp = sOp BinOp where sOp f b a = f a b - -parseExpr' :: Parser Expr -parseExpr' = buildExpressionParser parseTable parseTerm "expr" - -matchHex :: Char -> Bool -matchHex c = c == 'h' || c == 'H' - ---matchBin :: Char -> Bool ---matchBin c = c == 'b' || c == 'B' - -matchDec :: Char -> Bool -matchDec c = c == 'd' || c == 'D' - -matchOct :: Char -> Bool -matchOct c = c == 'o' || c == 'O' - --- | Parse a Number depending on if it is in a hex or decimal form. Octal and --- binary are not supported yet. -parseNum :: Parser Expr -parseNum = do - size <- fromIntegral <$> decimal - _ <- string "'" - matchNum size - where - matchNum size = - (satisfy matchHex >> Number size <$> hexadecimal) - <|> (satisfy matchDec >> Number size <$> decimal) - <|> (satisfy matchOct >> Number size <$> octal) - -parseVar :: Parser Expr -parseVar = Id <$> ident - -parseFunction :: Parser Function -parseFunction = - reserved "unsigned" $> UnSignedFunc <|> reserved "signed" $> SignedFunc - -parseFun :: Parser Expr -parseFun = do - f <- spaces *> reservedOp "$" *> parseFunction - expr <- string "(" *> spaces *> parseExpr - _ <- spaces *> string ")" *> spaces - return $ Func f expr - -parseTerm :: Parser Expr -parseTerm = - parens parseExpr - <|> (Concat <$> aroundList (string "{") (string "}") parseExpr) - <|> parseFun - <|> lexeme parseNum - <|> parseVar - "simple expr" - --- | Parses the ternary conditional operator. It will behave in a right --- associative way. -parseCond :: Expr -> Parser Expr -parseCond e = do - _ <- spaces *> reservedOp "?" - expr <- spaces *> parseExpr - _ <- spaces *> reservedOp ":" - Cond e expr <$> parseExpr - -parseExpr :: Parser Expr -parseExpr = do - e <- parseExpr' - option e . try $ parseCond e - --- | Table of binary and unary operators that encode the right precedence for --- each. -parseTable :: [[ParseOperator Expr]] -parseTable - = [ [prefix "!" (UnOp UnLNot), prefix "~" (UnOp UnNot)] - , [ prefix "&" (UnOp UnAnd) - , prefix "|" (UnOp UnOr) - , prefix "~&" (UnOp UnNand) - , prefix "~|" (UnOp UnNor) - , prefix "^" (UnOp UnXor) - , prefix "~^" (UnOp UnNxor) - , prefix "^~" (UnOp UnNxorInv) - ] - , [prefix "+" (UnOp UnPlus), prefix "-" (UnOp UnMinus)] - , [binary "**" (sBinOp BinPower) AssocRight] - , [ binary "*" (sBinOp BinTimes) AssocLeft - , binary "/" (sBinOp BinDiv) AssocLeft - , binary "%" (sBinOp BinMod) AssocLeft - ] - , [ binary "+" (sBinOp BinPlus) AssocLeft - , binary "-" (sBinOp BinPlus) AssocLeft - ] - , [ binary "<<" (sBinOp BinLSL) AssocLeft - , binary ">>" (sBinOp BinLSR) AssocLeft - ] - , [ binary "<<<" (sBinOp BinASL) AssocLeft - , binary ">>>" (sBinOp BinASR) AssocLeft - ] - , [ binary "<" (sBinOp BinLT) AssocNone - , binary ">" (sBinOp BinGT) AssocNone - , binary "<=" (sBinOp BinLEq) AssocNone - , binary ">=" (sBinOp BinLEq) AssocNone - ] - , [ binary "==" (sBinOp BinEq) AssocNone - , binary "!=" (sBinOp BinNEq) AssocNone - ] - , [ binary "===" (sBinOp BinEq) AssocNone - , binary "!==" (sBinOp BinNEq) AssocNone - ] - , [binary "&" (sBinOp BinAnd) AssocLeft] - , [ binary "^" (sBinOp BinXor) AssocLeft - , binary "^~" (sBinOp BinXNor) AssocLeft - , binary "~^" (sBinOp BinXNorInv) AssocLeft - ] - , [binary "|" (sBinOp BinOr) AssocLeft] - , [binary "&&" (sBinOp BinLAnd) AssocLeft] - , [binary "||" (sBinOp BinLOr) AssocLeft] - ] - -binary :: String -> (a -> a -> a) -> Assoc -> ParseOperator a -binary name fun = Infix ((reservedOp name "binary") >> return fun) - -prefix :: String -> (a -> a) -> ParseOperator a -prefix name fun = Prefix ((reservedOp name "prefix") >> return fun) - -aroundList :: Parser a -> Parser b -> Parser c -> Parser [c] -aroundList a b c = lexeme $ do - l <- a *> spaces *> commaSep c - _ <- b - return l - -parseContAssign :: Parser ContAssign -parseContAssign = do - var <- reserved "assign" *> ident - expr <- reservedOp "=" *> parseExpr - _ <- symbol ";" - return $ ContAssign var expr - --- | Parse a range and return the total size. As it is inclusive, 1 has to be --- added to the difference. -parseRange :: Parser Int -parseRange = do - rangeH <- symbol "[" *> decimal - rangeL <- symbol ":" *> decimal - _ <- symbol "]" - return . fromIntegral $ rangeH - rangeL + 1 - -ident :: Parser Identifier -ident = Identifier . T.pack <$> identifier - -parseNetDecl :: Maybe PortDir -> Parser ModItem -parseNetDecl pd = do - t <- option Wire type_ - sign <- option False (reserved "signed" $> True) - range <- option 1 parseRange - name <- ident - _ <- symbol ";" - return . Decl pd . Port t sign range $ name - where type_ = reserved "wire" $> Wire <|> reserved "reg" $> Reg - -parsePortDir :: Parser PortDir -parsePortDir = - reserved "output" - $> PortOut - <|> reserved "input" - $> PortIn - <|> reserved "inout" - $> PortInOut - -parseDecl :: Parser ModItem -parseDecl = (Just <$> parsePortDir >>= parseNetDecl) <|> parseNetDecl Nothing - -parseModItem :: Parser ModItem -parseModItem = (ModCA <$> parseContAssign) <|> parseDecl - -parseModList :: Parser [Identifier] -parseModList = list <|> spaces $> [] - where list = aroundList (string "(") (string ")") ident - -filterDecl :: PortDir -> ModItem -> Bool -filterDecl p (Decl (Just p') _) = p == p' -filterDecl _ _ = False - -modPorts :: PortDir -> [ModItem] -> [Port] -modPorts p mis = filter (filterDecl p) mis ^.. traverse . declPort - -parseModDecl :: Parser ModDecl -parseModDecl = do - name <- reserved "module" *> ident - _ <- fmap defaultPort <$> parseModList - _ <- symbol ";" - modItem <- lexeme $ option [] . try $ many1 parseModItem - _ <- reserved "endmodule" - return $ ModDecl name - (modPorts PortOut modItem) - (modPorts PortIn modItem) - modItem - -parseDescription :: Parser Description -parseDescription = Description <$> lexeme parseModDecl - --- | Parses a 'String' into 'VerilogSrc' by skipping any beginning whitespace --- and then parsing multiple Verilog source. -parseVerilogSrc :: Parser VerilogSrc -parseVerilogSrc = VerilogSrc <$> (whiteSpace *> many parseDescription) - --- | Parse a 'String' containing verilog code. The parser currently only supports --- the subset of Verilog that is being generated randomly. -parseVerilog :: String -> String -> Either ParseError VerilogSrc -parseVerilog = parse parseVerilogSrc +import VeriFuzz.Parser.Parser diff --git a/src/VeriFuzz/Parser/Lex.x b/src/VeriFuzz/Parser/Lex.x new file mode 100644 index 0000000..86c431e --- /dev/null +++ b/src/VeriFuzz/Parser/Lex.x @@ -0,0 +1,187 @@ +{ +{-# OPTIONS_GHC -w #-} +module VeriFuzz.Parser.Lex + ( alexScanTokens + ) where + +import VeriFuzz.Parser.Token + +} + +%wrapper "posn" + +-- Numbers + +$nonZeroDecimalDigit = [1-9] +$decimalDigit = [0-9] +@binaryDigit = [0-1] +@octalDigit = [0-7] +@hexDigit = [0-9a-fA-F] + +@decimalBase = "'" [dD] +@binaryBase = "'" [bB] +@octalBase = "'" [oO] +@hexBase = "'" [hH] + +@binaryValue = @binaryDigit ("_" | @binaryDigit)* +@octalValue = @octalDigit ("_" | @octalDigit)* +@hexValue = @hexDigit ("_" | @hexDigit)* + +@unsignedNumber = $decimalDigit ("_" | $decimalDigit)* + +@size = @unsignedNumber + +@decimalNumber + = @unsignedNumber + | @size? @decimalBase @unsignedNumber + +@binaryNumber = @size? @binaryBase @binaryValue +@octalNumber = @size? @octalBase @octalValue +@hexNumber = @size? @hexBase @hexValue + +-- $exp = [eE] +-- $sign = [\+\-] +-- @realNumber = unsignedNumber "." unsignedNumber | unsignedNumber ( "." unsignedNumber)? exp sign? unsignedNumber +@number = @decimalNumber | @octalNumber | @binaryNumber | @hexNumber + +-- Strings + +@string = \" [^\r\n]* \" + +-- Identifiers + +@escapedIdentifier = "\" ($printable # $white)+ $white +@simpleIdentifier = [a-zA-Z_] [a-zA-Z0-9_\$]* +@systemIdentifier = "$" [a-zA-Z0-9_\$]+ + + +tokens :- + + "always" { tok KWAlways } + "assign" { tok KWAssign } + "begin" { tok KWBegin } + "case" { tok KWCase } + "default" { tok KWDefault } + "else" { tok KWElse } + "end" { tok KWEnd } + "endcase" { tok KWEndcase } + "endmodule" { tok KWEndmodule } + "for" { tok KWFor } + "if" { tok KWIf } + "initial" { tok KWInitial } + "inout" { tok KWInout } + "input" { tok KWInput } + "integer" { tok KWInteger } + "localparam" { tok KWLocalparam } + "module" { tok KWModule } + "negedge" { tok KWNegedge } + "or" { tok KWOr } + "output" { tok KWOutput } + "parameter" { tok KWParameter } + "posedge" { tok KWPosedge } + "reg" { tok KWReg } + "wire" { tok KWWire } + "signed" { tok KWSigned } + + @simpleIdentifier { tok IdSimple } + @escapedIdentifier { tok IdEscaped } + @systemIdentifier { tok IdSystem } + + @number { tok LitNumber } + @string { tok LitString } + + "(" { tok SymParenL } + ")" { tok SymParenR } + "[" { tok SymBrackL } + "]" { tok SymBrackR } + "{" { tok SymBraceL } + "}" { tok SymBraceR } + "~" { tok SymTildy } + "!" { tok SymBang } + "@" { tok SymAt } + "#" { tok SymPound } + "%" { tok SymPercent } + "^" { tok SymHat } + "&" { tok SymAmp } + "|" { tok SymBar } + "*" { tok SymAster } + "." { tok SymDot } + "," { tok SymComma } + ":" { tok SymColon } + ";" { tok SymSemi } + "=" { tok SymEq } + "<" { tok SymLt } + ">" { tok SymGt } + "+" { tok SymPlus } + "-" { tok SymDash } + "?" { tok SymQuestion } + "/" { tok SymSlash } + "$" { tok SymDollar } + "'" { tok SymSQuote } + + "~&" { tok SymTildyAmp } + "~|" { tok SymTildyBar } + "~^" { tok SymTildyHat } + "^~" { tok SymHatTildy } + "==" { tok SymEqEq } + "!=" { tok SymBangEq } + "&&" { tok SymAmpAmp } + "||" { tok SymBarBar } + "**" { tok SymAsterAster } + "<=" { tok SymLtEq } + ">=" { tok SymGtEq } + ">>" { tok SymGtGt } + "<<" { tok SymLtLt } + "++" { tok SymPlusPlus } + "--" { tok SymDashDash } + "+=" { tok SymPlusEq } + "-=" { tok SymDashEq } + "*=" { tok SymAsterEq } + "/=" { tok SymSlashEq } + "%=" { tok SymPercentEq } + "&=" { tok SymAmpEq } + "|=" { tok SymBarEq } + "^=" { tok SymHatEq } + "+:" { tok SymPlusColon } + "-:" { tok SymDashColon } + "::" { tok SymColonColon } + ".*" { tok SymDotAster } + "->" { tok SymDashGt } + ":=" { tok SymColonEq } + ":/" { tok SymColonSlash } + "##" { tok SymPoundPound } + "[*" { tok SymBrackLAster } + "[=" { tok SymBrackLEq } + "=>" { tok SymEqGt } + "@*" { tok SymAtAster } + "(*" { tok SymParenLAster } + "*)" { tok SymAsterParenR } + "*>" { tok SymAsterGt } + + "===" { tok SymEqEqEq } + "!==" { tok SymBangEqEq } + "=?=" { tok SymEqQuestionEq } + "!?=" { tok SymBangQuestionEq } + ">>>" { tok SymGtGtGt } + "<<<" { tok SymLtLtLt } + "<<=" { tok SymLtLtEq } + ">>=" { tok SymGtGtEq } + "|->" { tok SymBarDashGt } + "|=>" { tok SymBarEqGt } + "[->" { tok SymBrackLDashGt } + "@@(" { tok SymAtAtParenL } + "(*)" { tok SymParenLAsterParenR } + "->>" { tok SymDashGtGt } + "&&&" { tok SymAmpAmpAmp } + + "<<<=" { tok SymLtLtLtEq } + ">>>=" { tok SymGtGtGtEq } + + $white ; + + . { tok Unknown } + +{ +tok :: TokenName -> AlexPosn -> String -> Token +tok t (AlexPn _ l c) s = Token t s $ Position "" l c +} diff --git a/src/VeriFuzz/Parser/Parser.hs b/src/VeriFuzz/Parser/Parser.hs new file mode 100644 index 0000000..5a1d163 --- /dev/null +++ b/src/VeriFuzz/Parser/Parser.hs @@ -0,0 +1,329 @@ +{-| +Module : VeriFuzz.Parser.Parser +Description : Minimal Verilog parser to reconstruct the AST. +Copyright : (c) 2019, Yann Herklotz +License : GPL-3 +Maintainer : ymherklotz [at] gmail [dot] com +Stability : experimental +Portability : POSIX + +Minimal Verilog parser to reconstruct the AST. This parser does not support the +whole Verilog syntax, as the AST does not support it either. +-} + +module VeriFuzz.Parser.Parser + ( -- * Parsers + parseVerilog + , parseVerilogSrc + , parseDescription + , parseModDecl + , parseContAssign + , parseExpr + ) +where + +import Control.Lens +import Data.Functor (($>)) +import Data.Functor.Identity (Identity) +import qualified Data.Text as T +import Text.Parsec hiding (satisfy) +import Text.Parsec.Expr +import VeriFuzz.AST +--import VeriFuzz.CodeGen +import Data.Bits +import Data.List (isInfixOf, isPrefixOf) +import VeriFuzz.Internal +import VeriFuzz.Parser.Lex +import VeriFuzz.Parser.Preprocess +import VeriFuzz.Parser.Token + + +type Parser = Parsec [Token] () + +type ParseOperator = Operator [Token] () Identity + +data Decimal = Decimal { size :: Int + , num :: Integer + } + +instance Num Decimal where + (Decimal sa na) + (Decimal sb nb) = Decimal (max sa sb) (na + nb) + (Decimal sa na) - (Decimal sb nb) = Decimal (max sa sb) (na - nb) + (Decimal sa na) * (Decimal sb nb) = Decimal (max sa sb) (na * nb) + negate (Decimal s n) = Decimal s $ negate n + abs (Decimal s n) = Decimal s $ abs n + signum (Decimal s n) = Decimal s $ signum n + fromInteger = Decimal 32 . fromInteger + +-- | This parser succeeds whenever the given predicate returns true when called +-- with parsed `Token`. Same as 'Text.Parsec.Char.satisfy'. +satisfy :: (Token -> Bool) -> Parser TokenName +satisfy f = tokenPrim show nextPos tokeq + where + tokeq :: Token -> Maybe TokenName + tokeq t@(Token t' _ _) = if f t then Just t' else Nothing + +satisfy' :: (Token -> Maybe a) -> Parser a +satisfy' = tokenPrim show nextPos + +nextPos :: SourcePos -> Token -> [Token] -> SourcePos +nextPos pos _ (Token _ _ (Position _ l c):_) = setSourceColumn (setSourceLine pos l) c +nextPos pos _ [] = pos + +-- | Parses given `TokenName`. +tok :: TokenName -> Parser TokenName +tok t = satisfy (\(Token t' _ _) -> t' == t) show t + +-- | Parse without returning the `TokenName`. +tok' :: TokenName -> Parser () +tok' p = tok p >> return () + +parens :: Parser a -> Parser a +parens = between (tok SymParenL) (tok SymParenR) + +brackets :: Parser a -> Parser a +brackets = between (tok SymBrackL) (tok SymBrackR) + +braces :: Parser a -> Parser a +braces = between (tok SymBraceL) (tok SymBraceR) + +sBinOp :: BinaryOperator -> Expr -> Expr -> Expr +sBinOp = sOp BinOp where sOp f b a = f a b + +parseExpr' :: Parser Expr +parseExpr' = buildExpressionParser parseTable parseTerm "expr" + +matchHex :: Char -> Bool +matchHex c = c == 'h' || c == 'H' + +--matchBin :: Char -> Bool +--matchBin c = c == 'b' || c == 'B' + +matchDec :: Char -> Bool +matchDec c = c == 'd' || c == 'D' + +matchOct :: Char -> Bool +matchOct c = c == 'o' || c == 'O' + +decToExpr :: Decimal -> Expr +decToExpr (Decimal s n) = Number s n + +-- | Parse a Number depending on if it is in a hex or decimal form. Octal and +-- binary are not supported yet. +parseNum :: Parser Expr +parseNum = decToExpr <$> number + +parseVar :: Parser Expr +parseVar = Id <$> identifier + +systemFunc :: String -> Parser String +systemFunc s = satisfy' matchId + where + matchId (Token IdSystem s' _) = + if s == s' then Just s else Nothing + matchId _ = Nothing + +parseFunction :: Parser Function +parseFunction = + systemFunc "unsigned" $> UnSignedFunc <|> systemFunc "signed" $> SignedFunc + +parseFun :: Parser Expr +parseFun = do + f <- parseFunction + expr <- parens parseExpr + return $ Func f expr + +parseTerm :: Parser Expr +parseTerm = + parens parseExpr + <|> (Concat <$> braces (commaSep parseExpr)) + <|> parseFun + <|> parseNum + <|> parseVar + "simple expr" + +-- | Parses the ternary conditional operator. It will behave in a right +-- associative way. +parseCond :: Expr -> Parser Expr +parseCond e = do + tok' SymQuestion + expr <- parseExpr + tok' SymColon + Cond e expr <$> parseExpr + +parseExpr :: Parser Expr +parseExpr = do + e <- parseExpr' + option e . try $ parseCond e + +-- | Table of binary and unary operators that encode the right precedence for +-- each. +parseTable :: [[ParseOperator Expr]] +parseTable + = [ [prefix SymBang (UnOp UnLNot), prefix SymTildy (UnOp UnNot)] + , [ prefix SymAmp (UnOp UnAnd) + , prefix SymBar (UnOp UnOr) + , prefix SymTildyAmp (UnOp UnNand) + , prefix SymTildyBar (UnOp UnNor) + , prefix SymHat (UnOp UnXor) + , prefix SymTildyHat (UnOp UnNxor) + , prefix SymHatTildy (UnOp UnNxorInv) + ] + , [prefix SymPlus (UnOp UnPlus), prefix SymDash (UnOp UnMinus)] + , [binary SymAsterAster (sBinOp BinPower) AssocRight] + , [ binary SymAster (sBinOp BinTimes) AssocLeft + , binary SymSlash (sBinOp BinDiv) AssocLeft + , binary SymPercent (sBinOp BinMod) AssocLeft + ] + , [ binary SymPlus (sBinOp BinPlus) AssocLeft + , binary SymDash (sBinOp BinPlus) AssocLeft + ] + , [ binary SymLtLt (sBinOp BinLSL) AssocLeft + , binary SymGtGt (sBinOp BinLSR) AssocLeft + ] + , [ binary SymLtLtLt (sBinOp BinASL) AssocLeft + , binary SymGtGtGt (sBinOp BinASR) AssocLeft + ] + , [ binary SymLt (sBinOp BinLT) AssocNone + , binary SymGt (sBinOp BinGT) AssocNone + , binary SymLtEq (sBinOp BinLEq) AssocNone + , binary SymGtEq (sBinOp BinLEq) AssocNone + ] + , [ binary SymEqEq (sBinOp BinEq) AssocNone + , binary SymBangEq (sBinOp BinNEq) AssocNone + ] + , [ binary SymEqEqEq (sBinOp BinEq) AssocNone + , binary SymBangEqEq (sBinOp BinNEq) AssocNone + ] + , [binary SymAmp (sBinOp BinAnd) AssocLeft] + , [ binary SymHat (sBinOp BinXor) AssocLeft + , binary SymHatTildy (sBinOp BinXNor) AssocLeft + , binary SymTildyHat (sBinOp BinXNorInv) AssocLeft + ] + , [binary SymBar (sBinOp BinOr) AssocLeft] + , [binary SymAmpAmp (sBinOp BinLAnd) AssocLeft] + , [binary SymBarBar (sBinOp BinLOr) AssocLeft] + ] + +binary :: TokenName -> (a -> a -> a) -> Assoc -> ParseOperator a +binary name fun = Infix ((tok name "binary") >> return fun) + +prefix :: TokenName -> (a -> a) -> ParseOperator a +prefix name fun = Prefix ((tok name "prefix") >> return fun) + +commaSep :: Parser a -> Parser [a] +commaSep = flip sepBy $ tok SymComma + +parseContAssign :: Parser ContAssign +parseContAssign = do + var <- tok KWAssign *> identifier + expr <- tok SymEq *> parseExpr + tok SymSemi + return $ ContAssign var expr + +numLit :: Parser String +numLit = satisfy' matchId + where + matchId (Token LitNumber s _) = Just s + matchId _ = Nothing + +number :: Parser Decimal +number = number' <$> numLit + where + number' :: String -> Decimal + number' a + | all (flip elem ['0' .. '9']) a = fromInteger $ read a + | head a == '\'' = fromInteger $ f a + | isInfixOf "'" a = Decimal (read w) (f b) + | otherwise = error $ "Invalid number format: " ++ a + where + w = takeWhile (/= '\'') a + b = dropWhile (/= '\'') a + f a + | isPrefixOf "'d" a = read $ drop 2 a + | isPrefixOf "'h" a = read $ "0x" ++ drop 2 a + | isPrefixOf "'b" a = foldl (\ n b -> shiftL n 1 .|. (if b == '1' then 1 else 0)) 0 (drop 2 a) + | otherwise = error $ "Invalid number format: " ++ a + +toInteger' :: Decimal -> Integer +toInteger' (Decimal _ n) = n + +-- | Parse a range and return the total size. As it is inclusive, 1 has to be +-- added to the difference. +parseRange :: Parser Int +parseRange = do + rangeH <- tok SymBrackL *> number + rangeL <- tok SymColon *> number + tok' SymBrackR + return . fromInteger . toInteger' $ rangeH - rangeL + 1 + +strId :: Parser String +strId = satisfy' matchId + where + matchId (Token IdSimple s _) = Just s + matchId (Token IdEscaped s _) = Just s + matchId _ = Nothing + +identifier :: Parser Identifier +identifier = Identifier . T.pack <$> strId + +parseNetDecl :: Maybe PortDir -> Parser ModItem +parseNetDecl pd = do + t <- option Wire type_ + sign <- option False (tok KWSigned $> True) + range <- option 1 parseRange + name <- identifier + tok' SymSemi + return . Decl pd . Port t sign range $ name + where type_ = tok KWWire $> Wire <|> tok KWReg $> Reg + +parsePortDir :: Parser PortDir +parsePortDir = + tok KWOutput + $> PortOut + <|> tok KWInput + $> PortIn + <|> tok KWInout + $> PortInOut + +parseDecl :: Parser ModItem +parseDecl = (Just <$> parsePortDir >>= parseNetDecl) <|> parseNetDecl Nothing + +parseModItem :: Parser ModItem +parseModItem = (ModCA <$> parseContAssign) <|> parseDecl + +parseModList :: Parser [Identifier] +parseModList = list <|> return [] + where list = parens $ commaSep identifier + +filterDecl :: PortDir -> ModItem -> Bool +filterDecl p (Decl (Just p') _) = p == p' +filterDecl _ _ = False + +modPorts :: PortDir -> [ModItem] -> [Port] +modPorts p mis = filter (filterDecl p) mis ^.. traverse . declPort + +parseModDecl :: Parser ModDecl +parseModDecl = do + name <- tok KWModule *> identifier + _ <- fmap defaultPort <$> parseModList + tok' SymSemi + modItem <- option [] . try $ many1 parseModItem + tok' KWEndmodule + return $ ModDecl name + (modPorts PortOut modItem) + (modPorts PortIn modItem) + modItem + +parseDescription :: Parser Description +parseDescription = Description <$> parseModDecl + +-- | Parses a 'String' into 'VerilogSrc' by skipping any beginning whitespace +-- and then parsing multiple Verilog source. +parseVerilogSrc :: Parser VerilogSrc +parseVerilogSrc = VerilogSrc <$> many parseDescription + +-- | Parse a 'String' containing verilog code. The parser currently only supports +-- the subset of Verilog that is being generated randomly. +parseVerilog :: String -> String -> Either ParseError VerilogSrc +parseVerilog s = parse parseVerilogSrc s . alexScanTokens . preprocess [] s diff --git a/src/VeriFuzz/Parser/Preprocess.hs b/src/VeriFuzz/Parser/Preprocess.hs new file mode 100644 index 0000000..c0a4246 --- /dev/null +++ b/src/VeriFuzz/Parser/Preprocess.hs @@ -0,0 +1,88 @@ +{-| +Module : VeriFuzz.Parser.Preprocess +Description : Simple preprocessor for `define and comments. +Copyright : (c) 2011-2015 Tom Hawkins, 2019 Yann Herklotz +License : GPL-3 +Maintainer : ymherklotz [at] gmail [dot] com +Stability : experimental +Portability : POSIX + +Simple preprocessor for `define and comments. + +The code is from https://github.com/tomahawkins/verilog. + +Edits to the original code are warning fixes and formatting changes. +-} + +module VeriFuzz.Parser.Preprocess + ( uncomment + , preprocess + ) where + +-- | Remove comments from code. +uncomment :: FilePath -> String -> String +uncomment file = uncomment' + where + uncomment' a = case a of + "" -> "" + '/' : '/' : rest -> " " ++ removeEOL rest + '/' : '*' : rest -> " " ++ remove rest + '"' : rest -> '"' : ignoreString rest + b : rest -> b : uncomment' rest + + removeEOL a = case a of + "" -> "" + '\n' : rest -> '\n' : uncomment' rest + '\t' : rest -> '\t' : removeEOL rest + _ : rest -> ' ' : removeEOL rest + + remove a = case a of + "" -> error $ "File ended without closing comment (*/): " ++ file + '"' : rest -> removeString rest + '\n' : rest -> '\n' : remove rest + '\t' : rest -> '\t' : remove rest + '*' : '/' : rest -> " " ++ uncomment' rest + _ : rest -> " " ++ remove rest + + removeString a = case a of + "" -> error $ "File ended without closing string: " ++ file + '"' : rest -> " " ++ remove rest + '\\' : '"' : rest -> " " ++ removeString rest + '\n' : rest -> '\n' : removeString rest + '\t' : rest -> '\t' : removeString rest + _ : rest -> ' ' : removeString rest + + ignoreString a = case a of + "" -> error $ "File ended without closing string: " ++ file + '"' : rest -> '"' : uncomment' rest + '\\' : '"' : rest -> "\\\"" ++ ignoreString rest + b : rest -> b : ignoreString rest + +-- | A simple `define preprocessor. +preprocess :: [(String, String)] -> FilePath -> String -> String +preprocess env file content = unlines $ pp True [] env $ lines $ uncomment file content + where + pp :: Bool -> [Bool] -> [(String, String)] -> [String] -> [String] + pp _ _ _ [] = [] + pp on stack env_ (a : rest) = case words a of + "`define" : name : value -> "" : pp on stack (if on then (name, ppLine env_ $ unwords value) : env_ else env_) rest + "`ifdef" : name : _ -> "" : pp (on && elem name (map fst env_)) (on : stack) env_ rest + "`ifndef" : name : _ -> "" : pp (on && notElem name (map fst env_)) (on : stack) env_ rest + "`else" : _ + | not $ null stack -> "" : pp (head stack && not on) stack env_ rest + | otherwise -> error $ "`else without associated `ifdef/`ifndef: " ++ file + "`endif" : _ + | not $ null stack -> "" : pp (head stack) (tail stack) env_ rest + | otherwise -> error $ "`endif without associated `ifdef/`ifndef: " ++ file + _ -> (if on then ppLine env_ a else "") : pp on stack env_ rest + +ppLine :: [(String, String)] -> String -> String +ppLine _ "" = "" +ppLine env ('`' : a) = case lookup name env of + Just value -> value ++ ppLine env rest + Nothing -> error $ "Undefined macro: `" ++ name ++ " Env: " ++ show env + where + name = takeWhile (flip elem $ ['A' .. 'Z'] ++ ['a' .. 'z'] ++ ['0' .. '9'] ++ ['_']) a + rest = drop (length name) a +ppLine env (a : b) = a : ppLine env b + diff --git a/src/VeriFuzz/Parser/Token.hs b/src/VeriFuzz/Parser/Token.hs new file mode 100644 index 0000000..f776dd8 --- /dev/null +++ b/src/VeriFuzz/Parser/Token.hs @@ -0,0 +1,337 @@ +module VeriFuzz.Parser.Token + ( Token (..) + , TokenName (..) + , Position (..) + , tokenString + ) where + +import Text.Printf + +tokenString :: Token -> String +tokenString (Token _ s _) = s + +data Position = Position String Int Int deriving Eq + +instance Show Position where + show (Position f l c) = printf "%s:%d:%d" f l c + +data Token = Token TokenName String Position deriving (Show, Eq) + +data TokenName + = KWAlias + | KWAlways + | KWAlwaysComb + | KWAlwaysFf + | KWAlwaysLatch + | KWAnd + | KWAssert + | KWAssign + | KWAssume + | KWAutomatic + | KWBefore + | KWBegin + | KWBind + | KWBins + | KWBinsof + | KWBit + | KWBreak + | KWBuf + | KWBufif0 + | KWBufif1 + | KWByte + | KWCase + | KWCasex + | KWCasez + | KWCell + | KWChandle + | KWClass + | KWClocking + | KWCmos + | KWConfig + | KWConst + | KWConstraint + | KWContext + | KWContinue + | KWCover + | KWCovergroup + | KWCoverpoint + | KWCross + | KWDeassign + | KWDefault + | KWDefparam + | KWDesign + | KWDisable + | KWDist + | KWDo + | KWEdge + | KWElse + | KWEnd + | KWEndcase + | KWEndclass + | KWEndclocking + | KWEndconfig + | KWEndfunction + | KWEndgenerate + | KWEndgroup + | KWEndinterface + | KWEndmodule + | KWEndpackage + | KWEndprimitive + | KWEndprogram + | KWEndproperty + | KWEndspecify + | KWEndsequence + | KWEndtable + | KWEndtask + | KWEnum + | KWEvent + | KWExpect + | KWExport + | KWExtends + | KWExtern + | KWFinal + | KWFirstMatch + | KWFor + | KWForce + | KWForeach + | KWForever + | KWFork + | KWForkjoin + | KWFunction + | KWFunctionPrototype + | KWGenerate + | KWGenvar + | KWHighz0 + | KWHighz1 + | KWIf + | KWIff + | KWIfnone + | KWIgnoreBins + | KWIllegalBins + | KWImport + | KWIncdir + | KWInclude + | KWInitial + | KWInout + | KWInput + | KWInside + | KWInstance + | KWInt + | KWInteger + | KWInterface + | KWIntersect + | KWJoin + | KWJoinAny + | KWJoinNone + | KWLarge + | KWLiblist + | KWLibrary + | KWLocal + | KWLocalparam + | KWLogic + | KWLongint + | KWMacromodule + | KWMatches + | KWMedium + | KWModport + | KWModule + | KWNand + | KWNegedge + | KWNew + | KWNmos + | KWNor + | KWNoshowcancelled + | KWNot + | KWNotif0 + | KWNotif1 + | KWNull + | KWOption + | KWOr + | KWOutput + | KWPackage + | KWPacked + | KWParameter + | KWPathpulseDollar + | KWPmos + | KWPosedge + | KWPrimitive + | KWPriority + | KWProgram + | KWProperty + | KWProtected + | KWPull0 + | KWPull1 + | KWPulldown + | KWPullup + | KWPulsestyleOnevent + | KWPulsestyleOndetect + | KWPure + | KWRand + | KWRandc + | KWRandcase + | KWRandsequence + | KWRcmos + | KWReal + | KWRealtime + | KWRef + | KWReg + | KWRelease + | KWRepeat + | KWReturn + | KWRnmos + | KWRpmos + | KWRtran + | KWRtranif0 + | KWRtranif1 + | KWScalared + | KWSequence + | KWShortint + | KWShortreal + | KWShowcancelled + | KWSigned + | KWSmall + | KWSolve + | KWSpecify + | KWSpecparam + | KWStatic + | KWStrength0 + | KWStrength1 + | KWString + | KWStrong0 + | KWStrong1 + | KWStruct + | KWSuper + | KWSupply0 + | KWSupply1 + | KWTable + | KWTagged + | KWTask + | KWThis + | KWThroughout + | KWTime + | KWTimeprecision + | KWTimeunit + | KWTran + | KWTranif0 + | KWTranif1 + | KWTri + | KWTri0 + | KWTri1 + | KWTriand + | KWTrior + | KWTrireg + | KWType + | KWTypedef + | KWTypeOption + | KWUnion + | KWUnique + | KWUnsigned + | KWUse + | KWVar + | KWVectored + | KWVirtual + | KWVoid + | KWWait + | KWWaitOrder + | KWWand + | KWWeak0 + | KWWeak1 + | KWWhile + | KWWildcard + | KWWire + | KWWith + | KWWithin + | KWWor + | KWXnor + | KWXor + | IdSimple + | IdEscaped + | IdSystem + | LitNumberUnsigned + | LitNumber + | LitString + | SymParenL + | SymParenR + | SymBrackL + | SymBrackR + | SymBraceL + | SymBraceR + | SymTildy + | SymBang + | SymAt + | SymPound + | SymPercent + | SymHat + | SymAmp + | SymBar + | SymAster + | SymDot + | SymComma + | SymColon + | SymSemi + | SymEq + | SymLt + | SymGt + | SymPlus + | SymDash + | SymQuestion + | SymSlash + | SymDollar + | SymSQuote + | SymTildyAmp + | SymTildyBar + | SymTildyHat + | SymHatTildy + | SymEqEq + | SymBangEq + | SymAmpAmp + | SymBarBar + | SymAsterAster + | SymLtEq + | SymGtEq + | SymGtGt + | SymLtLt + | SymPlusPlus + | SymDashDash + | SymPlusEq + | SymDashEq + | SymAsterEq + | SymSlashEq + | SymPercentEq + | SymAmpEq + | SymBarEq + | SymHatEq + | SymPlusColon + | SymDashColon + | SymColonColon + | SymDotAster + | SymDashGt + | SymColonEq + | SymColonSlash + | SymPoundPound + | SymBrackLAster + | SymBrackLEq + | SymEqGt + | SymAtAster + | SymParenLAster + | SymAsterParenR + | SymAsterGt + | SymEqEqEq + | SymBangEqEq + | SymEqQuestionEq + | SymBangQuestionEq + | SymGtGtGt + | SymLtLtLt + | SymLtLtEq + | SymGtGtEq + | SymBarDashGt + | SymBarEqGt + | SymBrackLDashGt + | SymAtAtParenL + | SymParenLAsterParenR + | SymDashGtGt + | SymAmpAmpAmp + | SymLtLtLtEq + | SymGtGtGtEq + | Unknown + deriving (Show, Eq) diff --git a/verifuzz.cabal b/verifuzz.cabal index 81b71e3..267dffe 100644 --- a/verifuzz.cabal +++ b/verifuzz.cabal @@ -19,7 +19,8 @@ extra-source-files: README.md library hs-source-dirs: src default-language: Haskell2010 - ghc-options: -Wall -Werror + ghc-options: -Wall + build-tools: alex >=3 && <4 exposed-modules: VeriFuzz , VeriFuzz.AST , VeriFuzz.Config @@ -34,9 +35,12 @@ library , VeriFuzz.Env , VeriFuzz.Gen , VeriFuzz.Icarus - , VeriFuzz.Lexer , VeriFuzz.Mutate , VeriFuzz.Parser + , VeriFuzz.Parser.Parser + , VeriFuzz.Parser.Preprocess + , VeriFuzz.Parser.Token + , VeriFuzz.Parser.Lex , VeriFuzz.Random , VeriFuzz.RandomAlt , VeriFuzz.Reduce @@ -61,6 +65,7 @@ library , parsec >=3.1 && <3.2 , transformers >=0.5 && <0.6 , tomland >=0.5 && <0.6 + , array >=0.5 && <0.6 default-extensions: OverloadedStrings executable verifuzz -- cgit