 */
 let stmt_list : Parser<String, String>.Function = 
     fix { stmt_list in
-        let subgraph_id = %("subgraph") ++ ignore(whitespace*) ++ ID|? ++ ignore(whitespace*)
-        let subgraph = subgraph_id ++ %("{") ++ ignore(whitespace*) ++ stmt_list ++ ignore(whitespace*) ++ %("}") 
+        let subgraph_id = %("subgraph") ++ ignore(whitespace*) ++ id|? ++ ignore(whitespace*)
+        let subgraph = subgraph_id|? ++ %("{") ++ ignore(whitespace*) ++ stmt_list ++ ignore(whitespace*) ++ %("}") 
             |> map { "\($0)" }  // Render.
         let stmt = node_stmt | edge_stmt | attr_stmt | id_stmt | subgraph
+//        let a = stmt.flatMap()
             |> map { "\($0)" }  // Render.
         let stmt_list = stmt ++ ignore(whitespace*) ++ (%(";"))|? ++ ignore(whitespace*) ++ stmt_list* 
             |> map { (stmt, rem) in "\(stmt) \(rem.0) \(rem.1)" }

4. an HTML string (<...>).
> FIXME: This only partially implement case (1). Complete cases (2), (3) and (4).
*/
let ID = (lower | upper | digit | %underscore)+ |> map { "".join($0) }
/*:
## _id_stmt_ : ID '=' ID
*/
let id_stmt = ID ++ spaces ++ %equal ++ ignore(whitespace*) ++ ID ++ spaces
    |> map { (id1, rem) in "\(id1) \(rem.0) \(rem.1)" } // Render to string.
/*:
## _a_list_ : id_stmt [ (';' | ',') ] [ _a_list_ ]

        return self.either(ifLeft: {"\($0)"}, ifRight: {"\($0)"})
    }
}

/*:
 Dot Abstract Syntax Tree
 
*/

typealias ID = String

struct Attribute {
    let name: String
    let value: String
}

enum AttributeStatement {
    case Graph([Attribute])
    case Node([Attribute])
    case Edge([Attribute])
}

enum EdgeOp {
    case Directed
    case Undirected
}

enum Statement {
    case Node(id: ID, [Attribute])
//: FIXME: Doesn't support `Source -> Next -> Target` sequences of node and edges.
//: FIXME: `Edge` doesn't support `Subgraph` source and target
    case Edge(source: ID, edgeop: EdgeOp, target: ID)
    case Attr(AttributeStatement)
    case Property(Attribute)
    case Subgraph(id: ID?, stmt_list: [Statement])
}

enum Graph {
    case Directed(id: String?, stmt_list: [Statement])
    case Undirected(id: String?, stmt_list: [Statement])
}

//: Literal Characters and Strings
let space = " "
let underscore = "_"
