85d5b584 |
;;;; php_pre.lisp
(in-package #:php_pre)
(defclass statement ()
((statement-keyword :initarg :keyword :accessor statement-keyword)
(param :initarg :param :accessor param)
(body :initarg :body :accessor body)))
(defmethod print-object ((object statement) s)
(print-unreadable-object (object s :type t :identity t)
(format s "~a (~d expressions)"
(statement-keyword object)
(length (body object)))))
(defun make-statement (type param body)
(make-instance 'statement :keyword type :param param :body body))
(defun .constituent ()
(.is #'alpha-char-p))
(defun .keyword ()
(.first
(.map 'string (.constituent))))
(defun .whitespace-char ()
(.or (.char= #\space)
(.is-not #'graphic-char-p)))
(defun .comment ()
(.or (.first
(.prog2 (.string= "//")
(.word-list)
(.char= #\newline)
(.optional (.whitespace))))
(.first
(.prog2 (.string= "/*")
(.map 'string (.and (.not (.string= "*/"))
(.item)))
(.string= "*/")
(.optional (.whitespace))))))
(defun .whitespace ()
(.first (.map 'string (.whitespace-char))))
(defun .word-terminator ()
(.or (.whitespace-char)
(.is (lambda (x)
(or (char= x #\{)
(char= x #\})
(char= x #\})
(char= x #\;))))))
(defun .array-el ()
(.let* ((first (.first (.map 'string
(.prog2 (.optional (.whitespace))
(.is-not (lambda (it)
(member it '(#\= #\,))))
(.optional (.whitespace))))))
(second (.optional (.progn (.string= "=>")
(.optional (.whitespace))
(.first
(.map 'string
(.is-not #'char= #\,))))))
(divider (.optional (.char= #\,))))
divider
(.identity (cons first second))))
(defun .php-array ()
(.let* ((begin (.char= #\[))
(els (.map 'list (.array-el) :at-least 0))
(end (.char= #\])))
(.identity (list :array begin els end))))
(defun .word ()
(.or (.first (.concatenate 'string
(.string= "'")
(.map 'string (.is-not #'char= #\'))
(.string= "'")))
(.first (.concatenate 'string
(.string= "\"")
(.map 'string (.is-not #'char= #\"))
(.string= "\"")))
(.first (.map 'string (.and (.not (.word-terminator))
(.item))))))
(defun .word-list (&optional (word-parser '.word))
(.map 'list
(.progn (.optional (.whitespace))
(.first (funcall word-parser)))))
(defun .line (&optional (word-parser '.word))
(.prog1 (.word-list)
(.progn (.optional (.whitespace))
(.char= #\;))))
(defun .paren-word ()
(.map 'string (.and (.not (.or (.word-terminator)
(.char= #\( )
(.char= #\) )))
(.item))))
(defun .statement-list ()
(.map 'list (.or (.prog1 (.first (.word-list))
(.optional (.whitespace))
(.char= #\;))
(.progn (.optional (.whitespace))
(.first (.statement))))
:at-least 0))
(defun .statement-start ()
(.let* ((type (.progn (.optional (.whitespace))
(.first (.keyword))))
(param (.optional (.or (.prog2 (.progn (.optional (.whitespace))
(.char= #\( ))
(.word-list)
(.progn (.optional (.whitespace))
(.char= #\) )))
(.word-list))))
(_ (.progn (.whitespace)
(.char= #\{))))
(.identity (cons type param))))
(defun .statement ()
(.let* ((start (.progn (.prog1 (.map 'list
(.progn (.optional (.whitespace))
(.comment))
:at-least 0)
(.optional (.whitespace)))
(.statement-start)))
(statements (.progn (.whitespace)
(.statement-list)))
(_ (.progn (.optional (.whitespace))
(.char= #\}))))
(destructuring-bind (type . param) start
(.identity (make-statement type param statements)))))
(defun slurp (fn)
(with-open-file (s fn)
(let ((result (make-string (file-length s))))
(read-sequence result s)
result)))
(defun .main-parser ()
(.map 'list (.or (.prog1 (.word-list) (.char= #\;))
(.first
(.progn (.optional (.whitespace))
(.statement))))))
|