mod ast;
pub mod grammar;

#[cfg(test)]
mod tests {
    use ::grammar::*;
    use ::ast::*;

    fn test_parse(input: &str, expected: TopLevel) {
        match parse_TopLevel(input) {
            Ok(actual) =>
                assert!(expected == actual,
                        "expected = {:?}, actual = {:?}",
                        expected, actual),
            Err(msg) => panic!("Unable to parse {:?}: {:?}",
                               input, msg),
        }
    }

    #[test]
    fn empty_tuple_decl() {
        test_parse(
            "table foo().",
            TopLevel::TableDecl(Clause {
                name: "foo".to_string(),
                data: ClauseData::TupleClause(vec![])
            }));
    }

    #[test]
    fn empty_record_decl() {
        test_parse(
            "table foo{}.",
            TopLevel::TableDecl(Clause {
                name: "foo".to_string(),
                data: ClauseData::RecordClause(vec![])
            }));
    }

    #[test]
    fn tuple_parent_decl() {
        test_parse(
            "table parent(atom, atom).",
            TopLevel::TableDecl(Clause {
                name: "parent".to_string(),
                data: ClauseData::TupleClause(vec![
                    Type::AtomType,
                    Type::AtomType,
                ])
            }));
    }

    #[test]
    fn record_parent_decl() {
        test_parse(
            "table parent { parent: atom, child: atom }.",
            TopLevel::TableDecl(Clause {
                name: "parent".to_string(),
                data: ClauseData::RecordClause(vec![
                    Field { name: "parent".to_string(),
                            value: Type::AtomType },
                    Field { name: "child".to_string(),
                            value: Type::AtomType },
                ])
            }));
    }

    #[test]
    fn insert_tuple_row() {
        test_parse(
            "insert parent (foo, bar).",
            TopLevel::RowDecl(Clause {
                name: "parent".to_string(),
                data: ClauseData::TupleClause(vec![
                    Expr::Atom("foo".to_string()),
                    Expr::Atom("bar".to_string()),
                ])
            }));
    }

    #[test]
    fn insert_record_row() {
        test_parse(
            "insert parent { parent: foo, child: bar }.",
            TopLevel::RowDecl(Clause {
                name: "parent".to_string(),
                data: ClauseData::RecordClause(vec![
                    Field { name: "parent".to_string(),
                            value: Expr::Atom("foo".to_string())},
                    Field { name: "child".to_string(),
                            value: Expr::Atom("bar".to_string())},
                ])
            }));
    }

}
