diff --git a/cimple.cabal b/cimple.cabal
--- a/cimple.cabal
+++ b/cimple.cabal
@@ -1,5 +1,5 @@
 name:                 cimple
-version:              0.0.8
+version:              0.0.9
 synopsis:             Simple C-like programming language
 homepage:             https://toktok.github.io/
 license:              GPL-3
diff --git a/src/Language/Cimple/Annot.hs b/src/Language/Cimple/Annot.hs
--- a/src/Language/Cimple/Annot.hs
+++ b/src/Language/Cimple/Annot.hs
@@ -1,11 +1,8 @@
-{-# LANGUAGE DeriveFunctor      #-}
-{-# LANGUAGE DeriveGeneric      #-}
-{-# LANGUAGE DeriveTraversable  #-}
-{-# LANGUAGE DerivingVia        #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE StrictData         #-}
-{-# LANGUAGE TypeOperators      #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DerivingVia   #-}
+{-# LANGUAGE StrictData    #-}
+{-# LANGUAGE TypeOperators #-}
 module Language.Cimple.Annot
     ( AnnotF (..)
     , AnnotNode
diff --git a/src/Language/Cimple/Ast.hs b/src/Language/Cimple/Ast.hs
--- a/src/Language/Cimple/Ast.hs
+++ b/src/Language/Cimple/Ast.hs
@@ -1,10 +1,10 @@
-{-# LANGUAGE DeriveFunctor      #-}
-{-# LANGUAGE DeriveGeneric      #-}
-{-# LANGUAGE DeriveTraversable  #-}
-{-# LANGUAGE DerivingVia        #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE StrictData         #-}
+{-# LANGUAGE DeriveFunctor     #-}
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE DerivingVia       #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE Strict            #-}
+{-# LANGUAGE StrictData        #-}
 module Language.Cimple.Ast
     ( AssignOp (..)
     , BinaryOp (..)
@@ -64,10 +64,9 @@
     | Label lexeme a
     -- Variable declarations
     | VLA a lexeme a
-    | VarDecl a a
-    | Declarator a (Maybe a)
-    | DeclSpecVar lexeme
-    | DeclSpecArray a (Maybe a)
+    | VarDeclStmt a (Maybe a)
+    | VarDecl a lexeme [a]
+    | DeclSpecArray (Maybe a)
     -- Expressions
     | InitialiserList [a]
     | UnaryExpr UnaryOp a
@@ -94,7 +93,7 @@
     | TypedefFunction a
     | Struct lexeme [a]
     | Union lexeme [a]
-    | MemberDecl a a (Maybe lexeme)
+    | MemberDecl a (Maybe lexeme)
     | TyConst a
     | TyPointer a
     | TyStruct lexeme
@@ -105,7 +104,6 @@
     | FunctionDecl Scope a
     | FunctionDefn Scope a a
     | FunctionPrototype a lexeme [a]
-    | FunctionParam a a
     | Ellipsis
     -- Constants
     | ConstDecl a lexeme
diff --git a/src/Language/Cimple/Diagnostics.hs b/src/Language/Cimple/Diagnostics.hs
--- a/src/Language/Cimple/Diagnostics.hs
+++ b/src/Language/Cimple/Diagnostics.hs
@@ -1,18 +1,18 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE Strict            #-}
 {-# LANGUAGE StrictData        #-}
 module Language.Cimple.Diagnostics
   ( Diagnostics
-  , Diagnostics'
+  , Diagnostics' -- deprecated
   , HasDiagnostics (..)
   , warn
-  , warn'
+  , warn' -- deprecated
   , sloc
   ) where
 
-import           Control.Monad.State.Lazy   (State)
-import qualified Control.Monad.State.Lazy   as State
-import qualified Control.Monad.State.Strict as SState
+import           Control.Monad.State.Strict (State)
+import qualified Control.Monad.State.Strict as State
 import           Data.Fix                   (foldFix)
 import           Data.Text                  (Text)
 import qualified Data.Text                  as Text
@@ -22,19 +22,13 @@
 
 type DiagnosticsT diags a = State diags a
 type Diagnostics a = DiagnosticsT [Text] a
+type Diagnostics' a = Diagnostics a
 
-warn
+warn, warn'
     :: (HasLocation at, HasDiagnostics diags)
     => FilePath -> at -> Text -> DiagnosticsT diags ()
 warn file l w = State.modify (addDiagnostic $ sloc file l <> ": " <> w)
-
-type DiagnosticsT' diags a = SState.State diags a
-type Diagnostics' a = DiagnosticsT' [Text] a
-
-warn'
-    :: (HasLocation at, HasDiagnostics diags)
-    => FilePath -> at -> Text -> DiagnosticsT' diags ()
-warn' file l w = SState.modify (addDiagnostic $ sloc file l <> ": " <> w)
+warn' = warn
 
 
 class HasDiagnostics a where
diff --git a/src/Language/Cimple/Flatten.hs b/src/Language/Cimple/Flatten.hs
--- a/src/Language/Cimple/Flatten.hs
+++ b/src/Language/Cimple/Flatten.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE Strict                #-}
 {-# LANGUAGE StrictData            #-}
 {-# LANGUAGE TypeOperators         #-}
 module Language.Cimple.Flatten (lexemes) where
diff --git a/src/Language/Cimple/IO.hs b/src/Language/Cimple/IO.hs
--- a/src/Language/Cimple/IO.hs
+++ b/src/Language/Cimple/IO.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE Strict     #-}
 {-# LANGUAGE StrictData #-}
 module Language.Cimple.IO
     ( parseFile
@@ -7,7 +8,7 @@
     ) where
 
 import           Control.Monad                   ((>=>))
-import           Control.Monad.State.Lazy        (State, evalState, get, put)
+import           Control.Monad.State.Strict      (State, evalState, get, put)
 import qualified Data.ByteString                 as BS
 import           Data.Map.Strict                 (Map)
 import qualified Data.Map.Strict                 as Map
diff --git a/src/Language/Cimple/Lexer.x b/src/Language/Cimple/Lexer.x
--- a/src/Language/Cimple/Lexer.x
+++ b/src/Language/Cimple/Lexer.x
@@ -3,6 +3,7 @@
 {-# LANGUAGE DeriveGeneric      #-}
 {-# LANGUAGE DeriveTraversable  #-}
 {-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE StrictData         #-}
 module Language.Cimple.Lexer
     ( Alex
     , AlexPosn (..)
diff --git a/src/Language/Cimple/Parser.y b/src/Language/Cimple/Parser.y
--- a/src/Language/Cimple/Parser.y
+++ b/src/Language/Cimple/Parser.y
@@ -247,12 +247,15 @@
 |	'#ifndef' ID_CONST decls PreprocElse(decls) '#endif'	{ Fix $ PreprocIfndef $2 (reverse $3) $4 }
 
 PreprocIf(decls)
-:	'#if' PreprocConstExpr '\n' decls PreprocElse(decls) '#endif'	{ Fix $ PreprocIf $2 (reverse $4) $5 }
+:	'#if' PreprocConstExpr '\n' decls PreprocElif(decls) '#endif'	{ Fix $ PreprocIf $2 (reverse $4) $5 }
 
+PreprocElif(decls)
+:	PreprocElse(decls)					{ $1 }
+|	'#elif' PreprocConstExpr '\n' decls PreprocElif(decls)	{ Fix $ PreprocElif $2 (reverse $4) $5 }
+
 PreprocElse(decls)
 :								{ Fix $ PreprocElse [] }
 |	'#else' decls						{ Fix $ PreprocElse (reverse $2) }
-|	'#elif' PreprocConstExpr '\n' decls PreprocElse(decls)	{ Fix $ PreprocElif $2 (reverse $4) $5 }
 
 PreprocInclude :: { StringNode }
 PreprocInclude
@@ -287,7 +290,7 @@
 
 MacroParam :: { StringNode }
 MacroParam
-:	IdVar							{ Fix $ MacroParam $1 }
+:	ID_VAR							{ Fix $ MacroParam $1 }
 
 MacroBody :: { StringNode }
 MacroBody
@@ -345,7 +348,7 @@
 ForInit :: { StringNode }
 ForInit
 :	AssignExpr ';'						{ $1 }
-|	VarDecl							{ $1 }
+|	VarDeclStmt						{ $1 }
 
 ForNext :: { StringNode }
 ForNext
@@ -378,34 +381,33 @@
 
 DeclStmt :: { StringNode }
 DeclStmt
-:	VarDecl							{ $1 }
-|	VLA '(' QualType ',' IdVar ',' Expr ')' ';'		{ Fix $ VLA $3 $5 $7 }
+:	VarDeclStmt						{ $1 }
+|	VLA '(' QualType ',' ID_VAR ',' Expr ')' ';'		{ Fix $ VLA $3 $5 $7 }
 
+VarDeclStmt :: { StringNode }
+VarDeclStmt
+:	VarDecl '=' InitialiserExpr ';'				{ Fix $ VarDeclStmt $1 (Just $3) }
+|	VarDecl ';'						{ Fix $ VarDeclStmt $1 Nothing }
+
 VarDecl :: { StringNode }
 VarDecl
-:	QualType Declarator ';'					{ Fix $ VarDecl $1 $2 }
+:	QualType ID_VAR DeclSpecArrays				{ Fix $ VarDecl $1 $2 $3 }
 
-Declarator :: { StringNode }
-Declarator
-:	DeclSpec '=' InitialiserExpr				{ Fix $ Declarator $1 (Just $3) }
-|	DeclSpec						{ Fix $ Declarator $1 Nothing }
+DeclSpecArrays :: { [StringNode] }
+DeclSpecArrays
+:								{ [] }
+|	DeclSpecArrays DeclSpecArray				{ $2 : $1 }
 
+DeclSpecArray :: { StringNode }
+DeclSpecArray
+:	'[' ']'							{ Fix $ DeclSpecArray Nothing }
+|	'[' Expr ']'						{ Fix $ DeclSpecArray (Just $2) }
+
 InitialiserExpr :: { StringNode }
 InitialiserExpr
 :	InitialiserList						{ Fix $ InitialiserList $1 }
 |	Expr							{ $1 }
 
-DeclSpec :: { StringNode }
-DeclSpec
-:	IdVar							{ Fix $ DeclSpecVar $1 }
-|	DeclSpec '[' ']'					{ Fix $ DeclSpecArray $1 Nothing }
-|	DeclSpec '[' Expr ']'					{ Fix $ DeclSpecArray $1 (Just $3) }
-
-IdVar :: { Lexeme String }
-IdVar
-:	ID_VAR							{ $1 }
-|	default							{ $1 }
-
 InitialiserList :: { [StringNode] }
 InitialiserList
 :	'{' Initialisers '}'					{ reverse $2 }
@@ -479,10 +481,10 @@
 
 LhsExpr :: { StringNode }
 LhsExpr
-:	IdVar							{ Fix $ VarExpr $1 }
+:	ID_VAR							{ Fix $ VarExpr $1 }
 |	'*' LhsExpr %prec DEREF					{ Fix $ UnaryExpr UopDeref $2 }
-|	LhsExpr '.' IdVar					{ Fix $ MemberAccess $1 $3 }
-|	LhsExpr '->' IdVar					{ Fix $ PointerAccess $1 $3 }
+|	LhsExpr '.' ID_VAR					{ Fix $ MemberAccess $1 $3 }
+|	LhsExpr '->' ID_VAR					{ Fix $ PointerAccess $1 $3 }
 |	LhsExpr '[' Expr ']'					{ Fix $ ArrayAccess $1 $3 }
 
 Expr :: { StringNode }
@@ -587,8 +589,8 @@
 
 MemberDecl :: { StringNode }
 MemberDecl
-:	QualType DeclSpec ';'					{ Fix $ MemberDecl $1 $2 Nothing }
-|	QualType DeclSpec ':' LIT_INTEGER ';'			{ Fix $ MemberDecl $1 $2 (Just $4) }
+:	VarDecl ';'						{ Fix $ MemberDecl $1 Nothing }
+|	VarDecl ':' LIT_INTEGER ';'				{ Fix $ MemberDecl $1 (Just $3) }
 |	PreprocIfdef(MemberDeclList)				{ $1 }
 |	Comment							{ $1 }
 
@@ -628,8 +630,8 @@
 
 FunctionDeclarator :: { Scope -> StringNode }
 FunctionDeclarator
-:	FunctionPrototype(IdVar) ';'				{ \s -> Fix $ FunctionDecl s $1 }
-|	FunctionPrototype(IdVar) CompoundStmt			{ \s -> Fix $ FunctionDefn s $1 $2 }
+:	FunctionPrototype(ID_VAR) ';'				{ \s -> Fix $ FunctionDecl s $1 }
+|	FunctionPrototype(ID_VAR) CompoundStmt			{ \s -> Fix $ FunctionDefn s $1 $2 }
 
 FunctionPrototype(id)
 :	QualType id FunctionParamList				{ Fix $ FunctionPrototype $1 $2 $3 }
@@ -644,12 +646,8 @@
 
 FunctionParams :: { [StringNode] }
 FunctionParams
-:	FunctionParam						{ [$1] }
-|	FunctionParams ',' FunctionParam			{ $3 : $1 }
-
-FunctionParam :: { StringNode }
-FunctionParam
-:	QualType DeclSpec					{ Fix $ FunctionParam $1 $2 }
+:	VarDecl							{ [$1] }
+|	FunctionParams ',' VarDecl				{ $3 : $1 }
 
 ConstDecl :: { StringNode }
 ConstDecl
diff --git a/src/Language/Cimple/Pretty.hs b/src/Language/Cimple/Pretty.hs
--- a/src/Language/Cimple/Pretty.hs
+++ b/src/Language/Cimple/Pretty.hs
@@ -308,12 +308,9 @@
     CommentExpr   c e -> semi $ fst c <+> fst e
     Ellipsis          -> semi $ text "..."
 
-    Declarator dspec Nothing -> dspec
-    Declarator dspec (Just initr) -> bare $ fst dspec <+> char '=' <+> fst initr
-
-    DeclSpecVar var -> bare $ ppLexeme var
-    DeclSpecArray dspec Nothing     -> bare $ fst dspec <> text "[]"
-    DeclSpecArray dspec (Just dim)  -> bare $ fst dspec <> char '[' <> fst dim <> char ']'
+    VarDecl ty name arrs      -> bare $ fst ty <+> ppLexeme name <> ppSep empty arrs
+    DeclSpecArray Nothing     -> bare $ text "[]"
+    DeclSpecArray (Just dim)  -> bare $ char '[' <> fst dim <> char ']'
 
     TyPointer     ty -> bare $ fst ty <> char '*'
     TyConst       ty -> bare $ fst ty <+> text "const"
@@ -366,7 +363,7 @@
         ppSemiSep decls <>
         fst elseBranch <$>
         text "#endif"
-    PreprocElse [] -> bare $ empty
+    PreprocElse [] -> bare empty
     PreprocElse decls -> bare $
         linebreak <>
         text "#else" <$>
@@ -377,7 +374,6 @@
         fst elseBranch <$>
         text "#endif"
 
-    FunctionParam ty dspec -> bare $ fst ty <+> fst dspec
     FunctionPrototype ty name params -> bare $
         ppFunctionPrototype ty name params
     FunctionDecl scope proto -> semi $
@@ -385,10 +381,10 @@
     FunctionDefn scope proto body -> bare $
         ppScope scope <> fst proto <+> fst body
 
-    MemberDecl ty dspec Nothing -> semi $
-        fst ty <+> fst dspec
-    MemberDecl ty dspec (Just size) -> semi $
-        fst ty <+> fst dspec <+> char ':' <+> ppLexeme size
+    MemberDecl decl Nothing -> semi $
+        fst decl
+    MemberDecl decl (Just size) -> semi $
+        fst decl <+> char ':' <+> ppLexeme size
 
     Struct name members -> semi $
         nest 2 (
@@ -432,22 +428,23 @@
         ) <$> text "} " <> ppLexeme ty
 
     -- Statements
-    VarDecl ty declr   -> semi $ fst ty <+> fst declr
-    Return Nothing     -> semi $ text "return"
-    Return (Just e)    -> semi $ text "return" <+> fst e
-    Continue           -> semi $ text "continue"
-    Break              -> semi $ text "break"
-    IfStmt cond t e    -> bare $ ppIfStmt cond t e
-    ForStmt i c n body -> bare $ ppForStmt i c n body
-    Default s          -> cp s $ text "default:" <+> fst s
-    Label l s          -> bare $ ppLexeme l <> char ':' <$> fst s
-    Goto l             -> semi $ text "goto " <> ppLexeme l
-    Case e s           -> cp s $ text "case " <> fst e <> char ':' <+> fst s
-    WhileStmt c body   -> bare $ ppWhileStmt c body
-    DoWhileStmt body c -> semi $ ppDoWhileStmt body c
-    SwitchStmt c body  -> bare $ ppSwitchStmt c body
-    CompoundStmt body  -> bare $ ppCompoundStmt body
-    VLA ty n sz        -> semi $ ppVLA ty n sz
+    VarDeclStmt decl Nothing      -> semi $ fst decl
+    VarDeclStmt decl (Just initr) -> semi $ fst decl <+> char '=' <+> fst initr
+    Return Nothing                -> semi $ text "return"
+    Return (Just e)               -> semi $ text "return" <+> fst e
+    Continue                      -> semi $ text "continue"
+    Break                         -> semi $ text "break"
+    IfStmt cond t e               -> bare $ ppIfStmt cond t e
+    ForStmt i c n body            -> bare $ ppForStmt i c n body
+    Default s                     -> cp s $ text "default:" <+> fst s
+    Label l s                     -> bare $ ppLexeme l <> char ':' <$> fst s
+    Goto l                        -> semi $ text "goto " <> ppLexeme l
+    Case e s                      -> cp s $ text "case " <> fst e <> char ':' <+> fst s
+    WhileStmt c body              -> bare $ ppWhileStmt c body
+    DoWhileStmt body c            -> semi $ ppDoWhileStmt body c
+    SwitchStmt c body             -> bare $ ppSwitchStmt c body
+    CompoundStmt body             -> bare $ ppCompoundStmt body
+    VLA ty n sz                   -> semi $ ppVLA ty n sz
 
 
 ppTranslationUnit :: [Node (Lexeme Text)] -> Doc
diff --git a/src/Language/Cimple/SemCheck/Includes.hs b/src/Language/Cimple/SemCheck/Includes.hs
--- a/src/Language/Cimple/SemCheck/Includes.hs
+++ b/src/Language/Cimple/SemCheck/Includes.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE Strict     #-}
 {-# LANGUAGE StrictData #-}
 module Language.Cimple.SemCheck.Includes
   ( collectIncludes
diff --git a/src/Language/Cimple/TraverseAst.hs b/src/Language/Cimple/TraverseAst.hs
--- a/src/Language/Cimple/TraverseAst.hs
+++ b/src/Language/Cimple/TraverseAst.hs
@@ -1,10 +1,9 @@
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE LambdaCase            #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns        #-}
 {-# LANGUAGE RecordWildCards       #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE Strict                #-}
 {-# LANGUAGE StrictData            #-}
 {-# LANGUAGE TypeFamilies          #-}
 module Language.Cimple.TraverseAst
@@ -150,11 +149,11 @@
         CompoundStmt stmts ->
             Fix <$> (CompoundStmt <$> recurse stmts)
         Break ->
-            Fix <$> (pure Break)
+            pure $ Fix Break
         Goto label ->
             Fix <$> (Goto <$> recurse label)
         Continue ->
-            Fix <$> (pure Continue)
+            pure $ Fix Continue
         Return value ->
             Fix <$> (Return <$> recurse value)
         SwitchStmt value cases ->
@@ -175,14 +174,12 @@
             Fix <$> (Label <$> recurse label <*> recurse stmt)
         VLA ty name size ->
             Fix <$> (VLA <$> recurse ty <*> recurse name <*> recurse size)
-        VarDecl ty decl ->
-            Fix <$> (VarDecl <$> recurse ty <*> recurse decl)
-        Declarator spec value ->
-            Fix <$> (Declarator <$> recurse spec <*> recurse value)
-        DeclSpecVar name ->
-            Fix <$> (DeclSpecVar <$> recurse name)
-        DeclSpecArray spec size ->
-            Fix <$> (DeclSpecArray <$> recurse spec <*> recurse size)
+        VarDeclStmt decl ini ->
+            Fix <$> (VarDeclStmt <$> recurse decl <*> recurse ini)
+        VarDecl ty name arrs ->
+            Fix <$> (VarDecl <$> recurse ty <*> recurse name <*> recurse arrs)
+        DeclSpecArray size ->
+            Fix <$> (DeclSpecArray <$> recurse size)
         InitialiserList values ->
             Fix <$> (InitialiserList <$> recurse values)
         UnaryExpr op expr ->
@@ -231,8 +228,8 @@
             Fix <$> (Struct <$> recurse name <*> recurse members)
         Union name members ->
             Fix <$> (Union <$> recurse name <*> recurse members)
-        MemberDecl ty decl width ->
-            Fix <$> (MemberDecl <$> recurse ty <*> recurse decl <*> recurse width)
+        MemberDecl decl bits ->
+            Fix <$> (MemberDecl <$> recurse decl <*> recurse bits)
         TyConst ty ->
             Fix <$> (TyConst <$> recurse ty)
         TyPointer ty ->
@@ -251,10 +248,8 @@
             Fix <$> (FunctionDefn scope <$> recurse proto <*> recurse body)
         FunctionPrototype ty name params ->
             Fix <$> (FunctionPrototype <$> recurse ty <*> recurse name <*> recurse params)
-        FunctionParam ty decl ->
-            Fix <$> (FunctionParam <$> recurse ty <*> recurse decl)
         Ellipsis ->
-            Fix <$> (pure Ellipsis)
+            pure $ Fix Ellipsis
         ConstDecl ty name ->
             Fix <$> (ConstDecl <$> recurse ty <*> recurse name)
         ConstDefn scope ty name value ->
diff --git a/src/Language/Cimple/TreeParser.y b/src/Language/Cimple/TreeParser.y
--- a/src/Language/Cimple/TreeParser.y
+++ b/src/Language/Cimple/TreeParser.y
@@ -72,9 +72,8 @@
     label		{ Fix (Label{}) }
     -- Variable declarations
     vLA			{ Fix (VLA{}) }
+    varDeclStmt		{ Fix (VarDecl{}) }
     varDecl		{ Fix (VarDecl{}) }
-    declarator		{ Fix (Declarator{}) }
-    declSpecVar		{ Fix (DeclSpecVar{}) }
     declSpecArray	{ Fix (DeclSpecArray{}) }
     -- Expressions
     initialiserList	{ Fix (InitialiserList{}) }
@@ -113,7 +112,6 @@
     functionDecl	{ Fix (FunctionDecl{}) }
     functionDefn	{ Fix (FunctionDefn{}) }
     functionPrototype	{ Fix (FunctionPrototype{}) }
-    functionParam	{ Fix (FunctionParam{}) }
     ellipsis		{ Fix (Ellipsis) }
     -- Constants
     constDecl		{ Fix (ConstDecl{}) }
diff --git a/test/Language/Cimple/ParserSpec.hs b/test/Language/Cimple/ParserSpec.hs
--- a/test/Language/Cimple/ParserSpec.hs
+++ b/test/Language/Cimple/ParserSpec.hs
@@ -2,96 +2,55 @@
 module Language.Cimple.ParserSpec where
 
 import           Data.Fix           (Fix (..))
-import           Test.Hspec         (Spec, describe, it, shouldBe)
+import           Test.Hspec         (Spec, describe, it, shouldBe,
+                                     shouldSatisfy)
 
-import           Language.Cimple    (AlexPosn (..), CommentStyle (..),
-                                     Lexeme (..), LexemeClass (..),
-                                     LiteralType (..), NodeF (..), Scope (..))
+import           Language.Cimple    (AlexPosn (..), Lexeme (..),
+                                     LexemeClass (..), NodeF (..), Scope (..))
 import           Language.Cimple.IO (parseText)
 
 
+isRight1 :: Either a [b] -> Bool
+isRight1 (Right [_]) = True
+isRight1 _           = False
+
+
 spec :: Spec
 spec = do
     describe "C parsing" $ do
         it "should parse a simple function" $ do
             let ast = parseText "int a(void) { return 3; }"
-            ast `shouldBe` Right
-                [ Fix (FunctionDefn
-                      Global
-                      (Fix (FunctionPrototype
-                          (Fix (TyStd (L (AlexPn 0 1 1) IdStdType "int")))
-                          (L (AlexPn 4 1 5) IdVar "a")
-                          [Fix (TyStd (L (AlexPn 6 1 7) KwVoid "void"))]
-                      ))
-                      (Fix (CompoundStmt [ Fix (Return
-                            (Just
-                                (Fix (LiteralExpr
-                                    Int
-                                    (L (AlexPn 21 1 22) LitInteger "3")
-                                ))
-                            ))
-                      ])))
-                ]
+            ast `shouldSatisfy` isRight1
 
         it "should parse a type declaration" $ do
             let ast = parseText "typedef struct Foo { int x; } Foo;"
-            ast `shouldBe` Right
-                [ Fix (Typedef
-                      (Fix (Struct
-                          (L (AlexPn 15 1 16) IdSueType "Foo")
-                          [ Fix (MemberDecl
-                                (Fix (TyStd (L (AlexPn 21 1 22) IdStdType "int")))
-                                (Fix (DeclSpecVar (L (AlexPn 25 1 26) IdVar "x")))
-                                Nothing)
-                          ]
-                      ))
-                      (L (AlexPn 30 1 31) IdSueType "Foo"))
-                ]
+            ast `shouldSatisfy` isRight1
 
         it "should parse a struct with bit fields" $ do
             let ast = parseText "typedef struct Foo { int x : 123; } Foo;"
-            ast `shouldBe` Right
-                [ Fix (Typedef
-                      (Fix (Struct
-                          (L (AlexPn 15 1 16) IdSueType "Foo")
-                          [ Fix (MemberDecl
-                                (Fix (TyStd (L (AlexPn 21 1 22) IdStdType "int")))
-                                (Fix (DeclSpecVar (L (AlexPn 25 1 26) IdVar "x")))
-                                (Just (L (AlexPn 29 1 30) LitInteger "123")))
-                          ]
-                      ))
-                      (L (AlexPn 36 1 37) IdSueType "Foo"))
-                ]
+            ast `shouldSatisfy` isRight1
 
         it "should parse a comment" $ do
             let ast = parseText "/* hello */"
-            ast `shouldBe` Right
-                [ Fix (Comment Regular
-                          (L (AlexPn 0 1 1) CmtStart "/*")
-                          [L (AlexPn 3 1 4) CmtWord "hello"]
-                          (L (AlexPn 9 1 10) CmtEnd "*/"))
-                ]
+            ast `shouldSatisfy` isRight1
 
         it "supports single declarators" $ do
             let ast = parseText "int main() { int a; }"
             ast `shouldBe` Right
-                [ Fix (FunctionDefn
-                      Global
-                      (Fix (FunctionPrototype
-                          (Fix (TyStd (L (AlexPn 0 1 1) IdStdType "int")))
-                          (L (AlexPn 4 1 5) IdVar "main")
-                          []
-                      ))
-                      (Fix (CompoundStmt [ Fix (VarDecl
-                            (Fix (TyStd (L (AlexPn 13 1 14) IdStdType "int")))
-                            (Fix (Declarator
-                                (Fix (DeclSpecVar (L (AlexPn 17 1 18) IdVar "a")))
-                                Nothing
-                            )))
-                      ])))
+                [ Fix (FunctionDefn Global
+                    (Fix (FunctionPrototype
+                        (Fix (TyStd (L (AlexPn 0 1 1) IdStdType "int")))
+                        (L (AlexPn 4 1 5) IdVar "main")
+                        []))
+                    (Fix (CompoundStmt
+                        [ Fix (VarDeclStmt
+                            (Fix (VarDecl
+                              (Fix (TyStd (L (AlexPn 13 1 14) IdStdType "int")))
+                              (L (AlexPn 17 1 18) IdVar "a")
+                              [])) Nothing)])))
                 ]
 
         it "does not support multiple declarators per declaration" $ do
             let ast = parseText "int main() { int a, b; }"
             ast `shouldBe` Left
-                "1:19: Parse error near PctComma: \",\"; expected one of [\"';'\"]"
+                "1:19: Parse error near PctComma: \",\"; expected one of [\"'='\",\"';'\"]"
