Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

913 lines
30 KiB

  1. ;;; bison-mode.el --- Major mode for editing bison, yacc and lex files.
  2. ;; Copyright (C) 1998 Eric Beuscher
  3. ;;
  4. ;; Author: Eric Beuscher <beuscher@eecs.tulane.edu>
  5. ;; Created: 2 Feb 1998
  6. ;; Version: 0.2
  7. ;; Keywords: bison-mode, yacc-mode
  8. ;; This program is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2 of the License, or
  11. ;; (at your option) any later version.
  12. ;; This program is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;;; Commentary:
  17. ;;;; I wrote this since I saw one mode for yacc files out there roaming the
  18. ;;;; world. I was daunted by the fact the it was written in 1990, and Emacs
  19. ;;;; has evolved so much since then (this I assume based on its evolution since
  20. ;;;; i started using it). So I figured if i wanted one, I should make it
  21. ;;;; myself. Please excuse idiosyncrasies, as this was my first major mode
  22. ;;;; of this kind. The indentation code may be a bit weird, I am not sure,
  23. ;;;; it was my first go at doing Emacs indentation, so I look at how other
  24. ;;;; modes did it, but then basically did what I thought was right
  25. ;;;; I hope this is useful to other hackers, and happy Bison/Yacc hacking
  26. ;;;; If you have ideas/suggestions/problems with this code, I can be reached at
  27. ;;;; beuscher@eecs.tulane.edu
  28. ;;;; Eric --- Sat Mar 7 1:40:20 CDT 1998
  29. ;;;; Bison Sections:
  30. ;;;; there are five sections to a bison file (if you include the area above the
  31. ;;;; C declarations section. most everything in this file either does
  32. ;;;; actions based on which section you are deemed to be in, or based on an
  33. ;;;; assumption that the function will only be called from certain sections.
  34. ;;;; the function `bison--section-p' is the section parser
  35. ;;;; Indentation:
  36. ;;;; indentations are done based on the section of code you are in. there is
  37. ;;;; a procedure `bison--within-braced-c-expression-p' that checks for being in
  38. ;;;; C code. if you are within c-code, indentations should occur based on
  39. ;;;; how you have your C indentation set up. i am pretty sure this is the
  40. ;;;; case.
  41. ;;;; there are four variables, which control bison indentation within either
  42. ;;;; the bison declarations section or the bison grammar section
  43. ;;;; `bison-rule-separator-column'
  44. ;;;; `bison-rule-separator-column'
  45. ;;;; `bison-decl-type-column'
  46. ;;;; `bison-decl-token-column'
  47. ;;;; flaw: indentation works on a per-line basis, unless within braced C sexp,
  48. ;;;; i should fix this someday
  49. ;;;; and to make matters worse, i never took out c-indent-region, so that is
  50. ;;;; still the state of the `indent-region-function' variable
  51. ;;;; Electricity:
  52. ;;;; by default, there are electric -colon, -pipe, -open-brace, -close-brace,
  53. ;;;; -semicolon, -percent, -less-than, -greater-than
  54. ;;;; the indentation caused by these work closely with the 4 indentation
  55. ;;;; variables mentioned above.
  56. ;;;; any of these can be turned off individually by setting the appropriate
  57. ;;;; `bison-electric-...' variable. or all of them can be turned off by
  58. ;;;; setting `bison-all-electricity-off'
  59. ;;;; todo: should make available a way to use C-electricity if in C sexps
  60. ;;; Code:
  61. (require 'cc-mode)
  62. ;;;###autoload
  63. (add-to-list 'auto-mode-alist '("\\.y\\'" . bison-mode))
  64. ;;;###autoload
  65. (add-to-list 'auto-mode-alist '("\\.l\\'" . flex-mode))
  66. ;;;###autoload
  67. (add-to-list 'auto-mode-alist '("\\.jison\\'" . jison-mode))
  68. ;; *************** internal vars ***************
  69. (defvar bison--declarers '("%union" "%token" "%type"
  70. "%left" "%right" "%nonassoc")
  71. "commands which can declare a token or state type")
  72. (defvar bison--word-constituent-re "\\(\\sw\\|_\\)")
  73. (defvar bison--production-re
  74. (concat "^" bison--word-constituent-re "+:"))
  75. (defvar bison--pre-c-decls-section 0
  76. "section before c-declarations-section, if that section exists")
  77. (defvar bison--c-decls-section 1
  78. "section denoted by %{ and $} for c-declarations at the top of a bison file")
  79. (defvar bison--bison-decls-section 2
  80. "section before the rules section")
  81. (defvar bison--grammar-rules-section 3
  82. "section delimited by %%'s where productions and rules are enumerated")
  83. (defvar bison--c-code-section 4
  84. "section after the second %% where c-code can be placed")
  85. (defvar bison--c-decls-section-opener "%{")
  86. (defvar bison--c-decls-section-closer "%}")
  87. (defvar bison--grammar-rules-section-delimeter "%%")
  88. ;; *************** user-definable vars ***************
  89. (defvar bison-rule-separator-column 8
  90. "column for rule and production separators \"|\" and \";\"")
  91. (defvar bison-rule-enumeration-column 16
  92. "column for beginning enumeration of a production's rules")
  93. (defvar bison-decl-type-column 8
  94. "columnn in which tokens' and states' types should be when declared")
  95. (defvar bison-decl-token-column 24
  96. "column in which tokens and states are listed when declared,
  97. as with %token, %type, ...")
  98. (defvar bison-all-electricity-off nil
  99. "non-nil means all electric keys will be disabled,
  100. nil means that a bison-electric-* key will be on or off based on the individual
  101. key's electric variable")
  102. ;;; i know lisp has the dual name spaces, but i find it more aesthetically
  103. ;;; pleasing to not take advantage of that
  104. (defvar bison-electric-colon-v t
  105. "non-nil means use an electric colon")
  106. (defvar bison-electric-pipe-v t
  107. "non-nil means use an electric pipe")
  108. (defvar bison-electric-open-brace-v t
  109. "non-nil means use an electric open-brace")
  110. (defvar bison-electric-close-brace-v t
  111. "non-nil means use an electric close-brace")
  112. (defvar bison-electric-semicolon-v t
  113. "non-nil means use an electric semicolon")
  114. (defvar bison-electric-percent-v t
  115. "non-nil means use an electric percent")
  116. (defvar bison-electric-less-than-v t
  117. "non-nil means use an electric less-than")
  118. (defvar bison-electric-greater-than-v t
  119. "non-nil means use an electric greater-than")
  120. (defconst bison-font-lock-keywords
  121. (append
  122. (list
  123. (cons (concat "^\\(" (regexp-opt bison--declarers) "\\)")
  124. '(1 font-lock-keyword-face))
  125. )
  126. c-font-lock-keywords)
  127. "Default expressions to highlight in Bison mode")
  128. ;; *************** utilities ***************
  129. (defun just-no-space ()
  130. "Delete all spaces and tabs around point, leaving no spaces."
  131. (interactive "*")
  132. (skip-chars-backward " \t")
  133. (delete-region (point) (progn (skip-chars-forward " \t") (point)))
  134. t)
  135. (defun previous-white-space-p ()
  136. "return t if there is whitespace between the beginning of the line and the
  137. current (point)"
  138. (save-excursion
  139. (let ((current-point (point)))
  140. (beginning-of-line)
  141. (if (re-search-forward "\\s " current-point t)
  142. t
  143. nil))))
  144. (defun previous-non-ws-p ()
  145. "return t if there are non-whitespace characters between beginning of line
  146. and \(point\)"
  147. (save-excursion
  148. (let ((current-point (point)))
  149. (beginning-of-line)
  150. (re-search-forward "[^ \t]" current-point t)
  151. )))
  152. (defun following-non-ws-p ()
  153. "return t if there are non-whitespace characters on the line"
  154. (save-excursion
  155. (let ((current-point (point)))
  156. (end-of-line)
  157. (re-search-backward "[^ \t]+" current-point t)
  158. )))
  159. (defun line-of-whitespace-p ()
  160. "return t if the line consists of nothiing but whitespace, nil otherwise"
  161. (save-excursion
  162. (let ((eol (progn (end-of-line) (point))))
  163. (beginning-of-line) ;; should already be there anyway
  164. (not (re-search-forward "[^ \t\n]" eol t)))))
  165. ;; *************** bison-mode ***************
  166. ;;;###autoload
  167. (define-derived-mode bison-mode c-mode "Bison"
  168. "Major mode for editing bison/yacc files."
  169. ;; try to set the indentation correctly
  170. (setq c-basic-offset 4)
  171. (c-set-offset 'knr-argdecl-intro 0)
  172. ;; remove auto and hungry anything
  173. (c-toggle-auto-hungry-state -1)
  174. (c-toggle-auto-newline -1)
  175. (c-toggle-hungry-state -1)
  176. (use-local-map bison-mode-map)
  177. (define-key bison-mode-map ":" 'bison-electric-colon)
  178. (define-key bison-mode-map "|" 'bison-electric-pipe)
  179. (define-key bison-mode-map "{" 'bison-electric-open-brace)
  180. (define-key bison-mode-map "}" 'bison-electric-close-brace)
  181. (define-key bison-mode-map ";" 'bison-electric-semicolon)
  182. (define-key bison-mode-map "%" 'bison-electric-percent)
  183. (define-key bison-mode-map "<" 'bison-electric-less-than)
  184. (define-key bison-mode-map ">" 'bison-electric-greater-than)
  185. (define-key bison-mode-map [tab] 'bison-indent-line)
  186. (make-local-variable 'indent-line-function)
  187. (setq indent-line-function 'bison-indent-new-line)
  188. (make-local-variable 'comment-start)
  189. (make-local-variable 'comment-end)
  190. (setq comment-start "/*"
  191. comment-end "*/")
  192. (make-local-variable 'font-lock-keywords)
  193. (setq font-lock-keywords nil)
  194. (set (make-local-variable 'font-lock-defaults) '(bison-font-lock-keywords)))
  195. ;; *************** section parsers ***************
  196. (defun bison--section-p ()
  197. "Return the section that user is currently in"
  198. (save-excursion
  199. (let ((bound (point)))
  200. (goto-char (point-min))
  201. (bison--section-p-helper bound))))
  202. (defun bison--section-p-helper (bound)
  203. (if (re-search-forward
  204. (concat "^" bison--c-decls-section-opener)
  205. bound t)
  206. (if (re-search-forward
  207. (concat "^" bison--c-decls-section-closer)
  208. bound t)
  209. (if (re-search-forward
  210. (concat "^" bison--grammar-rules-section-delimeter)
  211. bound t)
  212. (if (re-search-forward
  213. (concat "^" bison--grammar-rules-section-delimeter)
  214. bound t)
  215. bison--c-code-section
  216. bison--grammar-rules-section)
  217. bison--bison-decls-section)
  218. bison--c-decls-section)
  219. (if (re-search-forward
  220. (concat "^" bison--grammar-rules-section-delimeter)
  221. bound t)
  222. (if (re-search-forward
  223. (concat "^" bison--grammar-rules-section-delimeter)
  224. bound t)
  225. bison--c-code-section
  226. bison--grammar-rules-section)
  227. (if (re-search-forward
  228. (concat "^" bison--c-decls-section-opener)
  229. nil t)
  230. bison--pre-c-decls-section
  231. (if (re-search-forward
  232. (concat "^" bison--grammar-rules-section-delimeter)
  233. nil t)
  234. bison--bison-decls-section
  235. bison--pre-c-decls-section)))))
  236. ;; *************** syntax parsers ***************
  237. (defun bison--production-p ()
  238. "return t if the \(point\) rests immediately after a production"
  239. (save-excursion
  240. (let ((current-point (point)))
  241. (beginning-of-line)
  242. (let ((position (re-search-forward
  243. bison--production-re current-point t)))
  244. (and position
  245. (not (previous-white-space-p))
  246. (= position current-point))))))
  247. (defun bison--find-production-opener ()
  248. "return and goto the point of the nearest production opener above \(point\)"
  249. (re-search-backward bison--production-re nil t))
  250. (defun bison--find-next-production ()
  251. "return the position of the beginning of the next production,
  252. or nil if there isnt one"
  253. (save-excursion
  254. (if (re-search-forward bison--production-re nil t)
  255. (progn
  256. (beginning-of-line)
  257. (point))
  258. nil)))
  259. (defun bison--find-grammar-end ()
  260. "return the position of the end of the grammar rules (assuming we are within
  261. the grammar rules section), or nil if there isnt one"
  262. (save-excursion
  263. (if (re-search-forward
  264. (concat "^" bison--grammar-rules-section-delimeter)
  265. nil t)
  266. (progn
  267. (beginning-of-line)
  268. (point))
  269. nil)))
  270. (defun bison--find-grammar-begin ()
  271. "return the position of the beginning of the grammar rules (assuming we are
  272. within the grammar rules section), or nil if there isnt one"
  273. (save-excursion
  274. (if (re-search-backward
  275. (concat "^" bison--grammar-rules-section-delimeter)
  276. nil t)
  277. (point)
  278. nil)))
  279. (defun bison--within-started-production-p ()
  280. "is used by bison-electric-* functions to determine actions
  281. return t if within a production, nil if not
  282. a point is within a production if there is some non whitespace text before
  283. either the beginnings of another production or the end of the grammar rules"
  284. (save-excursion
  285. (let ((bound (cond ((bison--find-next-production))
  286. ((bison--find-grammar-end))
  287. (t nil))))
  288. (if bound
  289. (let ((sval (re-search-forward
  290. (concat "\\(\\s \\|" ;; whitespace or
  291. ;; comments
  292. (regexp-quote comment-start)
  293. "\\(.\\|\n\\)*" ;; comment body
  294. (regexp-quote comment-end)
  295. "\\)+") ;; end or
  296. bound t)))
  297. (if sval
  298. (not (= sval bound))
  299. nil))
  300. nil))))
  301. (defun bison--within-some-sexp-p (starter ender)
  302. "return t if the \(point\) is within the sexp marked by the re's STARTER and
  303. ENDER"
  304. (save-excursion
  305. (let ((current-point (point)))
  306. (if (re-search-backward starter nil t) ;; find nearest starter
  307. ;; look for ender, if found, then not within sexp
  308. (progn
  309. (goto-char (match-end 0))
  310. (not (re-search-forward ender current-point t)))))))
  311. (defun bison--within-c-comment-p ()
  312. "return t if the point is within a c comment delimited by \"/*\" \"*/\""
  313. (bison--within-some-sexp-p (regexp-quote comment-start)
  314. (regexp-quote comment-end)))
  315. (defun bison--within-string-p (&optional point)
  316. "
  317. start from the beginning of the buffer and toggle state as un-escaped \"'s are
  318. found."
  319. (let ((point (or point (point)))
  320. (in-p nil))
  321. (save-excursion
  322. (goto-char (point-min))
  323. (while (re-search-forward "[^\\]\"" point t)
  324. (setq in-p (not in-p)))
  325. in-p)))
  326. ;;; bison--within-braced-c-expression-p
  327. ;;; new and improved, no more recursion, does not break when literal strings
  328. ;;; contain un-matched braces
  329. (defun bison--within-braced-c-expression-p (section)
  330. "return t if the point is within an sexp delimited by braces \({,}\)
  331. "
  332. (save-excursion
  333. (bison--within-braced-c-expression-p-h section (point))))
  334. (defun bison--within-braced-c-expression-p-h (section low-pt)
  335. "
  336. Notes:
  337. save excursion is done higher up, so i dont concern myself here.
  338. "
  339. (cond ((= section bison--pre-c-decls-section) nil)
  340. ((= section bison--c-decls-section)
  341. (let ((opener (save-excursion (search-backward "%{"))))
  342. (bison--within-braced-c-expression-p-h-h opener low-pt)))
  343. ((= section bison--bison-decls-section)
  344. (let ((opener (save-excursion
  345. (or (search-backward "%}" nil t)
  346. (point-min)))))
  347. (bison--within-braced-c-expression-p-h-h opener low-pt)))
  348. ((= section bison--grammar-rules-section)
  349. (let ((opener (save-excursion (bison--find-production-opener))))
  350. (if opener
  351. (bison--within-braced-c-expression-p-h-h opener low-pt)
  352. nil)))
  353. ((= section bison--c-code-section)
  354. t)))
  355. (defun bison--within-braced-c-expression-p-h-h (high-pt low-pt)
  356. "
  357. Notes:
  358. HIGH-PT goes toward (point-min), LOW-PT goes toward (point-max)
  359. save excursion is done higher up, so i dont concern myself here.
  360. "
  361. (let ((pt (point)))
  362. (let ((success nil) (count 1) (done nil))
  363. ;; loop until open brace found, that is not in comment or string literal
  364. (while (and (not done)
  365. (re-search-backward "[^%]{" high-pt t count)) ;find nearest
  366. ;starter
  367. (goto-char (match-end 0))
  368. (if (or (bison--within-c-comment-p)
  369. (bison--within-string-p))
  370. (setq count (+ count 1))
  371. (progn
  372. (setq success t)
  373. (setq done t))))
  374. (if success
  375. (let ((end-pt
  376. (condition-case nil
  377. (progn
  378. (backward-char)
  379. (forward-sexp)
  380. (point))
  381. (error nil))))
  382. (if end-pt
  383. (if (> end-pt low-pt)
  384. t ; then in braced-c-exp
  385. nil)
  386. t)) ; if no sexp close brace, then w/in
  387. nil))))
  388. (defun bison--bison-decl-opener-p (bol eol)
  389. "return t if the current line is a bison declaration starter
  390. \(i.e. has a %type, %token, %right, ...\)"
  391. (save-excursion
  392. (goto-char bol)
  393. (re-search-forward
  394. (concat "^" (regexp-opt (copy-sequence bison--declarers))) eol t)))
  395. (defun bison--production-opener-p (bol eol)
  396. "return t if the current line is a line that introduces a new production"
  397. (save-excursion
  398. (goto-char bol)
  399. (re-search-forward bison--production-re eol t)))
  400. (defun bison--find-bison-semicolon ()
  401. "return the position of next semicolon not within braces, nil otherwise"
  402. (save-excursion
  403. (if (search-forward ";" nil t)
  404. (if (not (bison--within-braced-c-expression-p (bison--section-p)))
  405. (point)
  406. (bison--find-bison-semicolon))
  407. nil)))
  408. (defun bison--within-production-body-p (section)
  409. "return t if the \(point\) is within the body of a production
  410. this procedure will fail if it is in a production header"
  411. (save-excursion
  412. (if (= section bison--grammar-rules-section)
  413. (let ((current-point (point)))
  414. (if (re-search-backward bison--production-re nil t)
  415. t
  416. nil))
  417. nil)))
  418. (defun bison--production-alternative-p (bol eol section)
  419. "return t if the current line contains a \"|\" used to designate a rule
  420. alternative"
  421. (save-excursion
  422. (goto-char bol)
  423. (if (search-forward "|" eol t)
  424. (not (bison--within-braced-c-expression-p section))
  425. nil)))
  426. ;; *************** indent functions ***************
  427. (defun bison--handle-indent-c-sexp (section indent-column bol)
  428. (let* ((o-brace (re-search-backward "[^%]{" bol t))
  429. )
  430. (if o-brace
  431. (if (save-excursion
  432. (goto-char o-brace)
  433. (bison--within-braced-c-expression-p section))
  434. (c-indent-line)
  435. (if (= (current-indentation) o-brace) ;; if o-brace is first char
  436. (if (not (= o-brace indent-column)) ;; but not in right spot
  437. (progn
  438. (back-to-indentation)
  439. (just-no-space)
  440. (indent-to-column indent-column))
  441. ;; else all is good
  442. )
  443. ;; else, non-ws before o-brace, leave it alone
  444. ))
  445. (c-indent-line))))
  446. (defun bison-indent-new-line (&optional c-sexp)
  447. "Indent a fresh line of bison code
  448. assumes indenting a new line, i.e. at column 0
  449. "
  450. (interactive)
  451. (let* ((section (bison--section-p))
  452. (c-sexp (or c-sexp (bison--within-braced-c-expression-p section)))
  453. )
  454. (cond
  455. (c-sexp
  456. (cond
  457. ((= section bison--grammar-rules-section)
  458. (c-indent-line
  459. (save-excursion
  460. (forward-line -1)
  461. (let ((bol (save-excursion (beginning-of-line) (point)))
  462. (eol (save-excursion (end-of-line) (point))))
  463. (if (bison--production-opener-p bol eol)
  464. (list
  465. (cons 'defun-block-intro
  466. (progn
  467. (re-search-forward bison--production-re) ; SIGERR
  468. (- (re-search-forward "[^ \t]") ; SIGERR
  469. 1))))
  470. nil)))))
  471. (t (c-indent-line))))
  472. ((= section bison--pre-c-decls-section)
  473. (c-indent-line))
  474. ((= section bison--bison-decls-section)
  475. (indent-to-column bison-decl-token-column))
  476. ((= section bison--grammar-rules-section)
  477. (indent-to-column
  478. (save-excursion
  479. (let* ((bound (or (save-excursion (bison--find-production-opener))
  480. (bison--find-grammar-begin)))
  481. (prev-semi (search-backward ";" bound t))
  482. )
  483. (if prev-semi
  484. (if (bison--within-braced-c-expression-p section) ; CRACK
  485. bison-rule-enumeration-column
  486. 0)
  487. (if (save-excursion (bison--find-production-opener))
  488. bison-rule-enumeration-column
  489. 0))))))
  490. ((= section bison--c-code-section)) ;;leave-alone
  491. )))
  492. (defun bison-indent-line ()
  493. "Indent a line of bison code."
  494. (interactive)
  495. (let* ((pos (- (point-max) (point)))
  496. (reset-pt (function (lambda ()
  497. (if (> (- (point-max) pos) (point))
  498. (goto-char (- (point-max) pos))))))
  499. (bol (save-excursion (beginning-of-line) (point)))
  500. (eol (save-excursion (end-of-line) (point)))
  501. )
  502. (let* ((section (bison--section-p))
  503. (c-sexp (bison--within-braced-c-expression-p section))
  504. (ws-line (line-of-whitespace-p))
  505. )
  506. (cond
  507. ;; if you are a line of whitespace, let indent-new-line take care of it
  508. (ws-line
  509. (bison-indent-new-line c-sexp))
  510. ((= section bison--pre-c-decls-section)
  511. ;; leave things alone
  512. )
  513. ((= section bison--c-decls-section)
  514. (if c-sexp
  515. (bison--handle-indent-c-sexp section 0 bol)
  516. (if (not (= (current-indentation) 0))
  517. (progn
  518. (back-to-indentation)
  519. (just-no-space)
  520. (funcall reset-pt)))))
  521. ((= section bison--bison-decls-section)
  522. (let ((opener (bison--bison-decl-opener-p bol eol)))
  523. (cond
  524. (opener
  525. (goto-char opener)
  526. (skip-chars-forward " \t" eol)
  527. (if (looking-at "{")
  528. (save-excursion
  529. (if (following-non-ws-p)
  530. (progn
  531. (forward-char 1)
  532. (just-no-space)
  533. (newline)
  534. (bison-indent-new-line t))))
  535. (let ((complete-type t))
  536. (if (looking-at "<")
  537. (progn
  538. (setq complete-type nil)
  539. (if (not (= (current-column) bison-decl-type-column))
  540. (progn
  541. (just-no-space)
  542. (indent-to-column bison-decl-type-column))
  543. (and (re-search-forward
  544. (concat "<" bison--word-constituent-re "+>")
  545. eol t)
  546. (setq complete-type t)))))
  547. (and complete-type
  548. (skip-chars-forward " \t" eol)
  549. (looking-at
  550. (concat "\\(" bison--word-constituent-re "\\|'\\)"))
  551. (if (not (= (current-column) bison-decl-token-column))
  552. (progn
  553. (just-no-space)
  554. (indent-to-column bison-decl-token-column))))))
  555. (funcall reset-pt))
  556. (c-sexp
  557. (bison--handle-indent-c-sexp section 0 bol))
  558. (t
  559. (back-to-indentation)
  560. ;; only tab in names, leave comments alone
  561. (cond (;; put word-constiuents in bison-decl-token-column
  562. (looking-at bison--word-constituent-re)
  563. (if (not (= (current-column) bison-decl-token-column))
  564. (progn
  565. (just-no-space)
  566. (indent-to-column bison-decl-token-column))))
  567. ;; put/keep close-brace in the 0 column
  568. ((looking-at "}")
  569. (if (not (= (current-column) 0))
  570. (just-no-space)))
  571. ;; leave comments alone
  572. ((looking-at (regexp-quote comment-start)) nil)
  573. ;; else do nothing
  574. )
  575. (funcall reset-pt)))))
  576. ((= section bison--grammar-rules-section)
  577. (cond
  578. ((bison--production-opener-p bol eol)
  579. (beginning-of-line)
  580. (re-search-forward bison--production-re);; SIGERR
  581. (if (following-non-ws-p)
  582. (if (> (current-column) bison-rule-enumeration-column)
  583. (progn
  584. (just-no-space)
  585. (newline)
  586. (indent-to-column bison-rule-enumeration-column))
  587. (save-excursion
  588. (re-search-forward bison--word-constituent-re);; SIGERR
  589. (let ((col (current-column)))
  590. (cond ((> col (+ 1 bison-rule-enumeration-column))
  591. (forward-char -1)
  592. (just-no-space)
  593. (indent-to-column bison-rule-enumeration-column))
  594. ((< col (+ 1 bison-rule-enumeration-column))
  595. (forward-char -1)
  596. (indent-to-column
  597. bison-rule-enumeration-column)))))))
  598. (funcall reset-pt))
  599. ((bison--production-alternative-p bol eol section)
  600. (back-to-indentation);; should put point on "|"
  601. (if (not (= (current-column) bison-rule-separator-column))
  602. (progn
  603. (just-no-space)
  604. (indent-to-column bison-rule-separator-column)))
  605. (forward-char 1)
  606. (if (following-non-ws-p)
  607. (save-excursion
  608. (re-search-forward bison--word-constituent-re);; SIGERR
  609. (let ((col (current-column)))
  610. (cond ((> col (+ 1 bison-rule-enumeration-column))
  611. (forward-char -1)
  612. (just-no-space)
  613. (indent-to-column bison-rule-enumeration-column))
  614. ((< col (+ 1 bison-rule-enumeration-column))
  615. (forward-char -1)
  616. (indent-to-column
  617. bison-rule-enumeration-column))))))
  618. (funcall reset-pt))
  619. (c-sexp
  620. (bison--handle-indent-c-sexp
  621. section bison-rule-enumeration-column bol)
  622. (funcall reset-pt))
  623. ((bison--within-production-body-p section)
  624. (back-to-indentation)
  625. (if (not (= (current-column) bison-rule-enumeration-column))
  626. (progn
  627. (just-no-space)
  628. (indent-to-column
  629. bison-rule-enumeration-column)))
  630. (funcall reset-pt))
  631. (t
  632. (let ((cur-ind (current-indentation)))
  633. (if (eq (save-excursion (search-backward "}" bol t))
  634. cur-ind)
  635. (if (not (= cur-ind bison-rule-enumeration-column))
  636. (progn
  637. (back-to-indentation)
  638. (just-no-space)
  639. (indent-to-column bison-rule-enumeration-column)
  640. (funcall reset-pt)))
  641. ;; else leave alone
  642. )))))
  643. ((= section bison--c-code-section)
  644. (c-indent-line))
  645. ))))
  646. ;; *************** electric-functions ***************
  647. (defun bison-electric-colon (arg)
  648. "If the colon <:> delineates a production,
  649. then insert a semicolon on the next line in the BISON-RULE-SEPARATOR-COLUMN,
  650. put the cursor in the BISON-RULE-ENUMERATION-COLUMN for the beginning
  651. of the rule
  652. else just run self-insert-command
  653. A colon delineates a production by the fact that it is immediately preceded by
  654. a word(alphanumerics or '_''s), and there is no previous white space.
  655. "
  656. (interactive "P")
  657. (self-insert-command (prefix-numeric-value arg))
  658. (if (and bison-electric-colon-v
  659. (not bison-all-electricity-off))
  660. (if (and (= bison--grammar-rules-section (bison--section-p))
  661. (bison--production-p)
  662. (not (bison--within-started-production-p)))
  663. (progn
  664. (save-excursion ; put in a closing semicolon
  665. (newline)
  666. (indent-to-column bison-rule-separator-column)
  667. (insert ";"))
  668. (save-excursion ; remove opening whitespace
  669. (if (re-search-backward
  670. "\\s "
  671. (save-excursion (beginning-of-line) (point))
  672. t)
  673. (just-no-space)))
  674. (if (not (< (current-column) bison-rule-enumeration-column))
  675. (newline))
  676. (indent-to-column bison-rule-enumeration-column)))))
  677. (defun bison-electric-pipe (arg)
  678. "If the pipe <|> is used as a rule separator within a production,
  679. then move it into BISON-RULE-SEPARATOR-COLUMN
  680. indent to BISON-RULE-ENUMERATION-COLUMN on the same line
  681. else just run self-insert-command
  682. "
  683. (interactive "P")
  684. (if (and bison-electric-pipe-v
  685. (not bison-all-electricity-off)
  686. (= bison--grammar-rules-section (bison--section-p))
  687. (line-of-whitespace-p)
  688. )
  689. (progn
  690. (beginning-of-line)
  691. (just-no-space)
  692. (indent-to-column bison-rule-separator-column)
  693. (self-insert-command (prefix-numeric-value arg))
  694. (indent-to-column bison-rule-enumeration-column)
  695. )
  696. (self-insert-command (prefix-numeric-value arg))))
  697. (defun bison-electric-open-brace (arg)
  698. "used for the opening brace of a C action definition for production rules,
  699. if there is only whitespace before \(point\), then put open-brace in
  700. bison-rule-enumeration-column"
  701. (interactive "P")
  702. (if (and bison-electric-open-brace-v
  703. (not bison-all-electricity-off))
  704. (let ((section (bison--section-p)))
  705. (cond ((and (= section bison--grammar-rules-section)
  706. (not (bison--within-braced-c-expression-p section))
  707. (not (previous-non-ws-p)))
  708. (if (not (= (current-column) bison-rule-enumeration-column))
  709. (progn
  710. (just-no-space)
  711. (indent-to-column bison-rule-enumeration-column))))
  712. ((and (= section bison--bison-decls-section)
  713. (not (bison--within-braced-c-expression-p section))
  714. (not (previous-non-ws-p)))
  715. (if (not (= (current-column) 0))
  716. (progn
  717. (just-no-space)
  718. (indent-to-column 0)))))))
  719. (self-insert-command (prefix-numeric-value arg)))
  720. (defun bison-electric-close-brace (arg)
  721. "If the close-brace \"}\" is used as the c-declarations section closer
  722. in \"%}\", then make sure the \"%}\" indents to the beginning of the line"
  723. (interactive "P")
  724. (self-insert-command (prefix-numeric-value arg))
  725. (if (and bison-electric-close-brace-v
  726. (not bison-all-electricity-off))
  727. (cond ((search-backward "%}" (- (point) 2) t)
  728. (if (= (bison--section-p) bison--c-decls-section)
  729. (progn
  730. (just-no-space)
  731. (forward-char 2)) ; for "%}"
  732. (forward-char 1)))
  733. )))
  734. (defun bison-electric-semicolon (arg)
  735. "if the semicolon is used to end a production, then place it in
  736. bison-rule-separator-column
  737. a semicolon is deemed to be used for ending a production if it is not found
  738. within braces
  739. this is just self-insert-command as i have yet to write the actual
  740. bison-electric-semicolon function yet
  741. "
  742. (interactive "P")
  743. (self-insert-command (prefix-numeric-value arg)))
  744. (defun bison-electric-percent (arg)
  745. "If the percent is a declarer in the bison declaration's section,
  746. then put it in the 0 column."
  747. (interactive "P")
  748. (if (and bison-electric-percent-v
  749. (not bison-all-electricity-off))
  750. (let ((section (bison--section-p)))
  751. (if (and (= section bison--bison-decls-section)
  752. (not (bison--within-braced-c-expression-p section))
  753. (not (previous-non-ws-p))
  754. (not (= (current-column) 0)))
  755. (just-no-space))))
  756. (self-insert-command (prefix-numeric-value arg)))
  757. (defun bison-electric-less-than (arg)
  758. "If the less-than is a type declarer opener for tokens in the bison
  759. declaration section, then put it in the bison-decl-type-column column."
  760. (interactive "P")
  761. (if (and bison-electric-less-than-v
  762. (not bison-all-electricity-off))
  763. (if (and (= (bison--section-p) bison--bison-decls-section)
  764. (bison--bison-decl-opener-p
  765. (save-excursion (beginning-of-line) (point))
  766. (point)))
  767. (progn
  768. (just-no-space)
  769. (indent-to-column bison-decl-type-column))))
  770. (self-insert-command (prefix-numeric-value arg)))
  771. (defun bison-electric-greater-than (arg)
  772. "If the greater-than is a type declarer closer for tokens in the bison
  773. declaration section, then indent to bison-decl-token-column."
  774. (interactive "P")
  775. (self-insert-command (prefix-numeric-value arg))
  776. (if (and bison-electric-greater-than-v
  777. (not bison-all-electricity-off))
  778. (let ((current-pt (point))
  779. (bol (save-excursion (beginning-of-line) (point))))
  780. (if (and (= (bison--section-p) bison--bison-decls-section)
  781. (bison--bison-decl-opener-p bol (point)))
  782. (if (search-backward "<" bol t)
  783. (if (re-search-forward
  784. (concat "<" bison--word-constituent-re "+>")
  785. current-pt t)
  786. (if (not (following-non-ws-p))
  787. (progn
  788. (just-no-space)
  789. (indent-to-column bison-decl-token-column)))))))))
  790. ;;;###autoload
  791. (define-derived-mode jison-mode bison-mode "jison"
  792. "Major mode for editing jison files.")
  793. ;;;###autoload
  794. (define-derived-mode flex-mode bison-mode "flex"
  795. "Major mode for editing flex files. (bison-mode by any other name)")
  796. (provide 'bison-mode)
  797. (provide 'jison-mode)
  798. (provide 'flex-mode)
  799. ;;; bison-mode.el ends here