diff options
author | Juan Manuel Tomás <jtomas1815@gmail.com> | 2025-06-10 13:57:22 -0300 |
---|---|---|
committer | Juan Manuel Tomás <jtomas1815@gmail.com> | 2025-06-10 13:57:22 -0300 |
commit | da008e637b5bff56fed8dfbacc2adabc4bca18b1 (patch) | |
tree | 0d0207034812652c5d7d6c90d45334c918e87e4d | |
parent | dcff69e9d6334c57faa5a690c449f12969a6526f (diff) | |
download | monparser-da008e637b5bff56fed8dfbacc2adabc4bca18b1.tar.gz monparser-da008e637b5bff56fed8dfbacc2adabc4bca18b1.zip |
Add better reporting and new features
Units report expected results on end of input.
Opposite parser helps with the complexity explosion
on unit parsers.
Input and error printing has context.
-rw-r--r-- | core.lisp | 15 | ||||
-rw-r--r-- | extra.lisp | 6 | ||||
-rw-r--r-- | input.lisp | 17 | ||||
-rw-r--r-- | main.lisp | 6 | ||||
-rw-r--r-- | package.lisp | 1 |
5 files changed, 30 insertions, 15 deletions
@@ -1,5 +1,14 @@ (in-package #:monparser) +(defun opposite (p) + (lambda (input &key lazy) + (let ((result (funcall p input))) + (cond ((parsing-p result) + (make-failure :place input :message "Unexpected match.")) + ((failure-p result) + (make-parsing :tree nil :left input)) + (t (error "Unexpected result type.")))))) + (defun fail (message) (lambda (input &key lazy) (make-failure :place input :message message))) @@ -28,7 +37,8 @@ (make-parsing :tree it :left (advance input)) (make-failure :place input :message (format nil "Expected: ~a, Got: ~a" ',predicate it)))) - (make-failure :place input :message "Reached end of input.")))) + (make-failure :place input + :message (format nil "Reached end of input. Expected: ~a" ',predicate))))) (defun lazily-select-parser (input parsers) (let ((intermediate-parsers '()) @@ -46,8 +56,7 @@ (input-cursor (parsing-left result)))) (setf result r))) ((failure-p r) - (when (or (failure-p result) - (= (length parsers) 1)) + (when (failure-p result) (setf result r))) (t (error (format nil "Invalid return value: ~a" r)))))) (if intermediate-parsers @@ -21,10 +21,8 @@ (defun many (p) (comp ((x p) - (xs (if x - (optional (many p)) - (fail "Parsing result is empty.")))) - (cons x xs))) + (xs (optional (many p)))) + (if x (cons x xs) xs))) (defun repeat (p min &optional (max 0)) (if (> min 0) @@ -28,10 +28,17 @@ (values line column))) (defmethod print-object ((obj parser-input) stream) - (let ((context-length 10)) + (let ((context-length 20)) (let ((begin (max (- (input-cursor obj) context-length) 0)) (end (min (+ (input-cursor obj) context-length) (length (input-data obj))))) - (format stream "...~a[1;33m~a[m~a..." - (substitute #\¶ #\Newline (subseq (input-data obj) begin (input-cursor obj))) - (substitute #\¶ #\Newline (subseq (input-data obj) (input-cursor obj) (1+ (input-cursor obj)))) - (substitute #\¶ #\Newline (subseq (input-data obj) (1+ (input-cursor obj)) end)))))) + (when (< 0 begin) + (format stream "...")) + (format stream "~a" + (substitute #\↲ #\Newline (subseq (input-data obj) begin (input-cursor obj)))) + (if (< (input-cursor obj) (length (input-data obj))) + (format stream "[4;33m~a[m~a" + (substitute #\↲ #\Newline (subseq (input-data obj) (input-cursor obj) (1+ (input-cursor obj)))) + (substitute #\↲ #\Newline (subseq (input-data obj) (1+ (input-cursor obj)) end))) + (format stream "[4;33m¬[m")) + (when (< end (length (input-data obj))) + (format stream "..."))))) @@ -6,9 +6,9 @@ :data data)))) (if (parsing-p result) (let ((finished? (not (has-data? (parsing-left result))))) - (values (parsing-tree result) finished?)) - (error (format nil "~a" result))))) + (values result finished?)) + result))) (defmethod print-object ((obj failure) stream) (multiple-value-bind (line column) (line-and-column (failure-place obj)) - (format stream "~a:~a: ~a" line column (failure-message obj)))) + (format stream "~a:~a: ~a~&~a" line column (failure-message obj) (failure-place obj)))) diff --git a/package.lisp b/package.lisp index 2b64c6f..a20934f 100644 --- a/package.lisp +++ b/package.lisp @@ -10,6 +10,7 @@ #:one-of #:unit #:fail + #:opposite #:literal #:nothing #:optional |