Commit 3eefd03c by Zachary Snow

additional declaration parsing errors

- general refactoring in decl parsing
- restrict charge strength to trireg
- require const vars to be initialized
- forbid const net declarations
- disallow run-on declarations in packages and classes
parent 11dbf1a4
...@@ -874,7 +874,7 @@ ClassItemQualifier :: { Qualifier } ...@@ -874,7 +874,7 @@ ClassItemQualifier :: { Qualifier }
| "protected" { QProtected } | "protected" { QProtected }
PackageOrClassItem :: { [PackageItem] } PackageOrClassItem :: { [PackageItem] }
: DeclTokens(";") { map Decl $ parseDTsAsDecls $1 } : DeclTokens(";") { map Decl $ parseDTsAsDecl $1 }
| ParameterDecl(";") { map Decl $1 } | ParameterDecl(";") { map Decl $1 }
| NonDeclPackageItem { $1 } | NonDeclPackageItem { $1 }
NonDeclPackageItem :: { [PackageItem] } NonDeclPackageItem :: { [PackageItem] }
...@@ -951,7 +951,7 @@ ExplicitLifetime :: { Lifetime } ...@@ -951,7 +951,7 @@ ExplicitLifetime :: { Lifetime }
| "automatic" { Automatic } | "automatic" { Automatic }
TFItems :: { [Decl] } TFItems :: { [Decl] }
: "(" DeclTokens(")") ";" { parseDTsAsDecls $2 } : "(" DeclTokens(")") ";" { parseDTsAsTFDecls $2 }
| "(" ")" ";" { [] } | "(" ")" ";" { [] }
| ";" { [] } | ";" { [] }
......
...@@ -39,7 +39,8 @@ module Language.SystemVerilog.Parser.ParseDecl ...@@ -39,7 +39,8 @@ module Language.SystemVerilog.Parser.ParseDecl
( DeclToken (..) ( DeclToken (..)
, parseDTsAsPortDecls , parseDTsAsPortDecls
, parseDTsAsModuleItems , parseDTsAsModuleItems
, parseDTsAsDecls , parseDTsAsTFDecls
, parseDTsAsDecl
, parseDTsAsDeclOrStmt , parseDTsAsDeclOrStmt
, parseDTsAsDeclsOrAsgns , parseDTsAsDeclsOrAsgns
) where ) where
...@@ -95,7 +96,8 @@ parseDTsAsPortDecls' pieces = ...@@ -95,7 +96,8 @@ parseDTsAsPortDecls' pieces =
Just simpleIdents = maybeSimpleIdents Just simpleIdents = maybeSimpleIdents
isSimpleList = maybeSimpleIdents /= Nothing isSimpleList = maybeSimpleIdents /= Nothing
declarations = propagateDirections Input $ parseDTsAsDecls pieces' declarations = propagateDirections Input $
parseDTsAsDecls ModeDefault pieces'
pieces' = filter (not . isAttr) pieces pieces' = filter (not . isAttr) pieces
...@@ -231,20 +233,15 @@ parseDTsAsIntantiation l0 delimTok = ...@@ -231,20 +233,15 @@ parseDTsAsIntantiation l0 delimTok =
asRange tok = parseError tok "expected instantiation dimensions" asRange tok = parseError tok "expected instantiation dimensions"
-- [PUBLIC]: parser for generic, comma-separated declarations -- [PUBLIC]: parser for comma-separated task/function port declarations
parseDTsAsDecls :: [DeclToken] -> [Decl] parseDTsAsTFDecls :: [DeclToken] -> [Decl]
parseDTsAsDecls tokens = parseDTsAsTFDecls = parseDTsAsDecls ModeDefault
concatMap finalize $ parseDTsAsComponents tokens
-- internal; used for "single" declarations, i.e., declarations appearing -- [PUBLIC]; used for "single" declarations, i.e., declarations appearing
-- outside of a port list -- outside of a port list
parseDTsAsDecl :: [DeclToken] -> [Decl] parseDTsAsDecl :: [DeclToken] -> [Decl]
parseDTsAsDecl tokens = parseDTsAsDecl = parseDTsAsDecls ModeSingle
if null rest
then finalize component
else parseError (head rest) "unexpected token in declaration"
where (component, rest) = parseDTsAsComponent tokens
-- [PUBLIC]: parser for single block item declarations or assign or arg-less -- [PUBLIC]: parser for single block item declarations or assign or arg-less
...@@ -305,20 +302,8 @@ portsToArgs bindings = ...@@ -305,20 +302,8 @@ portsToArgs bindings =
parseDTsAsDeclsOrAsgns :: [DeclToken] -> Either [Decl] [(LHS, Expr)] parseDTsAsDeclsOrAsgns :: [DeclToken] -> Either [Decl] [(LHS, Expr)]
parseDTsAsDeclsOrAsgns tokens = parseDTsAsDeclsOrAsgns tokens =
if declLookahead tokens if declLookahead tokens
then Left decls then Left $ parseDTsAsDecls ModeForLoop tokens
else Right asgns else Right $ parseDTsAsAsgns $ shiftIncOrDec tokens
where
decls = concatMap finalize components
components = map checkComponent $ parseDTsAsComponents tokens
asgns = parseDTsAsAsgns $ shiftIncOrDec tokens
checkComponent :: Component -> Component
checkComponent (pos, base, trips) =
(pos, base, map (checkTriplet pos) trips)
checkTriplet :: Position -> Triplet -> Triplet
checkTriplet pos (x, _, Nil) =
parseError pos $ "for loop declaration of " ++ show x
++ " is missing initialization"
checkTriplet _ trip = trip
-- internal parser for basic assignment lists -- internal parser for basic assignment lists
parseDTsAsAsgns :: [DeclToken] -> [(LHS, Expr)] parseDTsAsAsgns :: [DeclToken] -> [(LHS, Expr)]
...@@ -367,60 +352,68 @@ takeLHSStep curr (DTDot _ x : toks) = takeLHSStep (LHSDot curr x ) toks ...@@ -367,60 +352,68 @@ takeLHSStep curr (DTDot _ x : toks) = takeLHSStep (LHSDot curr x ) toks
takeLHSStep lhs toks = (lhs, toks) takeLHSStep lhs toks = (lhs, toks)
-- batches together separate declaration lists
type DeclBase = Identifier -> [Range] -> Expr -> Decl type DeclBase = Identifier -> [Range] -> Expr -> Decl
type Triplet = (Identifier, [Range], Expr) type Triplet = (Identifier, [Range], Expr)
type Component = (Position, DeclBase, [Triplet])
finalize :: Component -> [Decl]
finalize (pos, base, trips) =
CommentDecl ("Trace: " ++ show pos) :
map (\(x, a, e) -> base x a e) trips
data Mode
= ModeForLoop -- initialization always required
| ModeSingle -- single declaration (not port list)
| ModeDefault -- comma separated, multiple declarations
deriving Eq
-- internal; entrypoint of the critical portion of our parser -- internal; entrypoint of the critical portion of our parser
parseDTsAsComponents :: [DeclToken] -> [Component] parseDTsAsDecls :: Mode -> [DeclToken] -> [Decl]
parseDTsAsComponents [] = [] parseDTsAsDecls mode l0 =
parseDTsAsComponents tokens =
component : parseDTsAsComponents tokens'
where (component, tokens') = parseDTsAsComponent tokens
parseDTsAsComponent :: [DeclToken] -> (Component, [DeclToken])
parseDTsAsComponent l0 =
if l /= Nothing && l /= Just Automatic then if l /= Nothing && l /= Just Automatic then
parseError (head l1) "unexpected non-automatic lifetime" parseError (head l1) "unexpected non-automatic lifetime"
else if dir == Local && isImplicit t && not (isNet $ head l3) then else if dir == Local && isImplicit t && not (isNet $ head l3) then
parseError (head l0) "declaration missing type information" parseError (head l0) "declaration missing type information"
else if null l7 then
decls
else if mode == ModeSingle then
parseError (head l7) "unexpected token in declaration"
else else
(component, l7) decls ++ parseDTsAsDecls mode l7
where where
initReason
| hasDriveStrength (head l3) = "net with drive strength"
| mode == ModeForLoop = "for loop"
| con = "const"
| otherwise = ""
(dir, l1) = takeDir l0 (dir, l1) = takeDir l0
(l , l2) = takeLifetime l1 (l , l2) = takeLifetime l1
(_ct, l3) = takeConst l2 (con, l3) = takeConst l2
(von, l4) = takeVarOrNet l3 (von, l4) = takeVarOrNet l3
(tf , l5) = takeType l4 (tf , l5) = takeType l4
(rs , l6) = takeRanges l5 (rs , l6) = takeRanges l5
(tps, l7) = takeTrips l6 (tps, l7) = takeTrips l6 initReason
position = tokPos $ head l0 pos = tokPos $ head l0
base = von dir t base = von dir t
t = tf rs t = tf rs
component = (position, base, tps) decls =
CommentDecl ("Trace: " ++ show pos) :
map (\(x, a, e) -> base x a e) tps
hasDriveStrength :: DeclToken -> Bool
hasDriveStrength (DTNet _ _ DriveStrength{}) = True
hasDriveStrength _ = False
isImplicit :: Type -> Bool isImplicit :: Type -> Bool
isImplicit Implicit{} = True isImplicit Implicit{} = True
isImplicit _ = False isImplicit _ = False
takeTrips :: [DeclToken] -> ([Triplet], [DeclToken]) takeTrips :: [DeclToken] -> String -> ([Triplet], [DeclToken])
takeTrips l0 = takeTrips l0 initReason =
(trip : trips, l5) (trip : trips, l5)
where where
(x, l1) = takeIdent l0 (x, l1) = takeIdent l0
(a, l2) = takeRanges l1 (a, l2) = takeRanges l1
(e, l3) = takeAsgn l2 (e, l3) = takeAsgn l2 initReason
l4 = takeCommaOrEnd l3 l4 = takeCommaOrEnd l3
trip = (x, a, e) trip = (x, a, e)
(trips, l5) = (trips, l5) =
if tripLookahead l4 if tripLookahead l4
then takeTrips l4 then takeTrips l4 initReason
else ([], l4) else ([], l4)
tripLookahead :: [DeclToken] -> Bool tripLookahead :: [DeclToken] -> Bool
...@@ -434,7 +427,7 @@ tripLookahead l0 = ...@@ -434,7 +427,7 @@ tripLookahead l0 =
where where
(_, l1) = takeIdent l0 (_, l1) = takeIdent l0
(_, l2) = takeRanges l1 (_, l2) = takeRanges l1
(_, l3) = takeAsgn l2 (_, l3) = takeAsgn l2 ""
takeDir :: [DeclToken] -> (Direction, [DeclToken]) takeDir :: [DeclToken] -> (Direction, [DeclToken])
takeDir (DTDir _ dir : rest) = (dir , rest) takeDir (DTDir _ dir : rest) = (dir , rest)
...@@ -447,13 +440,22 @@ takeLifetime rest = (Nothing, rest) ...@@ -447,13 +440,22 @@ takeLifetime rest = (Nothing, rest)
takeConst :: [DeclToken] -> (Bool, [DeclToken]) takeConst :: [DeclToken] -> (Bool, [DeclToken])
takeConst (DTConst{} : DTConst pos : _) = takeConst (DTConst{} : DTConst pos : _) =
parseError pos "duplicate const modifier" parseError pos "duplicate const modifier"
takeConst (DTConst pos : DTNet _ typ _ : _) =
parseError pos $ show typ ++ " cannot be const"
takeConst (DTConst{} : tokens) = (True, tokens) takeConst (DTConst{} : tokens) = (True, tokens)
takeConst tokens = (False, tokens) takeConst tokens = (False, tokens)
takeVarOrNet :: [DeclToken] -> (Direction -> Type -> DeclBase, [DeclToken]) takeVarOrNet :: [DeclToken] -> (Direction -> Type -> DeclBase, [DeclToken])
takeVarOrNet (DTNet{} : DTVar pos : _) = takeVarOrNet (DTNet{} : DTVar pos : _) =
parseError pos "unexpected var after net type" parseError pos "unexpected var after net type"
takeVarOrNet (DTNet _ n s : tokens) = (\d -> Net d n s, tokens) takeVarOrNet (DTNet pos n s : tokens) =
if n /= TTrireg && isChargeStrength s
then parseError pos "only trireg can have a charge strength"
else (\d -> Net d n s, tokens)
where
isChargeStrength :: Strength -> Bool
isChargeStrength ChargeStrength{} = True
isChargeStrength _ = False
takeVarOrNet tokens = (Variable, tokens) takeVarOrNet tokens = (Variable, tokens)
takeType :: [DeclToken] -> ([Range] -> Type, [DeclToken]) takeType :: [DeclToken] -> ([Range] -> Type, [DeclToken])
...@@ -507,8 +509,8 @@ takeRanges tokens = ...@@ -507,8 +509,8 @@ takeRanges tokens =
lo = RawNum 0 lo = RawNum 0
hi = RawNum $ fromIntegral $ n - 1 hi = RawNum $ fromIntegral $ n - 1
takeAsgn :: [DeclToken] -> (Expr, [DeclToken]) takeAsgn :: [DeclToken] -> String -> (Expr, [DeclToken])
takeAsgn (tok @ (DTAsgn _ op mt e) : rest) = takeAsgn (DTAsgn pos op mt e : rest) _ =
if op == AsgnOpNonBlocking then if op == AsgnOpNonBlocking then
unexpected "non-blocking assignment operator" unexpected "non-blocking assignment operator"
else if op /= AsgnOpEq then else if op /= AsgnOpEq then
...@@ -519,8 +521,11 @@ takeAsgn (tok @ (DTAsgn _ op mt e) : rest) = ...@@ -519,8 +521,11 @@ takeAsgn (tok @ (DTAsgn _ op mt e) : rest) =
(e, rest) (e, rest)
where where
unexpected surprise = unexpected surprise =
parseError tok $ "unexpected " ++ surprise ++ " in declaration" parseError pos $ "unexpected " ++ surprise ++ " in declaration"
takeAsgn rest = (Nil, rest) takeAsgn rest "" = (Nil, rest)
takeAsgn toks initReason =
parseError (head toks) $
initReason ++ " declaration is missing initialization"
takeCommaOrEnd :: [DeclToken] -> [DeclToken] takeCommaOrEnd :: [DeclToken] -> [DeclToken]
takeCommaOrEnd tokens = takeCommaOrEnd tokens =
......
// pattern: charge_strength_non_trireg\.sv:3:5: Parse error: only trireg can have a charge strength
module top;
wire (small) x;
endmodule
// pattern: decl_const_var_uninit\.sv:3:16: Parse error: const declaration is missing initialization
module top;
const var x;
endmodule
// pattern: decl_const_wire\.sv:3:5: Parse error: wire cannot be const
module top;
const wire x = 1;
endmodule
// pattern: drive_strength_uninit\.sv:3:30: Parse error: net with drive strength declaration is missing initialization
module top;
wire (supply0, supply1) x;
endmodule
// pattern: for_loop_decl_no_init\.sv:4:14: Parse error: for loop declaration of "x" is missing initialization // pattern: for_loop_decl_no_init\.sv:4:23: Parse error: for loop declaration is missing initialization
module top; module top;
initial initial
for (integer x; x < 3; x = x + 1) for (integer x; x < 3; x = x + 1)
......
// pattern: run_on_decl_package\.sv:3:16: Parse error: unexpected token in declaration
package P;
integer x, byte y;
localparam Z = 1;
endpackage
module top;
initial $display(P::Z);
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment