From 6ee558b6b937bc02bc60fa7f144520e2cd3fe955 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sat, 3 Jul 2021 13:23:33 -0400 Subject: [PATCH] initial pass improving decl parsing error messages - all decl tokens are given an accurate starting position - key grammar productions return token positions to facilitate the above - helpers for standardized parse error generation - replaced annoying pattern-matching type argument restrictions - moving away from dumping raw decl tokens in error messages --- src/Language/SystemVerilog/Parser/Parse.y | 306 ++++++++++-------- .../SystemVerilog/Parser/ParseDecl.hs | 181 ++++++----- test/error/byte_packed.sv | 4 + test/error/const_const.sv | 4 + test/error/decl_binop_asgn.sv | 4 + test/error/decl_delay_asgn.sv | 4 + test/error/decl_delay_asgn_init.sv | 6 + test/error/decl_delay_asgn_package.sv | 7 + test/error/decl_delay_asgn_port.sv | 5 + test/error/decl_non_blocking_asgn.sv | 4 + test/error/enum_post_signed.sv | 6 + test/error/instantiation_extra_comma.sv | 4 + test/error/instantiation_missing_ports.sv | 4 + test/error/instantiation_no_label.sv | 4 + test/error/instantiation_no_module.sv | 4 + test/error/instantiation_not_ports.sv | 4 + test/error/instantiation_not_range.sv | 4 + test/error/instantiation_trailing_comma.sv | 4 + test/error/run_on_decl_item.sv | 4 + test/error/run_on_decl_stmt.sv | 6 + test/error/string_packed.sv | 4 + test/error/string_signed.sv | 4 + test/error/typeof_packed.sv | 5 + test/error/typeof_signed.sv | 5 + test/error/var_var.sv | 4 + 25 files changed, 383 insertions(+), 208 deletions(-) create mode 100644 test/error/byte_packed.sv create mode 100644 test/error/const_const.sv create mode 100644 test/error/decl_binop_asgn.sv create mode 100644 test/error/decl_delay_asgn.sv create mode 100644 test/error/decl_delay_asgn_init.sv create mode 100644 test/error/decl_delay_asgn_package.sv create mode 100644 test/error/decl_delay_asgn_port.sv create mode 100644 test/error/decl_non_blocking_asgn.sv create mode 100644 test/error/enum_post_signed.sv create mode 100644 test/error/instantiation_extra_comma.sv create mode 100644 test/error/instantiation_missing_ports.sv create mode 100644 test/error/instantiation_no_label.sv create mode 100644 test/error/instantiation_no_module.sv create mode 100644 test/error/instantiation_not_ports.sv create mode 100644 test/error/instantiation_not_range.sv create mode 100644 test/error/instantiation_trailing_comma.sv create mode 100644 test/error/run_on_decl_item.sv create mode 100644 test/error/run_on_decl_stmt.sv create mode 100644 test/error/string_packed.sv create mode 100644 test/error/string_signed.sv create mode 100644 test/error/typeof_packed.sv create mode 100644 test/error/typeof_signed.sv create mode 100644 test/error/var_var.sv diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index 5f1e8bd..1956095 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -28,7 +28,7 @@ import Language.SystemVerilog.Parser.Tokens %lexer { positionKeep } { TokenEOF } %name parseMain %tokentype { Token } -%error { parseError } +%error { parseErrorTok } %expect 0 @@ -462,58 +462,62 @@ TypeNonIdent :: { Type } : PartialType OptSigning Dimensions { $1 $2 $3 } | "type" "(" Expr ")" { TypeOf $3 } PartialType :: { Signing -> [Range] -> Type } - : IntegerVectorType { IntegerVector $1 } - | IntegerAtomType { \sg -> \[] -> IntegerAtom $1 sg } - | NonIntegerType { \Unspecified -> \[] -> NonInteger $1 } - | "enum" EnumBaseType "{" EnumItems "}" { \Unspecified -> Enum $2 $4 } - | "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 } - | "union" Packing "{" StructItems "}" { \Unspecified -> Union $2 $4 } + : PartialTypeP { snd $1 } +PartialTypeP :: { (Position, Signing -> [Range] -> Type) } + : IntegerVectorTypeP { (fst $1, makeIntegerVector $1) } + | IntegerAtomTypeP { (fst $1, makeIntegerAtom $1) } + | NonIntegerTypeP { (fst $1, makeNonInteger $1) } + | "enum" EnumBaseType "{" EnumItems "}" { makeComplex $1 $ Enum $2 $4 } + | "struct" Packing "{" StructItems "}" { makeComplex $1 $ Struct $2 $4 } + | "union" Packing "{" StructItems "}" { makeComplex $1 $ Union $2 $4 } CastingType :: { Type } - : IntegerVectorType { IntegerVector $1 Unspecified [] } - | IntegerAtomType { IntegerAtom $1 Unspecified } - | NonIntegerType { NonInteger $1 } - | Signing { Implicit $1 [] } + : IntegerVectorTypeP { IntegerVector (snd $1) Unspecified [] } + | IntegerAtomTypeP { IntegerAtom (snd $1) Unspecified } + | NonIntegerTypeP { NonInteger (snd $1) } + | SigningP { Implicit (snd $1) [] } EnumBaseType :: { Type } : Type { $1 } | Dimensions { Implicit Unspecified $1 } Signing :: { Signing } - : "signed" { Signed } - | "unsigned" { Unsigned } + : SigningP { snd $1 } +SigningP :: { (Position, Signing) } + : "signed" { withPos $1 Signed } + | "unsigned" { withPos $1 Unsigned } OptSigning :: { Signing } : Signing { $1 } | {- empty -} { Unspecified } -NetType :: { NetType } - : "supply0" { TSupply0 } - | "supply1" { TSupply1 } - | "tri" { TTri } - | "triand" { TTriand } - | "trior" { TTrior } - | "trireg" { TTrireg } - | "tri0" { TTri0 } - | "tri1" { TTri1 } - | "uwire" { TUwire } - | "wire" { TWire } - | "wand" { TWand } - | "wor" { TWor } -IntegerVectorType :: { IntegerVectorType } - : "bit" { TBit } - | "logic" { TLogic } - | "reg" { TReg } -IntegerAtomType :: { IntegerAtomType } - : "byte" { TByte } - | "shortint" { TShortint } - | "int" { TInt } - | "longint" { TLongint } - | "integer" { TInteger } - | "time" { TTime } -NonIntegerType :: { NonIntegerType } - : "shortreal" { TShortreal } - | "real" { TReal } - | "realtime" { TRealtime } - | "string" { TString } - | "event" { TEvent } +NetTypeP :: { (Position, NetType) } + : "supply0" { withPos $1 TSupply0 } + | "supply1" { withPos $1 TSupply1 } + | "tri" { withPos $1 TTri } + | "triand" { withPos $1 TTriand } + | "trior" { withPos $1 TTrior } + | "trireg" { withPos $1 TTrireg } + | "tri0" { withPos $1 TTri0 } + | "tri1" { withPos $1 TTri1 } + | "uwire" { withPos $1 TUwire } + | "wire" { withPos $1 TWire } + | "wand" { withPos $1 TWand } + | "wor" { withPos $1 TWor } +IntegerVectorTypeP :: { (Position, IntegerVectorType) } + : "bit" { withPos $1 TBit } + | "logic" { withPos $1 TLogic } + | "reg" { withPos $1 TReg } +IntegerAtomTypeP :: { (Position, IntegerAtomType) } + : "byte" { withPos $1 TByte } + | "shortint" { withPos $1 TShortint } + | "int" { withPos $1 TInt } + | "longint" { withPos $1 TLongint } + | "integer" { withPos $1 TInteger } + | "time" { withPos $1 TTime } +NonIntegerTypeP :: { (Position, NonIntegerType) } + : "shortreal" { withPos $1 TShortreal } + | "real" { withPos $1 TReal } + | "realtime" { withPos $1 TRealtime } + | "string" { withPos $1 TString } + | "event" { withPos $1 TEvent } EnumItems :: { [(Identifier, Expr)] } : VariablePortIdentifiers { $1 } @@ -607,9 +611,11 @@ ModportSimplePort :: { (Identifier, Expr) } | Identifier { ($1, Ident $1) } Identifier :: { Identifier } - : simpleIdentifier { tokenString $1 } - | escapedIdentifier { tokenString $1 } - | systemIdentifier { tokenString $1 } + : IdentifierP { snd $1 } +IdentifierP :: { (Position, Identifier) } + : simpleIdentifier { withPos $1 $ tokenString $1 } + | escapedIdentifier { withPos $1 $ tokenString $1 } + | systemIdentifier { withPos $1 $ tokenString $1 } Identifiers :: { [Identifier] } : Identifier { [$1] } @@ -624,48 +630,48 @@ Strength :: { Strength } DeclTokens(delim) :: { [DeclToken] } : DeclTokensBase(DeclTokens(delim), delim) { $1 } DeclTokensBase(repeat, delim) :: { [DeclToken] } - : DeclToken delim { [$1] } - | DeclToken repeat { [$1] ++ $2 } - | Identifier ParamBindings repeat {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 } - | DeclTokenAsgn "," repeat {% posInject \p -> [$1, DTComma p] ++ $3 } - | DeclTokenAsgn delim {% posInject \p -> [$1] } + : DeclToken delim { [$1] } + | DeclToken repeat { [$1] ++ $2 } + | IdentifierP ParamBindings repeat { [uncurry DTIdent $1, DTParams (fst $1) $2] ++ $3 } + | DeclTokenAsgn "," repeat { [$1, DTComma (tokenPosition $2)] ++ $3 } + | DeclTokenAsgn delim { [$1] } DeclToken :: { DeclToken } - : "," {% posInject \p -> DTComma p } - | "[" "]" {% posInject \p -> DTAutoDim p } - | "const" {% posInject \p -> DTConst p } - | "var" {% posInject \p -> DTVar p } - | PartSelect {% posInject \p -> DTRange p $1 } - | Identifier {% posInject \p -> DTIdent p $1 } - | Direction {% posInject \p -> DTDir p $1 } - | "[" Expr "]" {% posInject \p -> DTBit p $2 } - | LHSConcat {% posInject \p -> DTConcat p $1 } - | PartialType {% posInject \p -> DTType p $1 } - | NetType Strength {% posInject \p -> DTNet p $1 $2 } - | "." Identifier {% posInject \p -> DTDot p $2 } - | PortBindings {% posInject \p -> DTInstance p $1 } - | Signing {% posInject \p -> DTSigning p $1 } - | "automatic" {% posInject \p -> DTLifetime p Automatic } - | "{" StreamOp StreamSize Concat "}" {% posInject \p -> DTStream p $2 $3 (map toLHS $4) } - | "{" StreamOp Concat "}" {% posInject \p -> DTStream p $2 (RawNum 1) (map toLHS $3) } - | "type" "(" Expr ")" {% posInject \p -> DTType p (\Unspecified -> \[] -> TypeOf $3) } - | IncOrDecOperator {% posInject \p -> DTAsgn p (AsgnOp $1) Nothing (RawNum 1) } - | "<=" opt(DelayOrEvent) Expr %prec Asgn {% posInject \p -> DTAsgn p AsgnOpNonBlocking $2 $3 } - | Identifier "::" Identifier {% posInject \p -> DTPSIdent p $1 $3 } - | Identifier ParamBindings "::" Identifier {% posInject \p -> DTCSIdent p $1 $2 $4 } + : "," { DTComma $ tokenPosition $1 } + | "[" "]" { DTAutoDim $ tokenPosition $1 } + | "const" { DTConst $ tokenPosition $1 } + | "var" { DTVar $ tokenPosition $1 } + | PartSelectP { uncurry DTRange $1 } + | IdentifierP { uncurry DTIdent $1 } + | DirectionP { uncurry DTDir $1 } + | LHSConcatP { uncurry DTConcat $1 } + | PartialTypeP { uncurry DTType $1 } + | NetTypeP Strength { uncurry DTNet $1 $2 } + | PortBindingsP { uncurry DTPorts $1 } + | SigningP { uncurry DTSigning $1 } + | "[" Expr "]" { DTBit (tokenPosition $1) $2 } + | "." Identifier { DTDot (tokenPosition $1) $2 } + | "automatic" { DTLifetime (tokenPosition $1) Automatic } + | "{" StreamOp StreamSize Concat "}" { DTStream (tokenPosition $1) $2 $3 (map toLHS $4) } + | "{" StreamOp Concat "}" { DTStream (tokenPosition $1) $2 (RawNum 1) (map toLHS $3) } + | "type" "(" Expr ")" { uncurry DTType $ makeTypeOf $1 $3 } + | IncOrDecOperatorP { DTAsgn (fst $1) (AsgnOp $ snd $1) Nothing (RawNum 1) } + | "<=" opt(DelayOrEvent) Expr %prec Asgn { DTAsgn (tokenPosition $1) AsgnOpNonBlocking $2 $3 } + | IdentifierP "::" Identifier { uncurry DTPSIdent $1 $3 } + | IdentifierP ParamBindings "::" Identifier { uncurry DTCSIdent $1 $2 $4 } DeclTokenAsgn :: { DeclToken } - : "=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpEq $2 $3 } - | AsgnBinOp Expr {% posInject \p -> DTAsgn p $1 Nothing $2 } + : "=" opt(DelayOrEvent) Expr { DTAsgn (tokenPosition $1) AsgnOpEq $2 $3 } + | AsgnBinOpP Expr { uncurry DTAsgn $1 Nothing $2 } PortDeclTokens(delim) :: { [DeclToken] } : DeclTokensBase(PortDeclTokens(delim), delim) { $1 } | GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2} | GenericInterfaceDecl delim { $1 } - | AttributeInstance PortDeclTokens(delim) {% posInject \p -> DTAttr p $1 : $2 } + | AttributeInstanceP PortDeclTokens(delim) { uncurry DTAttr $1 : $2 } ModuleDeclTokens(delim) :: { [DeclToken] } : DeclTokensBase(ModuleDeclTokens(delim), delim) { $1 } | GenericInterfaceDecl ModuleDeclTokens(delim) { $1 ++ $2} | GenericInterfaceDecl delim { $1 } GenericInterfaceDecl :: { [DeclToken] } - : "interface" Identifier {% posInject \p -> [DTType p (\Unspecified -> InterfaceT "" ""), DTIdent p $2] } + : "interface" IdentifierP { [DTType (tokenPosition $1) (\Unspecified -> InterfaceT "" ""), uncurry DTIdent $2] } VariablePortIdentifiers :: { [(Identifier, Expr)] } : VariablePortIdentifier { [$1] } @@ -674,9 +680,11 @@ VariablePortIdentifier :: { (Identifier, Expr) } : Identifier OptAsgn { ($1,$2) } Direction :: { Direction } - : "inout" { Inout } - | "input" { Input } - | "output" { Output } + : DirectionP { snd $1 } +DirectionP :: { (Position, Direction) } + : "inout" { (tokenPosition $1, Inout ) } + | "input" { (tokenPosition $1, Input ) } + | "output" { (tokenPosition $1, Output) } ModuleItems :: { [ModuleItem] } : {- empty -} { [] } @@ -778,7 +786,9 @@ AttributeInstances :: { [Attr] } : {- empty -} { [] } | AttributeInstance AttributeInstances { $1 : $2 } AttributeInstance :: { Attr } - : "(*" AttrSpecs "*)" { Attr $2 } + : AttributeInstanceP { snd $1 } +AttributeInstanceP :: { (Position, Attr) } + : "(*" AttrSpecs "*)" { withPos $1 $ Attr $2 } AttrSpecs :: { [AttrSpec] } : AttrSpec { [$1] } | AttrSpecs "," AttrSpec { $1 ++ [$3] } @@ -910,7 +920,7 @@ Drive :: { String } : "pull0" { tokenString $1 } | "pull1" { tokenString $1 } DefaultNetType :: { String } - : NetType { show $1 } + : NetTypeP { show $ snd $1 } | Identifier { $1 } PackageImportItems :: { [(Identifier, Identifier)] } @@ -969,28 +979,28 @@ DeclAsgn :: { (Identifier, Expr, [Range]) } Range :: { Range } : "[" Expr ":" Expr "]" { ($2, $4) } -PartSelect :: { (PartSelectMode, Range) } - : "[" Expr ":" Expr "]" { (NonIndexed , ($2, $4)) } - | "[" Expr "+:" Expr "]" { (IndexedPlus , ($2, $4)) } - | "[" Expr "-:" Expr "]" { (IndexedMinus, ($2, $4)) } +PartSelectP :: { (Position, (PartSelectMode, Range)) } + : "[" Expr ":" Expr "]" { (tokenPosition $1, (NonIndexed , ($2, $4))) } + | "[" Expr "+:" Expr "]" { (tokenPosition $1, (IndexedPlus , ($2, $4))) } + | "[" Expr "-:" Expr "]" { (tokenPosition $1, (IndexedMinus, ($2, $4))) } LHS :: { LHS } : Identifier { LHSIdent $1 } - | LHS PartSelect { LHSRange $1 (fst $2) (snd $2) } + | LHS PartSelectP { uncurry (LHSRange $1) (snd $2) } | LHS "[" Expr "]" { LHSBit $1 $3 } | LHS "." Identifier { LHSDot $1 $3 } - | LHSConcat { LHSConcat $1 } + | LHSConcatP { LHSConcat $ snd $1 } | "{" StreamOp StreamSize Concat "}" { LHSStream $2 $3 (map toLHS $4) } | "{" StreamOp Concat "}" { LHSStream $2 (RawNum 1) (map toLHS $3) } -LHSConcat :: { [LHS] } - : "{" LHSs "}" { $2 } +LHSConcatP :: { (Position, [LHS]) } + : "{" LHSs "}" { withPos $1 $2 } LHSs :: { [LHS] } : LHS { [$1] } | LHSs "," LHS { $1 ++ [$3] } -PortBindings :: { [PortBinding] } - : "(" PortBindingsInside ")" {% checkPortBindings $2 } +PortBindingsP:: { (Position, [PortBinding]) } + : "(" PortBindingsInside ")" {% checkPortBindings $2 >>= return . withPos $1 } PortBindingsInside :: { [PortBinding] } : OptPortBinding { [$1] } | OptPortBinding "," PortBindingsInside { $1 : $3} @@ -1246,7 +1256,7 @@ Expr :: { Expr } | DimsFn "(" TypeOrExpr ")" { DimsFn $1 $3 } | DimFn "(" TypeOrExpr ")" { DimFn $1 $3 (RawNum 1) } | DimFn "(" TypeOrExpr "," Expr ")" { DimFn $1 $3 $5 } - | Expr PartSelect { Range $1 (fst $2) (snd $2) } + | Expr PartSelectP { uncurry (Range $1) (snd $2) } | Expr "[" Expr "]" { Bit $1 $3 } | "{" Expr Concat "}" { Repeat $2 $3 } | Concat { Concat $1 } @@ -1386,22 +1396,26 @@ AsgnOp :: { AsgnOp } : "=" { AsgnOpEq } | AsgnBinOp { $1 } AsgnBinOp :: { AsgnOp } - : "+=" { AsgnOp Add } - | "-=" { AsgnOp Sub } - | "*=" { AsgnOp Mul } - | "/=" { AsgnOp Div } - | "%=" { AsgnOp Mod } - | "&=" { AsgnOp BitAnd } - | "|=" { AsgnOp BitOr } - | "^=" { AsgnOp BitXor } - | "<<=" { AsgnOp ShiftL } - | ">>=" { AsgnOp ShiftR } - | "<<<=" { AsgnOp ShiftAL } - | ">>>=" { AsgnOp ShiftAR } + : AsgnBinOpP { snd $1 } +AsgnBinOpP :: { (Position, AsgnOp) } + : "+=" { withPos $1 $ AsgnOp Add } + | "-=" { withPos $1 $ AsgnOp Sub } + | "*=" { withPos $1 $ AsgnOp Mul } + | "/=" { withPos $1 $ AsgnOp Div } + | "%=" { withPos $1 $ AsgnOp Mod } + | "&=" { withPos $1 $ AsgnOp BitAnd } + | "|=" { withPos $1 $ AsgnOp BitOr } + | "^=" { withPos $1 $ AsgnOp BitXor } + | "<<=" { withPos $1 $ AsgnOp ShiftL } + | ">>=" { withPos $1 $ AsgnOp ShiftR } + | "<<<=" { withPos $1 $ AsgnOp ShiftAL } + | ">>>=" { withPos $1 $ AsgnOp ShiftAR } IncOrDecOperator :: { BinOp } - : "++" { Add } - | "--" { Sub } + : IncOrDecOperatorP { snd $1 } +IncOrDecOperatorP :: { (Position, BinOp) } + : "++" { withPos $1 Add } + | "--" { withPos $1 Sub } DimsFn :: { DimsFn } : "$bits" { FnBits } @@ -1455,11 +1469,6 @@ parse tokens = position = tokenPosition $ head tokens initialState = ParseData position tokens -posInject :: (Position -> a) -> ParseState a -posInject cont = do - pos <- gets pPosition - return $ cont pos - positionKeep :: (Token -> ParseState a) -> ParseState a positionKeep cont = do tokens <- gets pTokens @@ -1469,13 +1478,19 @@ positionKeep cont = do put $ ParseData (tokenPosition tok) toks cont tok -parseError :: Token -> ParseState a -parseError a = case a of +parseErrorTok :: Token -> ParseState a +parseErrorTok a = case a of TokenEOF -> do p <- gets pPosition - throwError $ show p ++ ": Parse error: unexpected end of file." - Token t s p -> throwError $ show p ++ ": Parse error: unexpected token '" - ++ s ++ "' (" ++ show t ++ ")." + parseErrorM p "unexpected end of file" + Token t s p -> + parseErrorM p $ "unexpected token '" ++ s ++ "' (" ++ show t ++ ")" + +parseErrorM :: Position -> String -> ParseState a +parseErrorM pos msg = throwError $ show pos ++ ": Parse error: " ++ msg + +parseError :: Position -> String -> a +parseError pos msg = error $ show pos ++ ": Parse error: " ++ msg genItemsToGenItem :: [GenItem] -> GenItem genItemsToGenItem [x] = x @@ -1487,8 +1502,8 @@ combineDeclsAndStmts (a1, b1) (a2, b2) = if not (null b1) && not (null a2) then do p <- gets pPosition - throwError $ show p - ++ ": Parse error: procedural block contains a declaration after a statement" + parseErrorM p + "procedural block contains a declaration after a statement" else return (a1 ++ a2, b1 ++ b2) makeInput :: Decl -> Decl @@ -1502,13 +1517,13 @@ checkTag :: String -> String -> a -> ParseState a checkTag _ "" x = return x checkTag "" b _ = do p <- gets pPosition - error $ show p ++ ": Parse error: block has only end label " ++ show b + parseErrorM p $ "block has only end label " ++ show b checkTag a b x = if a == b then return x else do p <- gets pPosition - error $ show p ++ ": Parse error: element " ++ show a + parseErrorM p $ "element " ++ show a ++ " has mismatched end label " ++ show b toLHS :: Expr -> LHS @@ -1538,14 +1553,12 @@ validateCases :: Token -> [([Expr], a)] -> [([Expr], a)] validateCases tok items = if length (filter (null . fst) items) <= 1 then items - else error $ show (tokenPosition tok) - ++ ": Parse error: case has multiple defaults" + else parseError (tokenPosition tok) "case has multiple defaults" caseInsideKW :: Token -> CaseKW -> CaseKW caseInsideKW _ CaseN = CaseInside caseInsideKW tok kw = - error $ show (tokenPosition tok) - ++ ": Parse error: cannot use inside with " ++ show kw + parseError (tokenPosition tok) $ "cannot use inside with " ++ show kw addMIAttr :: Attr -> ModuleItem -> ModuleItem addMIAttr _ (item @ (MIPackageItem (Decl CommentDecl{}))) = item @@ -1554,7 +1567,7 @@ addMIAttr attr item = MIAttr attr item missingToken :: String -> ParseState a missingToken expected = do p <- gets pPosition - throwError $ show p ++ ": Parse error: missing expected `" ++ expected ++ "`" + parseErrorM p $ "missing expected `" ++ expected ++ "`" checkPortBindings :: [PortBinding] -> ParseState [PortBinding] checkPortBindings [] = return [] @@ -1573,7 +1586,46 @@ checkBindings kind bindings = return bindings else do p <- gets pPosition - error $ show p ++ ": Parse error: illegal mix of ordered and named " ++ kind + parseErrorM p $ "illegal mix of ordered and named " ++ kind where bindingNames = map fst bindings +withPos :: Token -> a -> (Position, a) +withPos tok = (tokenPosition tok, ) + +type PartialType = Signing -> [Range] -> Type + +unexpectedPackedRanges :: Position -> String -> a +unexpectedPackedRanges pos typ = + parseError pos $ "unexpected packed range(s) applied to " ++ typ + +unexpectedSigning :: Position -> Signing -> String -> a +unexpectedSigning pos sg typ = + parseError pos $ "unexpected " ++ show sg ++ " applied to " ++ typ + +makeIntegerVector :: (Position, IntegerVectorType) -> PartialType +makeIntegerVector (_, typ) = IntegerVector typ + +makeIntegerAtom :: (Position, IntegerAtomType) -> PartialType +makeIntegerAtom (_, typ) sg [] = IntegerAtom typ sg +makeIntegerAtom (pos, typ) _ _ = unexpectedPackedRanges pos (show typ) + +makeNonInteger :: (Position, NonIntegerType) -> PartialType +makeNonInteger (_, typ) Unspecified [] = NonInteger typ +makeNonInteger (pos, typ) sg [] = unexpectedSigning pos sg (show typ) +makeNonInteger (pos, typ) Unspecified _ = unexpectedPackedRanges pos (show typ) + +makeComplex :: Token -> ([Range] -> Type) -> (Position, PartialType) +makeComplex (Token _ str pos) tf = (pos, check) + where + check Unspecified = tf + check sg = unexpectedSigning pos sg str + +makeTypeOf :: Token -> Expr -> (Position, PartialType) +makeTypeOf (Token _ _ pos) expr = (pos, check) + where + typ = TypeOf expr + check Unspecified [] = typ + check Unspecified _ = unexpectedPackedRanges pos (show typ) + check sg [] = unexpectedSigning pos sg (show typ) + } diff --git a/src/Language/SystemVerilog/Parser/ParseDecl.hs b/src/Language/SystemVerilog/Parser/ParseDecl.hs index c3dfd68..8c8a784 100644 --- a/src/Language/SystemVerilog/Parser/ParseDecl.hs +++ b/src/Language/SystemVerilog/Parser/ParseDecl.hs @@ -45,7 +45,7 @@ module Language.SystemVerilog.Parser.ParseDecl , parseDTsAsDeclsOrAsgns ) where -import Data.List (findIndex, findIndices, partition) +import Data.List (findIndex, findIndices, partition, uncons) import Language.SystemVerilog.AST import Language.SystemVerilog.Parser.Tokens (Position(..)) @@ -65,7 +65,7 @@ data DeclToken | DTType Position (Signing -> [Range] -> Type) | DTNet Position NetType Strength | DTParams Position [ParamBinding] - | DTInstance Position [PortBinding] + | DTPorts Position [PortBinding] | DTBit Position Expr | DTConcat Position [LHS] | DTStream Position StreamOp Expr [LHS] @@ -79,15 +79,17 @@ data DeclToken -- a non-blocking operator, binary assignment operator, or a timing control -- because we don't expect to see those assignment operators in declarations forbidNonEqAsgn :: [DeclToken] -> a -> a -forbidNonEqAsgn tokens = - if any isNonEqAsgn tokens - then error $ "decl tokens contain bad assignment operator: " ++ show tokens - else id - where - isNonEqAsgn :: DeclToken -> Bool - isNonEqAsgn (DTAsgn _ op mt _) = - op /= AsgnOpEq || mt /= Nothing - isNonEqAsgn _ = False +forbidNonEqAsgn [] = id +forbidNonEqAsgn (tok @ (DTAsgn _ op mt _) : toks) = + if op /= AsgnOpEq then + parseError tok $ "unexpected " ++ opKind + ++ " assignment operator in declaration" + else if mt /= Nothing then + parseError tok "unexpected timing modifier in declaration" + else + forbidNonEqAsgn toks + where opKind = if op == AsgnOpNonBlocking then "non-blocking" else "binary" +forbidNonEqAsgn (_ : toks) = forbidNonEqAsgn toks -- [PUBLIC]: parser for module port declarations, including interface ports @@ -102,7 +104,7 @@ parseDTsAsPortDecls pieces = -- internal parseDTsAsPortDecls after the removal of an optional trailing comma parseDTsAsPortDecls' :: [DeclToken] -> ([Identifier], [ModuleItem]) parseDTsAsPortDecls' pieces = - forbidNonEqAsgn pieces $ + forbidNonEqAsgn pieces `seq` if isSimpleList then (simpleIdents, []) else (portNames declarations, applyAttrs [] pieces declarations) @@ -173,10 +175,10 @@ parseDTsAsPortDecls' pieces = -- parameters) and module instantiations parseDTsAsModuleItems :: [DeclToken] -> [ModuleItem] parseDTsAsModuleItems tokens = - forbidNonEqAsgn tokens $ + forbidNonEqAsgn tokens `seq` if isElabTask $ head tokens then asElabTask tokens - else if any isInstance tokens then + else if any isPorts tokens then parseDTsAsIntantiations tokens else map (MIPackageItem . Decl) $ parseDTsAsDecl tokens @@ -185,80 +187,89 @@ parseDTsAsModuleItems tokens = isElabTask (DTIdent _ x) = elem x elabTasks where elabTasks = ["$fatal", "$error", "$warning", "$info"] isElabTask _ = False - isInstance :: DeclToken -> Bool - isInstance (DTInstance{}) = True - isInstance _ = False -- internal; approximates the behavior of the elaboration system tasks asElabTask :: [DeclToken] -> [ModuleItem] -asElabTask [DTIdent _ name, DTInstance _ args] = +asElabTask [DTIdent _ name, DTPorts _ args] = if name == "$info" then [] -- just drop them for simplicity else [Instance "ThisModuleDoesNotExist" [] name' [] args] where name' = "__sv2v_elab_" ++ tail name asElabTask [DTIdent pos name] = - asElabTask [DTIdent pos name, DTInstance pos []] + asElabTask [DTIdent pos name, DTPorts pos []] asElabTask tokens = error $ "could not parse elaboration system task: " ++ show tokens -- internal; parser for module instantiations parseDTsAsIntantiations :: [DeclToken] -> [ModuleItem] -parseDTsAsIntantiations (DTIdent _ name : tokens) = - if not (all isInstanceToken rest) - then error $ "instantiations mixed with other items: " ++ (show rest) - else step rest +parseDTsAsIntantiations (DTIdent _ name : DTParams _ params : tokens) = + step tokens where step :: [DeclToken] -> [ModuleItem] - step [] = error $ "unexpected end of instantiation list: " ++ (show tokens) - step toks = - case (init inst, last inst) of - (DTIdent _ x : ranges, DTInstance _ p) -> - Instance name params x rs p : follow - where rs = map asRange ranges - _ -> failure + step [] = parseError endTok "unexpected end of instantiation list" + step toks = inst : rest where - (inst, toks') = span (not . isComma) toks - follow = if null toks' then [] else step (tail toks') - asRange :: DeclToken -> Range - asRange (DTRange _ (NonIndexed, s)) = s - asRange (DTBit _ s) = (RawNum 0, BinOp Sub s (RawNum 1)) - asRange _ = failure - failure = error $ "unrecognized instantiation of " ++ name - ++ ": " ++ show inst - (params, rest) = - case head tokens of - DTParams _ ps -> (ps, tail tokens) - _ -> ([], tokens) - isInstanceToken :: DeclToken -> Bool - isInstanceToken (DTInstance{}) = True - isInstanceToken (DTRange{}) = True - isInstanceToken (DTBit{}) = True - isInstanceToken (DTIdent{}) = True - isInstanceToken (DTComma{}) = True - isInstanceToken _ = False + (delimTok, rest) = + if null restToks + then (endTok, []) + else (head restToks, step $ tail restToks) + inst = Instance name params x rs p + (x, rs, p) = parseDTsAsIntantiation instToks delimTok + (instToks, restToks) = break isComma toks + -- TODO: all public interfaces should take the ending token + endTok = last tokens +parseDTsAsIntantiations (DTIdent pos name : tokens) = + parseDTsAsIntantiations $ DTIdent pos name : DTParams pos [] : tokens parseDTsAsIntantiations tokens = - error $ - "DeclTokens contain instantiations, but start with non-ident: " - ++ (show tokens) + parseError (head tokens) + "expected module or interface name at beginning of instantiation list" + +-- internal; parser for an individual instantiations +parseDTsAsIntantiation :: [DeclToken] -> DeclToken + -> (Identifier, [Range], [PortBinding]) +parseDTsAsIntantiation l0 delimTok = + if null l0 then + parseError delimTok "expected instantiation before delimiter" + else if not (isIdent nameTok) then + parseError nameTok "expected instantiation name" + else if null l1 then + parseError delimTok "expected port connections before delimiter" + else if seq ranges not (isPorts portsTok) then + parseError portsTok "expected port connections" + else + (name, ranges, ports) + where + Just (nameTok, l1) = uncons l0 + rangeToks = init l1 + portsTok = last l1 + DTIdent _ name = nameTok + DTPorts _ ports = portsTok + ranges = map asRange rangeToks + asRange :: DeclToken -> Range + asRange (DTRange _ (NonIndexed, s)) = s + asRange (DTBit _ s) = (RawNum 0, BinOp Sub s (RawNum 1)) + asRange tok = parseError tok "expected instantiation dimensions" -- [PUBLIC]: parser for generic, comma-separated declarations parseDTsAsDecls :: [DeclToken] -> [Decl] parseDTsAsDecls tokens = - forbidNonEqAsgn tokens $ + forbidNonEqAsgn tokens `seq` concat $ map finalize $ parseDTsAsComponents tokens --- [PUBLIC]: used for "single" declarations, i.e., declarations appearing +-- internal; used for "single" declarations, i.e., declarations appearing -- outside of a port list parseDTsAsDecl :: [DeclToken] -> [Decl] parseDTsAsDecl tokens = - forbidNonEqAsgn tokens $ if length components /= 1 - then error $ "too many declarations: " ++ (show tokens) + then parseError tok $ "unexpected comma-separated declarations" else finalize $ head components - where components = parseDTsAsComponents tokens + where + components = parseDTsAsComponents tokens + _ : (pos, _, _) : _ = components + tok = DTComma pos -- [PUBLIC]: parser for single block item declarations or assign or arg-less @@ -274,7 +285,7 @@ parseDTsAsDeclOrStmt tokens = pos = tokPos $ last tokens stmt = case last tokens of DTAsgn _ op mt e -> Asgn op mt lhs e - DTInstance _ args -> asSubroutine lhsToks (instanceToArgs args) + DTPorts _ ports -> asSubroutine lhsToks (portsToArgs ports) _ -> asSubroutine tokens (Args [] []) lhsToks = init tokens lhs = case takeLHS lhsToks of @@ -301,8 +312,8 @@ asSubroutine tokens = Nothing -> error $ "invalid block item decl or stmt: " ++ show tokens -- converts port bindings to call args -instanceToArgs :: [PortBinding] -> Args -instanceToArgs bindings = +portsToArgs :: [PortBinding] -> Args +portsToArgs bindings = Args pnArgs kwArgs where (pnBindings, kwBindings) = partition (null . fst) bindings @@ -313,7 +324,7 @@ instanceToArgs bindings = -- is only used for `for` loop initialization lists parseDTsAsDeclsOrAsgns :: [DeclToken] -> Either [Decl] [(LHS, Expr)] parseDTsAsDeclsOrAsgns tokens = - forbidNonEqAsgn tokens $ + forbidNonEqAsgn tokens `seq` if hasLeadingAsgn || tripLookahead tokens then Right $ parseDTsAsAsgns tokens else Left $ map checkDecl $ parseDTsAsDecls tokens @@ -376,24 +387,23 @@ takeLHSStep _ _ = Nothing -- batches together separate declaration lists -type DeclBase = Direction -> Identifier -> [Range] -> Expr -> Decl +type DeclBase = Identifier -> [Range] -> Expr -> Decl type Triplet = (Identifier, [Range], Expr) -type Component = (Direction, DeclBase, [Triplet]) -finalize :: (Position, Component) -> [Decl] -finalize (pos, (dir, base, trips)) = +type Component = (Position, DeclBase, [Triplet]) +finalize :: Component -> [Decl] +finalize (pos, base, trips) = CommentDecl ("Trace: " ++ show pos) : - map (\(x, a, e) -> base dir x a e) trips + map (\(x, a, e) -> base x a e) trips -- internal; entrypoint of the critical portion of our parser -parseDTsAsComponents :: [DeclToken] -> [(Position, Component)] +parseDTsAsComponents :: [DeclToken] -> [Component] parseDTsAsComponents [] = [] parseDTsAsComponents tokens = - (position, component) : parseDTsAsComponents tokens' - where - (position, component, tokens') = parseDTsAsComponent tokens + component : parseDTsAsComponents tokens' + where (component, tokens') = parseDTsAsComponent tokens -parseDTsAsComponent :: [DeclToken] -> (Position, Component, [DeclToken]) +parseDTsAsComponent :: [DeclToken] -> (Component, [DeclToken]) parseDTsAsComponent [] = error "parseDTsAsComponent unexpected end of tokens" parseDTsAsComponent l0 = if l /= Nothing && l /= Just Automatic then @@ -402,7 +412,7 @@ parseDTsAsComponent l0 = error $ "declaration(s) missing type information: " ++ show (position, tps) else - (position, component, l6) + (component, l6) where (dir, l1) = takeDir l0 (l , l2) = takeLifetime l1 @@ -410,8 +420,9 @@ parseDTsAsComponent l0 = (tf , l4) = takeType l3 (rs , l5) = takeRanges l4 (tps, l6) = takeTrips l5 True - component = (dir, von $ tf rs, tps) position = tokPos $ head l0 + base = von dir $ tf rs + component = (position, base, tps) takeTrips :: [DeclToken] -> Bool -> ([Triplet], [DeclToken]) takeTrips [] True = error "incomplete declaration" @@ -461,12 +472,12 @@ takeLifetime :: [DeclToken] -> (Maybe Lifetime, [DeclToken]) takeLifetime (DTLifetime _ l : rest) = (Just l, rest) takeLifetime rest = (Nothing, rest) -takeVarOrNet :: [DeclToken] -> (Type -> DeclBase, [DeclToken]) -takeVarOrNet (DTConst _ : DTConst pos : _) = - error $ "unexpected const after const at " ++ show pos +takeVarOrNet :: [DeclToken] -> (Direction -> Type -> DeclBase, [DeclToken]) +takeVarOrNet (DTConst{} : tok @ DTConst{} : _) = + parseError tok "duplicate const modifier" takeVarOrNet (DTConst _ : tokens) = takeVarOrNet tokens -takeVarOrNet (DTNet _ n s : tokens) = (\t d -> Net d n s t, tokens) -takeVarOrNet tokens = (flip Variable, tokens) +takeVarOrNet (DTNet _ n s : tokens) = (\d -> Net d n s, tokens) +takeVarOrNet tokens = (Variable, tokens) takeType :: [DeclToken] -> ([Range] -> Type, [DeclToken]) takeType (DTIdent _ a : DTDot _ b : rest) = (InterfaceT a b , rest) @@ -488,8 +499,8 @@ takeType (DTIdent pos tn : rest) = (_, Nothing) -> True -- if comma is first, then this ident is a declaration (Just a, Just b) -> a < b -takeType (DTVar _ : DTVar pos : _) = - error $ "unexpected var after var at " ++ show pos +takeType (DTVar{} : tok @ DTVar{} : _) = + parseError tok "duplicate var modifier" takeType (DTVar _ : rest) = case tf [] of Implicit sg [] -> (IntegerVector TLogic sg, rest') @@ -549,6 +560,10 @@ isComma :: DeclToken -> Bool isComma (DTComma{}) = True isComma _ = False +isPorts :: DeclToken -> Bool +isPorts DTPorts{} = True +isPorts _ = False + tokPos :: DeclToken -> Position tokPos (DTComma p) = p tokPos (DTAutoDim p) = p @@ -563,7 +578,7 @@ tokPos (DTDir p _) = p tokPos (DTType p _) = p tokPos (DTNet p _ _) = p tokPos (DTParams p _) = p -tokPos (DTInstance p _) = p +tokPos (DTPorts p _) = p tokPos (DTBit p _) = p tokPos (DTConcat p _) = p tokPos (DTStream p _ _ _) = p @@ -571,3 +586,7 @@ tokPos (DTDot p _) = p tokPos (DTSigning p _) = p tokPos (DTLifetime p _) = p tokPos (DTAttr p _) = p + +parseError :: DeclToken -> String -> a +parseError tok msg = error $ show pos ++ ": Parse error: " ++ msg + where pos = tokPos tok diff --git a/test/error/byte_packed.sv b/test/error/byte_packed.sv new file mode 100644 index 0000000..3632315 --- /dev/null +++ b/test/error/byte_packed.sv @@ -0,0 +1,4 @@ +// pattern: unexpected packed range\(s\) applied to byte +module top; + byte [1:0] x; +endmodule diff --git a/test/error/const_const.sv b/test/error/const_const.sv new file mode 100644 index 0000000..84e42ee --- /dev/null +++ b/test/error/const_const.sv @@ -0,0 +1,4 @@ +// pattern: const_const\.sv:3:11: Parse error: duplicate const modifier +module top; + const const logic x = 1'b1; +endmodule diff --git a/test/error/decl_binop_asgn.sv b/test/error/decl_binop_asgn.sv new file mode 100644 index 0000000..fe4a8a5 --- /dev/null +++ b/test/error/decl_binop_asgn.sv @@ -0,0 +1,4 @@ +// pattern: decl_binop_asgn\.sv:3:13: Parse error: unexpected binary assignment operator in declaration +module top; + logic x += 1; +endmodule diff --git a/test/error/decl_delay_asgn.sv b/test/error/decl_delay_asgn.sv new file mode 100644 index 0000000..665f675 --- /dev/null +++ b/test/error/decl_delay_asgn.sv @@ -0,0 +1,4 @@ +// pattern: decl_delay_asgn\.sv:3:13: Parse error: unexpected timing modifier in declaration +module top; + logic x = #1 1; +endmodule diff --git a/test/error/decl_delay_asgn_init.sv b/test/error/decl_delay_asgn_init.sv new file mode 100644 index 0000000..f09aa25 --- /dev/null +++ b/test/error/decl_delay_asgn_init.sv @@ -0,0 +1,6 @@ +// pattern: decl_delay_asgn_init\.sv:4:24: Parse error: unexpected timing modifier in declaration +module top; + initial + for (integer x = #1 1; 1; x++) + $display("Hi!"); +endmodule diff --git a/test/error/decl_delay_asgn_package.sv b/test/error/decl_delay_asgn_package.sv new file mode 100644 index 0000000..195dc56 --- /dev/null +++ b/test/error/decl_delay_asgn_package.sv @@ -0,0 +1,7 @@ +// pattern: decl_delay_asgn_package\.sv:3:13: Parse error: unexpected timing modifier in declaration +package P; + logic x = #1 1; +endpackage +module top; + import P::*; +endmodule diff --git a/test/error/decl_delay_asgn_port.sv b/test/error/decl_delay_asgn_port.sv new file mode 100644 index 0000000..5e9480b --- /dev/null +++ b/test/error/decl_delay_asgn_port.sv @@ -0,0 +1,5 @@ +// pattern: decl_delay_asgn_port\.sv:3:14: Parse error: unexpected timing modifier in declaration +module top( + output x = #1 1 +); +endmodule diff --git a/test/error/decl_non_blocking_asgn.sv b/test/error/decl_non_blocking_asgn.sv new file mode 100644 index 0000000..1ab6b6f --- /dev/null +++ b/test/error/decl_non_blocking_asgn.sv @@ -0,0 +1,4 @@ +// pattern: decl_non_blocking_asgn\.sv:3:13: Parse error: unexpected non-blocking assignment operator in declaration +module top; + logic x <= 1; +endmodule diff --git a/test/error/enum_post_signed.sv b/test/error/enum_post_signed.sv new file mode 100644 index 0000000..efa2c3b --- /dev/null +++ b/test/error/enum_post_signed.sv @@ -0,0 +1,6 @@ +// pattern: unexpected signed applied to enum +module top; + enum { + A, B + } signed x; +endmodule diff --git a/test/error/instantiation_extra_comma.sv b/test/error/instantiation_extra_comma.sv new file mode 100644 index 0000000..112a4e0 --- /dev/null +++ b/test/error/instantiation_extra_comma.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_extra_comma\.sv:3:18: Parse error: expected instantiation before delimiter +module top; + example a(), , b(); +endmodule diff --git a/test/error/instantiation_missing_ports.sv b/test/error/instantiation_missing_ports.sv new file mode 100644 index 0000000..f8aa081 --- /dev/null +++ b/test/error/instantiation_missing_ports.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_missing_ports\.sv:3:14: Parse error: expected port connections before delimiter +module top; + example a, c(); +endmodule diff --git a/test/error/instantiation_no_label.sv b/test/error/instantiation_no_label.sv new file mode 100644 index 0000000..3286949 --- /dev/null +++ b/test/error/instantiation_no_label.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_no_label\.sv:3:13: Parse error: expected instantiation name +module top; + example (); +endmodule diff --git a/test/error/instantiation_no_module.sv b/test/error/instantiation_no_module.sv new file mode 100644 index 0000000..e9ea22d --- /dev/null +++ b/test/error/instantiation_no_module.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_no_module\.sv:3:5: Parse error: expected module or interface name at beginning of instantiation list +module top; + , (); +endmodule diff --git a/test/error/instantiation_not_ports.sv b/test/error/instantiation_not_ports.sv new file mode 100644 index 0000000..ca2c000 --- /dev/null +++ b/test/error/instantiation_not_ports.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_not_ports\.sv:3:15: Parse error: expected port connections +module top; + example a b, c(); +endmodule diff --git a/test/error/instantiation_not_range.sv b/test/error/instantiation_not_range.sv new file mode 100644 index 0000000..83bdf68 --- /dev/null +++ b/test/error/instantiation_not_range.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_not_range\.sv:3:15: Parse error: expected instantiation dimensions +module top; + example a b(); +endmodule diff --git a/test/error/instantiation_trailing_comma.sv b/test/error/instantiation_trailing_comma.sv new file mode 100644 index 0000000..257065a --- /dev/null +++ b/test/error/instantiation_trailing_comma.sv @@ -0,0 +1,4 @@ +// pattern: instantiation_trailing_comma\.sv:3:16: Parse error: unexpected end of instantiation list +module top; + example a(), ; +endmodule diff --git a/test/error/run_on_decl_item.sv b/test/error/run_on_decl_item.sv new file mode 100644 index 0000000..b223e0d --- /dev/null +++ b/test/error/run_on_decl_item.sv @@ -0,0 +1,4 @@ +// pattern: run_on_decl_item.sv:3:16: Parse error: unexpected comma-separated declarations +module top; + integer x, byte y; +endmodule diff --git a/test/error/run_on_decl_stmt.sv b/test/error/run_on_decl_stmt.sv new file mode 100644 index 0000000..073bade --- /dev/null +++ b/test/error/run_on_decl_stmt.sv @@ -0,0 +1,6 @@ +// pattern: run_on_decl_stmt.sv:4:20: Parse error: unexpected comma-separated declarations +module top; + initial begin + integer x, byte y; + end +endmodule diff --git a/test/error/string_packed.sv b/test/error/string_packed.sv new file mode 100644 index 0000000..8a28b28 --- /dev/null +++ b/test/error/string_packed.sv @@ -0,0 +1,4 @@ +// pattern: unexpected packed range\(s\) applied to string +module top; + string [1:0] x; +endmodule diff --git a/test/error/string_signed.sv b/test/error/string_signed.sv new file mode 100644 index 0000000..785d952 --- /dev/null +++ b/test/error/string_signed.sv @@ -0,0 +1,4 @@ +// pattern: unexpected signed applied to string +module top; + string signed x; +endmodule diff --git a/test/error/typeof_packed.sv b/test/error/typeof_packed.sv new file mode 100644 index 0000000..5137c2f --- /dev/null +++ b/test/error/typeof_packed.sv @@ -0,0 +1,5 @@ +// pattern: unexpected packed range\(s\) applied to type\(y\) +module top; + logic y; + var type(y) [1:0] x; +endmodule diff --git a/test/error/typeof_signed.sv b/test/error/typeof_signed.sv new file mode 100644 index 0000000..e959921 --- /dev/null +++ b/test/error/typeof_signed.sv @@ -0,0 +1,5 @@ +// pattern: unexpected signed applied to type\(y\) +module top; + logic y; + var type(y) signed x; +endmodule diff --git a/test/error/var_var.sv b/test/error/var_var.sv new file mode 100644 index 0000000..61a473c --- /dev/null +++ b/test/error/var_var.sv @@ -0,0 +1,4 @@ +// pattern: var_var\.sv:3:9: Parse error: duplicate var modifier +module top; + var var x = 1'b1; +endmodule