changeset 14:f641cfcd5153

Add gather pattern.
author Karn Kallio <kkallio@eka>
date Mon, 25 Jul 2011 20:55:09 -0430
parents 7eea7ff1904c
children 0140b1662994
files src/ur/feed.ur src/ur/feed.urs
diffstat 2 files changed, 57 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/ur/feed.ur	Sun Jul 24 03:36:07 2011 -0430
+++ b/src/ur/feed.ur	Mon Jul 25 20:55:09 2011 -0430
@@ -242,6 +242,55 @@
                                    None => None
                                  | Some (cdata, _) => Some ((pdata, cdata), True)}
 
+con gatherInternal (parent :: Type) (child :: Type) (data :: Type) = option (parent * bool * int * option child * list data)
+
+fun gather [parentI ::: Type] [parent ::: Type] [childI ::: Type] [child ::: Type]
+    (parent : pattern parentI parent) (child : pattern childI child)
+    : pattern (gatherInternal parentI childI child) (parent * list child) =
+    {Initial = None,
+     EnterTag = fn tinfo state =>
+                   case state of
+                       None =>
+                       (case parent.EnterTag tinfo parent.Initial of
+                            None => None
+                          | Some pstate => Some (Some (pstate, False, 1, None, Nil)))
+                     | Some (pstate, return, depth, cstate, clist) =>
+                       let
+                           val cstate' = child.EnterTag tinfo (Option.get child.Initial cstate)
+                       in
+                           case child.Finished (Option.get child.Initial cstate') of
+                               None =>
+                               Some (Some (pstate, return, depth+1, cstate', clist))
+                             | Some (cdata, _) =>
+                               Some (Some (pstate, return, depth+1, None, cdata :: clist))
+                       end,
+     ExitTag = fn state =>
+                  case state of
+                      None => None
+                    | Some (pstate, _, 1, cstate, clist) =>
+                      Some (Some (pstate, True, 1, cstate, clist))
+                    | Some (pstate, return, depth, cstate, clist) =>
+                      let
+                          val cstate' = child.ExitTag (Option.get child.Initial cstate)
+                      in
+                          case child.Finished (Option.get child.Initial cstate') of
+                              None =>
+                              Some (Some (pstate, return, depth-1, cstate', clist))
+                            | Some (cdata, _) =>
+                              Some (Some (pstate, return, depth-1, None, cdata :: clist))
+                      end,
+     Finished = fn state =>
+                   case state of
+                       None => None
+                     | Some (pstate, return, _, _, clist) =>
+                       case parent.Finished pstate of
+                           None => None
+                         | Some (pdata, _) =>
+                           if return then
+                               Some ((pdata, List.rev clist), False)
+                           else
+                               None}
+
 type document = string
 val show_document = _
 
--- a/src/ur/feed.urs	Sun Jul 24 03:36:07 2011 -0430
+++ b/src/ur/feed.urs	Mon Jul 25 20:55:09 2011 -0430
@@ -71,6 +71,14 @@
  * be matched at any depth within the parent's subtree.  Unlike [children],
  * [tree] finds as many subtree matches per parent node as possible. *)
 
+con gatherInternal :: Type -> Type -> Type -> Type
+
+val gather : parentI ::: Type -> parent ::: Type -> childI ::: Type -> child ::: Type
+             -> pattern parentI parent -> pattern childI child
+             -> pattern (gatherInternal parentI childI child) (parent * list child)
+(* A combinator like tree that collects matching subtree patterns into a list rather
+ * than handling them one at a time. *)
+
 type document
 val show_document : show document
 (* Type of uninterpreted XML documents *)