Documentation
use std::collections::HashMap;
use sgf_node::*;

#[export]
collection -> SgfCollection
    = gs:game_tree+ {
        SgfCollection::new(gs)
    }

game_tree -> SgfNode
    = [ \t\r\n\v]* "(" s:sequence gs:game_tree* ")" [ \t\r\n\v]* {
        let mut s = s;
        let mut gs = gs;
            {
            let mut l = s.leaf_mut();
            l.children.append(&mut gs);
        }
        s
    }

sequence -> SgfNode
    = [ \t\r\n\v]* ns:node+ [ \t\r\n\v]* {
        let mut ns = ns;
        ns.reverse();
        let mut i = ns.into_iter();
        let mut l = i.next().unwrap();
        for mut n in i {
            n.children.push(l);
            l = n;
        }
        l
    }

node -> SgfNode
    = [ \t\r\n\v]* ";" props:property* [ \t\r\n\v]* {?
        let mut h = HashMap::new();
        let mut duplicated = false;
        for e in props {
            if h.contains_key(&e.0) {
                duplicated = true;
                break
            }
            h.insert(e.0, e.1);
        }
        if duplicated {
            Err("duplicated properties")
        } else {
            Ok(SgfNode::new(h))
        }
    }

property -> (String, Vec<String>)
    = [ \t\r\n\v]* i:prop_ident vs:prop_value+ [ \t\r\n\v]* {
        (i, vs)
    }

prop_ident -> String
    = match_str:$([A-Z]+) {
        match_str.to_string()
    }

prop_value -> String
    = [ \t\r\n\v]* "[" match_str:$(("\\]" / [^\]])*) "]" [ \t\r\n\v]* {
        match_str.to_string()
    }