; FP interpreter/compiler
; Copyright (c) 1982 Scott B. Baden
; Copyright (c) 1982 Regents of the University of California.
; All rights reserved. The Berkeley software License Agreement
; specifies the terms and conditions for redistribution.
(setq SCCS-scanner.l "@(#)scanner.l 5.1 (Berkeley) 5/31/85")
; get the next token: names, numbers, special symbols
; this is the top-level scanner section.
(declare (localf alpha$ numer$ get_num$ get_nam$ namtyp two_kind))
(do ((char_num (Getc) (Getc))
((eq char_num -1) (*throw 'parse$err 'eof$$)) ; eof control D
; if the first character is a letter then the next token is a name
(cond ((alpha$ char_num) (return (namtyp char_num)))
; if the first character is a number then next token is a number
((numer$ char_num) (return
((memq char_num #.whiteSpace))
((eq char_num 35) (clr_teol)) ; # is the comment char.
(t (setq scan_fn (get char_set (ascii char_num)))
(*throw 'parse$err `(err$$ bad_char ,(ascii char_num))))
(t (return (funcall scan_fn))))))))
; these are the scanner action functions
(defun (scan$asc |[|) nil
(defun (scan$asc |]|) nil
(defun (scan$asc |{|) nil
(defun (scan$asc |}|) nil
(defun (scan$asc |(|) nil
(defun (scan$asc |)|) nil
(defun (scan$asc |@|) nil
(defun (scan$asc |!|) nil
(defun (scan$asc |\||) nil ; tree insert
(defun (scan$asc |&|) nil
(defun (scan$asc |;|) nil
(defun (scan$asc |:|) nil
(defun (scan$asc |,|) nil
(defun (scan$asc |+|) nil ; plus or pos select
(cond ((numer$ (peekc)) (list 'select$$ (get_num$ #/0)))
(defun (scan$asc |*|) nil
(defun (scan$asc |/|) nil
(defun (scan$asc |=|) nil
; either a 1 or 2-char token
(defun (scan$asc |-|) nil
(cond ((numer$ (peekc)) ; subtract or neg select
(list 'select$$ (minus (get_num$ #/0))))
(t (two_kind #/> 'arrow$$ '(builtin$$ sub))))) ; or arrow
(defun (scan$asc |>|) nil ; > or >=
(two_kind #/= '(builtin$$ ge) '(builtin$$ gt)))
(defun (scan$asc |<|) nil ; < or <=
(two_kind #/= '(builtin$$ le) '(builtin$$ lt)))
(defun (scan$asc |~|) nil ; ~= or error
(two_kind #/= '(builtin$$ ne)
`(badtkn$$ ,(ascii char_num))))
; if a % then read in the next constant (object)
(defun (scan$asc |%|) nil
(list 'constant$$ (list 'quote v))))
; these are the support routines
; routine to tell if a character is a letter
(or (and (greaterp x 96) (lessp x 123))
(and (greaterp x 64) (lessp x 91))))
; routine to tell if character is a number
(and (greaterp x 47) (lessp x 58)))
; routine to read in a number
(defun get_num$ (first_c)
(do ((num$ (diff first_c 48 ))
((memq c num_delim$) (return num$))
(cond ((not (numer$ c)) (*throw 'parse$err '(err$$ badnum)))
(t (setq num$ (plus (times 10 num$) (diff (Getc) 48 )))))))
; routine to read in a name
(defun get_nam$ (first_c)
(do ((name$ (cons first_c nil))
((not (or (numer$ c) (alpha$ c) (eq #/_ c))) (implode (nreverse name$)))
(setq name$ (cons (Getc) name$))))
; routine to determine whether the name represents a builtin
(cond ((eq x 'while) 'while$$)
(cond ((null (memq x builtins)) 'defined$$)
; read in a lisp sequence
(If (not (memq (car in_buf) '(< % :)))
then (setq in_buf (cons 32 in_buf)))
(setq in_buf (cons #/< in_buf))
(cond ((and ptport (null infile)) (patom '< ptport)))
(let ((readtable newreadtable))
(do ((xx (*catch 'parse$err (get_obj t)) (*catch 'parse$err (get_obj t)))
((eq xx '>) (nreverse result))
(cond ((find 'err$$ xx) (*throw 'parse$err `(err$$ bad_obj ,xx))))
(t (setq result (cons xx result)))))))
; peek ahead to see if the single character token in really
; a double character token
(defun two_kind (char2 dbl_nm sing_nm)
(cond ((eq (peekc) char2)
(setq dummy (Getc)) (return dbl_nm)))
; check if any ? (bottom) in sequence
(cond ((atom x) (eq x '?))
(t (or (chk_bot$ (car x)) (chk_bot$ (cdr x))))))
; get an object and check for bottom (?) or errors (reserved symbols)
(defun get_obj (read_seq)
(let ((readtable newreadtable))
(cond ((chk_bot$ x) (return '?))
((and (atom x) (memq x '(|,| |>|)))
(cond (read_seq (return x))
(t (*throw 'parse$err '(err$$ bad_comma)))))
((and (atom x) (memq x '(+ -)))
(let ((z (*catch 'parse$err (get_obj nil))))
(*throw 'parse$err `(err$$ bad_num ,z)))
(*throw 'parse$err `(err$$ bad_num ,z)))
(t (cond ((eq x '+) (return z))
(t (return (diff z))))))))
(t (*throw 'parse$err `(err$$ bad_num ,x)))))
((and (symbolp x) (numer$ (car (exploden x))))
(*throw 'parse$err `(err$$ bad_num ,x)))
((and (atom x) (memq x e_rsrvd)) (*throw 'parse$err `(err$$ bad_obj ,x)))
then (let ((ob (exploden c)))
(If (and (not (= (car in_buf) #/<))
(not (= (car in_buf) #/>))
then (setq in_buf (cons (car OB) in_buf))
else (setq in_buf (append (reverse OB) in_buf))))))
(cond ((not in_def) (setq in_buf nil)))
(cond ((and (not infile) (not in_def))