;;; basic.el -- BASIC Compiler/Interpreter ;; ;;; Copyright (C) 2008 Kyle W T Sherman ;; ;; Author: Kyle W T Sherman <kylewsherman at gmail dot com> ;; Created: 2008-03-29 ;; Version: 0.1 ;; Keywords: basic compiler interpreter mode ;; ;;; Commentary: ;; ;; Provides `basic-mode' function that implements syntax highlighting ;; ;;; Installation: ;; ;; Put `basic.el' where you keep your elisp files and add something like ;; the following to your .emacs file: ;; ;; (require 'basic) ;; ;;; Usage: ;; ;; ;; Example: ;; ;; (basic ... ??? ;;; Code: ;; cl (require 'cl) ;;; basic-mode: ;; font lock settings ;; regular expression keyword generator (defmacro basic-keywords-re (&rest keywords) "Compile-time generation of regexp matching any one of KEYWORDS." `(eval-when-compile (concat "\\b" (regexp-opt ',keywords t) "\\b"))) (defvar basic-mode-font-lock-keywords nil "BASIC keywords used by font-lock.") ;; types (let ((basic-types (basic-keywords-re ;; "bigint" "binary" "bit" "blob" "char" "character" "date" "datetime" "dec" ;; "decimal" "double" "enum" "float" "float4" "float8" "int" "int1" "int2" "int3" ;; "int4" "int8" "integer" "long" "longblob" "longtext" "mediumblob" "mediumint" ;; "mediumtext" "numeric" "precision" "real" "smallint" "time" "timestamp" ;; "tinyblob" "tinyint" "tinytext" "unsigned" "varbinary" "varchar" ;; "varcharacter" "year" "zerofill" "dim" "string" )) ;; keywords (basic-keywords (basic-keywords-re ;; "all" "alter" "and" "as" "asc" "between" "by" "check" "create" "cross" ;; "declare" "default" "delete" "desc" "distinct" "drop" "exists" "for" "from" ;; "grant" "group" "having" "in" "inner" "insert" "into" "is" "join" "left" ;; "like" "not" "null" "on" "option" "or" "order" "outer" "right" "select" "set" ;; "table" "to" "top" "union" "unique" "update" "values" "view" "where" "with" "goto" "print" "rem" )) ;; reserved words (basic-reserved-words (basic-keywords-re ;; "add" "after" "analyze" "asensitive" "before" "both" "call" "cascade" "btree" ;; "change" "collate" "column" "condition" "connection" "constraint" "continue" ;; "convert" "cursor" "database" "databases" "delayed" "describe" "deterministic" ;; "distinctrow" "div" "dual" "each" "else" "elseif" "enclosed" "escaped" "exit" ;; "explain" "false" "fetch" "force" "foreign" "fulltext" "goto" "high_priority" ;; "if" "ignore" "index" "infile" "inout" "insensitive" "interval" "iterate" ;; "key" "keys" "kill" "label" "leading" "leave" "leave" "limit" "lines" "load" ;; "lock" "loop" "match" "mod" "modifies" "natural" "optimize" "optionally" "out" ;; "outfile" "primary" "procedure" "purge" "raid0" "read" "reads" "real" ;; "references" "regexp" "release" "rename" "repeat" "replace" "require" ;; "restrict" "return" "revoke" "rlike" "schema" "schemas" "sensitive" ;; "separator" "show" "soname" "spatial" "specific" "sql" "sqlexception" ;; "sqlstate" "sqlwarning" "ssl" "starting" "straight_join" "terminated" "then" ;; "trailing" "trigger" "true" "undo" "unlock" "unsigned" "upgrade" "usage" "use" ;; "using" "varying" "when" "while" "write" "x509" "xor" "if" "then" )) ;; functions (basic-builtin-functions (basic-keywords-re ;; "case" "current_date" "current_time" "current_timestamp" "current_user" ;; "day_hour" "day_microsecond" "day_minute" "day_second" "hour_microsecond" ;; "hour_minute" "hour_second" "localtime" "localtimestamp" "low_priority" ;; "minute_microsecond" "minute_second" "no_write_to_binlog" "second_microsecond" ;; "sql_big_result" "sql_calc_found_rows" "sql_small_result" "utc_date" ;; "utc_time" "utc_timestamp" "year_month" "chr" "int" ))) ;; add all keywords to font lock list (setq basic-mode-font-lock-keywords (list (cons basic-types 'font-lock-type-face) (cons basic-keywords 'font-lock-keyword-face) (cons basic-reserved-words 'font-lock-function-name-face) (cons basic-builtin-functions 'font-lock-builtin-face)))) ;; turn on keyword highlighting (defun basic-highlight-keywords (keywords) "Highlight BASIC keywords. \nSet `font-lock-keywords' using KEYWORDS." (interactive) (setq font-lock-keywords keywords) (font-lock-fontify-buffer)) ;; mode map (defvar basic-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-c C-c") 'basic-send-paragraph) (define-key map (kbd "C-c C-r") 'basic-send-region) (define-key map (kbd "C-c C-s") 'basic-send-string) (define-key map (kbd "C-c C-b") 'basic-send-buffer) map) "Mode map used for `basic-mode'.") ;;;###autoload (defun basic-mode () "Major mode to edit, compile, and execute BASIC programs." (interactive) (kill-all-local-variables) (setq major-mode 'basic-mode) (setq mode-name "BASIC") ;; set local key map (use-local-map basic-mode-map) ;; (when sql-mode-menu ;; (easy-menu-add sql-mode-menu)) ; xemacs ;; (set-syntax-table sql-mode-syntax-table) ;;(make-local-variable 'font-lock-defaults) ;; set font lock (make-local-variable 'basic-mode-font-lock-keywords) (basic-highlight-keywords basic-mode-font-lock-keywords) ;; set comment start (make-local-variable 'basic-comment-start) (setq comment-start "rem") ;; run hooks (run-hooks 'basic-mode-hook) ) ;;; basic compiler ;; token hash (defvar basic-token-hash nil "Buffer local variable to hold current compile tokens.") ;; parse line (defun basic-parse-line "Parse current line and return a list of tokens." (save-excursion ;; parse buffer and convert syntax to lisp code ;; compile and run buffer (defun basic-run (&optional buffer) "Compile and run a BASIC program in BUFFER. \nBUFFER defaults to `current-buffer'." (interactive) (unless buffer (setq buffer (current-buffer))) ;; setup token bag (make-local-variable 'basic-token-hash) (setq basic-token-hash (make-hash-table)) ;; traverse buffer and create token tree (save-excursion (goto-char (point-min)) (while (and (not (eobp)) (let ((error (basic-parse-line))) (if error (error error) t))) (forward-line 1)) ) ) (provide 'basic) ;;; basic.el ends here