summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md21
-rw-r--r--parser.lisp16
2 files changed, 31 insertions, 6 deletions
diff --git a/README.md b/README.md
index 24b5ea6..6705ffd 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,24 @@ The goal is to have a good enough parser generator for use in my other personal
# The type of parsers
Parsers are lambdas that receive some *input* and return either a *parsing* or a *failure*.
+
+A *parsing* denotes a successful execution of the parser on the given input.
+
+Failures can be either *normal-failure* or *critical-failure*.
+
+The distinction of failure types allows to discern between an input that needs to be
+parsed with another parser, and a syntax error.
+
+## Interaction with parser control flow
+
+### Choice (either)
+
+- parsing -> exit
+- normal-failure -> continue
+- critical-failure -> exit
+
+### Sequence (comp)
+
+- parsing -> continue
+- normal-failure -> exit
+- critical-failure -> exit
diff --git a/parser.lisp b/parser.lisp
index 30c68fd..04d3f2b 100644
--- a/parser.lisp
+++ b/parser.lisp
@@ -14,6 +14,10 @@
place
message)
+(defstruct (normal-failure (:include failure)))
+
+(defstruct (critical-failure (:include failure)))
+
(defun new (tree)
(lambda (input)
(make-parsing :tree tree :left input)))
@@ -27,16 +31,16 @@
(defun fail (&optional (message "Unknown error."))
(lambda (input)
- (make-failure :place input :message message)))
+ (make-critical-failure :place input :message message)))
(defun either (first-parser &rest other-parsers)
(lambda (input)
(labels ((either-rec (body)
(if (cdr body)
(let ((r (funcall (car body) input)))
- (if (parsing-p r)
- r
- (either-rec (cdr body))))
+ (if (normal-failure-p r)
+ (either-rec (cdr body))
+ r))
(funcall (car body) input))))
(either-rec (cons first-parser other-parsers)))))
@@ -46,8 +50,8 @@
(let ((c (input::element input)))
(if (funcall predicate c)
(make-parsing :tree c :left (input::advance input))
- (make-failure :place input :message "Predicate not satisfied.")))
- (make-failure :place input :message "Reached end of input."))))
+ (make-normal-failure :place input :message "Predicate not satisfied.")))
+ (make-normal-failure :place input :message "Reached end of input."))))
(defmacro comp (bindings &body body)
(if (null bindings)