added macros, temporarily removed some error checks

This commit is contained in:
2024-08-14 00:38:29 +03:00
parent 72201d5c8d
commit 3e855bbc23
3 changed files with 146 additions and 129 deletions

View File

@@ -1,8 +1,8 @@
(in-package :cl-forth) (in-package :cl-forth)
(defparameter *psuedo-identifiers* (defparameter *psuedo-identifiers*
'(syscall-1 syscall-2 syscall-3 syscall-4 syscall-5 syscall-6) '(syscall-1 syscall-2 syscall-3 syscall-4 syscall-5 syscall-6 makro son)
"These do not map to operations directly, but are valid to lexer") "These do not map to operations that generate code directly, but are valid to lexer and parser")
(defparameter *identifiers* ()) (defparameter *identifiers* ())
;; '(+ - dump = ise yoksa yap eş push değiş üst rot düş döngü iken < > ;; '(+ - dump = ise yoksa yap eş push değiş üst rot düş döngü iken < >

View File

@@ -6,11 +6,8 @@
(cond ((numberp sym?) :number) (cond ((numberp sym?) :number)
((stringp sym?) :string) ((stringp sym?) :string)
((is-identifier sym?) :identifier) ((is-identifier sym?) :identifier)
(t (t :unknown))))
;; temporary hack... (list sym? :line line :col col :type type))
(return-from make-token
(values (list sym? :line line :col col :error t) t))))))
(values (list sym? :line line :col col :type type) nil))
(defun token-op (token) (defun token-op (token)
(car token)) (car token))
@@ -35,12 +32,10 @@
(for next-char = (peek-char nil line-stream nil nil)) (for next-char = (peek-char nil line-stream nil nil))
(until (null next-char)) (until (null next-char))
(let ((flag t)) (let ((flag t))
(cond ;; ((char= #\. next-char) (cond ((char= #\| next-char)
;; (collect (make-token '|.| line-num col) into tokens)
;; (read-char line-stream))
((char= #\| next-char)
(read-char line-stream) (read-char line-stream)
(collect (make-token :pipe line-num col :identifier) into tokens)) (collect (make-token :pipe line-num col :identifier)
into tokens))
((char= #\Space next-char) (read-char line-stream)) ((char= #\Space next-char) (read-char line-stream))
((char= #\; next-char) ;; and not in string ((char= #\; next-char) ;; and not in string
(finish)) (finish))
@@ -55,113 +50,142 @@
(next-iteration))) (next-iteration)))
(for next-sym in-stream line-stream (for next-sym in-stream line-stream
using #'read-preserving-whitespace) using #'read-preserving-whitespace)
(multiple-value-bind (token err) (collect (make-token next-sym line-num col) into tokens)
(make-token next-sym line-num col) (incf col (length (princ-to-string next-sym)))
(collect token into tokens) (finally (return tokens)))))
(when err ;; skip line on error and continue lexing
(setf has-err t)
(finish))
(incf col (length (princ-to-string next-sym))))
(finally (return (values tokens has-err))))))
(defun lex-file (file-name &optional report-errors) (defun lex-stream (str)
(let ((has-error nil)) (iter (for line = (read-line str nil nil))
(values (until (null line))
(for line-num from 1)
(appending (lex-line line line-num))))
(defun lex-file (file-name)
(with-open-file (str file-name :external-format :utf-8) (with-open-file (str file-name :external-format :utf-8)
(iter outer (lex-stream str)))
(for line = (read-line str nil nil))
(until (null line)) (defun lex-string (string)
(for line-num from 1) (lex-stream (make-string-input-stream string)))
(multiple-value-bind (tokens has-err)
(lex-line line line-num)
(when has-err
(setf has-error t)
(when report-errors
(let ((err-token (find-if (lambda (tok) (find :error tok))
tokens)))
(format t "~5@a ~a~%"
(format nil "~a:" (getf (cdr err-token) :line))
line)
(format t " ~a^~%"
(make-string (getf (cdr err-token) :col)
:initial-element #\Space)))))
(appending tokens))))
has-error)))
(defun lex-string (string &optional report-errors)
(let ((has-error nil))
(values
(let ((str (make-string-input-stream string)))
(iter outer
(for line = (read-line str nil nil))
(until (null line))
(for line-num from 1)
(multiple-value-bind (tokens has-err)
(lex-line line line-num)
(when has-err
(setf has-error t)
(when report-errors
(format t "~a~%" line)
(let ((err-token (find-if (lambda (tok) (find :error tok))
tokens)))
(format t "~a^"
(make-string (getf (cdr err-token) :col)
:initial-element #\Space)))))
(appending tokens))))
has-error)))
;;; PARSER ;;; PARSER
(defun parse-tokens (tokens) (defmacro add-op (token parser)
(iter (with ops = (make-array (length tokens) :fill-pointer 0 `(progn (vector-push-extend ,token (ops ,parser))
(incf (index ,parser))))
(defparameter *makro-defs* (make-hash-table))
(defclass parser ()
((if-stack :initform ()
:accessor if-stack)
(ops :accessor ops)
(tokens :initarg :tokens
:accessor tokens)
(index :initform 0
:accessor index)))
(defun make-parser (tokens)
(let ((parser (make-instance 'parser :tokens tokens)))
(setf (ops parser) (make-array (length tokens) :fill-pointer 0
:adjustable t)) :adjustable t))
(with stack = ()) parser))
(for i from 0)
(for token in tokens) (defmethod peek-token ((parser parser))
(let ((op (token-op token)) (car (tokens parser)))
(op-type (getf (cdr token) :type)))
(cond ((eq :number op-type) (defmethod read-token ((parser parser))
(vector-push-extend `(:push-int ,op) ops)) (pop (tokens parser)))
((eq :string op-type)
(vector-push-extend `(:push-str ,(length op) ,i ,op) (defmethod parse-token ((parser parser) (type (eql :number)))
ops)) (add-op `(:push-int ,(car (read-token parser))) parser))
((string= :ise op)
(push (list :ise i) stack) (defmethod parse-token ((parser parser) (type (eql :string)))
(vector-push-extend (list :ise nil) ops)) (let ((token (read-token parser)))
((string= :yoksa op) (add-op `(:push-str ,(length (car token))
(let ((top (pop stack))) ,(index parser)
(assert (string= :ise (car top))) ,(car token))
(setf (second (aref ops (cadr top))) i) parser)))
(push (list :yoksa i) stack)
(vector-push-extend (list :yoksa nil i) ops))) (defmethod parse-token ((parser parser) (type (eql :identifier)))
((string= :yap op) (let ((token (read-token parser)))
(let ((top (pop stack))) (parse-op parser token (car token))))
(defmethod parse-token ((parser parser) (type (eql :unknown)))
(let* ((token (read-token parser))
(makrodef (gethash (car token) *makro-defs*)))
(if (not (null makrodef))
;; (parser-parse-tokens parser makrodef)
(setf (tokens parser) (append makrodef (tokens parser)))
(error "parse-token: token has unknown identifier: ~a"
(read-token parser)))))
;; (defmethod parser-parse-tokens ((parser parser) tokens)
;; (iter (for makro-op in-vector)
;; (add-op makro-op ops))
;; ())
(defmethod parse-op ((parser parser) token (type (eql :ise)))
(push (list :ise (index parser)) (if-stack parser))
(add-op (list :ise nil) parser))
(defmethod parse-op ((parser parser) token (type (eql :yoksa)))
(let ((top (pop (if-stack parser))))
(assert (and (string= :ise (car top))
(string= :ise (car (aref (ops parser) (cadr top))))))
(setf (second (aref (ops parser) (cadr top))) (index parser))
(push (list :yoksa (index parser)) (if-stack parser))
(add-op (list :yoksa nil (index parser)) parser)))
(defmethod parse-op ((parser parser) token (type (eql :yap)))
(let ((top (pop (if-stack parser))))
(unless (and (find (car top) (list :yoksa :ise :iken))
(find (car (aref (ops parser) (cadr top)))
(list :yoksa :ise :iken)))
(error "yap cannot close ~a" (aref (ops parser) (cadr top))))
(cond ((find (car top) (list :yoksa :ise)) (cond ((find (car top) (list :yoksa :ise))
(setf (second (aref ops (cadr top))) i) (setf (second (aref (ops parser) (cadr top))) (index parser))
(vector-push-extend (list :yap i) ops)) (add-op (list :yap (index parser)) parser))
((string= :iken (car top)) ((string= :iken (car top))
(setf (second (aref ops (cadr top))) i) (setf (second (aref (ops parser) (cadr top))) (index parser))
(vector-push-extend (list :yap i (third top)) ops)) (add-op (list :yap (index parser) (third top)) parser))
(t (error "yap cannot reference: ~a" (car top)))))) (t (error "yap cannot reference: ~a" (car top))))))
((string= :döngü op)
(push (list :döngü i) stack) (defmethod parse-op ((parser parser) token (type (eql :döngü)))
(vector-push-extend (list :döngü i) ops)) (push (list :döngü (index parser)) (if-stack parser))
((string= :iken op) (add-op (list :döngü (index parser)) parser))
(let ((top (pop stack)))
(defmethod parse-op ((parser parser) token (type (eql :iken)))
(let ((top (pop (if-stack parser))))
(assert (string= :döngü (car top))) (assert (string= :döngü (car top)))
(push (list :iken i (cadr top)) stack) (push (list :iken (index parser) (cadr top)) (if-stack parser))
(vector-push-extend (list :iken nil) ops))) (add-op (list :iken nil) parser)))
((search "syscall" (string-downcase (string op)))
(let ((syscall-num (parse-integer (subseq (string op) 8)))) (defmethod parse-op ((parser parser) token (type (eql :makro)))
(vector-push-extend (list :syscall syscall-num) ops))) ;; makro name must be undefined before
(t (vector-push-extend (list op) ops)))) (let ((makro-name-tok (read-token parser)))
(finally (return ops)))) (assert (eq :unknown (getf (cdr makro-name-tok) :type)))
(setf (gethash (car makro-name-tok) *makro-defs*)
(do ((tok (read-token parser)
(read-token parser))
(makrodef ()))
((eq :son (car tok)) (reverse makrodef))
(push tok makrodef)))))
(defmethod parse-op ((parser parser) token type)
(cond ((search "syscall" (string-downcase (string (car token))))
(let ((syscall-num (parse-integer (subseq (string (car token)) 8))))
(add-op (list :syscall syscall-num) parser)))
(t (add-op (list type) parser))))
(defun parse-tokens (tokens)
(let ((parser (make-parser tokens)))
(iter (while (not (null (tokens parser))))
(parse-token parser (getf (cdr (peek-token parser)) :type)))
(ops parser)))
(defun make-program (file-name) (defun make-program (file-name)
(multiple-value-bind (tokens has-error) (parse-tokens (lex-file file-name)))
(lex-file file-name t)
(when has-error
(error "Can't generate program due to error during lexing"))
(parse-tokens tokens)))
;;; COMPILER ;;; COMPILER
;;(defgeneric write-program (target program stream)) ;;(defgeneric write-program (target program stream))

View File

@@ -16,13 +16,6 @@
(:string new-file) (:string new-file)
(:file (pathname new-file))))) (:file (pathname new-file)))))
(defun lex-stream (str)
(iter outer
(for line = (read-line str nil nil))
(until (null line))
(for line-num from 1)
(appending (lex-line line line-num))))
(defun read-form-comment (str) (defun read-form-comment (str)
(read-from-string (read-from-string
(format nil "~{~a~^~%~}" (format nil "~{~a~^~%~}"