summaryrefslogtreecommitdiff
path: root/.config/emacs/bison-mode.el
diff options
context:
space:
mode:
Diffstat (limited to '.config/emacs/bison-mode.el')
-rw-r--r--.config/emacs/bison-mode.el989
1 files changed, 989 insertions, 0 deletions
diff --git a/.config/emacs/bison-mode.el b/.config/emacs/bison-mode.el
new file mode 100644
index 0000000..5f99106
--- /dev/null
+++ b/.config/emacs/bison-mode.el
@@ -0,0 +1,989 @@
+; -*- Mode: Emacs-Lisp; -*-
+
+;;;; bison-mode.el --- Major mode for editing bison/yacc files
+;;;; Copyright (C) 1998 Eric Beuscher
+
+;; Author: Eric Beuscher <beuscher@eecs.tulane.edu>
+;; Created: 2 Feb 1998
+;; Version: .1 (why not start somewhere besides 1.)
+;; Keywords: bison-mode, yacc-mode
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;;;;Commentary
+
+;;;; I wrote this since I saw one mode for yacc files out there roaming the
+;;;; world. I was daunted by the fact the it was written in 1990, and emacs
+;;;; has evolved so much since then (this I assume based on its evolution since
+;;;; i started using it). So I figured if i wanted one, I should make it
+;;;; myself. Please excuse idiosyncrasies, as this was my first major mode
+;;;; of this kind. The indentation code may be a bit weird, I am not sure,
+;;;; it was my first go at doing emacs indentation, so I look at how other
+;;;; modes did it, but then basically did what I thought was right
+
+;;;; I hope this is useful to other hackers, and happy Bison/Yacc hacking
+;;;; If you have ideas/suggestions/problems with this code, I can be reached at
+;;;; beuscher@eecs.tulane.edu
+
+;;;; Eric --- Sat Mar 7 1:40:20 CDT 1998
+
+
+;;;; Bison Sections:
+;;;; there are five sections to a bison file (if you include the area above the
+;;;; C declarations section. most everything in this file either does
+;;;; actions based on which section you are deemed to be in, or based on an
+;;;; assumption that the function will only be called from certain sections.
+;;;; the function `bison--section-p' is the section parser
+
+;;;; Indentation:
+;;;; indentations are done based on the section of code you are in. there is
+;;;; a procedure `bison--within-braced-c-expression-p' that checks for being in
+;;;; C code. if you are within c-code, indentations should occur based on
+;;;; how you have your C indentation set up. i am pretty sure this is the
+;;;; case.
+;;;; there are four variables, which control bison indentation within either
+;;;; the bison declarations section or the bison grammar section
+;;;; `bison-rule-separator-column'
+;;;; `bison-rule-separator-column'
+;;;; `bison-decl-type-column'
+;;;; `bison-decl-token-column'
+
+;;;; flaw: indentation works on a per-line basis, unless within braced C sexp,
+;;;; i should fix this someday
+;;;; and to make matters worse, i never took out c-indent-region, so that is
+;;;; still the state of the `indent-region-function' variable
+
+;;;; Electricity:
+;;;; by default, there are electric -colon, -pipe, -open-brace, -close-brace,
+;;;; -semicolon, -percent, -less-than, -greater-than
+;;;; the indentation caused by these work closely with the 4 indentation
+;;;; variables mentioned above.
+;;;; any of these can be turned off individually by setting the appropriate
+;;;; `bison-electric-...' variable. or all of them can be turned off by
+;;;; setting `bison-all-electricity-off'
+
+;;;; todo: should make available a way to use C-electricity if in C sexps
+
+
+;;;; these are the lines i use to set up correct auto-ing
+;;(autoload 'bison-mode "bison-mode.el")
+;;(add-to-set! auto-mode-alist '("\\.y$" . bison-mode))
+
+;;(autoload 'flex-mode "flex-mode")
+;;(add-to-set! auto-mode-alist '("\\.l$" . flex-mode))
+
+
+
+;; *************** dependencies ***************
+
+(require 'derived) ;; define-derived-mode
+;(require 'flex-mode) ;; for flex-mode derivation
+(require 'make-regexp) ;; make-regexp
+
+
+;; *************** internal vars ***************
+
+(defvar bison--declarers '("%union" "%token" "%type"
+ "%left" "%right" "%nonassoc")
+ "commands which can declare a token or state type")
+
+(defvar bison--word-constituent-re "\\(\\sw\\|_\\)")
+(defvar bison--production-re
+ (concat "^" bison--word-constituent-re "+:"))
+
+(defvar bison--pre-c-decls-section 0
+ "section before c-declarations-section, if that section exists")
+(defvar bison--c-decls-section 1
+ "section denoted by %{ and $} for c-declarations at the top of a bison file")
+(defvar bison--bison-decls-section 2
+ "section before the rules section")
+(defvar bison--grammar-rules-section 3
+ "section delimited by %%'s where productions and rules are enumerated")
+(defvar bison--c-code-section 4
+ "section after the second %% where c-code can be placed")
+
+(defvar bison--c-decls-section-opener "%{")
+(defvar bison--c-decls-section-closer "%}")
+(defvar bison--grammar-rules-section-delimeter "%%")
+
+
+;; *************** user-definable vars ***************
+
+(defvar bison-rule-separator-column 8
+ "column for rule and production separators \"|\" and \";\"")
+(defvar bison-rule-enumeration-column 16
+ "column for beginning enumeration of a production's rules")
+(defvar bison-decl-type-column 8
+ "columnn in which tokens' and states' types should be when declared")
+(defvar bison-decl-token-column 24
+ "column in which tokens and states are listed when declared,
+as with %token, %type, ...")
+
+
+(defvar bison-all-electricity-off nil
+ "non-nil means all electric keys will be disabled,
+nil means that a bison-electric-* key will be on or off based on the individual
+key's electric variable")
+
+;;; i know lisp has the dual name spaces, but i find it more aesthetically
+;;; pleasing to not take advantage of that
+(defvar bison-electric-colon-v t
+ "non-nil means use an electric colon")
+(defvar bison-electric-pipe-v t
+ "non-nil means use an electric pipe")
+(defvar bison-electric-open-brace-v t
+ "non-nil means use an electric open-brace")
+(defvar bison-electric-close-brace-v t
+ "non-nil means use an electric close-brace")
+(defvar bison-electric-semicolon-v t
+ "non-nil means use an electric semicolon")
+(defvar bison-electric-percent-v t
+ "non-nil means use an electric percent")
+(defvar bison-electric-less-than-v t
+ "non-nil means use an electric less-than")
+(defvar bison-electric-greater-than-v t
+ "non-nil means use an electric greater-than")
+
+
+(defvar bison-font-lock-keywords-1 c-font-lock-keywords
+ "Basic highlighting for Bison mode.")
+
+(defvar bison-font-lock-keywords-2
+ (append
+ (list
+ (cons (concat "^\\(" (make-regexp bison--declarers) "\\)")
+ '(1 font-lock-keyword-face))
+ )
+ bison-font-lock-keywords-1)
+ "Gaudy highlighting for Bison mode.")
+
+(defvar bison-font-lock-keywords bison-font-lock-keywords-2
+ "Default expressions to highlight in Bison mode")
+
+
+;; *************** utilities ***************
+
+(defun copy-list (ls)
+ "return a new list with the same elements as LS"
+ (cond ((null ls) '())
+ (t (cons (car ls) (copy-list (cdr ls))))))
+
+(defun same-line-p (pt1 pt2 &optional bol eol)
+ (let ((bol (or bol (save-excursion (beginning-of-line) (point))))
+ (eol (or eol (save-excursion (end-of-line) (point)))))
+ (and (<= bol pt1) (<= bol pt2)
+ (>= eol pt1) (>= eol pt2))))
+
+(defun just-no-space ()
+ "Delete all spaces and tabs around point, leaving no spaces."
+ (interactive "*")
+ (skip-chars-backward " \t")
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ t)
+
+(defun white-space-separation (pt1 pt2)
+ "return t if there is nothing but whitespace between pt1 and pt2 not
+inclusive"
+ (save-excursion
+ (goto-char (+ pt1 1))
+ (not (re-search-forward "[^ \t\n]" pt2 t))))
+
+(defun previous-white-space-p ()
+ "return t if there is whitespace between the beginning of the line and the
+current (point)"
+ (save-excursion
+ (let ((current-point (point)))
+ (beginning-of-line)
+ (if (re-search-forward "\\s " current-point t)
+ t
+ nil))))
+
+(defun previous-non-ws-p ()
+ "return t if there are non-whitespace characters between beginning of line
+and \(point\)"
+ (save-excursion
+ (let ((current-point (point)))
+ (beginning-of-line)
+ (re-search-forward "[^ \t]" current-point t)
+ )))
+
+(defun following-non-ws-p ()
+ "return t if there are non-whitespace characters on the line"
+ (save-excursion
+ (let ((current-point (point)))
+ (end-of-line)
+ (re-search-backward "[^ \t]+" current-point t)
+ )))
+
+(defun line-of-whitespace-p ()
+ "return t if the line consists of nothiing but whitespace, nil otherwise"
+ (save-excursion
+ (let ((eol (progn (end-of-line) (point))))
+ (beginning-of-line) ;; should already be there anyway
+ (not (re-search-forward "[^ \t\n]" eol t)))))
+
+
+(defun goto-next-non-ws ()
+ "goto and return pt of next non-whitespace character")
+
+;; *************** bison-mode ***************
+
+(define-derived-mode bison-mode flex-mode "Bison"
+ "Major mode for editing bison/yacc files
+
+"
+ ;; try to set the indentation correctly
+ (setq-default c-basic-offset 4)
+ (make-variable-buffer-local 'c-basic-offset)
+
+ (c-set-offset 'knr-argdecl-intro 0)
+ (make-variable-buffer-local 'c-offsets-alist)
+
+ ;; remove auto and hungry anything
+ (c-toggle-auto-hungry-state -1)
+ (c-toggle-auto-state -1)
+ (c-toggle-hungry-state -1)
+
+ (use-local-map bison-mode-map)
+
+ (define-key bison-mode-map ":" 'bison-electric-colon)
+ (define-key bison-mode-map "|" 'bison-electric-pipe)
+ (define-key bison-mode-map "{" 'bison-electric-open-brace)
+ (define-key bison-mode-map "}" 'bison-electric-close-brace)
+ (define-key bison-mode-map ";" 'bison-electric-semicolon)
+ (define-key bison-mode-map "%" 'bison-electric-percent)
+ (define-key bison-mode-map "<" 'bison-electric-less-than)
+ (define-key bison-mode-map ">" 'bison-electric-greater-than)
+
+ ;(define-key bison-mode-map [tab] 'bison-indent-command)
+ (define-key bison-mode-map [tab] 'bison-indent-line)
+ ;(define-key bison-mode-map [f10] 'c-indent-command)
+
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'bison-indent-new-line)
+ (make-local-variable 'comment-start)
+ (make-local-variable 'comment-end)
+ (setq comment-start "/*"
+ comment-end "*/")
+ (make-local-variable 'font-lock-keywords)
+ (setq font-lock-keywords nil)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '((bison-font-lock-keywords
+ bison-font-lock-keywords-1
+ bison-font-lock-keywords-2)
+ nil nil nil))
+
+)
+
+
+;; *************** section parsers ***************
+
+(defun bison--section-p ()
+ "Return the section that user is currently in"
+ (save-excursion
+ (let ((bound (point)))
+ (beginning-of-buffer)
+ (bison--section-p-helper bound))))
+
+(defun bison--section-p-helper (bound)
+ (if (re-search-forward
+ (concat "^" bison--c-decls-section-opener)
+ bound t)
+ (if (re-search-forward
+ (concat "^" bison--c-decls-section-closer)
+ bound t)
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ bound t)
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ bound t)
+ bison--c-code-section
+ bison--grammar-rules-section)
+ bison--bison-decls-section)
+ bison--c-decls-section)
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ bound t)
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ bound t)
+ bison--c-code-section
+ bison--grammar-rules-section)
+ (if (re-search-forward
+ (concat "^" bison--c-decls-section-opener)
+ nil t)
+ bison--pre-c-decls-section
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ nil t)
+ bison--bison-decls-section
+ bison--pre-c-decls-section)))))
+
+
+;; *************** syntax parsers ***************
+
+(defun bison--production-p ()
+ "return t if the \(point\) rests immediately after a production"
+ (save-excursion
+ (let ((current-point (point)))
+ (beginning-of-line)
+ (let ((position (re-search-forward
+ bison--production-re current-point t)))
+ (and position
+ (not (previous-white-space-p))
+ (= position current-point))))))
+
+(defun bison--find-production-opener ()
+ "return and goto the point of the nearest production opener above \(point\)"
+ (re-search-backward bison--production-re nil t))
+
+
+(defun bison--find-next-production ()
+ "return the position of the beginning of the next production,
+or nil if there isnt one"
+ (save-excursion
+ (if (re-search-forward bison--production-re nil t)
+ (progn
+ (beginning-of-line)
+ (point))
+ nil)))
+
+(defun bison--find-grammar-end ()
+ "return the position of the end of the grammar rules (assuming we are within
+the grammar rules section), or nil if there isnt one"
+ (save-excursion
+ (if (re-search-forward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ nil t)
+ (progn
+ (beginning-of-line)
+ (point))
+ nil)))
+
+(defun bison--find-grammar-begin ()
+ "return the position of the beginning of the grammar rules (assuming we are
+within the grammar rules section), or nil if there isnt one"
+ (save-excursion
+ (if (re-search-backward
+ (concat "^" bison--grammar-rules-section-delimeter)
+ nil t)
+ (point)
+ nil)))
+
+(defun bison--within-started-production-p ()
+ "is used by bison-electric-* functions to determine actions
+return t if within a production, nil if not
+
+a point is within a production if there is some non whitespace text before
+either the beginnings of another production or the end of the grammar rules"
+ (save-excursion
+ (let ((bound (cond ((bison--find-next-production))
+ ((bison--find-grammar-end))
+ (t nil))))
+ (if bound
+ (let ((sval (re-search-forward
+ (concat "\\(\\s \\|" ;; whitespace or
+ ;; comments
+ (regexp-quote comment-start)
+ "\\(.\\|\n\\)*" ;; comment body
+ (regexp-quote comment-end)
+ "\\)+") ;; end or
+ bound t)))
+ (if sval
+ (not (= sval bound))
+ nil))
+ nil))))
+
+(defun bison--within-some-sexp-p (starter ender)
+ "return t if the \(point\) is within the sexp marked by the re's STARTER and
+ENDER"
+ (save-excursion
+ (let ((current-point (point)))
+ (if (re-search-backward starter nil t) ;; find nearest starter
+ ;; look for ender, if found, then not within sexp
+ (progn
+ (goto-char (match-end 0))
+ (not (re-search-forward ender current-point t)))))))
+
+(defun bison--within-c-comment-p ()
+ "return t if the point is within a c comment delimited by \"/*\" \"*/\""
+ (bison--within-some-sexp-p (regexp-quote comment-start)
+ (regexp-quote comment-end)))
+
+
+(defun bison--within-string-p (&optional point)
+ "
+start from the beginning of the buffer and toggle state as un-escaped \"'s are
+found."
+ (let ((point (or point (point)))
+ (in-p nil))
+ (save-excursion
+ (beginning-of-buffer)
+
+ (while (re-search-forward "[^\\]\"" point t)
+ (setq in-p (not in-p)))
+
+ in-p)))
+
+;;; bison--within-braced-c-expression-p
+;;; new and improved, no more recursion, does not break when literal strings
+;;; contain un-matched braces
+(defun bison--within-braced-c-expression-p (section)
+ "return t if the point is within an sexp delimited by braces \({,}\)
+"
+ ;;(debug)
+ (save-excursion
+ (bison--within-braced-c-expression-p-h section (point))))
+
+(defun bison--within-braced-c-expression-p-h (section low-pt)
+ "
+Notes:
+save excursion is done higher up, so i dont concern myself here.
+"
+ (cond ((= section bison--pre-c-decls-section) nil)
+ ((= section bison--c-decls-section)
+ (let ((opener (save-excursion (search-backward "%{"))))
+ (bison--within-braced-c-expression-p-h-h opener low-pt)))
+ ((= section bison--bison-decls-section)
+ (let ((opener (save-excursion
+ (or (search-backward "%}" nil t)
+ (point-min)))))
+ (bison--within-braced-c-expression-p-h-h opener low-pt)))
+ ((= section bison--grammar-rules-section)
+ (let ((opener (save-excursion (bison--find-production-opener))))
+ (if opener
+ (bison--within-braced-c-expression-p-h-h opener low-pt)
+ nil)))
+ ((= section bison--c-code-section)
+ t)
+;; (let ((opener (save-excursion (bison--find-production-opener))))
+;; (if opener
+;; (bison--within-braced-c-expression-p-h-h
+;; opener low-pt 1))))
+ ))
+
+(defun bison--within-braced-c-expression-p-h-h (high-pt low-pt)
+ "
+Notes:
+HIGH-PT goes toward (point-min), LOW-PT goes toward (point-max)
+save excursion is done higher up, so i dont concern myself here.
+"
+ (let ((pt (point)))
+ (let ((success nil) (count 1) (done nil))
+ ;; loop until open brace found, that is not in comment or string literal
+ (while (and (not done)
+ (re-search-backward "[^%]{" high-pt t count)) ;find nearest
+ ;starter
+ (goto-char (match-end 0))
+ (if (or (bison--within-c-comment-p)
+ (bison--within-string-p))
+
+ (setq count (+ count 1))
+ (progn
+ (setq success t)
+ (setq done t))))
+
+ (if success
+ (let ((end-pt
+ (condition-case nil
+ (progn (forward-sexp) (point))
+ (error nil))))
+ (if end-pt
+ (if (> end-pt low-pt)
+ t ; then in braced-c-exp
+ nil)
+ t)) ; if no sexp close brace, then w/in
+ nil))))
+
+
+(defun bison--bison-decl-opener-p (bol eol)
+ "return t if the current line is a bison declaration starter
+\(i.e. has a %type, %token, %right, ...\)"
+ (save-excursion
+ (goto-char bol)
+ (re-search-forward
+ (concat "^" (make-regexp (copy-list bison--declarers))) eol t)))
+
+(defun bison--production-opener-p (bol eol)
+ "return t if the current line is a line that introduces a new production"
+ (save-excursion
+ (goto-char bol)
+ (re-search-forward bison--production-re eol t)))
+
+(defun bison--find-bison-semicolon ()
+ "return the position of next semicolon not within braces, nil otherwise"
+ (save-excursion
+ (if (search-forward ";" nil t)
+ (if (not (bison--within-braced-c-expression-p (bison--section-p)))
+ (point)
+ (bison--find-bison-semicolon))
+ nil)))
+
+(defun bison--within-production-body-p (section)
+ "return t if the \(point\) is within the body of a production
+
+this procedure will fail if it is in a production header"
+ (save-excursion
+ (if (= section bison--grammar-rules-section)
+ (let ((current-point (point)))
+ (if (re-search-backward bison--production-re nil t)
+ t
+ nil))
+ nil)))
+
+(defun bison--production-alternative-p (bol eol section)
+ "return t if the current line contains a \"|\" used to designate a rule
+alternative"
+ (save-excursion
+ (goto-char bol)
+ (if (search-forward "|" eol t)
+ (not (bison--within-braced-c-expression-p section))
+ nil)))
+
+
+;; *************** indent functions ***************
+
+(defun bison--handle-indent-c-sexp (section indent-column bol)
+ (let* ((o-brace (re-search-backward "[^%]{" bol t))
+ )
+ (if o-brace
+ (if (save-excursion
+ (goto-char o-brace)
+ (bison--within-braced-c-expression-p section))
+ (c-indent-line)
+ (if (= (current-indentation) o-brace) ;; if o-brace is first char
+ (if (not (= o-brace indent-column)) ;; but not in right spot
+ (progn
+ (back-to-indentation)
+ (just-no-space)
+ (indent-to-column indent-column))
+ ;; else all is good
+ )
+ ;; else, non-ws before o-brace, leave it alone
+ ))
+ (c-indent-line))))
+
+(defun bison-indent-new-line (&optional c-sexp)
+ "Indent a fresh line of bison code
+
+assumes indenting a new line, i.e. at column 0
+"
+ (interactive)
+
+ ;;(message "indent new line")
+ (let* ((section (bison--section-p))
+ (c-sexp (or c-sexp (bison--within-braced-c-expression-p section)))
+ )
+ (cond
+ (c-sexp
+ (cond
+ ((= section bison--grammar-rules-section)
+ (c-indent-line
+ (save-excursion
+ (forward-line -1)
+ (let ((bol (save-excursion (beginning-of-line) (point)))
+ (eol (save-excursion (end-of-line) (point))))
+ (if (bison--production-opener-p bol eol)
+ (list
+ (cons 'defun-block-intro
+ (progn
+ (re-search-forward bison--production-re) ; SIGERR
+ (- (re-search-forward "[^ \t]") ; SIGERR
+ 1))))
+ nil)))))
+ (t (c-indent-line))))
+ ((= section bison--pre-c-decls-section)
+ (c-indent-line))
+;;; ((= section bison--c-decls-section) ; is on column 0 anyway
+;;; (indent-to-column 0)
+;;; )
+ ((= section bison--bison-decls-section)
+ (indent-to-column bison-decl-token-column))
+ ((= section bison--grammar-rules-section)
+ (indent-to-column
+ (save-excursion
+ (let* ((bound (or (save-excursion (bison--find-production-opener))
+ (bison--find-grammar-begin)))
+ (prev-semi (search-backward ";" bound t))
+ )
+ (if prev-semi
+ (if (bison--within-braced-c-expression-p section) ; CRACK
+ bison-rule-enumeration-column
+ 0)
+ (if (save-excursion (bison--find-production-opener))
+ bison-rule-enumeration-column
+ 0))))))
+ ((= section bison--c-code-section)) ;;leave-alone
+ )))
+
+(defun bison-indent-line ()
+ "Indent a line of bison code
+"
+ (interactive)
+
+ ;;(message "indent-line")
+ (let* ((pos (- (point-max) (point)))
+ (reset-pt (function (lambda ()
+ (if (> (- (point-max) pos) (point))
+ (goto-char (- (point-max) pos))))))
+ (bol (save-excursion (beginning-of-line) (point)))
+ (eol (save-excursion (end-of-line) (point)))
+ )
+ (let* ((section (bison--section-p))
+ (c-sexp (bison--within-braced-c-expression-p section))
+ (ws-line (line-of-whitespace-p))
+ )
+ (cond
+ ;; if you are a line of whitespace, let indent-new-line take care of it
+ (ws-line
+ (bison-indent-new-line c-sexp))
+
+ ((= section bison--pre-c-decls-section)
+ ;; leave things alone
+ )
+
+ ((= section bison--c-decls-section)
+ (if c-sexp
+ (bison--handle-indent-c-sexp section 0 bol)
+ (if (not (= (current-indentation) 0))
+ (progn
+ (back-to-indentation)
+ (just-no-space)
+ (function reset-pt)))))
+
+ ((= section bison--bison-decls-section)
+ (let ((opener (bison--bison-decl-opener-p bol eol)))
+ (cond
+ (opener
+ (goto-char opener)
+ (skip-chars-forward " \t" eol)
+ (if (looking-at "{")
+ (save-excursion
+ (if (following-non-ws-p)
+ (progn
+ (forward-char 1)
+ (just-no-space)
+ (newline)
+ (bison-indent-new-line t))))
+ (let ((complete-type t))
+ (if (looking-at "<")
+ (progn
+ (setq complete-type nil)
+ (if (not (= (current-column) bison-decl-type-column))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-decl-type-column))
+ (and (re-search-forward
+ (concat "<" bison--word-constituent-re "+>")
+ eol t)
+ (setq complete-type t)))))
+ (and complete-type
+ (skip-chars-forward " \t" eol)
+ (looking-at
+ (concat "\\(" bison--word-constituent-re "\\|'\\)"))
+ (if (not (= (current-column) bison-decl-token-column))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-decl-token-column))))))
+ (funcall reset-pt))
+ (c-sexp
+ (bison--handle-indent-c-sexp section 0 bol))
+ (t
+ (back-to-indentation)
+ ;; only tab in names, leave comments alone
+ (cond (;; put word-constiuents in bison-decl-token-column
+ (looking-at bison--word-constituent-re)
+ (if (not (= (current-column) bison-decl-token-column))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-decl-token-column))))
+ ;; put/keep close-brace in the 0 column
+ ((looking-at "}")
+ (if (not (= (current-column) 0))
+ (just-no-space)))
+ ;; leave comments alone
+ ((looking-at (regexp-quote comment-start)) nil)
+ ;; else do nothing
+ )
+ (funcall reset-pt)))))
+ ((= section bison--grammar-rules-section)
+ (cond
+ ((bison--production-opener-p bol eol)
+ (beginning-of-line)
+ (re-search-forward bison--production-re);; SIGERR
+ (if (following-non-ws-p)
+ (if (> (current-column) bison-rule-enumeration-column)
+ (progn
+ (just-no-space)
+ (newline)
+ (indent-to-column bison-rule-enumeration-column))
+ (save-excursion
+ (re-search-forward bison--word-constituent-re);; SIGERR
+ (let ((col (current-column)))
+ (cond ((> col (+ 1 bison-rule-enumeration-column))
+ (forward-char -1)
+ (just-no-space)
+ (indent-to-column bison-rule-enumeration-column))
+ ((< col (+ 1 bison-rule-enumeration-column))
+ (forward-char -1)
+ (indent-to-column
+ bison-rule-enumeration-column)))))))
+ (funcall reset-pt))
+ ((bison--production-alternative-p bol eol section)
+ (back-to-indentation);; should put point on "|"
+ (if (not (= (current-column) bison-rule-separator-column))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-rule-separator-column)))
+ (forward-char 1)
+ (if (following-non-ws-p)
+ (save-excursion
+ (re-search-forward bison--word-constituent-re);; SIGERR
+ (let ((col (current-column)))
+ (cond ((> col (+ 1 bison-rule-enumeration-column))
+ (forward-char -1)
+ (just-no-space)
+ (indent-to-column bison-rule-enumeration-column))
+ ((< col (+ 1 bison-rule-enumeration-column))
+ (forward-char -1)
+ (indent-to-column
+ bison-rule-enumeration-column))))))
+ (funcall reset-pt))
+ (c-sexp
+ (bison--handle-indent-c-sexp
+ section bison-rule-enumeration-column bol)
+ (funcall reset-pt))
+ ((bison--within-production-body-p section)
+ (back-to-indentation)
+ (if (not (= (current-column) bison-rule-enumeration-column))
+ (progn
+ (just-no-space)
+ (indent-to-column
+ bison-rule-enumeration-column)))
+ (funcall reset-pt))
+ (t
+ (let ((cur-ind (current-indentation)))
+ (if (eq (save-excursion (search-backward "}" bol t))
+ cur-ind)
+ (if (not (= cur-ind bison-rule-enumeration-column))
+ (progn
+ (back-to-indentation)
+ (just-no-space)
+ (indent-to-column bison-rule-enumeration-column)
+ (funcall reset-pt)))
+ ;; else leave alone
+ )))))
+ ((= section bison--c-code-section)
+ (c-indent-line))
+ ))))
+
+;; *************** electric-functions ***************
+
+(defun bison-electric-colon (arg)
+ "If the colon <:> delineates a production,
+ then insert a semicolon on the next line in the BISON-RULE-SEPARATOR-COLUMN,
+ put the cursor in the BISON-RULE-ENUMERATION-COLUMN for the beginning
+ of the rule
+ else just run self-insert-command
+A colon delineates a production by the fact that it is immediately preceded by
+a word(alphanumerics or '_''s), and there is no previous white space.
+"
+ (interactive "P")
+
+ (self-insert-command (prefix-numeric-value arg))
+ (if (and bison-electric-colon-v
+ (not bison-all-electricity-off))
+ (if (and (= bison--grammar-rules-section (bison--section-p))
+ (bison--production-p)
+ (not (bison--within-started-production-p)))
+ (progn
+ (save-excursion ; put in a closing semicolon
+ (newline)
+ (indent-to-column bison-rule-separator-column)
+ (insert ";"))
+ (save-excursion ; remove opening whitespace
+ (if (re-search-backward
+ "\\s "
+ (save-excursion (beginning-of-line) (point))
+ t)
+ (just-no-space)))
+ (if (not (< (current-column) bison-rule-enumeration-column))
+ (newline))
+ (indent-to-column bison-rule-enumeration-column)))
+ ))
+
+(defun bison-electric-pipe (arg)
+ "If the pipe <|> is used as a rule separator within a production,
+ then move it into BISON-RULE-SEPARATOR-COLUMN
+ indent to BISON-RULE-ENUMERATION-COLUMN on the same line
+ else just run self-insert-command
+"
+ (interactive "P")
+
+ (if (and bison-electric-pipe-v
+ (not bison-all-electricity-off)
+ (= bison--grammar-rules-section (bison--section-p))
+ (line-of-whitespace-p)
+ )
+ (progn
+ (beginning-of-line)
+ (just-no-space)
+ (indent-to-column bison-rule-separator-column)
+ (self-insert-command (prefix-numeric-value arg))
+ (indent-to-column bison-rule-enumeration-column)
+ )
+ (self-insert-command (prefix-numeric-value arg))))
+
+(defun bison-electric-open-brace (arg)
+ "used for the opening brace of a C action definition for production rules,
+if there is only whitespace before \(point\), then put open-brace in
+bison-rule-enumeration-column"
+ (interactive "P")
+
+ (if (and bison-electric-open-brace-v
+ (not bison-all-electricity-off))
+ (let ((section (bison--section-p)))
+ (cond ((and (= section bison--grammar-rules-section)
+ (not (bison--within-braced-c-expression-p section))
+ (not (previous-non-ws-p)))
+ (if (not (= (current-column) bison-rule-enumeration-column))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-rule-enumeration-column))))
+ ((and (= section bison--bison-decls-section)
+ (not (bison--within-braced-c-expression-p section))
+ (not (previous-non-ws-p)))
+ (if (not (= (current-column) 0))
+ (progn
+ (just-no-space)
+ (indent-to-column 0)))))))
+
+ (self-insert-command (prefix-numeric-value arg)))
+
+
+(defun bison-electric-close-brace (arg)
+ "If the close-brace \"}\" is used as the c-declarations section closer
+in \"%}\", then make sure the \"%}\" indents to the beginning of the line"
+ (interactive "P")
+
+ (self-insert-command (prefix-numeric-value arg))
+
+ (if (and bison-electric-close-brace-v
+ (not bison-all-electricity-off))
+ (cond ((search-backward "%}" (- (point) 2) t)
+ (if (= (bison--section-p) bison--c-decls-section)
+ (progn
+ (just-no-space)
+ (forward-char 2)) ; for "%}"
+ (forward-char 1)))
+ )))
+
+(defun bison-electric-semicolon (arg)
+ "if the semicolon is used to end a production, then place it in
+bison-rule-separator-column
+
+a semicolon is deemed to be used for ending a production if it is not found
+within braces
+
+this is just self-insert-command as i have yet to write the actual
+bison-electric-semicolon function yet
+"
+ (interactive "P")
+
+ (self-insert-command (prefix-numeric-value arg)))
+
+(defun bison-electric-percent (arg)
+ "if the percent is a declarer in the bison declaration's section,
+then put it in the 0 column
+"
+ (interactive "P")
+
+ (if (and bison-electric-percent-v
+ (not bison-all-electricity-off))
+ (let ((section (bison--section-p)))
+ (if (and (= section bison--bison-decls-section)
+ (not (bison--within-braced-c-expression-p section))
+ (not (previous-non-ws-p))
+ (not (= (current-column) 0)))
+ (just-no-space))))
+
+ (self-insert-command (prefix-numeric-value arg)))
+
+(defun bison-electric-less-than (arg)
+ "if the less-than is a type declarer opener for tokens in the bison
+declaration section, then put it in the bison-decl-type-column column
+"
+ (interactive "P")
+
+ (if (and bison-electric-less-than-v
+ (not bison-all-electricity-off))
+ (if (and (= (bison--section-p) bison--bison-decls-section)
+ (bison--bison-decl-opener-p
+ (save-excursion (beginning-of-line) (point))
+ (point)))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-decl-type-column))))
+
+ (self-insert-command (prefix-numeric-value arg)))
+
+(defun bison-electric-greater-than (arg)
+ "if the greater-than is a type declarer closer for tokens in the bison
+declaration section, then indent to bison-decl-token-column
+"
+ (interactive "P")
+
+ (self-insert-command (prefix-numeric-value arg))
+
+ (if (and bison-electric-greater-than-v
+ (not bison-all-electricity-off))
+ (let ((current-pt (point))
+ (bol (save-excursion (beginning-of-line) (point))))
+ (if (and (= (bison--section-p) bison--bison-decls-section)
+ (bison--bison-decl-opener-p bol (point)))
+ (if (search-backward "<" bol t)
+ (if (re-search-forward
+ (concat "<" bison--word-constituent-re "+>")
+ current-pt t)
+ (if (not (following-non-ws-p))
+ (progn
+ (just-no-space)
+ (indent-to-column bison-decl-token-column)))))))))
+
+;(defun bison-electric-semicolon (arg)
+; "if the semicolon is used to end a production, then place it in
+;bison-rule-separator-column
+
+;a semicolon is deemed to be used for ending a production if it is not found
+;within braces
+;"
+; (interactive "P")
+; (if (and (not (bison--within-braced-c-expression-p))
+; (line-of-whitespace-p)
+; (
+; (progn
+; (just-no-space) ;; remove extraneous whitespace
+; (indent-to-column bison-rule-separator-column)))
+
+; (self-insert-command (prefix-numeric-value arg)))
+
+;; *************** other ***************
+
+;(defun bison--confirm-productions-closed ()
+; (save-excursion
+; (goto-char (point-max))
+; (if (re-search-forward "^%%" nil t)
+
+
+(provide 'bison-mode)
+
+;; *************** end of code *************** \ No newline at end of file