split3.q 1.62 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
import "xml.q"

type Person = FPerson | MPerson
type MPerson = person[ @gender["M"], Name, Children ]
type FPerson = person[ @gender["F"], Name, Children ]
type Children = children[Person*]
type Name = name[ String ]

type Man = man[  @name[String], Sons,Daughters ]
type Woman = woman[ @name[String], Sons,Daughters ]
type Sons = sons[ Man* ]
type Daughters = daughters[ Woman* ]

fun split_mpersons (val c as Person* ) : Man* = match c with
  val m as ~[ @gender["M"], ~[Any]* ], val rest -> 
    split_m(m), split_mpersons(rest)
| ~[Any], val rest ->
    split_mpersons(rest)
| () -> 
    ()

fun split_fpersons (val c as Person* ) : Woman* = match c with
  val f as ~[ @gender["F"], ~[Any]* ], val rest -> 
    split_f(f), split_fpersons(rest)
| ~[Any], val rest ->
    split_fpersons(rest)
| () -> 
    ()

fun split_children (val c as Person* ) : (Sons,Daughters) =
 let val s = split_mpersons(c) in
 let val d = split_fpersons(c) in
 sons[s], daughters[d]

fun split_m (val p as MPerson) : Man =
 match p with
  ~[ @gender[String], ~[val n], ~[val c] ] ->
   man[ @name[n], split_children(c) ] 

fun split_f (val p as FPerson) : Woman =
 match p with
  ~[ @gender[String], ~[val n], ~[val c] ] ->
   woman[ @name[n], split_children(c) ]

fun split_seq (val p as Person* ) : (Man|Woman)* =
 filter p { 
   ( val f as ~[ @gender["F"], ~[Any], ~[Any] ] { split_f(f) } 
   | val m as ~[ @gender["M"], ~[Any], ~[Any] ] { split_m(m) })* 
 }

let val _ = 
 match argv() with
  val fn as String ->
   ( match load_xml(fn) with
       doc[val p as Person*] -> doc[ split_seq(p) ]
     | Any -> raise("Invalid document") )
 | Any -> raise("Invalid command line")