(defpackage tl-rpc (:use :cl :parser-combinators :alexandria)) (in-package :tl-rpc) (defun not-equal (a b) (not (equal a b))) (defun () (named-seq? (<- char (choice (sat (curry #'not-equal #\*)) (except? #\* "*/"))) (string char))) (defun (ml-comment) (named-seq? (<- content (many? (choice (named-seq? (<- inner ml-comment) (concatenate 'string "/*" inner "*/")) ()))) (apply #'concatenate 'string content))) (defun () (named? ml-comment (bracket? "/*" ( ml-comment) "*/"))) (defun () (bracket? "//" (named-seq? (<- comment (many? (sat (curry #'not-equal #\Newline)))) (coerce comment 'string)) #\Newline)) (defun () (sat (rcurry #'member '(#\; #\( #\) #\{ #\} #\. #\# #\: #\[ #\] #\= #\? #\% #\+ #\< #\> #\, #\* #\!)))) (defun () (choice (between? (sat #'(lambda (i) (or (alphanumericp i) (member i '(#\_))))) 1 nil 'string) (quoted? :quote-char #\`))) (defun tokenize (input) (remove :whitespace (parse-string* (many? (choices () () (chook? :whitespace (choices (whitespace?) "---" () ())))) input))) ;; Actual parsers (defun () (choice (digit?) (sat (rcurry #'member '(#\a #\b #\c #\d #\e #\f))))) (defun () (choice (lower?) (upper?))) (defun () (choices () (digit?) #\_)) (defmacro def-string-parser (name arguments &body body) (with-unique-names (inp res peek) (multiple-value-bind (forms declarations docstring) (parse-body body :documentation t) `(defun ,name ,arguments ,docstring ,@declarations #'(lambda (,inp) (typecase ,inp (parser-combinators::end-context (constantly nil)) (parser-combinators::context (let* ((,peek (parser-combinators::context-peek ,inp)) (,res (and (stringp ,peek) (parse-string* ,@forms ,peek :complete t)))) (if ,res (let ((closure-value (make-instance 'parser-possibility :tree ,res :suffix (parser-combinators::context-next ,inp)))) #'(lambda () (when closure-value (prog1 closure-value (setf closure-value nil))))) (constantly nil)))))))))) (defstruct ident ns id name) (def-string-parser () (named-seq? (<- hd (lower?)) (<- tl (many? ())) (make-ident :id (coerce (cons hd tl) 'string)))) (def-string-parser () (named-seq? (<- hd (upper?)) (<- tl (many? ())) (make-ident :id (coerce (cons hd tl) 'string)))) (def-string-parser (&optional len) (between? () len len)) (defun () (named-seq? (<- ns ()) (make-ident :ns (ident-id ns)))) (defun () (named-seq? (<- ns (opt? (seq-list? () #\.))) (<- id ()) (let ((ident (if ns (car ns) id))) (when ns (setf (ident-id ident) (ident-id id))) ident))) (defun () (named-seq? (<- ns (opt? (seq-list? () #\.))) (<- id ()) (let ((ident (if ns (car ns) id))) (when ns (setf (ident-id ident) (ident-id id))) ident))) (defun () (named-seq? (<- id ()) (<- name (opt? (seq-list? #\# ( 8)))) (progn (when name (setf (ident-name id) (second name))) id))) (defun () ()) (defun () (choices () () (named-seq? #\# (make-ident :id "nat")))) (defun () (choice () ())) (def-string-parser () (named-seq? (<- digits (many1? (digit?))) (parse-integer (coerce digits 'string)))) (defun (expr) (named? term (choices (seq-list? #\( expr #\)) (seq-list? () #\< (sepby1? expr #\,) #\>) () () () (seq-list? #\% term)))) (defun () (named? subexpr1 (opt? (named-seq? #\+ (<- hd ()) (<- tl subexpr1) (append (list #\+ hd) (cdr tl)))))) (defun (expr) (named? subexpr (choices (named-seq? (<- hd ()) #\+ (<- tl subexpr) (<- sub ()) (append (list #\+ hd) (list tl) (cdr sub))) (named-seq? (<- term ( expr)) (<- sub ()) (if sub (append (list #\+ term) (cdr sub)) term))))) (defun () (named? expr (many? ( expr)))) (defun () ()) (defun () ()) (defun () ( ())) (defun () ( ())) (defun () (choice () #\_)) (defun () (choice () #\_)) (defun () (named-seq? #\{ (<- vars (many1? ())) #\: (<- excl (opt? #\!)) (<- type-expr ()) #\} (list :opt-args vars excl type-expr))) (defun () ()) (defun () (choices () #\_)) (defun () (seq-list? () (opt? (seq-list? #\. ())) #\?)) (defun () (named? args (choices (seq-list? () #\: (opt? ()) (opt? #\!) ()) (seq-list? (opt? (seq-list? () #\:)) (opt? (seq-list? () #\*)) #\[ (many? args) #\]) (seq-list? #\( (many1? ()) #\: (opt? #\!) () #\)) (seq-list? (opt? #\!) ())))) (defun () (choices (seq-list? () (many? ( ()))) (seq-list? () #\< (sepby1? ( ()) #\,) #\>))) (defun () (named-seq? (<- comb ()) (<- opt-args (many? ())) (<- args (many? ())) #\= (<- result-type ()) #\; (list :comb-decl comb opt-args args result-type))) (defun () (choices (named-seq? (<- type ()) (<- ex (many1? ( ()))) #\; (list :part-type type ex)) (named-seq? (<- type ()) #\< (<- ex (sepby1? () #\,)) #\> (list :part-type type ex)))) (defun () (seq-list? () (many1? ( ())))) (defun () (choices () ())) (defun () (named-seq? (<- comb ()) #\? #\= (<- type ()) #\; (list :builtin-decl comb type))) (defun () (named-seq? (<- type (choices "New" "Final" "Empty")) (<- ind ()) #\; (list :final-decl type ind))) (defun () (choices () () () ())) (defun () (many? ())) (defun () (many? ())) (defstruct tl-program constructors functions) (defun () (named-seq? (<- hd ()) (<- tl (many? (choice (named-seq? "---" "functions" "---" (<- decs ()) (cons :funcs decs)) (named-seq? "---" "types" "---" (<- decs ()) (cons :constrs decs))))) (make-tl-program :constructors (append hd (mapcar #'cdr (remove :funcs tl :key #'car))) :functions (mapcar #'cdr (remove :constrs tl :key #'car)))))