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 }
| "protected" { QProtected }
PackageOrClassItem :: { [PackageItem] }
: DeclTokens(";") { map Decl $ parseDTsAsDecls $1 }
: DeclTokens(";") { map Decl $ parseDTsAsDecl $1 }
| ParameterDecl(";") { map Decl $1 }
| NonDeclPackageItem { $1 }
NonDeclPackageItem :: { [PackageItem] }
......@@ -951,7 +951,7 @@ ExplicitLifetime :: { Lifetime }
| "automatic" { Automatic }
TFItems :: { [Decl] }
: "(" DeclTokens(")") ";" { parseDTsAsDecls $2 }
: "(" DeclTokens(")") ";" { parseDTsAsTFDecls $2 }
| "(" ")" ";" { [] }
| ";" { [] }
......
......@@ -39,7 +39,8 @@ module Language.SystemVerilog.Parser.ParseDecl
( DeclToken (..)
, parseDTsAsPortDecls
, parseDTsAsModuleItems
, parseDTsAsDecls
, parseDTsAsTFDecls
, parseDTsAsDecl
, parseDTsAsDeclOrStmt
, parseDTsAsDeclsOrAsgns
) where
......@@ -95,7 +96,8 @@ parseDTsAsPortDecls' pieces =
Just simpleIdents = maybeSimpleIdents
isSimpleList = maybeSimpleIdents /= Nothing
declarations = propagateDirections Input $ parseDTsAsDecls pieces'
declarations = propagateDirections Input $
parseDTsAsDecls ModeDefault pieces'
pieces' = filter (not . isAttr) pieces
......@@ -231,20 +233,15 @@ parseDTsAsIntantiation l0 delimTok =
asRange tok = parseError tok "expected instantiation dimensions"
-- [PUBLIC]: parser for generic, comma-separated declarations
parseDTsAsDecls :: [DeclToken] -> [Decl]
parseDTsAsDecls tokens =
concatMap finalize $ parseDTsAsComponents tokens
-- [PUBLIC]: parser for comma-separated task/function port declarations
parseDTsAsTFDecls :: [DeclToken] -> [Decl]
parseDTsAsTFDecls = parseDTsAsDecls ModeDefault
-- internal; used for "single" declarations, i.e., declarations appearing
-- [PUBLIC]; used for "single" declarations, i.e., declarations appearing
-- outside of a port list
parseDTsAsDecl :: [DeclToken] -> [Decl]
parseDTsAsDecl tokens =
if null rest
then finalize component
else parseError (head rest) "unexpected token in declaration"
where (component, rest) = parseDTsAsComponent tokens
parseDTsAsDecl = parseDTsAsDecls ModeSingle
-- [PUBLIC]: parser for single block item declarations or assign or arg-less
......@@ -305,20 +302,8 @@ portsToArgs bindings =
parseDTsAsDeclsOrAsgns :: [DeclToken] -> Either [Decl] [(LHS, Expr)]
parseDTsAsDeclsOrAsgns tokens =
if declLookahead tokens
then Left decls
else Right asgns
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
then Left $ parseDTsAsDecls ModeForLoop tokens
else Right $ parseDTsAsAsgns $ shiftIncOrDec tokens
-- internal parser for basic assignment lists
parseDTsAsAsgns :: [DeclToken] -> [(LHS, Expr)]
......@@ -367,60 +352,68 @@ takeLHSStep curr (DTDot _ x : toks) = takeLHSStep (LHSDot curr x ) toks
takeLHSStep lhs toks = (lhs, toks)
-- batches together separate declaration lists
type DeclBase = Identifier -> [Range] -> Expr -> Decl
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
parseDTsAsComponents :: [DeclToken] -> [Component]
parseDTsAsComponents [] = []
parseDTsAsComponents tokens =
component : parseDTsAsComponents tokens'
where (component, tokens') = parseDTsAsComponent tokens
parseDTsAsComponent :: [DeclToken] -> (Component, [DeclToken])
parseDTsAsComponent l0 =
parseDTsAsDecls :: Mode -> [DeclToken] -> [Decl]
parseDTsAsDecls mode l0 =
if l /= Nothing && l /= Just Automatic then
parseError (head l1) "unexpected non-automatic lifetime"
else if dir == Local && isImplicit t && not (isNet $ head l3) then
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
(component, l7)
decls ++ parseDTsAsDecls mode l7
where
initReason
| hasDriveStrength (head l3) = "net with drive strength"
| mode == ModeForLoop = "for loop"
| con = "const"
| otherwise = ""
(dir, l1) = takeDir l0
(l , l2) = takeLifetime l1
(_ct, l3) = takeConst l2
(con, l3) = takeConst l2
(von, l4) = takeVarOrNet l3
(tf , l5) = takeType l4
(rs , l6) = takeRanges l5
(tps, l7) = takeTrips l6
position = tokPos $ head l0
(tps, l7) = takeTrips l6 initReason
pos = tokPos $ head l0
base = von dir t
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 Implicit{} = True
isImplicit _ = False
takeTrips :: [DeclToken] -> ([Triplet], [DeclToken])
takeTrips l0 =
takeTrips :: [DeclToken] -> String -> ([Triplet], [DeclToken])
takeTrips l0 initReason =
(trip : trips, l5)
where
(x, l1) = takeIdent l0
(a, l2) = takeRanges l1
(e, l3) = takeAsgn l2
(e, l3) = takeAsgn l2 initReason
l4 = takeCommaOrEnd l3
trip = (x, a, e)
(trips, l5) =
if tripLookahead l4
then takeTrips l4
then takeTrips l4 initReason
else ([], l4)
tripLookahead :: [DeclToken] -> Bool
......@@ -434,7 +427,7 @@ tripLookahead l0 =
where
(_, l1) = takeIdent l0
(_, l2) = takeRanges l1
(_, l3) = takeAsgn l2
(_, l3) = takeAsgn l2 ""
takeDir :: [DeclToken] -> (Direction, [DeclToken])
takeDir (DTDir _ dir : rest) = (dir , rest)
......@@ -447,13 +440,22 @@ takeLifetime rest = (Nothing, rest)
takeConst :: [DeclToken] -> (Bool, [DeclToken])
takeConst (DTConst{} : DTConst pos : _) =
parseError pos "duplicate const modifier"
takeConst (DTConst pos : DTNet _ typ _ : _) =
parseError pos $ show typ ++ " cannot be const"
takeConst (DTConst{} : tokens) = (True, tokens)
takeConst tokens = (False, tokens)
takeVarOrNet :: [DeclToken] -> (Direction -> Type -> DeclBase, [DeclToken])
takeVarOrNet (DTNet{} : DTVar pos : _) =
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)
takeType :: [DeclToken] -> ([Range] -> Type, [DeclToken])
......@@ -507,8 +509,8 @@ takeRanges tokens =
lo = RawNum 0
hi = RawNum $ fromIntegral $ n - 1
takeAsgn :: [DeclToken] -> (Expr, [DeclToken])
takeAsgn (tok @ (DTAsgn _ op mt e) : rest) =
takeAsgn :: [DeclToken] -> String -> (Expr, [DeclToken])
takeAsgn (DTAsgn pos op mt e : rest) _ =
if op == AsgnOpNonBlocking then
unexpected "non-blocking assignment operator"
else if op /= AsgnOpEq then
......@@ -519,8 +521,11 @@ takeAsgn (tok @ (DTAsgn _ op mt e) : rest) =
(e, rest)
where
unexpected surprise =
parseError tok $ "unexpected " ++ surprise ++ " in declaration"
takeAsgn rest = (Nil, rest)
parseError pos $ "unexpected " ++ surprise ++ " in declaration"
takeAsgn rest "" = (Nil, rest)
takeAsgn toks initReason =
parseError (head toks) $
initReason ++ " declaration is missing initialization"
takeCommaOrEnd :: [DeclToken] -> [DeclToken]
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;
initial
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