From 4d355a842737f7938d148c53338ce6f3fa055628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Tom=C3=A1s?= Date: Sun, 15 Jun 2025 07:24:38 -0300 Subject: Make many into an iterative parser --- core.lisp | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) (limited to 'core.lisp') diff --git a/core.lisp b/core.lisp index 6e4bf6e..ac06a1f 100644 --- a/core.lisp +++ b/core.lisp @@ -30,37 +30,28 @@ (make-failure :place input :message (format nil "Reached end of input. Expected: ~a." ',predicate))))) -(defparameter end +(defun one-of (first-parser second-parser &rest other-parsers) (lambda (input) - (if (has-data? input) - (make-failure :place input :message "Didn't reach end of input.") - (make-parsing :tree nil :left input)))) - -(defun select-parser (input parsers) - (let ((result (make-failure :place input))) - (dolist (p parsers) - (let ((r (funcall p input))) - (cond ((parsing-p r) - (when (or (not (parsing-p result)) - (> (input-cursor (parsing-left r)) - (input-cursor (parsing-left result)))) - (setf result r))) - ((failure-p r) - (when (failure-p result) - (let ((priority-cmp (- (failure-priority r) - (failure-priority result)))) - (when (or (> priority-cmp 0) - (and (= priority-cmp 0) - (>= (input-cursor (failure-place r)) - (input-cursor (failure-place result))))) - (setf result r))))) - (t (error (format nil "Invalid return value: ~a." r)))))) - result)) - -(defmacro one-of (first-parser second-parser &rest other-parsers) - `(lambda (input) - (select-parser input - (list ,first-parser ,second-parser ,@other-parsers)))) + (let ((parsers `(,first-parser ,second-parser ,@other-parsers)) + (result (make-failure :place input))) + (dolist (p parsers) + (let ((r (funcall p input))) + (cond ((parsing-p r) + (when (or (not (parsing-p result)) + (> (input-cursor (parsing-left r)) + (input-cursor (parsing-left result)))) + (setf result r))) + ((failure-p r) + (when (failure-p result) + (let ((priority-cmp (- (failure-priority r) + (failure-priority result)))) + (when (or (> priority-cmp 0) + (and (= priority-cmp 0) + (>= (input-cursor (failure-place r)) + (input-cursor (failure-place result))))) + (setf result r))))) + (t (error (format nil "Invalid return value: ~a." r)))))) + result))) ;;; TODO: Find a way to be able to use the input without needing to define a name for it. (defmacro comp (bindings &body body) -- cgit v1.2.3