summaryrefslogtreecommitdiff
path: root/src/ast.lisp
diff options
context:
space:
mode:
authorriton <riton@riton.home>2025-07-15 23:45:18 +0300
committerriton <riton@riton.home>2025-07-15 23:45:18 +0300
commita31668c560e211f64501e6b640c823824bd1b100 (patch)
tree58115d027bd876791d1f603432ff1a10465ace6c /src/ast.lisp
parent1c90d9ae3b84f62168337f3c8b1c3854f6198330 (diff)
added parserHEADmaster
Squashed commit of the following: commit 744b32488bfd56193e22d5144c41b8fc0b08705e Author: riton <riton@riton.home> Date: Tue Jul 15 23:27:11 2025 +0300 parse function literals and call expressions commit 46e04e75efeed277b9bd102348e3eebb2d42f762 Author: riton <riton@riton.home> Date: Tue Jul 15 21:17:00 2025 +0300 parse if expressions commit 19bfdae150be2a3fa72f9d030f169355e8a9c035 Author: riton <riton@riton.home> Date: Tue Jul 15 20:21:48 2025 +0300 don't need (emit bool) because generic handles it commit 1b6953a608c18a26244c52fcc455809982d0b616 Author: riton <riton@riton.home> Date: Tue Jul 15 20:13:39 2025 +0300 parse grouped expr, return and let statements commit be480aed29ce5d2ad72677f6ae0abebf16d9ad0e Author: riton <riton@riton.home> Date: Tue Jul 15 19:49:54 2025 +0300 parse infix expressions commit 70859a54c500ace8541f2e4d56c580b3b13824bc Author: riton <riton@riton.home> Date: Tue Jul 15 18:27:38 2025 +0300 parse booleans and prefix expressions commit bb9e53dbfe39fd53e57837795b81e425f9028883 Author: riton <riton@riton.home> Date: Tue Jul 15 17:15:23 2025 +0300 start parser
Diffstat (limited to 'src/ast.lisp')
-rw-r--r--src/ast.lisp207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/ast.lisp b/src/ast.lisp
new file mode 100644
index 0000000..c33de88
--- /dev/null
+++ b/src/ast.lisp
@@ -0,0 +1,207 @@
+(in-package :ast)
+
+(defclass node ()
+ ((token :accessor token
+ :initarg :token
+ :type token)))
+
+(defgeneric stringify (node)
+ (:method ((node node))
+ (with-output-to-string (out)
+ (emit node out))))
+
+(defparameter *indent* 0)
+(defun emit-new-line (stream)
+ (write-char #\Newline stream)
+ (loop :for i :from 0 :below *indent*
+ :do (write-char #\Space stream)))
+
+(defgeneric emit (node stream)
+ (:method ((node node) stream)
+ (write-string (token-literal node) stream)))
+
+(defgeneric token-literal (node)
+ (:method ((node node))
+ (token:literal (token node))))
+
+(defclass statement (node)
+ ())
+
+(defclass expression (node)
+ ())
+
+(defclass program (node)
+ ((statements :accessor statements
+ :initform (make-array 10 :adjustable t :fill-pointer 0))))
+
+(defmethod token-literal ((node program))
+ (if (> (length (statements node)) 0)
+ (token-literal (aref (statements node) 0))
+ ""))
+
+(defmethod emit ((node program) stream)
+ (loop :for stmt :across (statements node)
+ :do (emit stmt stream)))
+
+(defclass identifier (expression)
+ ())
+
+(defclass let-statement (statement)
+ ((name :accessor name
+ :initarg :name
+ :type identifier)
+ (value :accessor value
+ :initarg :value
+ :type expression)))
+
+(defmethod emit ((node let-statement) stream)
+ (write-string (token-literal node) stream)
+ (write-char #\Space stream)
+ (emit (name node) stream)
+ (write-string " = " stream)
+ (emit (value node) stream)
+ (write-char #\; stream)
+ (write-char #\Newline stream))
+
+(defclass return-statement (statement)
+ ((return-value :accessor return-value
+ :initarg :return-value
+ :type expression)))
+
+(defmethod emit ((node return-statement) stream)
+ (write-string (token-literal node) stream)
+ (write-char #\Space stream)
+ (emit (return-value node) stream)
+ (write-char #\; stream)
+ (write-char #\Newline stream))
+
+(defclass integer-literal (expression)
+ ((value :accessor value
+ :initarg :value
+ :type integer)))
+
+(defclass prefix-expression (expression)
+ ((operator :accessor operator
+ :initarg :operator
+ :type token-type)
+ (right :accessor right
+ :initarg :right
+ :type expression)))
+
+(defmethod emit ((node prefix-expression) stream)
+ (write-char #\( stream)
+ (write-string (token-literal node) stream)
+ (emit (right node) stream)
+ (write-char #\) stream))
+
+
+(defclass expression-statement (statement)
+ ((expression :accessor expression
+ :initarg :expression
+ :type expression)))
+
+(defmethod emit ((node expression-statement) stream)
+ (emit (expression node) stream)
+ (write-char #\; stream)
+ (write-char #\Newline stream))
+
+(defclass boolean-expression (expression)
+ ((value :accessor value
+ :initarg :value
+ :type boolean)))
+
+(defclass infix-expression (expression)
+ ((left :accessor left
+ :initarg :left
+ :type expression)
+ (operator :accessor operator
+ :initarg :operator
+ :type token-type)
+ (right :accessor right
+ :initarg :right
+ :type expression)))
+
+(defmethod emit ((node infix-expression) stream)
+ (write-char #\( stream)
+ (emit (left node) stream)
+ (let ((tok (token:as-token (operator node))))
+ (format stream " ~a " (token:literal tok)))
+ (emit (right node) stream)
+ (write-char #\) stream))
+
+(defclass if-expression (expression)
+ ((con :accessor con
+ :initarg :condition
+ :type expression)
+ (consequence :accessor consequence
+ :initarg :consequence
+ :type block-statement)
+ (alternative :accessor alternative
+ :initform nil
+ :initarg :alternative
+ :type (or block-statement null))))
+
+(defmethod emit ((node if-expression) stream)
+ (write-string "if (" stream)
+ (emit (con node) stream)
+ (write-string ") " stream)
+ (emit (consequence node) stream)
+ (unless (null (alternative node))
+ (write-string "else " stream)
+ (emit (alternative node) stream)))
+
+(defclass block-statement (statement)
+ ((statements :accessor statements
+ :initarg statements
+ :initform (make-array 0 :element-type 'statement
+ :adjustable t :fill-pointer 0)
+ :type (vector statement))))
+
+(defmethod emit ((node block-statement) stream)
+ (write-char #\{ stream)
+ (let ((*indent* (+ 4 *indent*)))
+ (emit-new-line stream)
+ (loop :for stmt :across (statements node)
+ :do (emit stmt stream)))
+ (format stream "}"))
+
+(defclass function-literal (expression)
+ ((parameters :accessor parameters
+ :initarg :parameters
+ :initform (make-array 0 :element-type 'identifier
+ :adjustable t :fill-pointer 0)
+ :type (vector identifier))
+ (body :accessor body
+ :initarg :body
+ :type block-statement)))
+
+(defmethod emit ((node function-literal) stream)
+ (write-string (token-literal node) stream)
+ (write-char #\( stream)
+ (loop :for param :across (parameters node)
+ :for i :from 1
+ :do (write-string (token-literal param) stream)
+ (when (< i (length (parameters node)))
+ (write-string ", " stream)))
+ (write-char #\) stream)
+ (emit (body node) stream))
+
+(defclass call-expression (expression)
+ ((fn-expr :accessor fn-expr
+ :initarg :function
+ :type expression)
+ (args :accessor args
+ :initarg :args
+ :initform (make-array 0 :element-type 'expression
+ :adjustable t :fill-pointer 0)
+ :type (vector expression))))
+
+(defmethod emit ((node call-expression) stream)
+ (emit (fn-expr node) stream)
+ (write-char #\( stream)
+ (loop :for arg :across (args node)
+ :for i :from 1
+ :do (emit arg stream)
+ (when (< i (length (args node)))
+ (write-string ", " stream)))
+ (write-char #\) stream))