Index: trunk/parse3.lisp
===================================================================
--- trunk/parse3.lisp	(revision trunk,12)
+++ trunk/parse3.lisp	(revision trunk,13)
@@ -1,3 +1,3 @@
-(in-package #:dso-parse)
+;(in-package #:dso-parse)
 
 
@@ -29,5 +29,5 @@
   `(if (and (string/= "" ,input) (char= ,char (char ,input 0)))
     (let ((,next (substring ,input :start 1))
-	  (,match '(,char)))
+	  (,match ,char))
       ,then)
     ,else))
@@ -42,5 +42,5 @@
 	  (string= ,string (substring ,input :length ,len)))
       (let ((,next (substring ,input :start ,len))
-	    (,match '(,string)))
+	    (,match ,string))
 	,then)
       ,else)))
@@ -58,5 +58,5 @@
 	(if ,start
 	    (let ((,next (substring ,input :start ,end))
-		  (,match (list (substring ,input :end ,end))))
+		  (,match (substring ,input :end ,end)))
 	      ,then)
 	    ,else)))))
@@ -86,5 +86,5 @@
 	  `(if-matches ,input ,head (,head-next ,head-match)
 	    (if-matches-sequence ,head-next ,tail (,next ,tail-match)
-	      (let ((,match (cons ,head-match ,tail-match)))
+	      (let ((,match (if ,head-match (cons ,head-match ,tail-match) ,tail-match)))
 		,then)
 	      ,else)
@@ -92,5 +92,5 @@
 	(with-gensyms (tail-match)
 	  `(if-matches ,input ,head (,next ,tail-match)
-	    (let ((,match (list ,tail-match)))
+	    (let ((,match (if ,tail-match (list ,tail-match) nil)))
 	      ,then)
 	    ,else)))))
@@ -110,5 +110,5 @@
 	  (if-matches ,next ,rule (,next2 ,match2)
 	    (setf ,next ,next2
-		  ,match (cons ,match2 ,match))
+		  ,match (if ,match2 (cons ,match2 ,match) ,match))
 	    (return-from ,r ,else)))
 	(setf ,match (nreverse ,match))
@@ -131,5 +131,5 @@
 		      (progn
 			(psetf ,next ,next2
-			       ,match (cons ,match2 ,match)
+			       ,match (if ,match2 (cons ,match2 ,match) ,match)
 			       ,i (1+ ,i))
 			t)))))
@@ -152,10 +152,8 @@
       ,else)))
 
-;;; The required and forbidden rules don't quite work right, as using
-;;; a rule like (#\a (& #\b)) will put an extaneous NIL on the end of
-;;; the match tree.
-
 (defmacro if-matches-required (input rule (next match)
 			       &body (&optional (then t) else))
+  "Matches if RULE matches against INPUT, but neither consumes input
+nor contributes to the parse tree."
   `(if-matches ,input ,rule (,(gensym) ,(gensym))
     (let ((,next ,input)
@@ -166,4 +164,6 @@
 (defmacro if-matches-forbidden (input rule (next match)
 				&body (&optional (then t) else))
+  "Matches if RULE doesn't match against INPUT, but neither consumes
+input nor contributes to the parse tree."
   `(if-matches ,input ,rule (,(gensym) ,(gensym))
     ,else
@@ -174,11 +174,43 @@
 (defmacro if-matches-only (input rule (next match)
 			   &body (&optional (then t) else))
-  (with-gensyms (match2)
-    `(if-matches ,input ,rule (,next ,match2)
-      (let ((,match nil))
-	,then)
-      ,else)))
+  "Matches RULE against INPUT and consumes input, but doesn't
+contribute to the parse tree."
+  `(if-matches ,input ,rule (,next ,match)
+    (let ((,match nil))
+      ,then)
+    ,else))
 
 (defmacro if-matches (input rule (next match) &body (&optional (then t) else))
+  "Matches RULE against INPUT.  If the rule is matched, the THEN form
+is executed with NEXT bound to the remainder of the input after
+consumption (if any), and MATCH to the parse tree.
+
+Rules may be defined in a short-hand using this macro, and nested:
+
+* Characters and strings match themselves.
+
+* A regular expression is denoted as (^ regex).
+
+* A sequence is a list of rules (rule1 rule2) that doesn't begin with
+  a reserved mark.
+
+* An ordered choice is (/ rule1 rule2).
+
+* A Kleene-closure is (* rule).  + and ? may be used as well, and all
+  act as in regular expressions.
+
+* Range matching is ({} min max rule).  If MIN is NIL, it is treated
+  as 0.  If MAX is NIL, no limit is placed on matches.
+
+* Requiring a match without consuming or tree-building is done as (&
+  rule).  Forbidding a match likewise as (! rule).
+
+* Matching and consuming without tree-building is (= rule).
+
+If RULE is a symbol, that symbol will be used as the name of a parsing
+function.  The function will be given the input as its only argument,
+and is expected to return (VALUES T NEXT MATCH) (where NEXT refers to
+the remaining, unsonsumed input, and MATCH is the generated tree), or
+NIL otherwise."
   (etypecase rule
     (symbol `(if-matches-parser ,input ,rule (,next ,match) ,then ,else))
