diff --git a/src/lib.rs b/src/lib.rs
index 77551c9ee9a0538f2fe5214c1a0cb76fb67e046c..283db99b46e74600b6b4120c6b804ac99be5a2ca 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -69,8 +69,33 @@ key!{KeyEnabled, "enabled"}
 
 #[proc_macro]
 pub fn app(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let app = parse_app(input);
+    //let app = check_app(app);
+    // let v = kv.value.as_ref().right().unwrap();
+    // let tokens = quote!(#v);
+    // panic!("{}", v)
+    quote!().into()
+}
+
+struct App {
+    device: Option<Path>,
+    resources: Vec<ResFields>,
+    init: Option<Path>,
+    idle: Vec<IdleFields>,
+    tasks: Vec<(Ident, Vec<EnumTask>)>,
+}
+
+fn parse_app(input: proc_macro::TokenStream) -> Option<App> {
     let app: Punct<AppFields, Token![,]> = syn::parse(input).unwrap();
 
+    let mut device: Option<Path> = None;
+    let mut resources: Vec<ResFields> = Vec::new();
+    let mut init: Option<Path> = None;
+    let mut idle: Vec<IdleFields> = Vec::new();
+    let mut tasks: Vec<(Ident, Vec<EnumTask>)> = Vec::new();
+
+    let mut ok = true;
+
     for AppFields { key, value } in app.data.into_iter() {
         //println!("k {:?} v {:?}", key, value)
         match key.as_ref() {
@@ -80,6 +105,12 @@ pub fn app(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
                     Some(path) => {
                         println!("path");
                         println!("path {:?}", path);
+                        if device == None {
+                            device = Some(path.clone());
+                        } else {
+                            println!("Field `device` multiple defined.");
+                            ok = false;
+                        }
                     }
                     _ => {
                         println!("device should be a path");
@@ -89,87 +120,120 @@ pub fn app(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
             }
             "resources" => {
                 println!("resources");
-                match value.right() {
-                    Some(ts) => {
-                        println!("ts");
-                        let _res: Punct<ResFields, Token![;]> = syn::parse2(ts).unwrap();
-                    }
-                    _ => {
-                        println!("expected list of resource definitions");
-                        panic!("internal error");
+                if resources.is_empty() {
+                    match value.right() {
+                        Some(ts) => {
+                            println!("ts");
+                            let _res: Punct<ResFields, Token![;]> = syn::parse2(ts).unwrap();
+                        }
+                        _ => {
+                            println!("expected list of resource definitions");
+                            panic!("internal error");
+                        }
                     }
+                } else {
+                    println!("Field `resource` multiple defined.");
+                    ok = false;
                 }
             }
             "init" => {
                 println!("init");
-                match value.right() {
-                    Some(ts) => {
-                        println!("ts");
-                        let _init: Punct<PathField, Token![,]> = syn::parse2(ts).unwrap();
-                    }
-                    _ => {
-                        println!("expected list of resource definitions");
-                        panic!("internal error");
+                if init == None {
+                    match value.right() {
+                        Some(ts) => {
+                            println!("ts");
+                            let _init: Punct<PathField, Token![,]> = syn::parse2(ts).unwrap();
+                        }
+                        _ => {
+                            println!("expected list of resource definitions");
+                            panic!("internal error");
+                        }
                     }
+                } else {
+                    println!("Field `init` multiple defined.");
+                    ok = false;
                 }
             }
             "idle" => {
                 println!("idle");
-                match value.right() {
-                    Some(ts) => {
-                        println!("ts");
-
-                        let idle: Punct<EnumIdle, Token![,]> = syn::parse2(ts).unwrap();
-                        for e in idle.data.iter() {
-                            match e {
-                                EnumIdle::IdlePath(path) => println!("path {:?}", path),
-                                EnumIdle::IdleResources(res) => println!("resources {:?}", res),
+                if idle.is_empty() {
+                    match value.right() {
+                        Some(ts) => {
+                            println!("ts");
+
+                            let idle: Punct<EnumIdle, Token![,]> = syn::parse2(ts).unwrap();
+                            for e in idle.data.iter() {
+                                match e {
+                                    EnumIdle::IdlePath(path) => println!("path {:?}", path),
+                                    EnumIdle::IdleResources(res) => println!("resources {:?}", res),
+                                }
                             }
                         }
+                        _ => {
+                            println!("expected list of idle definitions");
+                            panic!("internal error");
+                        }
                     }
-                    _ => {
-                        println!("expected list of idle definitions");
-                        panic!("internal error");
-                    }
+                } else {
+                    println!("Field `idle` multiple defined.");
+                    ok = false;
                 }
             }
             "tasks" => {
                 println!("tasks");
-                match value.right() {
-                    Some(ts) => {
-                        println!("ts");
-
-                        let tasks: Punct<Tasks, Token![,]> = syn::parse2(ts).unwrap();
-
-                        for Tasks { id, task } in tasks.data.into_iter() {
-                            println!("task {}", id.as_ref());
-
-                            let task: Punct<EnumTask, Token![,]> = syn::parse2(task).unwrap();
-                            for tf in task.data {
-                                match tf {
-                                    EnumTask::TaskPrio(prio) => println!("prio"),
-                                    EnumTask::TaskPath(path) => println!("path"),
-                                    EnumTask::TaskResources(res) => println!("res"),
-                                    EnumTask::TaskEnabled(b) => println!("bool"),
+                if tasks.is_empty() {
+                    match value.right() {
+                        Some(ts) => {
+                            println!("ts");
+
+                            let tasks: Punct<Tasks, Token![,]> = syn::parse2(ts).unwrap();
+
+                            for Tasks { id, task } in tasks.data.into_iter() {
+                                println!("task {}", id.as_ref());
+
+                                let task: Punct<
+                                    EnumTask,
+                                    Token![,],
+                                > = syn::parse2(task).unwrap();
+                                for tf in task.data {
+                                    match tf {
+                                        EnumTask::TaskPrio(prio) => println!("prio"),
+                                        EnumTask::TaskPath(path) => println!("path"),
+                                        EnumTask::TaskResources(res) => println!("res"),
+                                        EnumTask::TaskEnabled(b) => println!("bool"),
+                                    }
                                 }
                             }
                         }
+                        _ => {
+                            println!("expected list of task definitions");
+                            panic!("internal error");
+                        }
                     }
-                    _ => {
-                        println!("expected list of task definitions");
-                        panic!("internal error");
-                    }
+                } else {
+                    println!("Field `tasks` multiple defined.");
+                    ok = false;
                 }
             }
-            _ => (), // unimplemented!(),
+
+            _ => {
+                println!("Illegal field");
+                ok = false;
+            }
         }
-        //        println!("k {:?} ", key);
     }
 
-    // let v = kv.value.as_ref().right().unwrap();
-    // let tokens = quote!(#v);
-    // panic!("{}", v)
-    quote!().into()
+    if ok {
+        Some(App {
+            device,
+            resources,
+            init,
+            idle,
+            tasks,
+        })
+    } else {
+        None
+    }
 }
 
 // Vec[T] (or perhaps not quite)
@@ -352,3 +416,20 @@ impl Synom for Tasks {
         (Tasks{id, task: task.1})
     ));
 }
+
+fn check_app(app: App) -> Option<App> {
+    let mut ok = true;
+
+    // check device
+    if app.device == None {
+        println!("Device field missing");
+        ok = false;
+    }
+
+    // check idle
+    if ok {
+        Some(app)
+    } else {
+        None
+    }
+}