diff --git a/cimple.cabal b/cimple.cabal
--- a/cimple.cabal
+++ b/cimple.cabal
@@ -1,5 +1,5 @@
 name:          cimple
-version:       0.0.22
+version:       0.0.23
 synopsis:      Simple C-like programming language
 homepage:      https://toktok.github.io/
 license:       GPL-3
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
@@ -119,6 +119,8 @@
     | CallbackDecl lexeme lexeme
     | Ellipsis
     | NonNull [lexeme] [lexeme] a
+    | NonNullParam a
+    | NullableParam a
     -- Constants
     | ConstDecl a lexeme
     | ConstDefn Scope a lexeme a
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
@@ -151,7 +151,11 @@
 <0>		"#define"				{ mkL PpDefine `andBegin` ppSC }
 <0>		"#undef"				{ mkL PpUndef }
 <0>		"#include"				{ mkL PpInclude }
-<0,ppSC>	"bitwise"				{ mkL KwBitwise }
+<0,ppSC>	"tox_"?"bitwise"			{ mkL KwBitwise }
+<0,ppSC>	"tox_"?"force"				{ mkL KwForce }
+<0,ppSC>	"tox_"?"non_null"			{ mkL KwNonNull }
+<0,ppSC>	"tox_"?"nullable"			{ mkL KwNullable }
+<0,ppSC>	"tox_"?"owner"				{ mkL KwOwner }
 <0,ppSC>	"break"					{ mkL KwBreak }
 <0,ppSC>	"case"					{ mkL KwCase }
 <0,ppSC>	"const"					{ mkL KwConst }
@@ -162,12 +166,8 @@
 <0,ppSC>	"enum"					{ mkL KwEnum }
 <0,ppSC>	"extern"				{ mkL KwExtern }
 <0,ppSC>	"for"					{ mkL KwFor }
-<0,ppSC>	"force"					{ mkL KwForce }
 <0,ppSC>	"goto"					{ mkL KwGoto }
 <0,ppSC>	"if"					{ mkL KwIf }
-<0,ppSC>	"non_null"				{ mkL KwNonNull }
-<0,ppSC>	"nullable"				{ mkL KwNullable }
-<0,ppSC>	"owner"					{ mkL KwOwner }
 <0,ppSC>	"return"				{ mkL KwReturn }
 <0,ppSC>	"sizeof"				{ mkL KwSizeof }
 <0,ppSC>	"static"				{ mkL KwStatic }
@@ -200,7 +200,7 @@
 <0,ppSC>	[A-Z][A-Z0-9_]{1,2}			{ mkL IdSueType }
 <0,ppSC>	_*[A-Z][A-Z0-9_]*			{ mkL IdConst }
 <0,ppSC>	[A-Z][A-Za-z0-9_]*[a-z][A-Za-z0-9_]*	{ mkL IdSueType }
-<0,ppSC>	"cmp_"[a-z][a-z0-9_]*_[stu]		{ mkL IdSueType }
+<0,ppSC>	"cmp_"[a-z][a-z0-9_]*_[suet]		{ mkL IdSueType }
 <0,ppSC>	[a-z][a-z0-9_]*_t			{ mkL IdStdType }
 <0,ppSC>	[a-z][a-z0-9_]*_cb			{ mkL IdFuncType }
 <0,ppSC>	"cmp_"("reader"|"writer"|"skipper")	{ mkL IdFuncType }
diff --git a/src/Language/Cimple/MapAst.hs b/src/Language/Cimple/MapAst.hs
--- a/src/Language/Cimple/MapAst.hs
+++ b/src/Language/Cimple/MapAst.hs
@@ -357,6 +357,10 @@
             Fix <$> (CallbackDecl <$> recurse ty <*> recurse name)
         NonNull nonnull nullable f ->
             Fix <$> (NonNull <$> recurse nonnull <*> recurse nullable <*> recurse f)
+        NonNullParam p ->
+            Fix <$> (NonNullParam <$> recurse p)
+        NullableParam p ->
+            Fix <$> (NullableParam <$> recurse p)
         Ellipsis ->
             pure $ Fix Ellipsis
         ConstDecl ty name ->
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
@@ -659,13 +659,14 @@
 MemberDecl
 :	VarDecl ';'						{ Fix $ MemberDecl $1 Nothing }
 |	VarDecl ':' LIT_INTEGER ';'				{ Fix $ MemberDecl $1 (Just $3) }
-|	PreprocIfdef(MemberDeclList)				{ $1 }
+|	PreprocIfdef(MemberDecls)				{ $1 }
 |	Comment							{ $1 }
 
 TypedefDecl :: { NonTerm }
 TypedefDecl
 :	typedef QualType ID_SUE_TYPE ';'			{ Fix $ Typedef $2 $3 }
 |	typedef FunctionPrototype(ID_FUNC_TYPE) ';'		{ Fix $ TypedefFunction $2 }
+|	struct ID_SUE_TYPE ';'					{ Fix $ Typedef (Fix (TyStruct $2)) $2 }
 
 QualType :: { NonTerm }
 QualType
@@ -757,6 +758,8 @@
 FunctionParam :: { NonTerm }
 FunctionParam
 :	VarDecl							{ $1 }
+|	non_null '(' ')' VarDecl			{ Fix $ NonNullParam $4 }
+|	nullable '(' ')' VarDecl			{ Fix $ NullableParam $4 }
 
 ConstDecl :: { NonTerm }
 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
@@ -549,6 +549,11 @@
     NonNull nonnull nullable f ->
         kwNonNull <> ppIntList nonnull <+> kwNullable <> ppIntList nullable <$$> f
 
+    NonNullParam p ->
+        kwNonNull <> pretty "()" <+> p
+    NullableParam p ->
+        kwNullable <> pretty "()" <+> p
+
     -- Statements
     VarDeclStmt decl Nothing      -> decl <> semi
     VarDeclStmt decl (Just initr) -> decl <+> equals <+> initr <> semi
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
@@ -471,6 +471,10 @@
             _ <- recurse nullable
             _ <- recurse f
             pure ()
+        NonNullParam p ->
+            recurse p
+        NullableParam p ->
+            recurse p
         ConstDecl ty name -> do
             _ <- recurse ty
             _ <- recurse name
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
@@ -22,6 +22,18 @@
             let ast = parseText "int a(void) { return 3; }"
             ast `shouldSatisfy` isRight1
 
+        it "should parse non_null annotations" $ do
+            let ast = parseText "non_null() int a(char *p);"
+            ast `shouldSatisfy` isRight1
+
+        it "should parse non_null and nullable annotations" $ do
+            let ast = parseText "non_null(2) nullable(1) int a(char *p, int *q);"
+            ast `shouldSatisfy` isRight1
+
+        it "should parse per-param non_null and nullable annotations" $ do
+            let ast = parseText "int a(non_null() char *p, non_null() int *q);"
+            ast `shouldSatisfy` isRight1
+
         it "should parse a type declaration" $ do
             let ast = parseText "typedef struct Foo { int x; } Foo;"
             ast `shouldSatisfy` isRight1
diff --git a/test/Language/Cimple/PrettySpec.hs b/test/Language/Cimple/PrettySpec.hs
--- a/test/Language/Cimple/PrettySpec.hs
+++ b/test/Language/Cimple/PrettySpec.hs
@@ -89,6 +89,27 @@
                 , "} Foo;"
                 ]
 
+        it "pretty-prints ifdef'd struct members in the correct order" $
+            compact (unlines
+                [ "typedef struct Foo {"
+                , "  int32_t a;"
+                , "#ifdef ENABLE_XY"
+                , "  int32_t x;"
+                , "  int32_t y;"
+                , "#endif /* ENABLE_XY */"
+                , "} Foo;"
+                ])
+            `shouldBe` unlines
+                [ "typedef struct Foo {"
+                , "int32_t a;"
+                , "#ifdef ENABLE_XY"
+                , "int32_t x;"
+                , ""
+                , "int32_t y;"
+                , "#endif  /* ENABLE_XY */"
+                , "} Foo;"
+                ]
+
         it "respects newlines at end of comments" $ do
             compact "/* foo bar */" `shouldBe` "/* foo bar */\n"
             compact "/* foo bar\n */" `shouldBe` "/* foo bar\n */\n"
