(defpackage :toy-lang (:use :cl :clex2 :parse2)) (in-package :toy-lang) (defun parse-foo (input) (parse (input) (:precedence (:right ":=") (:left "+" "-") (:left "*" "/")) (:precedence (:right ":=") (:nonassoc "=" "/=" "<" ">" "<=" ">=") (:left "+" "-") (:left "*" "/")) (expr -> "defun" :identifier "(" (** "," :identifier) ")" expr => `(defun ,$2 ,$4 ,$6) -> "cond" clauses "end" => `(cond ,@$2) -> "begin" (** ";" expr) (? ";") "end" => `(progn ,@$2) -> expr ":=" expr => `(setq ,$1 ,$3) -> expr "=" expr => `(= ,$1 ,$3) -> expr "/=" expr => `(/= ,$1 ,$3) -> expr "<" expr => `(< ,$1 ,$3) -> expr ">" expr => `(> ,$1 ,$3) -> expr "<=" expr => `(<= ,$1 ,$3) -> expr ">=" expr => `(>= ,$1 ,$3) -> expr "+" expr => `(+ ,$1 ,$3) -> expr "-" expr => `(- ,$1 ,$3) -> expr "*" expr => `(* ,$1 ,$3) -> expr "/" expr => `(/ ,$1 ,$3) -> postfix) (postfix -> postfix "(" (** "," expr) ")" => `(,$1 ,@$3) -> postfix "[" (** "," expr) "]" => `(AREF ,$1 ,@$3) -> primary) (primary -> :identifier -> :number) ;; (clauses -> (** ";" clause) (? ";") => $1) (clause -> expr "->" expr => `(,$1 ,$3)) (:number -> "[0-9]+" => (parse-integer $$)) (:identifier -> "[a-zA-Z0-9]+" => (intern (string-upcase $$))) (-> "\\s+"))) ;; (parse-foo "1+3+4") => (+ (+ 1 3) 4) ;; ;; (parse-foo "defun fib(n) ;; cond ;; n < 2 -> n; ;; t -> fib(n-2) + fib(n-1) ;; end") ;; => (DEFUN FIB (N) (COND ((< N 2) N) (T (+ (FIB (- N 2)) (FIB (- N 1))))))