12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666 |
- ;;; antlr-mode.el --- major mode for ANTLR grammar files
- ;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
- ;; Author: Christoph.Wedler@sap.com
- ;; Keywords: languages, ANTLR, code generator
- ;; Version: 2.2c
- ;; X-URL: http://antlr-mode.sourceforge.net/
- ;; This file is part of GNU Emacs.
- ;; GNU Emacs 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 3 of the License, or
- ;; (at your option) any later version.
- ;; GNU Emacs 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.
- ;; You should have received a copy of the GNU General Public License
- ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
- ;;; Commentary:
- ;; The Emacs package ANTLR-Mode provides: syntax highlighting for ANTLR grammar
- ;; files, automatic indentation, menus containing rule/token definitions and
- ;; supported options and various other things like running ANTLR from within
- ;; Emacs.
- ;; For details, check <http://antlr-mode.sourceforge.net/> or, if you prefer
- ;; the manual style, follow all commands mentioned in the documentation of
- ;; `antlr-mode'. ANTLR is a LL(k)-based recognition tool which generates
- ;; lexers, parsers and tree transformers in Java, C++ or Sather and can be
- ;; found at <http://www.antlr.org/>.
- ;; Bug fixes, bug reports, improvements, and suggestions for the newest version
- ;; are strongly appreciated.
- ;; To-do/Wish-list:
- ;;
- ;; * Next Version [C-c C-w]. Produce HTML document with syntax highlighted
- ;; and hyper-links (using htmlize).
- ;; * Next Version [C-c C-u]. Insert/update special comments: each rule lists
- ;; all rules which use the current rule. With font-lock update.
- ;; * Next Version. Make hiding much more customizable.
- ;; * Planned [C-c C-j]. Jump to generated coding.
- ;; * Planned. Further support for imenu, i.e., include entries for method
- ;; definitions at beginning of grammar class.
- ;; * Planned [C-c C-p]. Pack/unpack rule/subrule & options (one/multi-line).
- ;;
- ;; * Probably. Show rules/dependencies for ANT like for Makefile (does ANT
- ;; support vocabularies and grammar inheritance?), I have to look at
- ;; jde-ant.el: http://jakarta.apache.org/ant/manual/OptionalTasks/antlr.html
- ;; * Probably. Make `indent-region' faster, especially in actions. ELP
- ;; profiling in a class init action shows half the time is spent in
- ;; `antlr-next-rule', the other half in `c-guess-basic-syntax'.
- ;; * Unlikely. Sather as generated language with syntax highlighting etc/.
- ;; Questions/problems: is sather-mode.el the standard mode for sather, is it
- ;; still supported, what is its relationship to eiffel3.el? Requirement:
- ;; this mode must not depend on a Sather mode.
- ;; * Unlikely. Faster syntax highlighting: sectionize the buffer into Antlr
- ;; and action code and run special highlighting functions on these regions.
- ;; Problems: code size, this mode would depend on font-lock internals.
- ;;; Installation:
- ;; This file requires Emacs-20.3, XEmacs-20.4 or higher and package cc-mode.
- ;; If antlr-mode is not part of your distribution, put this file into your
- ;; load-path and the following into your ~/.emacs:
- ;; (autoload 'antlr-mode "antlr-mode" nil t)
- ;; (setq auto-mode-alist (cons '("\\.g\\'" . antlr-mode) auto-mode-alist))
- ;; (add-hook 'speedbar-load-hook ; would be too late in antlr-mode.el
- ;; (lambda () (speedbar-add-supported-extension ".g")))
- ;; I strongly recommend to use font-lock with a support mode like fast-lock,
- ;; lazy-lock or better jit-lock (Emacs-21.1+) / lazy-shot (XEmacs).
- ;; To customize, use menu item "Antlr" -> "Customize Antlr".
- ;;; Code:
- (eval-when-compile
- (require 'cl))
- (require 'easymenu)
- (require 'cc-mode)
- ;; Just to get the rid of the byte compiler warning. The code for
- ;; this function and its friends are too complex for their own good.
- (declare-function cond-emacs-xemacs-macfn "antlr-mode" (args &optional msg))
- ;; General Emacs/XEmacs-compatibility compile-time macros
- (eval-when-compile
- (defmacro cond-emacs-xemacs (&rest args)
- (cond-emacs-xemacs-macfn
- args "`cond-emacs-xemacs' must return exactly one element"))
- (defun cond-emacs-xemacs-macfn (args &optional msg)
- (if (atom args) args
- (and (eq (car args) :@) (null msg) ; (:@ ...spliced...)
- (setq args (cdr args)
- msg "(:@ ....) must return exactly one element"))
- (let ((ignore (if (featurep 'xemacs) :EMACS :XEMACS))
- (mode :BOTH) code)
- (while (consp args)
- (if (memq (car args) '(:EMACS :XEMACS :BOTH)) (setq mode (pop args)))
- (if (atom args)
- (or args (error "Used selector %s without elements" mode))
- (or (eq ignore mode)
- (push (cond-emacs-xemacs-macfn (car args)) code))
- (pop args)))
- (cond (msg (if (or args (cdr code)) (error msg) (car code)))
- ((or (null args) (eq ignore mode)) (nreverse code))
- (t (nconc (nreverse code) args))))))
- ;; Emacs/XEmacs-compatibility `defun': remove interactive "_" for Emacs, use
- ;; existing functions when they are `fboundp', provide shortcuts if they are
- ;; known to be defined in a specific Emacs branch (for short .elc)
- (defmacro defunx (name arglist &rest definition)
- (let ((xemacsp (featurep 'xemacs)) reuses)
- (while (memq (car definition)
- '(:try :emacs-and-try :xemacs-and-try))
- (if (eq (pop definition) (if xemacsp :xemacs-and-try :emacs-and-try))
- (setq reuses (car definition)
- definition nil)
- (push (pop definition) reuses)))
- (if (and reuses (symbolp reuses))
- `(defalias ',name ',reuses)
- (let* ((docstring (if (stringp (car definition)) (pop definition)))
- (spec (and (not xemacsp)
- (eq (car-safe (car definition)) 'interactive)
- (null (cddar definition))
- (cadar definition))))
- (if (and (stringp spec)
- (not (string-equal spec ""))
- (eq (aref spec 0) ?_))
- (setq definition
- (cons (if (string-equal spec "_")
- '(interactive)
- `(interactive ,(substring spec 1)))
- (cdr definition))))
- (if (null reuses)
- `(defun ,name ,arglist ,docstring
- ,@(cond-emacs-xemacs-macfn definition))
- ;; no dynamic docstring in this case
- `(eval-and-compile ; no warnings in Emacs
- (defalias ',name
- (cond ,@(mapcar (lambda (func) `((fboundp ',func) ',func))
- (nreverse reuses))
- (t ,(if definition
- `(lambda ,arglist ,docstring
- ,@(cond-emacs-xemacs-macfn definition))
- 'ignore))))))))))
- (defmacro ignore-errors-x (&rest body)
- (let ((specials '((scan-sexps . 4) (scan-lists . 5)))
- spec nils)
- (if (and (featurep 'xemacs)
- (null (cdr body)) (consp (car body))
- (setq spec (assq (caar body) specials))
- (>= (setq nils (- (cdr spec) (length (car body)))) 0))
- `(,@(car body) ,@(make-list nils nil) t)
- `(ignore-errors ,@body)))))
- ;; More compile-time-macros
- (eval-when-compile
- (defmacro save-buffer-state-x (&rest body) ; similar to EMACS/lazy-lock.el
- (let ((modified (with-no-warnings (gensym "save-buffer-state-x-modified-"))))
- `(let ((,modified (buffer-modified-p)))
- (unwind-protect
- (let ((buffer-undo-list t) (inhibit-read-only t)
- ,@(unless (featurep 'xemacs)
- '((inhibit-point-motion-hooks t) deactivate-mark))
- before-change-functions after-change-functions
- buffer-file-name buffer-file-truename)
- ,@body)
- (and (not ,modified) (buffer-modified-p)
- (set-buffer-modified-p nil)))))))
- (put 'save-buffer-state-x 'lisp-indent-function 0)
- ;; get rid of byte-compile warnings
- (eval-when-compile
- (require 'cc-mode))
- (defvar outline-level)
- (defvar imenu-use-markers)
- (defvar imenu-create-index-function)
- ;; We cannot use `c-forward-syntactic-ws' directly since it is a macro since
- ;; cc-mode-5.30 => antlr-mode compiled with older cc-mode would fail (macro
- ;; call) when used with newer cc-mode. Also, antlr-mode compiled with newer
- ;; cc-mode would fail (undefined `c-forward-sws') when used with older cc-mode.
- ;; Additional to the `defalias' below, we must set `antlr-c-forward-sws' to
- ;; `c-forward-syntactic-ws' when `c-forward-sws' is not defined after requiring
- ;; cc-mode.
- (defalias 'antlr-c-forward-sws 'c-forward-sws)
- ;;;;##########################################################################
- ;;;; Variables
- ;;;;##########################################################################
- (defgroup antlr nil
- "Major mode for ANTLR grammar files."
- :group 'languages
- :link '(emacs-commentary-link "antlr-mode.el")
- :link '(url-link "http://antlr-mode.sourceforge.net/")
- :prefix "antlr-")
- (defconst antlr-version "2.2c"
- "ANTLR major mode version number.
- Check <http://antlr-mode.sourceforge.net/> for the newest.")
- ;;;===========================================================================
- ;;; Controlling ANTLR's code generator (language option)
- ;;;===========================================================================
- (defvar antlr-language nil
- "Major mode corresponding to ANTLR's \"language\" option.
- Set via `antlr-language-alist'. The only useful place to change this
- buffer-local variable yourself is in `antlr-mode-hook' or in the \"local
- variable list\" near the end of the file, see
- `enable-local-variables'.")
- (defcustom antlr-language-alist
- '((java-mode "Java" nil "\"Java\"" "Java")
- (c++-mode "C++" "\"Cpp\"" "Cpp"))
- "List of ANTLR's supported languages.
- Each element in this list looks like
- \(MAJOR-MODE MODELINE-STRING OPTION-VALUE...)
- MAJOR-MODE, the major mode of the code in the grammar's actions, is the
- value of `antlr-language' if the first group in the string matched by
- REGEXP in `antlr-language-limit-n-regexp' is one of the OPTION-VALUEs.
- An OPTION-VALUE of nil denotes the fallback element. MODELINE-STRING is
- also displayed in the modeline next to \"Antlr\"."
- :group 'antlr
- :type '(repeat (group :value (java-mode "")
- (function :tag "Major mode")
- (string :tag "Modeline string")
- (repeat :tag "ANTLR language option" :inline t
- (choice (const :tag "Default" nil)
- string )))))
- (defcustom antlr-language-limit-n-regexp
- '(8192 . "language[ \t]*=[ \t]*\\(\"?[A-Z][A-Za-z_]*\"?\\)")
- "Used to set a reasonable value for `antlr-language'.
- Looks like \(LIMIT \. REGEXP). Search for REGEXP from the beginning of
- the buffer to LIMIT and use the first group in the matched string to set
- the language according to `antlr-language-alist'."
- :group 'antlr
- :type '(cons (choice :tag "Limit" (const :tag "No" nil) (integer :value 0))
- regexp))
- ;;;===========================================================================
- ;;; Hide/Unhide, Indent/Tabs
- ;;;===========================================================================
- (defcustom antlr-action-visibility 3
- "Visibility of actions when command `antlr-hide-actions' is used.
- If nil, the actions with their surrounding braces are hidden. If a
- number, do not hide the braces, only hide the contents if its length is
- greater than this number."
- :group 'antlr
- :type '(choice (const :tag "Completely hidden" nil)
- (integer :tag "Hidden if longer than" :value 3)))
- (defcustom antlr-indent-comment 'tab
- "*Non-nil, if the indentation should touch lines in block comments.
- If nil, no continuation line of a block comment is changed. If t, they
- are changed according to `c-indentation-line'. When not nil and not t,
- they are only changed by \\[antlr-indent-command]."
- :group 'antlr
- :type '(radio (const :tag "No" nil)
- (const :tag "Always" t)
- (sexp :tag "With TAB" :format "%t" :value tab)))
- (defcustom antlr-tab-offset-alist
- '((antlr-mode nil 4 nil)
- (java-mode "antlr" 4 nil))
- "Alist to determine whether to use ANTLR's convention for TABs.
- Each element looks like \(MAJOR-MODE REGEXP TAB-WIDTH INDENT-TABS-MODE).
- The first element whose MAJOR-MODE is nil or equal to `major-mode' and
- whose REGEXP is nil or matches variable `buffer-file-name' is used to
- set `tab-width' and `indent-tabs-mode'. This is useful to support both
- ANTLR's and Java's indentation styles. Used by `antlr-set-tabs'."
- :group 'antlr
- :type '(repeat (group :value (antlr-mode nil 8 nil)
- (choice (const :tag "All" nil)
- (function :tag "Major mode"))
- (choice (const :tag "All" nil) regexp)
- (integer :tag "Tab width")
- (boolean :tag "Indent-tabs-mode"))))
- (defcustom antlr-indent-style "java"
- "*If non-nil, cc-mode indentation style used for `antlr-mode'.
- See `c-set-style' and for details, where the most interesting part in
- `c-style-alist' is the value of `c-basic-offset'."
- :group 'antlr
- :type '(choice (const nil) regexp))
- (defcustom antlr-indent-item-regexp
- "[]}):;|&]" ; & is local ANTLR extension (SGML's and-connector)
- "Regexp matching lines which should be indented by one TAB less.
- See `antlr-indent-line' and command \\[antlr-indent-command]."
- :group 'antlr
- :type 'regexp)
- (defcustom antlr-indent-at-bol-alist
- ;; eval-when-compile not usable with defcustom...
- '((java-mode . "\\(package\\|import\\)\\>")
- (c++-mode . "#\\(assert\\|cpu\\|define\\|endif\\|el\\(if\\|se\\)\\|i\\(dent\\|f\\(def\\|ndef\\)?\\|mport\\|nclude\\(_next\\)?\\)\\|line\\|machine\\|pragma\\|system\\|un\\(assert\\|def\\)\\|warning\\)\\>"))
- "Alist of regexps matching lines are indented at column 0.
- Each element in this list looks like (MODE . REGEXP) where MODE is a
- function and REGEXP is a regular expression.
- If `antlr-language' equals to a MODE, the line starting at the first
- non-whitespace is matched by the corresponding REGEXP, and the line is
- part of a header action, indent the line at column 0 instead according
- to the normal rules of `antlr-indent-line'."
- :group 'antlr
- :type '(repeat (cons (function :tag "Major mode") regexp)))
- ;; adopt indentation to cc-engine
- (defvar antlr-disabling-cc-syntactic-symbols
- '(statement-block-intro
- defun-block-intro topmost-intro statement-case-intro member-init-intro
- arglist-intro brace-list-intro knr-argdecl-intro inher-intro
- objc-method-intro
- block-close defun-close class-close brace-list-close arglist-close
- inline-close extern-lang-close namespace-close))
- ;;;===========================================================================
- ;;; Options: customization
- ;;;===========================================================================
- (defcustom antlr-options-use-submenus t
- "*Non-nil, if the major mode menu should include option submenus.
- If nil, the menu just includes a command to insert options. Otherwise,
- it includes four submenus to insert file/grammar/rule/subrule options."
- :group 'antlr
- :type 'boolean)
- (defcustom antlr-tool-version 20701
- "*The version number of the Antlr tool.
- The value is an integer of the form XYYZZ which stands for vX.YY.ZZ.
- This variable is used to warn about non-supported options and to supply
- version correct option values when using \\[antlr-insert-option].
- Don't use a number smaller than 20600 since the stored history of
- Antlr's options starts with v2.06.00, see `antlr-options-alists'. You
- can make this variable buffer-local."
- :group 'antlr
- :type 'integer)
- (defcustom antlr-options-auto-colon t
- "*Non-nil, if `:' is inserted with a rule or subrule options section.
- A `:' is only inserted if this value is non-nil, if a rule or subrule
- option is inserted with \\[antlr-insert-option], if there was no rule or
- subrule options section before, and if a `:' is not already present
- after the section, ignoring whitespace, comments and the init action."
- :group 'antlr
- :type 'boolean)
- (defcustom antlr-options-style nil
- "List of symbols which determine the style of option values.
- If a style symbol is present, the corresponding option value is put into
- quotes, i.e., represented as a string, otherwise it is represented as an
- identifier.
- The only style symbol used in the default value of `antlr-options-alist'
- is `language-as-string'. See also `antlr-read-value'."
- :group 'antlr
- :type '(repeat (symbol :tag "Style symbol")))
- (defcustom antlr-options-push-mark t
- "*Non-nil, if inserting an option should set & push mark.
- If nil, never set mark when inserting an option with command
- \\[antlr-insert-option]. If t, always set mark via `push-mark'. If a
- number, only set mark if point was outside the options area before and
- the number of lines between point and the insert position is greater
- than this value. Otherwise, only set mark if point was outside the
- options area before."
- :group 'antlr
- :type '(radio (const :tag "No" nil)
- (const :tag "Always" t)
- (integer :tag "Lines between" :value 10)
- (sexp :tag "If outside options" :format "%t" :value outside)))
- (defcustom antlr-options-assign-string " = "
- "*String containing `=' to use between option name and value.
- This string is only used if the option to insert did not exist before
- or if there was no `=' after it. In other words, the spacing around an
- existing `=' won't be changed when changing an option value."
- :group 'antlr
- :type 'string)
- ;;;===========================================================================
- ;;; Options: definitions
- ;;;===========================================================================
- (defvar antlr-options-headings '("file" "grammar" "rule" "subrule")
- "Headings for the four different option kinds.
- The standard value is (\"file\" \"grammar\" \"rule\" \"subrule\"). See
- `antlr-options-alists'")
- (defvar antlr-options-alists
- '(;; file options ----------------------------------------------------------
- (("language" antlr-language-option-extra
- (20600 antlr-read-value
- "Generated language: " language-as-string
- (("Java") ("Cpp") ("HTML") ("Diagnostic")))
- (20700 antlr-read-value
- "Generated language: " language-as-string
- (("Java") ("Cpp") ("HTML") ("Diagnostic") ("Sather"))))
- ("mangleLiteralPrefix" nil
- (20600 antlr-read-value
- "Prefix for literals (default LITERAL_): " t))
- ("namespace" antlr-c++-mode-extra
- (20700 antlr-read-value
- "Wrap generated C++ code in namespace: " t))
- ("namespaceStd" antlr-c++-mode-extra
- (20701 antlr-read-value
- "Replace ANTLR_USE_NAMESPACE(std) by: " t))
- ("namespaceAntlr" antlr-c++-mode-extra
- (20701 antlr-read-value
- "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
- ("genHashLines" antlr-c++-mode-extra
- (20701 antlr-read-boolean
- "Include #line in generated C++ code? "))
- )
- ;; grammar options --------------------------------------------------------
- (("k" nil
- (20600 antlr-read-value
- "Lookahead depth: "))
- ("importVocab" nil
- (20600 antlr-read-value
- "Import vocabulary: "))
- ("exportVocab" nil
- (20600 antlr-read-value
- "Export vocabulary: "))
- ("testLiterals" nil ; lexer only
- (20600 antlr-read-boolean
- "Test each token against literals table? "))
- ("defaultErrorHandler" nil ; not for lexer
- (20600 antlr-read-boolean
- "Generate default exception handler for each rule? "))
- ("codeGenMakeSwitchThreshold" nil
- (20600 antlr-read-value
- "Min number of alternatives for 'switch': "))
- ("codeGenBitsetTestThreshold" nil
- (20600 antlr-read-value
- "Min size of lookahead set for bitset test: "))
- ("analyzerDebug" nil
- (20600 antlr-read-boolean
- "Display debugging info during grammar analysis? "))
- ("codeGenDebug" nil
- (20600 antlr-read-boolean
- "Display debugging info during code generation? "))
- ("buildAST" nil ; not for lexer
- (20600 antlr-read-boolean
- "Use automatic AST construction/transformation? "))
- ("ASTLabelType" nil ; not for lexer
- (20600 antlr-read-value
- "Class of user-defined AST node: " t))
- ("charVocabulary" nil ; lexer only
- (20600 nil
- "Insert character vocabulary"))
- ("interactive" nil
- (20600 antlr-read-boolean
- "Generate interactive lexer/parser? "))
- ("caseSensitive" nil ; lexer only
- (20600 antlr-read-boolean
- "Case significant when matching characters? "))
- ("caseSensitiveLiterals" nil ; lexer only
- (20600 antlr-read-boolean
- "Case significant when testing literals table? "))
- ("classHeaderSuffix" nil
- (20600 nil
- "Additional string for grammar class definition"))
- ("filter" nil ; lexer only
- (20600 antlr-read-boolean
- "Skip rule (the name, true or false): "
- antlr-grammar-tokens))
- ("namespace" antlr-c++-mode-extra
- (20700 antlr-read-value
- "Wrap generated C++ code for grammar in namespace: " t))
- ("namespaceStd" antlr-c++-mode-extra
- (20701 antlr-read-value
- "Replace ANTLR_USE_NAMESPACE(std) by: " t))
- ("namespaceAntlr" antlr-c++-mode-extra
- (20701 antlr-read-value
- "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
- ("genHashLines" antlr-c++-mode-extra
- (20701 antlr-read-boolean
- "Include #line in generated C++ code? "))
- ;;; ("autoTokenDef" nil ; parser only
- ;;; (80000 antlr-read-boolean ; default: true
- ;;; "Automatically define referenced token? "))
- ;;; ("keywordsMeltTo" nil ; parser only
- ;;; (80000 antlr-read-value
- ;;; "Change non-matching keywords to token type: "))
- )
- ;; rule options ----------------------------------------------------------
- (("testLiterals" nil ; lexer only
- (20600 antlr-read-boolean
- "Test this token against literals table? "))
- ("defaultErrorHandler" nil ; not for lexer
- (20600 antlr-read-boolean
- "Generate default exception handler for this rule? "))
- ("ignore" nil ; lexer only
- (20600 antlr-read-value
- "In this rule, ignore tokens of type: " nil
- antlr-grammar-tokens))
- ("paraphrase" nil ; lexer only
- (20600 antlr-read-value
- "In messages, replace name of this token by: " t))
- )
- ;; subrule options -------------------------------------------------------
- (("warnWhenFollowAmbig" nil
- (20600 antlr-read-boolean
- "Display warnings for ambiguities with FOLLOW? "))
- ("generateAmbigWarnings" nil
- (20600 antlr-read-boolean
- "Display warnings for ambiguities? "))
- ("greedy" nil
- (20700 antlr-read-boolean
- "Make this optional/loop subrule greedy? "))
- ))
- "Definitions for Antlr's options of all four different kinds.
- The value looks like \(FILE GRAMMAR RULE SUBRULE) where each FILE,
- GRAMMAR, RULE, and SUBRULE is a list of option definitions of the
- corresponding kind, i.e., looks like \(OPTION-DEF...).
- Each OPTION-DEF looks like \(OPTION-NAME EXTRA-FN VALUE-SPEC...) which
- defines a file/grammar/rule/subrule option with name OPTION-NAME. The
- OPTION-NAMEs are used for the creation of the \"Insert XXX Option\"
- submenus, see `antlr-options-use-submenus', and to allow to insert the
- option name with completion when using \\[antlr-insert-option].
- If EXTRA-FN is a function, it is called at different phases of the
- insertion with arguments \(PHASE OPTION-NAME). PHASE can have the
- values `before-input' or `after-insertion', additional phases might be
- defined in future versions of this mode. The phase `before-input'
- occurs before the user is asked to insert a value. The phase
- `after-insertion' occurs after the option value has been inserted.
- EXTRA-FN might be called with additional arguments in future versions of
- this mode.
- Each specification VALUE-SPEC looks like \(VERSION READ-FN ARG...). The
- last VALUE-SPEC in an OPTION-DEF whose VERSION is smaller or equal to
- `antlr-tool-version' specifies how the user is asked for the value of
- the option.
- If READ-FN is nil, the only ARG is a string which is printed at the echo
- area to guide the user what to insert at point. Otherwise, READ-FN is
- called with arguments \(INIT-VALUE ARG...) to get the new value of the
- option. INIT-VALUE is the old value of the option or nil.
- The standard value contains the following functions as READ-FN:
- `antlr-read-value' with ARGs = \(PROMPT AS-STRING TABLE) which reads a
- general value, or `antlr-read-boolean' with ARGs = \(PROMPT TABLE) which
- reads a boolean value or a member of TABLE. PROMPT is the prompt when
- asking for a new value. If non-nil, TABLE is a table for completion or
- a function evaluating to such a table. The return value is quoted if
- AS-STRING is non-nil and is either t or a symbol which is a member of
- `antlr-options-style'.")
- ;;;===========================================================================
- ;;; Run tool, create Makefile dependencies
- ;;;===========================================================================
- (defcustom antlr-tool-command "java antlr.Tool"
- "*Command used in \\[antlr-run-tool] to run the Antlr tool.
- This variable should include all options passed to Antlr except the
- option \"-glib\" which is automatically suggested if necessary."
- :group 'antlr
- :type 'string)
- (defcustom antlr-ask-about-save t
- "*If not nil, \\[antlr-run-tool] asks which buffers to save.
- Otherwise, it saves all modified buffers before running without asking."
- :group 'antlr
- :type 'boolean)
- (defcustom antlr-makefile-specification
- '("\n" ("GENS" "GENS%d" " \\\n\t") "$(ANTLR)")
- "*Variable to specify the appearance of the generated makefile rules.
- This variable influences the output of \\[antlr-show-makefile-rules].
- It looks like \(RULE-SEP GEN-VAR-SPEC COMMAND).
- RULE-SEP is the string to separate different makefile rules. COMMAND is
- a string with the command which runs the Antlr tool, it should include
- all options except the option \"-glib\" which is automatically added
- if necessary.
- If GEN-VAR-SPEC is nil, each target directly consists of a list of
- files. If GEN-VAR-SPEC looks like \(GEN-VAR GEN-VAR-FORMAT GEN-SEP), a
- Makefile variable is created for each rule target.
- Then, GEN-VAR is a string with the name of the variable which contains
- the file names of all makefile rules. GEN-VAR-FORMAT is a format string
- producing the variable of each target with substitution COUNT/%d where
- COUNT starts with 1. GEN-SEP is used to separate long variable values."
- :group 'antlr
- :type '(list (string :tag "Rule separator")
- (choice
- (const :tag "Direct targets" nil)
- (list :tag "Variables for targets"
- (string :tag "Variable for all targets")
- (string :tag "Format for each target variable")
- (string :tag "Variable separator")))
- (string :tag "ANTLR command")))
- (defvar antlr-file-formats-alist
- '((java-mode ("%sTokenTypes.java") ("%s.java"))
- (c++-mode ("%sTokenTypes.hpp") ("%s.cpp" "%s.hpp")))
- "Language dependent formats which specify generated files.
- Each element in this list looks looks like
- \(MAJOR-MODE (VOCAB-FILE-FORMAT...) (CLASS-FILE-FORMAT...)).
- The element whose MAJOR-MODE is equal to `antlr-language' is used to
- specify the generated files which are language dependent. See variable
- `antlr-special-file-formats' for language independent files.
- VOCAB-FILE-FORMAT is a format string, it specifies with substitution
- VOCAB/%s the generated file for each export vocabulary VOCAB.
- CLASS-FILE-FORMAT is a format string, it specifies with substitution
- CLASS/%s the generated file for each grammar class CLASS.")
- (defvar antlr-special-file-formats '("%sTokenTypes.txt" "expanded%s.g")
- "Language independent formats which specify generated files.
- The value looks like \(VOCAB-FILE-FORMAT EXPANDED-GRAMMAR-FORMAT).
- VOCAB-FILE-FORMAT is a format string, it specifies with substitution
- VOCAB/%s the generated or input file for each export or import
- vocabulary VOCAB, respectively. EXPANDED-GRAMMAR-FORMAT is a format
- string, it specifies with substitution GRAMMAR/%s the constructed
- grammar file if the file GRAMMAR.g contains a grammar class which
- extends a class other than \"Lexer\", \"Parser\" or \"TreeParser\".
- See variable `antlr-file-formats-alist' for language dependent
- formats.")
- (defvar antlr-unknown-file-formats '("?%s?.g" "?%s?")
- "*Formats which specify the names of unknown files.
- The value looks like \(SUPER-GRAMMAR-FILE-FORMAT SUPER-EVOCAB-FORMAT).
- SUPER-GRAMMAR-FORMAT is a format string, it specifies with substitution
- SUPER/%s the name of a grammar file for Antlr's option \"-glib\" if no
- grammar file in the current directory defines the class SUPER or if it
- is defined more than once. SUPER-EVOCAB-FORMAT is a format string, it
- specifies with substitution SUPER/%s the name for the export vocabulary
- of above mentioned class SUPER.")
- (defvar antlr-help-unknown-file-text
- "## The following rules contain filenames of the form
- ## \"?SUPERCLASS?.g\" (and \"?SUPERCLASS?TokenTypes.txt\")
- ## where SUPERCLASS is not found to be defined in any grammar file of
- ## the current directory or is defined more than once. Please replace
- ## these filenames by the grammar files (and their exportVocab).\n\n"
- "String indicating the existence of unknown files in the Makefile.
- See \\[antlr-show-makefile-rules] and `antlr-unknown-file-formats'.")
- (defvar antlr-help-rules-intro
- "The following Makefile rules define the dependencies for all (non-
- expanded) grammars in directory \"%s\".\n
- They are stored in the kill-ring, i.e., you can insert them with C-y
- into your Makefile. You can also invoke M-x antlr-show-makefile-rules
- from within a Makefile to insert them directly.\n\n\n"
- "Introduction to use with \\[antlr-show-makefile-rules].
- It is a format string and used with substitution DIRECTORY/%s where
- DIRECTORY is the name of the current directory.")
- ;;;===========================================================================
- ;;; Menu
- ;;;===========================================================================
- (defcustom antlr-imenu-name t ; (featurep 'xemacs) ; TODO: Emacs-21 bug?
- "*Non-nil, if a \"Index\" menu should be added to the menubar.
- If it is a string, it is used instead \"Index\". Requires package
- imenu."
- :group 'antlr
- :type '(choice (const :tag "No menu" nil)
- (const :tag "Index menu" t)
- (string :tag "Other menu name")))
- (defvar antlr-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\t" 'antlr-indent-command)
- (define-key map "\e\C-a" 'antlr-beginning-of-rule)
- (define-key map "\e\C-e" 'antlr-end-of-rule)
- (define-key map "\C-c\C-a" 'antlr-beginning-of-body)
- (define-key map "\C-c\C-e" 'antlr-end-of-body)
- (define-key map "\C-c\C-f" 'c-forward-into-nomenclature)
- (define-key map "\C-c\C-b" 'c-backward-into-nomenclature)
- (define-key map "\C-c\C-c" 'comment-region)
- (define-key map "\C-c\C-v" 'antlr-hide-actions)
- (define-key map "\C-c\C-r" 'antlr-run-tool)
- (define-key map "\C-c\C-o" 'antlr-insert-option)
- ;; I'm too lazy to define my own:
- (define-key map "\ea" 'c-beginning-of-statement)
- (define-key map "\ee" 'c-end-of-statement)
- ;; electric keys:
- (define-key map ":" 'antlr-electric-character)
- (define-key map ";" 'antlr-electric-character)
- (define-key map "|" 'antlr-electric-character)
- (define-key map "&" 'antlr-electric-character)
- (define-key map "(" 'antlr-electric-character)
- (define-key map ")" 'antlr-electric-character)
- (define-key map "{" 'antlr-electric-character)
- (define-key map "}" 'antlr-electric-character)
- map)
- "Keymap used in `antlr-mode' buffers.")
- (easy-menu-define antlr-mode-menu antlr-mode-map
- "Major mode menu."
- `("Antlr"
- ,@(if (cond-emacs-xemacs
- :EMACS (and antlr-options-use-submenus
- (>= emacs-major-version 21))
- :XEMACS antlr-options-use-submenus)
- `(("Insert File Option"
- :filter ,(lambda (x) (antlr-options-menu-filter 1 x)))
- ("Insert Grammar Option"
- :filter ,(lambda (x) (antlr-options-menu-filter 2 x)))
- ("Insert Rule Option"
- :filter ,(lambda (x) (antlr-options-menu-filter 3 x)))
- ("Insert Subrule Option"
- :filter ,(lambda (x) (antlr-options-menu-filter 4 x)))
- "---")
- '(["Insert Option" antlr-insert-option
- :active (not buffer-read-only)]))
- ("Forward/Backward"
- ["Backward Rule" antlr-beginning-of-rule t]
- ["Forward Rule" antlr-end-of-rule t]
- ["Start of Rule Body" antlr-beginning-of-body
- :active (antlr-inside-rule-p)]
- ["End of Rule Body" antlr-end-of-body
- :active (antlr-inside-rule-p)]
- "---"
- ["Backward Statement" c-beginning-of-statement t]
- ["Forward Statement" c-end-of-statement t]
- ["Backward Into Nomencl." c-backward-into-nomenclature t]
- ["Forward Into Nomencl." c-forward-into-nomenclature t])
- ["Indent Region" indent-region
- :active (and (not buffer-read-only) (c-region-is-active-p))]
- ["Comment Out Region" comment-region
- :active (and (not buffer-read-only) (c-region-is-active-p))]
- ["Uncomment Region"
- (comment-region (region-beginning) (region-end) '(4))
- :active (and (not buffer-read-only) (c-region-is-active-p))]
- "---"
- ["Hide Actions (incl. Args)" antlr-hide-actions t]
- ["Hide Actions (excl. Args)" (antlr-hide-actions 2) t]
- ["Unhide All Actions" (antlr-hide-actions 0) t]
- "---"
- ["Run Tool on Grammar" antlr-run-tool t]
- ["Show Makefile Rules" antlr-show-makefile-rules t]
- "---"
- ["Customize Antlr" (customize-group 'antlr) t]))
- ;;;===========================================================================
- ;;; font-lock
- ;;;===========================================================================
- (defcustom antlr-font-lock-maximum-decoration 'inherit
- "*The maximum decoration level for fontifying actions.
- Value `none' means, do not fontify actions, just normal grammar code
- according to `antlr-font-lock-additional-keywords'. Value `inherit'
- means, use value of `font-lock-maximum-decoration'. Any other value is
- interpreted as in `font-lock-maximum-decoration' with no level-0
- fontification, see `antlr-font-lock-keywords-alist'.
- While calculating the decoration level for actions, `major-mode' is
- bound to `antlr-language'. For example, with value
- \((java-mode \. 2) (c++-mode \. 0))
- Java actions are fontified with level 2 and C++ actions are not
- fontified at all."
- :group 'antlr
- :type '(choice (const :tag "None" none)
- (const :tag "Inherit" inherit)
- (const :tag "Default" nil)
- (const :tag "Maximum" t)
- (integer :tag "Level" 1)
- (repeat :menu-tag "Mode specific" :tag "Mode specific"
- :value ((t . t))
- (cons :tag "Instance"
- (radio :tag "Mode"
- (const :tag "All" t)
- (symbol :tag "Name"))
- (radio :tag "Decoration"
- (const :tag "Default" nil)
- (const :tag "Maximum" t)
- (integer :tag "Level" 1))))))
- (defconst antlr-no-action-keywords nil
- ;; Using nil directly won't work (would use highest level, see
- ;; `font-lock-choose-keywords'), but a non-symbol, i.e., (list), at `car'
- ;; would break Emacs-21.0:
- "Empty font-lock keywords for actions.
- Do not change the value of this constant.")
- (defvar antlr-font-lock-keywords-alist
- '((java-mode
- antlr-no-action-keywords
- java-font-lock-keywords-1 java-font-lock-keywords-2
- java-font-lock-keywords-3)
- (c++-mode
- antlr-no-action-keywords
- c++-font-lock-keywords-1 c++-font-lock-keywords-2
- c++-font-lock-keywords-3))
- "List of font-lock keywords for actions in the grammar.
- Each element in this list looks like
- \(MAJOR-MODE KEYWORD...)
- If `antlr-language' is equal to MAJOR-MODE, the KEYWORDs are the
- font-lock keywords according to `font-lock-defaults' used for the code
- in the grammar's actions and semantic predicates, see
- `antlr-font-lock-maximum-decoration'.")
- (defvar antlr-default-face 'antlr-default)
- (defface antlr-default '((t nil))
- "Face to prevent strings from language dependent highlighting.
- Do not change."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-default-face 'face-alias 'antlr-default)
- (put 'antlr-font-lock-default-face 'obsolete-face "22.1")
- (defvar antlr-keyword-face 'antlr-keyword)
- (defface antlr-keyword
- (cond-emacs-xemacs
- '((((class color) (background light))
- (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
- (t :inherit font-lock-keyword-face)))
- "ANTLR keywords."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-keyword-face 'face-alias 'antlr-keyword)
- (put 'antlr-font-lock-keyword-face 'obsolete-face "22.1")
- (defvar antlr-syntax-face 'antlr-keyword)
- (defface antlr-syntax
- (cond-emacs-xemacs
- '((((class color) (background light))
- (:foreground "black" :EMACS :weight bold :XEMACS :bold t))
- (t :inherit font-lock-constant-face)))
- "ANTLR syntax symbols like :, |, (, ), ...."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-syntax-face 'face-alias 'antlr-syntax)
- (put 'antlr-font-lock-syntax-face 'obsolete-face "22.1")
- (defvar antlr-ruledef-face 'antlr-ruledef)
- (defface antlr-ruledef
- (cond-emacs-xemacs
- '((((class color) (background light))
- (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
- (t :inherit font-lock-function-name-face)))
- "ANTLR rule references (definition)."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-ruledef-face 'face-alias 'antlr-ruledef)
- (put 'antlr-font-lock-ruledef-face 'obsolete-face "22.1")
- (defvar antlr-tokendef-face 'antlr-tokendef)
- (defface antlr-tokendef
- (cond-emacs-xemacs
- '((((class color) (background light))
- (:foreground "blue" :EMACS :weight bold :XEMACS :bold t))
- (t :inherit font-lock-function-name-face)))
- "ANTLR token references (definition)."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-tokendef-face 'face-alias 'antlr-tokendef)
- (put 'antlr-font-lock-tokendef-face 'obsolete-face "22.1")
- (defvar antlr-ruleref-face 'antlr-ruleref)
- (defface antlr-ruleref
- '((((class color) (background light)) (:foreground "blue4"))
- (t :inherit font-lock-type-face))
- "ANTLR rule references (usage)."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-ruleref-face 'face-alias 'antlr-ruleref)
- (put 'antlr-font-lock-ruleref-face 'obsolete-face "22.1")
- (defvar antlr-tokenref-face 'antlr-tokenref)
- (defface antlr-tokenref
- '((((class color) (background light)) (:foreground "orange4"))
- (t :inherit font-lock-type-face))
- "ANTLR token references (usage)."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-tokenref-face 'face-alias 'antlr-tokenref)
- (put 'antlr-font-lock-tokenref-face 'obsolete-face "22.1")
- (defvar antlr-literal-face 'antlr-literal)
- (defface antlr-literal
- (cond-emacs-xemacs
- '((((class color) (background light))
- (:foreground "brown4" :EMACS :weight bold :XEMACS :bold t))
- (t :inherit font-lock-string-face)))
- "ANTLR special literal tokens.
- It is used to highlight strings matched by the first regexp group of
- `antlr-font-lock-literal-regexp'."
- :group 'antlr)
- ;; backward-compatibility alias
- (put 'antlr-font-lock-literal-face 'face-alias 'antlr-literal)
- (put 'antlr-font-lock-literal-face 'obsolete-face "22.1")
- (defcustom antlr-font-lock-literal-regexp "\"\\(\\sw\\(\\sw\\|-\\)*\\)\""
- "Regexp matching literals with special syntax highlighting, or nil.
- If nil, there is no special syntax highlighting for some literals.
- Otherwise, it should be a regular expression which must contain a regexp
- group. The string matched by the first group is highlighted with
- `antlr-font-lock-literal-face'."
- :group 'antlr
- :type '(choice (const :tag "None" nil) regexp))
- (defvar antlr-class-header-regexp
- "\\(class\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;"
- "Regexp matching class headers.")
- (defvar antlr-font-lock-additional-keywords
- (cond-emacs-xemacs
- `((antlr-invalidate-context-cache)
- ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))"
- (1 antlr-tokendef-face))
- ("\\$\\sw+" (0 antlr-keyword-face))
- ;; the tokens are already fontified as string/docstrings:
- (,(lambda (limit)
- (if antlr-font-lock-literal-regexp
- (antlr-re-search-forward antlr-font-lock-literal-regexp limit)))
- (1 antlr-literal-face t)
- :XEMACS (0 nil)) ; XEmacs bug workaround
- (,(lambda (limit)
- (antlr-re-search-forward antlr-class-header-regexp limit))
- (1 antlr-keyword-face)
- (2 antlr-ruledef-face)
- (3 antlr-keyword-face)
- (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser"))
- antlr-keyword-face
- font-lock-type-face)))
- (,(lambda (limit)
- (antlr-re-search-forward
- "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>"
- limit))
- (1 antlr-keyword-face))
- (,(lambda (limit)
- (antlr-re-search-forward
- "^\\(private\\|public\\|protected\\)\\>[ \t]*\\(\\(\\sw+[ \t]*\\(:\\)?\\)\\)?"
- limit))
- (1 font-lock-type-face) ; not XEmacs's java level-3 fruit salad
- (3 (if (antlr-upcase-p (char-after (match-beginning 3)))
- antlr-tokendef-face
- antlr-ruledef-face) nil t)
- (4 antlr-syntax-face nil t))
- (,(lambda (limit)
- (antlr-re-search-forward "^\\(\\sw+\\)[ \t]*\\(:\\)?" limit))
- (1 (if (antlr-upcase-p (char-after (match-beginning 0)))
- antlr-tokendef-face
- antlr-ruledef-face) nil t)
- (2 antlr-syntax-face nil t))
- (,(lambda (limit)
- ;; v:ruleref and v:"literal" is allowed...
- (antlr-re-search-forward "\\(\\sw+\\)[ \t]*\\([=:]\\)?" limit))
- (1 (if (match-beginning 2)
- (if (eq (char-after (match-beginning 2)) ?=)
- antlr-default-face
- font-lock-variable-name-face)
- (if (antlr-upcase-p (char-after (match-beginning 1)))
- antlr-tokenref-face
- antlr-ruleref-face)))
- (2 antlr-default-face nil t))
- (,(lambda (limit)
- (antlr-re-search-forward "[|&:;(~]\\|)\\([*+?]\\|=>\\)?" limit))
- (0 antlr-syntax-face))))
- "Font-lock keywords for ANTLR's normal grammar code.
- See `antlr-font-lock-keywords-alist' for the keywords of actions.")
- (defvar antlr-font-lock-defaults
- '(antlr-font-lock-keywords
- nil nil ((?_ . "w") (?\( . ".") (?\) . ".")) beginning-of-defun)
- "Font-lock defaults used for ANTLR syntax highlighting.
- The SYNTAX-ALIST element is also used to initialize
- `antlr-action-syntax-table'.")
- ;;;===========================================================================
- ;;; Internal variables
- ;;;===========================================================================
- (defvar antlr-mode-hook nil
- "Hook called by `antlr-mode'.")
- (defvar antlr-mode-syntax-table
- (let ((st (make-syntax-table)))
- (c-populate-syntax-table st)
- st)
- "Syntax table used in `antlr-mode' buffers.
- If non-nil, it will be initialized in `antlr-mode'.")
- ;; used for "in Java/C++ code" = syntactic-depth>0
- (defvar antlr-action-syntax-table
- (let ((st (copy-syntax-table antlr-mode-syntax-table))
- (slist (nth 3 antlr-font-lock-defaults)))
- (while slist
- (modify-syntax-entry (caar slist) (cdar slist) st)
- (setq slist (cdr slist)))
- st)
- "Syntax table used for ANTLR action parsing.
- Initialized by `antlr-mode-syntax-table', changed by SYNTAX-ALIST in
- `antlr-font-lock-defaults'. This table should be selected if you use
- `buffer-syntactic-context' and `buffer-syntactic-context-depth' in order
- not to confuse their context_cache.")
- (defvar antlr-mode-abbrev-table nil
- "Abbreviation table used in `antlr-mode' buffers.")
- (define-abbrev-table 'antlr-mode-abbrev-table ())
- (defvar antlr-slow-cache-enabling-symbol 'loudly
- ;; Emacs's font-lock changes buffer's tick counter, therefore this value should
- ;; be a parameter of a font-lock function, but not any other variable of
- ;; functions which call `antlr-slow-syntactic-context'.
- "If value is a bound symbol, cache will be used even with text changes.
- This is no user option. Used for `antlr-slow-syntactic-context'.")
- (defvar antlr-slow-cache-diff-threshold 5000
- "Maximum distance between `point' and cache position for cache use.
- Used for `antlr-slow-syntactic-context'.")
- ;;;;##########################################################################
- ;;;; The Code
- ;;;;##########################################################################
- ;;;===========================================================================
- ;;; Syntax functions -- Emacs vs XEmacs dependent, part 1
- ;;;===========================================================================
- ;; From help.el (XEmacs-21.1), without `copy-syntax-table'
- (defmacro antlr-with-syntax-table (syntab &rest body)
- "Evaluate BODY with the syntax table SYNTAB."
- `(let ((stab (syntax-table)))
- (unwind-protect
- (progn (set-syntax-table ,syntab) ,@body)
- (set-syntax-table stab))))
- (put 'antlr-with-syntax-table 'lisp-indent-function 1)
- (put 'antlr-with-syntax-table 'edebug-form-spec '(form body))
- (defunx antlr-default-directory ()
- :xemacs-and-try default-directory
- "Return `default-directory'."
- default-directory)
- ;; Check Emacs-21.1 simple.el, `shell-command'.
- (defunx antlr-read-shell-command (prompt &optional initial-input history)
- :xemacs-and-try read-shell-command
- "Read a string from the minibuffer, using `shell-command-history'."
- (read-from-minibuffer prompt initial-input nil nil
- (or history 'shell-command-history)))
- (defunx antlr-with-displaying-help-buffer (thunk &optional _name)
- :xemacs-and-try with-displaying-help-buffer
- "Make a help buffer and call `thunk' there."
- (with-output-to-temp-buffer "*Help*"
- (save-excursion (funcall thunk))))
- ;;;===========================================================================
- ;;; Context cache
- ;;;===========================================================================
- (defvar antlr-slow-context-cache nil "Internal.")
- ;;;(defvar antlr-statistics-full-neg 0)
- ;;;(defvar antlr-statistics-full-diff 0)
- ;;;(defvar antlr-statistics-full-other 0)
- ;;;(defvar antlr-statistics-cache 0)
- ;;;(defvar antlr-statistics-inval 0)
- (defunx antlr-invalidate-context-cache (&rest _dummies)
- ;; checkdoc-params: (dummies)
- "Invalidate context cache for syntactical context information."
- :XEMACS ; XEmacs bug workaround
- (with-current-buffer (get-buffer-create " ANTLR XEmacs bug workaround")
- (buffer-syntactic-context-depth)
- nil)
- :EMACS
- ;;; (incf antlr-statistics-inval)
- (setq antlr-slow-context-cache nil))
- (defunx antlr-syntactic-context ()
- "Return some syntactic context information.
- Return `string' if point is within a string, `block-comment' or
- `comment' is point is within a comment or the depth within all
- parenthesis-syntax delimiters at point otherwise.
- WARNING: this may alter `match-data'."
- :XEMACS
- (or (buffer-syntactic-context) (buffer-syntactic-context-depth))
- :EMACS
- (let ((orig (point)) diff state
- ;; Arg, Emacs's (buffer-modified-tick) changes with font-lock. Use
- ;; hack that `loudly' is bound during font-locking => cache use will
- ;; increase from 7% to 99.99% during font-locking.
- (tick (or (boundp antlr-slow-cache-enabling-symbol)
- (buffer-modified-tick))))
- (if (and (cdr antlr-slow-context-cache)
- (>= (setq diff (- orig (cadr antlr-slow-context-cache))) 0)
- (< diff antlr-slow-cache-diff-threshold)
- (eq (current-buffer) (caar antlr-slow-context-cache))
- (eq tick (cdar antlr-slow-context-cache)))
- ;; (setq antlr-statistics-cache (1+ antlr-statistics-cache) ...)
- (setq state (parse-partial-sexp (cadr antlr-slow-context-cache) orig
- nil nil
- (cddr antlr-slow-context-cache)))
- (if (>= orig antlr-slow-cache-diff-threshold)
- (beginning-of-defun)
- (goto-char (point-min)))
- ;;; (cond ((and diff (< diff 0)) (incf antlr-statistics-full-neg))
- ;;; ((and diff (>= diff 3000)) (incf antlr-statistics-full-diff))
- ;;; (t (incf antlr-statistics-full-other)))
- (setq state (parse-partial-sexp (point) orig)))
- (goto-char orig)
- (if antlr-slow-context-cache
- (setcdr antlr-slow-context-cache (cons orig state))
- (setq antlr-slow-context-cache
- (cons (cons (current-buffer) tick)
- (cons orig state))))
- (cond ((nth 3 state) 'string)
- ((nth 4 state) 'comment) ; block-comment? -- we don't care
- (t (car state)))))
- ;;; (incf (aref antlr-statistics 2))
- ;;; (unless (and (eq (current-buffer)
- ;;; (caar antlr-slow-context-cache))
- ;;; (eq (buffer-modified-tick)
- ;;; (cdar antlr-slow-context-cache)))
- ;;; (incf (aref antlr-statistics 1))
- ;;; (setq antlr-slow-context-cache nil))
- ;;; (let* ((orig (point))
- ;;; (base (cadr antlr-slow-context-cache))
- ;;; (curr (cddr antlr-slow-context-cache))
- ;;; (state (cond ((eq orig (car curr)) (cdr curr))
- ;;; ((eq orig (car base)) (cdr base))))
- ;;; diff diff2)
- ;;; (unless state
- ;;; (incf (aref antlr-statistics 3))
- ;;; (when curr
- ;;; (if (< (setq diff (abs (- orig (car curr))))
- ;;; (setq diff2 (abs (- orig (car base)))))
- ;;; (setq state curr)
- ;;; (setq state base
- ;;; diff diff2))
- ;;; (if (or (>= (1+ diff) (point)) (>= diff 3000))
- ;;; (setq state nil))) ; start from bod/bob
- ;;; (if state
- ;;; (setq state
- ;;; (parse-partial-sexp (car state) orig nil nil (cdr state)))
- ;;; (if (>= orig 3000) (beginning-of-defun) (goto-char (point-min)))
- ;;; (incf (aref antlr-statistics 4))
- ;;; (setq cw (list orig (point) base curr))
- ;;; (setq state (parse-partial-sexp (point) orig)))
- ;;; (goto-char orig)
- ;;; (if antlr-slow-context-cache
- ;;; (setcdr (cdr antlr-slow-context-cache) (cons orig state))
- ;;; (setq antlr-slow-context-cache
- ;;; (cons (cons (current-buffer) (buffer-modified-tick))
- ;;; (cons (cons orig state) (cons orig state))))))
- ;;; (cond ((nth 3 state) 'string)
- ;;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
- ;;; (t (car state)))))
- ;;; (beginning-of-defun)
- ;;; (let ((state (parse-partial-sexp (point) orig)))
- ;;; (goto-char orig)
- ;;; (cond ((nth 3 state) 'string)
- ;;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
- ;;; (t (car state))))))
- ;;;===========================================================================
- ;;; Miscellaneous functions
- ;;;===========================================================================
- (defun antlr-upcase-p (char)
- "Non-nil, if CHAR is an uppercase character (if CHAR was a char)."
- ;; in XEmacs, upcase only works for ASCII
- (or (and (<= ?A char) (<= char ?Z))
- (and (<= ?\300 char) (<= char ?\337)))) ; ?\327 is no letter
- (defun antlr-re-search-forward (regexp bound)
- "Search forward from point for regular expression REGEXP.
- Set point to the end of the occurrence found, and return point. Return
- nil if no occurrence was found. Do not search within comments, strings
- and actions/semantic predicates. BOUND bounds the search; it is a
- buffer position. See also the functions `match-beginning', `match-end'
- and `replace-match'."
- ;; WARNING: Should only be used with `antlr-action-syntax-table'!
- (let ((continue t))
- (while (and (re-search-forward regexp bound 'limit)
- (save-match-data
- (if (eq (antlr-syntactic-context) 0)
- (setq continue nil)
- t))))
- (if continue nil (point))))
- (defun antlr-search-forward (string)
- "Search forward from point for STRING.
- Set point to the end of the occurrence found, and return point. Return
- nil if no occurrence was found. Do not search within comments, strings
- and actions/semantic predicates."
- ;; WARNING: Should only be used with `antlr-action-syntax-table'!
- (let ((continue t))
- (while (and (search-forward string nil 'limit)
- (if (eq (antlr-syntactic-context) 0) (setq continue nil) t)))
- (if continue nil (point))))
- (defun antlr-search-backward (string)
- "Search backward from point for STRING.
- Set point to the beginning of the occurrence found, and return point.
- Return nil if no occurrence was found. Do not search within comments,
- strings and actions/semantic predicates."
- ;; WARNING: Should only be used with `antlr-action-syntax-table'!
- (let ((continue t))
- (while (and (search-backward string nil 'limit)
- (if (eq (antlr-syntactic-context) 0) (setq continue nil) t)))
- (if continue nil (point))))
- (defsubst antlr-skip-sexps (count)
- "Skip the next COUNT balanced expressions and the comments after it.
- Return position before the comments after the last expression."
- (goto-char (or (ignore-errors-x (scan-sexps (point) count)) (point-max)))
- (prog1 (point)
- (antlr-c-forward-sws)))
- ;;;===========================================================================
- ;;; font-lock
- ;;;===========================================================================
- (defun antlr-font-lock-keywords ()
- "Return font-lock keywords for current buffer.
- See `antlr-font-lock-additional-keywords', `antlr-language' and
- `antlr-font-lock-maximum-decoration'."
- (if (eq antlr-font-lock-maximum-decoration 'none)
- antlr-font-lock-additional-keywords
- (append antlr-font-lock-additional-keywords
- (eval (let ((major-mode antlr-language)) ; dynamic
- (font-lock-choose-keywords
- (cdr (assq antlr-language
- antlr-font-lock-keywords-alist))
- (if (eq antlr-font-lock-maximum-decoration 'inherit)
- font-lock-maximum-decoration
- antlr-font-lock-maximum-decoration)))))))
- ;;;===========================================================================
- ;;; imenu support
- ;;;===========================================================================
- (defun antlr-grammar-tokens ()
- "Return alist for tokens defined in current buffer."
- (save-excursion (antlr-imenu-create-index-function t)))
- (defun antlr-imenu-create-index-function (&optional tokenrefs-only)
- "Return imenu index-alist for ANTLR grammar files.
- IF TOKENREFS-ONLY is non-nil, just return alist with tokenref names."
- (let ((items nil)
- (classes nil)
- (continue t))
- ;; Using `imenu-progress-message' would require imenu for compilation, but
- ;; nobody is missing these messages. The generic imenu function searches
- ;; backward, which is slower and more likely not to work during editing.
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (goto-char (point-min))
- (antlr-skip-file-prelude t)
- (while continue
- (if (looking-at "{") (antlr-skip-sexps 1))
- (if (looking-at antlr-class-header-regexp)
- (or tokenrefs-only
- (push (cons (match-string 2)
- (if imenu-use-markers
- (copy-marker (match-beginning 2))
- (match-beginning 2)))
- classes))
- (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)")
- (antlr-skip-sexps 1))
- (when (looking-at "\\sw+")
- (if tokenrefs-only
- (if (antlr-upcase-p (char-after (point)))
- (push (list (match-string 0)) items))
- (push (cons (match-string 0)
- (if imenu-use-markers
- (copy-marker (match-beginning 0))
- (match-beginning 0)))
- items))))
- (if (setq continue (antlr-search-forward ";"))
- (antlr-skip-exception-part t))))
- (if classes
- (cons (cons "Classes" (nreverse classes)) (nreverse items))
- (nreverse items))))
- ;;;===========================================================================
- ;;; Parse grammar files (internal functions)
- ;;;===========================================================================
- (defun antlr-skip-exception-part (skip-comment)
- "Skip exception part of current rule, i.e., everything after `;'.
- This also includes the options and tokens part of a grammar class
- header. If SKIP-COMMENT is non-nil, also skip the comment after that
- part."
- (let ((pos (point))
- (class nil))
- (antlr-c-forward-sws)
- (while (looking-at "options\\>\\|tokens\\>")
- (setq class t)
- (setq pos (antlr-skip-sexps 2)))
- (if class
- ;; Problem: an action only belongs to a class def, not a normal rule.
- ;; But checking the current rule type is too expensive => only expect
- ;; an action if we have found an option or tokens part.
- (if (looking-at "{") (setq pos (antlr-skip-sexps 1)))
- (while (looking-at "exception\\>")
- (setq pos (antlr-skip-sexps 1))
- (when (looking-at "\\[")
- (setq pos (antlr-skip-sexps 1)))
- (while (looking-at "catch\\>")
- (setq pos (antlr-skip-sexps 3)))))
- (or skip-comment (goto-char pos))))
- (defun antlr-skip-file-prelude (skip-comment)
- "Skip the file prelude: the header and file options.
- If SKIP-COMMENT is non-nil, also skip the comment after that part.
- Return the start position of the file prelude.
- Hack: if SKIP-COMMENT is `header-only' only skip header and return
- position before the comment after the header."
- (let* ((pos (point))
- (pos0 pos))
- (antlr-c-forward-sws)
- (if skip-comment (setq pos0 (point)))
- (while (looking-at "header\\>[ \t]*\\(\"\\)?")
- (setq pos (antlr-skip-sexps (if (match-beginning 1) 3 2))))
- (if (eq skip-comment 'header-only) ; a hack...
- pos
- (when (looking-at "options\\>")
- (setq pos (antlr-skip-sexps 2)))
- (or skip-comment (goto-char pos))
- pos0)))
- (defun antlr-next-rule (arg skip-comment)
- "Move forward to next end of rule. Do it ARG many times.
- A grammar class header and the file prelude are also considered as a
- rule. Negative argument ARG means move back to ARGth preceding end of
- rule. The behavior is not defined when ARG is zero. If SKIP-COMMENT
- is non-nil, move to beginning of the rule."
- ;; WARNING: Should only be used with `antlr-action-syntax-table'!
- ;; PRE: ARG<>0
- (let ((pos (point))
- (beg (point)))
- ;; first look whether point is in exception part
- (if (antlr-search-backward ";")
- (progn
- (setq beg (point))
- (forward-char)
- (antlr-skip-exception-part skip-comment))
- (antlr-skip-file-prelude skip-comment))
- (if (< arg 0)
- (unless (and (< (point) pos) (zerop (incf arg)))
- ;; if we have moved backward, we already moved one defun backward
- (goto-char beg) ; rewind (to ";" / point)
- (while (and arg (<= (incf arg) 0))
- (if (antlr-search-backward ";")
- (setq beg (point))
- (when (>= arg -1)
- ;; try file prelude:
- (setq pos (antlr-skip-file-prelude skip-comment))
- (if (zerop arg)
- (if (>= (point) beg)
- (goto-char (if (>= pos beg) (point-min) pos)))
- (goto-char (if (or (>= (point) beg) (= (point) pos))
- (point-min) pos))))
- (setq arg nil)))
- (when arg ; always found a ";"
- (forward-char)
- (antlr-skip-exception-part skip-comment)))
- (if (<= (point) pos) ; moved backward?
- (goto-char pos) ; rewind
- (decf arg)) ; already moved one defun forward
- (unless (zerop arg)
- (while (>= (decf arg) 0)
- (antlr-search-forward ";"))
- (antlr-skip-exception-part skip-comment)))))
- (defun antlr-outside-rule-p ()
- "Non-nil if point is outside a grammar rule.
- Move to the beginning of the current rule if point is inside a rule."
- ;; WARNING: Should only be used with `antlr-action-syntax-table'!
- (let ((pos (point)))
- (antlr-next-rule -1 nil)
- (let ((between (or (bobp) (< (point) pos))))
- (antlr-c-forward-sws)
- (and between (> (point) pos) (goto-char pos)))))
- ;;;===========================================================================
- ;;; Parse grammar files (commands)
- ;;;===========================================================================
- ;; No (interactive "_") in Emacs... use `zmacs-region-stays'.
- (defun antlr-inside-rule-p ()
- "Non-nil if point is inside a grammar rule.
- A grammar class header and the file prelude are also considered as a
- rule."
- (save-excursion
- (antlr-with-syntax-table antlr-action-syntax-table
- (not (antlr-outside-rule-p)))))
- (defunx antlr-end-of-rule (&optional arg)
- "Move forward to next end of rule. Do it ARG [default: 1] many times.
- A grammar class header and the file prelude are also considered as a
- rule. Negative argument ARG means move back to ARGth preceding end of
- rule. If ARG is zero, run `antlr-end-of-body'."
- (interactive "_p")
- (if (zerop arg)
- (antlr-end-of-body)
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-next-rule arg nil))))
- (defunx antlr-beginning-of-rule (&optional arg)
- "Move backward to preceding beginning of rule. Do it ARG many times.
- A grammar class header and the file prelude are also considered as a
- rule. Negative argument ARG means move forward to ARGth next beginning
- of rule. If ARG is zero, run `antlr-beginning-of-body'."
- (interactive "_p")
- (if (zerop arg)
- (antlr-beginning-of-body)
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-next-rule (- arg) t))))
- (defunx antlr-end-of-body (&optional msg)
- "Move to position after the `;' of the current rule.
- A grammar class header is also considered as a rule. With optional
- prefix arg MSG, move to `:'."
- (interactive "_")
- (antlr-with-syntax-table antlr-action-syntax-table
- (let ((orig (point)))
- (if (antlr-outside-rule-p)
- (error "Outside an ANTLR rule"))
- (let ((bor (point)))
- (when (< (antlr-skip-file-prelude t) (point))
- ;; Yes, we are in the file prelude
- (goto-char orig)
- (error (or msg "The file prelude is without `;'")))
- (antlr-search-forward ";")
- (when msg
- (when (< (point)
- (progn (goto-char bor)
- (or (antlr-search-forward ":") (point-max))))
- (goto-char orig)
- (error msg))
- (antlr-c-forward-sws))))))
- (defunx antlr-beginning-of-body ()
- "Move to the first element after the `:' of the current rule."
- (interactive "_")
- (antlr-end-of-body "Class headers and the file prelude are without `:'"))
- ;;;===========================================================================
- ;;; Literal normalization, Hide Actions
- ;;;===========================================================================
- (defun antlr-downcase-literals (&optional transform)
- "Convert all literals in buffer to lower case.
- If non-nil, TRANSFORM is used on literals instead of `downcase-region'."
- (interactive)
- (or transform (setq transform 'downcase-region))
- (let ((literals 0))
- (save-excursion
- (goto-char (point-min))
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (while (antlr-re-search-forward "\"\\(\\sw\\(\\sw\\|-\\)*\\)\"" nil)
- (funcall transform (match-beginning 0) (match-end 0))
- (incf literals))))
- (message "Transformed %d literals" literals)))
- (defun antlr-upcase-literals ()
- "Convert all literals in buffer to upper case."
- (interactive)
- (antlr-downcase-literals 'upcase-region))
- (defun antlr-hide-actions (arg &optional silent)
- "Hide or unhide all actions in buffer.
- Hide all actions including arguments in brackets if ARG is 1 or if
- called interactively without prefix argument. Hide all actions
- excluding arguments in brackets if ARG is 2 or higher. Unhide all
- actions if ARG is 0 or negative. See `antlr-action-visibility'.
- Display a message unless optional argument SILENT is non-nil."
- (interactive "p")
- (save-buffer-state-x
- (if (> arg 0)
- (let ((regexp (if (= arg 1) "[]}]" "}"))
- (diff (and antlr-action-visibility
- (+ (max antlr-action-visibility 0) 2))))
- (antlr-hide-actions 0 t)
- (save-excursion
- (goto-char (point-min))
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (while (antlr-re-search-forward regexp nil)
- (let ((beg (ignore-errors-x (scan-sexps (point) -1))))
- (when beg
- (if diff ; braces are visible
- (if (> (point) (+ beg diff))
- (add-text-properties (1+ beg) (1- (point))
- '(invisible t intangible t)))
- ;; if actions is on line(s) of its own, hide WS
- (and (looking-at "[ \t]*$")
- (save-excursion
- (goto-char beg)
- (skip-chars-backward " \t")
- (and (bolp) (setq beg (point))))
- (beginning-of-line 2)) ; beginning of next line
- (add-text-properties beg (point)
- '(invisible t intangible t))))))))
- (or silent
- (message "Hide all actions (%s arguments)...done"
- (if (= arg 1) "including" "excluding"))))
- (remove-text-properties (point-min) (point-max)
- '(invisible nil intangible nil))
- (or silent
- (message "Unhide all actions (including arguments)...done")))))
- ;;;===========================================================================
- ;;; Insert option: command
- ;;;===========================================================================
- (defun antlr-insert-option (level option &optional location)
- "Insert file/grammar/rule/subrule option near point.
- LEVEL determines option kind to insert: 1=file, 2=grammar, 3=rule,
- 4=subrule. OPTION is a string with the name of the option to insert.
- LOCATION can be specified for not calling `antlr-option-kind' twice.
- Inserting an option with this command works as follows:
- 1. When called interactively, LEVEL is determined by the prefix
- argument or automatically deduced without prefix argument.
- 2. Signal an error if no option of that level could be inserted, e.g.,
- if the buffer is read-only, the option area is outside the visible
- part of the buffer or a subrule/rule option should be inserted with
- point outside a subrule/rule.
- 3. When called interactively, OPTION is read from the minibuffer with
- completion over the known options of the given LEVEL.
- 4. Ask user for confirmation if the given OPTION does not seem to be a
- valid option to insert into the current file.
- 5. Find a correct position to insert the option.
- 6. Depending on the option, insert it the following way \(inserting an
- option also means inserting the option section if necessary\):
- - Insert the option and let user insert the value at point.
- - Read a value (with completion) from the minibuffer, using a
- previous value as initial contents, and insert option with value.
- 7. Final action depending on the option. For example, set the language
- according to a newly inserted language option.
- The name of all options with a specification for their values are stored
- in `antlr-options-alists'. The used specification also depends on the
- value of `antlr-tool-version', i.e., step 4 will warn you if you use an
- option that has been introduced in newer version of ANTLR, and step 5
- will offer completion using version-correct values.
- If the option already exists inside the visible part of the buffer, this
- command can be used to change the value of that option. Otherwise, find
- a correct position where the option can be inserted near point.
- The search for a correct position is as follows:
- * If search is within an area where options can be inserted, use the
- position of point. Inside the options section and if point is in
- the middle of a option definition, skip the rest of it.
- * If an options section already exists, insert the options at the end.
- If only the beginning of the area is visible, insert at the
- beginning.
- * Otherwise, find the position where an options section can be
- inserted and insert a new section before any comments. If the
- position before the comments is not visible, insert the new section
- after the comments.
- This function also inserts \"options {...}\" and the \":\" if necessary,
- see `antlr-options-auto-colon'. See also `antlr-options-assign-string'.
- This command might also set the mark like \\[set-mark-command] does, see
- `antlr-options-push-mark'."
- (interactive (antlr-insert-option-interactive current-prefix-arg))
- (barf-if-buffer-read-only)
- (or location (setq location (cdr (antlr-option-kind level))))
- (cond ((null level)
- (error "Cannot deduce what kind of option to insert"))
- ((atom location)
- (error "Cannot insert any %s options around here"
- (elt antlr-options-headings (1- level)))))
- (let ((area (car location))
- (place (cdr location)))
- (cond ((null place) ; invisible
- (error (if area
- "Invisible %s options, use %s to make them visible"
- "Invisible area for %s options, use %s to make it visible")
- (elt antlr-options-headings (1- level))
- (substitute-command-keys "\\[widen]")))
- ((null area) ; without option part
- (antlr-insert-option-do level option nil
- (null (cdr place))
- (car place)))
- ((save-excursion ; with option part, option visible
- (goto-char (max (point-min) (car area)))
- (re-search-forward (concat "\\(^\\|;\\)[ \t]*\\(\\<"
- (regexp-quote option)
- "\\>\\)[ \t\n]*\\(\\(=[ \t]?\\)[ \t]*\\(\\(\\sw\\|\\s_\\)+\\|\"\\([^\n\"\\]\\|[\\][^\n]\\)*\"\\)?\\)?")
- ;; 2=name, 3=4+5, 4="=", 5=value
- (min (point-max) (cdr area))
- t))
- (antlr-insert-option-do level option
- (cons (or (match-beginning 5)
- (match-beginning 3))
- (match-end 5))
- (and (null (cdr place)) area)
- (or (match-beginning 5)
- (match-end 4)
- (match-end 2))))
- (t ; with option part, option not yet
- (antlr-insert-option-do level option t
- (and (null (cdr place)) area)
- (car place))))))
- (defun antlr-insert-option-interactive (arg)
- "Interactive specification for `antlr-insert-option'.
- Return \(LEVEL OPTION LOCATION)."
- (barf-if-buffer-read-only)
- (if arg (setq arg (prefix-numeric-value arg)))
- (unless (memq arg '(nil 1 2 3 4))
- (error "Valid prefix args: no=auto, 1=file, 2=grammar, 3=rule, 4=subrule"))
- (let* ((kind (antlr-option-kind arg))
- (level (car kind)))
- (if (atom (cdr kind))
- (list level nil (cdr kind))
- (let* ((table (elt antlr-options-alists (1- level)))
- (completion-ignore-case t) ;dynamic
- (input (completing-read (format "Insert %s option: "
- (elt antlr-options-headings
- (1- level)))
- table)))
- (list level input (cdr kind))))))
- (defun antlr-options-menu-filter (level _menu-items)
- "Return items for options submenu of level LEVEL."
- ;; checkdoc-params: (menu-items)
- (let ((active (if buffer-read-only
- nil
- (consp (cdr-safe (cdr (antlr-option-kind level)))))))
- (mapcar (lambda (option)
- (vector option
- (list 'antlr-insert-option level option)
- :active active))
- (sort (mapcar 'car (elt antlr-options-alists (1- level)))
- 'string-lessp))))
- ;;;===========================================================================
- ;;; Insert option: determine section-kind
- ;;;===========================================================================
- (defun antlr-option-kind (requested)
- "Return level and location for option to insert near point.
- Call function `antlr-option-level' with argument REQUESTED. If the
- result is nil, return \(REQUESTED \. error). If the result has the
- non-nil value LEVEL, return \(LEVEL \. LOCATION) where LOCATION looks
- like \(AREA \. PLACE), see `antlr-option-location'."
- (save-excursion
- (save-restriction
- (let ((min0 (point-min)) ; before `widen'!
- (max0 (point-max))
- (orig (point))
- (level (antlr-option-level requested)) ; calls `widen'!
- pos)
- (cond ((null level)
- (setq level requested))
- ((eq level 1) ; file options
- (goto-char (point-min))
- (setq pos (antlr-skip-file-prelude 'header-only)))
- ((not (eq level 3)) ; grammar or subrule options
- (setq pos (point))
- (antlr-c-forward-sws))
- ((looking-at "^\\(private[ \t\n]\\|public[ \t\n]\\|protected[ \t\n]\\)?[ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)[ \t\n]*\\(!\\)?[ \t\n]*\\(\\[\\)?")
- ;; rule options, with complete rule header
- (goto-char (or (match-end 4) (match-end 3)))
- (setq pos (antlr-skip-sexps (if (match-end 5) 1 0)))
- (when (looking-at "returns[ \t\n]*\\[")
- (goto-char (1- (match-end 0)))
- (setq pos (antlr-skip-sexps 1)))))
- (cons level
- (cond ((null pos) 'error)
- ((looking-at "options[ \t\n]*{")
- (goto-char (match-end 0))
- (setq pos (ignore-errors-x (scan-lists (point) 1 1)))
- (antlr-option-location orig min0 max0
- (point)
- (if pos (1- pos) (point-max))
- t))
- (t
- (antlr-option-location orig min0 max0
- pos (point)
- nil))))))))
- (defun antlr-option-level (requested)
- "Return level for option to insert near point.
- Remove any restrictions from current buffer and return level for the
- option to insert near point, i.e., 1, 2, 3, 4, or nil if no such option
- can be inserted. If REQUESTED is non-nil, it is the only possible value
- to return except nil. If REQUESTED is nil, return level for the nearest
- option kind, i.e., the highest number possible.
- If the result is 2, point is at the beginning of the class after the
- class definition. If the result is 3 or 4, point is at the beginning of
- the rule/subrule after the init action. Otherwise, the point position
- is undefined."
- (widen)
- (if (eq requested 1)
- 1
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (let* ((orig (point))
- (outsidep (antlr-outside-rule-p))
- bor depth)
- (if (eq (char-after) ?\{) (antlr-skip-sexps 1))
- (setq bor (point)) ; beginning of rule (after init action)
- (cond ((eq requested 2) ; grammar options required?
- (let (boc) ; beginning of class
- (goto-char (point-min))
- (while (and (<= (point) bor)
- (antlr-re-search-forward antlr-class-header-regexp
- nil))
- (if (<= (match-beginning 0) bor)
- (setq boc (match-end 0))))
- (when boc
- (goto-char boc)
- 2)))
- ((save-excursion ; in region of file options?
- (goto-char (point-min))
- (antlr-skip-file-prelude t) ; ws/comment after: OK
- (< orig (point)))
- (and (null requested) 1))
- (outsidep ; outside rule not OK
- nil)
- ((looking-at antlr-class-header-regexp) ; rule = class def?
- (goto-char (match-end 0))
- (and (null requested) 2))
- ((eq requested 3) ; rule options required?
- (goto-char bor)
- 3)
- ((setq depth (antlr-syntactic-grammar-depth orig bor))
- (if (> depth 0) ; move out of actions
- (goto-char (scan-lists (point) -1 depth)))
- (set-syntax-table antlr-mode-syntax-table)
- (antlr-invalidate-context-cache)
- (if (eq (antlr-syntactic-context) 0) ; not in subrule?
- (unless (eq requested 4)
- (goto-char bor)
- 3)
- (goto-char (1+ (scan-lists (point) -1 1)))
- 4)))))))
- (defun antlr-option-location (orig min-vis max-vis min-area max-area withp)
- "Return location for the options area.
- ORIG is the original position of `point', MIN-VIS is `point-min' and
- MAX-VIS is `point-max'. If WITHP is non-nil, there exists an option
- specification and it starts after the brace at MIN-AREA and stops at
- MAX-AREA. If WITHP is nil, there is no area and the region where it
- could be inserted starts at MIN-AREA and stops at MAX-AREA.
- The result has the form (AREA . PLACE). AREA is (MIN-AREA . MAX-AREA)
- if WITHP is non-nil, and nil otherwise. PLACE is nil if the area is
- invisible, (ORIG) if ORIG is inside the area, (MIN-AREA . beginning) for
- a visible start position and (MAX-AREA . end) for a visible end position
- where the beginning is preferred if WITHP is nil and the end if WITHP is
- non-nil."
- (cons (and withp (cons min-area max-area))
- (cond ((and (<= min-area orig) (<= orig max-area)
- (save-excursion
- (goto-char orig)
- (not (memq (antlr-syntactic-context)
- '(comment block-comment)))))
- ;; point in options area and not in comment
- (list orig))
- ((and (null withp) (<= min-vis min-area) (<= min-area max-vis))
- ;; use start of options area (only if not `withp')
- (cons min-area 'beginning))
- ((and (<= min-vis max-area) (<= max-area max-vis))
- ;; use end of options area
- (cons max-area 'end))
- ((and withp (<= min-vis min-area) (<= min-area max-vis))
- ;; use start of options area (only if `withp')
- (cons min-area 'beginning)))))
- (defun antlr-syntactic-grammar-depth (pos beg)
- "Return syntactic context depth at POS.
- Move to POS and from there on to the beginning of the string or comment
- if POS is inside such a construct. Then, return the syntactic context
- depth at point if the point position is smaller than BEG.
- WARNING: this may alter `match-data'."
- (goto-char pos)
- (let ((context (or (antlr-syntactic-context) 0)))
- (while (and context (not (integerp context)))
- (cond ((eq context 'string)
- (setq context
- (and (search-backward "\"" nil t)
- (>= (point) beg)
- (or (antlr-syntactic-context) 0))))
- ((memq context '(comment block-comment))
- (setq context
- (and (re-search-backward "/[/*]" nil t)
- (>= (point) beg)
- (or (antlr-syntactic-context) 0))))))
- context))
- ;;;===========================================================================
- ;;; Insert options: do the insertion
- ;;;===========================================================================
- (defun antlr-insert-option-do (level option old area pos)
- "Insert option into buffer at position POS.
- Insert option of level LEVEL and name OPTION. If OLD is non-nil, an
- options area is already exists. If OLD looks like \(BEG \. END), the
- option already exists. Then, BEG is the start position of the option
- value, the position of the `=' or nil, and END is the end position of
- the option value or nil.
- If the original point position was outside an options area, AREA is nil.
- Otherwise, and if an option specification already exists, AREA is a cons
- cell where the two values determine the area inside the braces."
- (let* ((spec (cdr (assoc option (elt antlr-options-alists (1- level)))))
- (value (antlr-option-spec level option (cdr spec) (consp old))))
- (if (fboundp (car spec)) (funcall (car spec) 'before-input option))
- ;; set mark (unless point was inside options area before)
- (if (cond (area (eq antlr-options-push-mark t))
- ((numberp antlr-options-push-mark)
- (> (count-lines (min (point) pos) (max (point) pos))
- antlr-options-push-mark))
- (antlr-options-push-mark))
- (push-mark))
- ;; read option value -----------------------------------------------------
- (goto-char pos)
- (if (null value)
- ;; no option specification found
- (if (y-or-n-p (format "Insert unknown %s option %s? "
- (elt antlr-options-headings (1- level))
- option))
- (message "Insert value for %s option %s"
- (elt antlr-options-headings (1- level))
- option)
- (error "Didn't insert unknown %s option %s"
- (elt antlr-options-headings (1- level))
- option))
- ;; option specification found
- (setq value (cdr value))
- (if (car value)
- (let ((initial (and (consp old) (cdr old)
- (buffer-substring (car old) (cdr old)))))
- (setq value (apply (car value)
- (and initial
- (if (eq (aref initial 0) ?\")
- (read initial)
- initial))
- (cdr value))))
- (message "%s" (or (cadr value) ""))
- (setq value nil)))
- ;; insert value ----------------------------------------------------------
- (if (consp old)
- (antlr-insert-option-existing old value)
- (if (consp area)
- ;; Move outside string/comment if point is inside option spec
- (antlr-syntactic-grammar-depth (point) (car area)))
- (antlr-insert-option-space area old)
- (or old (antlr-insert-option-area level))
- (insert option " = ;")
- (backward-char)
- (if value (insert value)))
- ;; final -----------------------------------------------------------------
- (if (fboundp (car spec)) (funcall (car spec) 'after-insertion option))))
- (defun antlr-option-spec (level option specs existsp)
- "Return version correct option value specification.
- Return specification for option OPTION of kind level LEVEL. SPECS
- should correspond to the VALUE-SPEC... in `antlr-option-alists'.
- EXISTSP determines whether the option already exists."
- (let (value)
- (while (and specs (>= antlr-tool-version (caar specs)))
- (setq value (pop specs)))
- (cond (value) ; found correct spec
- ((null specs) nil) ; didn't find any specs
- (existsp (car specs)) ; wrong version, but already present
- ((y-or-n-p (format "Insert v%s %s option %s in v%s? "
- (antlr-version-string (caar specs))
- (elt antlr-options-headings (1- level))
- option
- (antlr-version-string antlr-tool-version)))
- (car specs))
- (t
- (error "Didn't insert v%s %s option %s in v%s"
- (antlr-version-string (caar specs))
- (elt antlr-options-headings (1- level))
- option
- (antlr-version-string antlr-tool-version))))))
- (defun antlr-version-string (version)
- "Format the Antlr version number VERSION, see `antlr-tool-version'."
- (let ((version100 (/ version 100)))
- (format "%d.%d.%d"
- (/ version100 100) (mod version100 100) (mod version 100))))
- ;;;===========================================================================
- ;;; Insert options: the details (used by `antlr-insert-option-do')
- ;;;===========================================================================
- (defun antlr-insert-option-existing (old value)
- "Insert option value VALUE at point for existing option.
- For OLD, see `antlr-insert-option-do'."
- ;; no = => insert =
- (unless (car old) (insert antlr-options-assign-string))
- ;; with user input => insert if necessary
- (when value
- (if (cdr old) ; with value
- (if (string-equal value (buffer-substring (car old) (cdr old)))
- (goto-char (cdr old))
- (delete-region (car old) (cdr old))
- (insert value))
- (insert value)))
- (unless (looking-at "\\([^\n=;{}/'\"]\\|'\\([^\n'\\]\\|\\\\.\\)*'\\|\"\\([^\n\"\\]\\|\\\\.\\)*\"\\)*;")
- ;; stuff (no =, {, } or /) at point is not followed by ";"
- (insert ";")
- (backward-char)))
- (defun antlr-insert-option-space (area old)
- "Find appropriate place to insert option, insert newlines/spaces.
- For AREA and OLD, see `antlr-insert-option-do'."
- (let ((orig (point))
- (open t))
- (skip-chars-backward " \t")
- (unless (bolp)
- (let ((before (char-after (1- (point)))))
- (goto-char orig)
- (and old ; with existing options area
- (consp area) ; if point inside existing area
- (not (eq before ?\;)) ; if not at beginning of option
- ; => skip to end of option
- (if (and (search-forward ";" (cdr area) t)
- (let ((context (antlr-syntactic-context)))
- (or (null context) (numberp context))))
- (setq orig (point))
- (goto-char orig)))
- (skip-chars-forward " \t")
- (if (looking-at "$\\|//")
- ;; just comment after point => skip (+ lines w/ same col comment)
- (let ((same (if (> (match-end 0) (match-beginning 0))
- (current-column))))
- (beginning-of-line 2)
- (or (bolp) (insert "\n"))
- (when (and same (null area)) ; or (consp area)?
- (while (and (looking-at "[ \t]*\\(//\\)")
- (goto-char (match-beginning 1))
- (= (current-column) same))
- (beginning-of-line 2)
- (or (bolp) (insert "\n")))))
- (goto-char orig)
- (if (null old)
- (progn (insert "\n") (antlr-indent-line))
- (unless (eq (char-after (1- (point))) ?\ )
- (insert " "))
- (unless (eq (char-after (point)) ?\ )
- (insert " ")
- (backward-char))
- (setq open nil)))))
- (when open
- (beginning-of-line 1)
- (insert "\n")
- (backward-char)
- (antlr-indent-line))))
- (defun antlr-insert-option-area (level)
- "Insert new options area for options of level LEVEL.
- Used by `antlr-insert-option-do'."
- (insert "options {\n\n}")
- (when (and antlr-options-auto-colon
- (memq level '(3 4))
- (save-excursion
- (antlr-c-forward-sws)
- (if (eq (char-after (point)) ?\{) (antlr-skip-sexps 1))
- (not (eq (char-after (point)) ?\:))))
- (insert "\n:")
- (antlr-indent-line)
- (end-of-line 0))
- (backward-char 1)
- (antlr-indent-line)
- (beginning-of-line 0)
- (antlr-indent-line))
- ;;;===========================================================================
- ;;; Insert options: in `antlr-options-alists'
- ;;;===========================================================================
- (defun antlr-read-value (initial-contents prompt
- &optional as-string table table-x)
- "Read a string from the minibuffer, possibly with completion.
- If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
- PROMPT is a string to prompt with, normally it ends in a colon and a
- space. If AS-STRING is t or is a member \(comparison done with `eq') of
- `antlr-options-style', return printed representation of the user input,
- otherwise return the user input directly.
- If TABLE or TABLE-X is non-nil, read with completion. The completion
- table is the resulting alist of TABLE-X concatenated with TABLE where
- TABLE can also be a function evaluation to an alist.
- Used inside `antlr-options-alists'."
- (let* ((completion-ignore-case t) ; dynamic
- (table0 (and (or table table-x)
- (append table-x
- (if (functionp table) (funcall table) table))))
- (input (if table0
- (completing-read prompt table0 nil nil initial-contents)
- (read-from-minibuffer prompt initial-contents))))
- (if (and as-string
- (or (eq as-string t)
- (cdr (assq as-string antlr-options-style))))
- (format "%S" input)
- input)))
- (defun antlr-read-boolean (initial-contents prompt &optional table)
- "Read a boolean value from the minibuffer, with completion.
- If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
- PROMPT is a string to prompt with, normally it ends in a question mark
- and a space. \"(true or false) \" is appended if TABLE is nil.
- Read with completion over \"true\", \"false\" and the keys in TABLE, see
- also `antlr-read-value'.
- Used inside `antlr-options-alists'."
- (antlr-read-value initial-contents
- (if table prompt (concat prompt "(true or false) "))
- nil
- table '(("false") ("true"))))
- (defun antlr-language-option-extra (phase &rest _dummies)
- ;; checkdoc-params: (dummies)
- "Change language according to the new value of the \"language\" option.
- Call `antlr-mode' if the new language would be different from the value
- of `antlr-language', keeping the value of variable `font-lock-mode'.
- Called in PHASE `after-insertion', see `antlr-options-alists'."
- (when (eq phase 'after-insertion)
- (let ((new-language (antlr-language-option t)))
- (or (null new-language)
- (eq new-language antlr-language)
- (let ((font-lock (and (boundp 'font-lock-mode) font-lock-mode)))
- (if font-lock (font-lock-mode 0))
- (antlr-mode)
- (and font-lock (null font-lock-mode) (font-lock-mode 1)))))))
- (defun antlr-c++-mode-extra (phase option &rest _dummies)
- ;; checkdoc-params: (option dummies)
- "Warn if C++ option is used with the wrong language.
- Ask user \(\"y or n\"), if a C++ only option is going to be inserted but
- `antlr-language' has not the value `c++-mode'.
- Called in PHASE `before-input', see `antlr-options-alists'."
- (and (eq phase 'before-input)
- (not (eq antlr-language 'c++-mode))
- (not (y-or-n-p (format "Insert C++ %s option? " option)))
- (error "Didn't insert C++ %s option with language %s"
- option (cadr (assq antlr-language antlr-language-alist)))))
- ;;;===========================================================================
- ;;; Compute dependencies
- ;;;===========================================================================
- (defun antlr-file-dependencies ()
- "Return dependencies for grammar in current buffer.
- The result looks like \(FILE \(CLASSES \. SUPERS) VOCABS \. LANGUAGE)
- where CLASSES = ((CLASS . CLASS-EVOCAB) ...),
- SUPERS = ((SUPER . USE-EVOCAB-P) ...), and
- VOCABS = ((EVOCAB ...) . (IVOCAB ...))
- FILE is the current buffer's file-name without directory part and
- LANGUAGE is the value of `antlr-language' in the current buffer. Each
- EVOCAB is an export vocabulary and each IVOCAB is an import vocabulary.
- Each CLASS is a grammar class with its export vocabulary CLASS-EVOCAB.
- Each SUPER is a super-grammar class where USE-EVOCAB-P indicates whether
- its export vocabulary is used as an import vocabulary."
- (unless buffer-file-name
- (error "Grammar buffer does not visit a file"))
- (let (classes export-vocabs import-vocabs superclasses default-vocab)
- (antlr-with-syntax-table antlr-action-syntax-table
- (goto-char (point-min))
- (while (antlr-re-search-forward antlr-class-header-regexp nil)
- ;; parse class definition --------------------------------------------
- (let* ((class (match-string 2))
- (sclass (match-string 4))
- ;; export vocab defaults to class name (first grammar in file)
- ;; or to the export vocab of the first grammar in file:
- (evocab (or default-vocab class))
- (ivocab nil))
- (goto-char (match-end 0))
- (antlr-c-forward-sws)
- (while (looking-at "options\\>\\|\\(tokens\\)\\>")
- (if (match-beginning 1)
- (antlr-skip-sexps 2)
- (goto-char (match-end 0))
- (antlr-c-forward-sws)
- ;; parse grammar option sections -------------------------------
- (when (eq (char-after (point)) ?\{)
- (let* ((beg (1+ (point)))
- (end (1- (antlr-skip-sexps 1)))
- (cont (point)))
- (goto-char beg)
- (if (re-search-forward "\\<exportVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t)
- (setq evocab (match-string 1)))
- (goto-char beg)
- (if (re-search-forward "\\<importVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t)
- (setq ivocab (match-string 1)))
- (goto-char cont)))))
- (unless (member sclass '("Parser" "Lexer" "TreeParser"))
- (let ((super (assoc sclass superclasses)))
- (if super
- (or ivocab (setcdr super t))
- (push (cons sclass (null ivocab)) superclasses))))
- ;; remember class with export vocabulary:
- (push (cons class evocab) classes)
- ;; default export vocab is export vocab of first grammar in file:
- (or default-vocab (setq default-vocab evocab))
- (or (member evocab export-vocabs) (push evocab export-vocabs))
- (or (null ivocab)
- (member ivocab import-vocabs) (push ivocab import-vocabs)))))
- (if classes
- (list* (file-name-nondirectory buffer-file-name)
- (cons (nreverse classes) (nreverse superclasses))
- (cons (nreverse export-vocabs) (nreverse import-vocabs))
- antlr-language))))
- (defun antlr-directory-dependencies (dirname)
- "Return dependencies for all grammar files in directory DIRNAME.
- The result looks like \((CLASS-SPEC ...) \. \(FILE-DEP ...))
- where CLASS-SPEC = (CLASS (FILE \. EVOCAB) ...).
- FILE-DEP are the dependencies for each grammar file in DIRNAME, see
- `antlr-file-dependencies'. For each grammar class CLASS, FILE is a
- grammar file in which CLASS is defined and EVOCAB is the name of the
- export vocabulary specified in that file."
- (let ((grammar (directory-files dirname t "\\.g\\'")))
- (when grammar
- (let ((antlr-imenu-name nil) ; dynamic-let: no imenu
- (expanded-regexp
- (concat (format (regexp-quote
- (cadr antlr-special-file-formats))
- ".+")
- "\\'"))
- classes dependencies)
- (with-temp-buffer
- (dolist (file grammar)
- (when (and (file-regular-p file)
- (null (string-match expanded-regexp file)))
- (insert-file-contents file t nil nil t)
- (normal-mode t) ; necessary for major-mode, syntax
- ; table and `antlr-language'
- (when (derived-mode-p 'antlr-mode)
- (let* ((file-deps (antlr-file-dependencies))
- (file (car file-deps)))
- (when file-deps
- (dolist (class-def (caadr file-deps))
- (let ((file-evocab (cons file (cdr class-def)))
- (class-spec (assoc (car class-def) classes)))
- (if class-spec
- (nconc (cdr class-spec) (list file-evocab))
- (push (list (car class-def) file-evocab)
- classes))))
- (push file-deps dependencies)))))))
- (cons (nreverse classes) (nreverse dependencies))))))
- ;;;===========================================================================
- ;;; Compilation: run ANTLR tool
- ;;;===========================================================================
- (defun antlr-superclasses-glibs (supers classes)
- "Compute the grammar lib option for the super grammars SUPERS.
- Look in CLASSES for the right grammar lib files for SUPERS. SUPERS is
- part SUPER in the result of `antlr-file-dependencies'. CLASSES is the
- part \(CLASS-SPEC ...) in the result of `antlr-directory-dependencies'.
- The result looks like \(OPTION WITH-UNKNOWN GLIB ...). OPTION is the
- complete \"-glib\" option. WITH-UNKNOWN is t if there is none or more
- than one grammar file for at least one super grammar.
- Each GLIB looks like \(GRAMMAR-FILE \. EVOCAB). GRAMMAR-FILE is a file
- in which a super-grammar is defined. EVOCAB is the value of the export
- vocabulary of the super-grammar or nil if it is not needed."
- ;; If the superclass is defined in the same file, that file will be included
- ;; with -glib again. This will lead to a redefinition. But defining a
- ;; analyzer of the same class twice in a file will lead to an error anyway...
- (let (glibs unknown)
- (while supers
- (let* ((super (pop supers))
- (sup-files (cdr (assoc (car super) classes)))
- (file (and sup-files (null (cdr sup-files)) (car sup-files))))
- (or file (setq unknown t)) ; not exactly one file
- (push (cons (or (car file)
- (format (car antlr-unknown-file-formats)
- (car super)))
- (and (cdr super)
- (or (cdr file)
- (format (cadr antlr-unknown-file-formats)
- (car super)))))
- glibs)))
- (cons (if glibs (concat " -glib " (mapconcat 'car glibs ";")) "")
- (cons unknown glibs))))
- (defun antlr-run-tool (command file &optional saved)
- "Run Antlr took COMMAND on grammar FILE.
- When called interactively, COMMAND is read from the minibuffer and
- defaults to `antlr-tool-command' with a computed \"-glib\" option if
- necessary.
- Save all buffers first unless optional value SAVED is non-nil. When
- called interactively, the buffers are always saved, see also variable
- `antlr-ask-about-save'."
- (interactive (antlr-run-tool-interactive))
- (or saved (save-some-buffers (not antlr-ask-about-save)))
- (let ((default-directory (file-name-directory file)))
- (compilation-start (concat command " " (file-name-nondirectory file))
- nil (lambda (_mode-name) "*Antlr-Run*"))))
- (defun antlr-run-tool-interactive ()
- ;; code in `interactive' is not compiled
- "Interactive specification for `antlr-run-tool'.
- Use prefix argument ARG to return \(COMMAND FILE SAVED)."
- (let* ((supers (cdadr (save-excursion
- (save-restriction
- (widen)
- (antlr-file-dependencies)))))
- (glibs ""))
- (when supers
- (save-some-buffers (not antlr-ask-about-save) nil)
- (setq glibs (car (antlr-superclasses-glibs
- supers
- (car (antlr-directory-dependencies
- (antlr-default-directory)))))))
- (list (antlr-read-shell-command "Run Antlr on current file with: "
- (concat antlr-tool-command glibs " "))
- buffer-file-name
- supers)))
- ;;;===========================================================================
- ;;; Makefile creation
- ;;;===========================================================================
- (defun antlr-makefile-insert-variable (number pre post)
- "Insert Makefile variable numbered NUMBER according to specification.
- Also insert strings PRE and POST before and after the variable."
- (let ((spec (cadr antlr-makefile-specification)))
- (when spec
- (insert pre
- (if number (format (cadr spec) number) (car spec))
- post))))
- (defun antlr-insert-makefile-rules (&optional in-makefile)
- "Insert Makefile rules in the current buffer at point.
- IN-MAKEFILE is non-nil, if the current buffer is the Makefile. See
- command `antlr-show-makefile-rules' for detail."
- (let* ((dirname (antlr-default-directory))
- (deps0 (antlr-directory-dependencies dirname))
- (classes (car deps0)) ; CLASS -> (FILE . EVOCAB) ...
- (deps (cdr deps0)) ; FILE -> (c . s) (ev . iv) . LANGUAGE
- (with-error nil)
- (gen-sep (or (caddr (cadr antlr-makefile-specification)) " "))
- (n (and (cdr deps) (cadr antlr-makefile-specification) 0)))
- (or in-makefile (set-buffer standard-output))
- (dolist (dep deps)
- (let ((supers (cdadr dep))
- (lang (cdr (assoc (cdddr dep) antlr-file-formats-alist))))
- (if n (incf n))
- (antlr-makefile-insert-variable n "" " =")
- (if supers
- (insert " "
- (format (cadr antlr-special-file-formats)
- (file-name-sans-extension (car dep)))))
- (dolist (class-def (caadr dep))
- (let ((sep gen-sep))
- (dolist (class-file (cadr lang))
- (insert sep (format class-file (car class-def)))
- (setq sep " "))))
- (dolist (evocab (caaddr dep))
- (let ((sep gen-sep))
- (dolist (vocab-file (cons (car antlr-special-file-formats)
- (car lang)))
- (insert sep (format vocab-file evocab))
- (setq sep " "))))
- (antlr-makefile-insert-variable n "\n$(" ")")
- (insert ": " (car dep))
- (dolist (ivocab (cdaddr dep))
- (insert " " (format (car antlr-special-file-formats) ivocab)))
- (let ((glibs (antlr-superclasses-glibs supers classes)))
- (if (cadr glibs) (setq with-error t))
- (dolist (super (cddr glibs))
- (insert " " (car super))
- (if (cdr super)
- (insert " " (format (car antlr-special-file-formats)
- (cdr super)))))
- (insert "\n\t"
- (caddr antlr-makefile-specification)
- (car glibs)
- " $<\n"
- (car antlr-makefile-specification)))))
- (if n
- (let ((i 0))
- (antlr-makefile-insert-variable nil "" " =")
- (while (<= (incf i) n)
- (antlr-makefile-insert-variable i " $(" ")"))
- (insert "\n" (car antlr-makefile-specification))))
- (if (string-equal (car antlr-makefile-specification) "\n")
- (backward-delete-char 1))
- (when with-error
- (goto-char (point-min))
- (insert antlr-help-unknown-file-text))
- (unless in-makefile
- (copy-region-as-kill (point-min) (point-max))
- (goto-char (point-min))
- (insert (format antlr-help-rules-intro dirname)))))
- ;;;###autoload
- (defun antlr-show-makefile-rules ()
- "Show Makefile rules for all grammar files in the current directory.
- If the `major-mode' of the current buffer has the value `makefile-mode',
- the rules are directory inserted at point. Otherwise, a *Help* buffer
- is shown with the rules which are also put into the `kill-ring' for
- \\[yank].
- This command considers import/export vocabularies and grammar
- inheritance and provides a value for the \"-glib\" option if necessary.
- Customize variable `antlr-makefile-specification' for the appearance of
- the rules.
- If the file for a super-grammar cannot be determined, special file names
- are used according to variable `antlr-unknown-file-formats' and a
- commentary with value `antlr-help-unknown-file-text' is added. The
- *Help* buffer always starts with the text in `antlr-help-rules-intro'."
- (interactive)
- (if (null (derived-mode-p 'makefile-mode))
- (antlr-with-displaying-help-buffer 'antlr-insert-makefile-rules)
- (push-mark)
- (antlr-insert-makefile-rules t)))
- ;;;===========================================================================
- ;;; Indentation
- ;;;===========================================================================
- (defun antlr-indent-line ()
- "Indent the current line as ANTLR grammar code.
- The indentation of grammar lines are calculated by `c-basic-offset',
- multiplied by:
- - the level of the paren/brace/bracket depth,
- - plus 0/2/1, depending on the position inside the rule: header, body,
- exception part,
- - minus 1 if `antlr-indent-item-regexp' matches the beginning of the
- line starting from the first non-whitespace.
- Lines inside block comments are indented by `c-indent-line' according to
- `antlr-indent-comment'.
- Lines in actions except top-level actions in a header part or an option
- area are indented by `c-indent-line'.
- Lines in header actions are indented at column 0 if `antlr-language'
- equals to a key in `antlr-indent-at-bol-alist' and the line starting at
- the first non-whitespace is matched by the corresponding value.
- For the initialization of `c-basic-offset', see `antlr-indent-style' and,
- to a lesser extent, `antlr-tab-offset-alist'."
- (save-restriction
- (let ((orig (point))
- (min0 (point-min))
- bol boi indent syntax cc-syntax)
- (widen)
- (beginning-of-line)
- (setq bol (point))
- (if (< bol min0)
- (error "Beginning of current line not visible"))
- (skip-chars-forward " \t")
- (setq boi (point))
- ;; check syntax at beginning of indentation ----------------------------
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (setq syntax (antlr-syntactic-context))
- (cond ((symbolp syntax)
- (setq indent nil)) ; block-comments, strings, (comments)
- ((progn
- (antlr-next-rule -1 t)
- (if (antlr-search-forward ":") (< boi (1- (point))) t))
- (setq indent 0)) ; in rule header
- ((if (antlr-search-forward ";") (< boi (point)) t)
- (setq indent 2)) ; in rule body
- (t
- (forward-char)
- (antlr-skip-exception-part nil)
- (setq indent (if (> (point) boi) 1 0))))) ; in exception part?
- ;; check whether to use indentation engine of cc-mode ------------------
- (antlr-invalidate-context-cache)
- (goto-char boi)
- (when (and indent (> syntax 0))
- (cond ((> syntax 1) ; block in action => use cc-mode
- (setq indent nil))
- ((and (= indent 0)
- (assq antlr-language antlr-indent-at-bol-alist)
- (looking-at (cdr (assq antlr-language
- antlr-indent-at-bol-alist))))
- (setq syntax 'bol))
- ((setq cc-syntax (c-guess-basic-syntax))
- (let ((cc cc-syntax) symbol)
- (while (setq symbol (pop cc))
- (when (cdr symbol)
- (or (memq (car symbol)
- antlr-disabling-cc-syntactic-symbols)
- (setq indent nil))
- (setq cc nil)))))))
- ;;; ((= indent 1) ; exception part => use cc-mode
- ;;; (setq indent nil))
- ;;; ((save-restriction ; not in option part => cc-mode
- ;;; (goto-char (scan-lists (point) -1 1))
- ;;; (skip-chars-backward " \t\n")
- ;;; (narrow-to-region (point-min) (point))
- ;;; (not (re-search-backward "\\<options\\'" nil t)))
- ;;; (setq indent nil)))))
- ;; compute the corresponding indentation and indent --------------------
- (if (null indent)
- ;; Use the indentation engine of cc-mode
- (progn
- (goto-char orig)
- (if (or (numberp syntax)
- (if (eq syntax 'string) nil (eq antlr-indent-comment t)))
- (c-indent-line cc-syntax)))
- ;; do it ourselves
- (goto-char boi)
- (unless (symbolp syntax) ; direct indentation
- ;;(antlr-invalidate-context-cache)
- (incf indent (antlr-syntactic-context))
- (and (> indent 0) (looking-at antlr-indent-item-regexp) (decf indent))
- (setq indent (* indent c-basic-offset)))
- ;; the usual major-mode indent stuff ---------------------------------
- (setq orig (- (point-max) orig))
- (unless (= (current-column) indent)
- (delete-region bol boi)
- (beginning-of-line)
- (indent-to indent))
- ;; If initial point was within line's indentation,
- ;; position after the indentation. Else stay at same point in text.
- (if (> (- (point-max) orig) (point))
- (goto-char (- (point-max) orig)))))))
- (defun antlr-indent-command (&optional arg)
- "Indent the current line or insert tabs/spaces.
- With optional prefix argument ARG or if the previous command was this
- command, insert ARG tabs or spaces according to `indent-tabs-mode'.
- Otherwise, indent the current line with `antlr-indent-line'."
- (interactive "*P")
- (if (or arg (eq last-command 'antlr-indent-command))
- (insert-tab arg)
- (let ((antlr-indent-comment (and antlr-indent-comment t))) ; dynamic
- (antlr-indent-line))))
- (defun antlr-electric-character (&optional arg)
- "Insert the character you type and indent the current line.
- Insert the character like `self-insert-command' and indent the current
- line as `antlr-indent-command' does. Do not indent the line if
- * this command is called with a prefix argument ARG,
- * there are characters except whitespaces between point and the
- beginning of the line, or
- * point is not inside a normal grammar code, { and } are also OK in
- actions.
- This command is useful for a character which has some special meaning in
- ANTLR's syntax and influences the auto indentation, see
- `antlr-indent-item-regexp'."
- (interactive "*P")
- (if (or arg
- (save-excursion (skip-chars-backward " \t") (not (bolp)))
- (antlr-with-syntax-table antlr-action-syntax-table
- (antlr-invalidate-context-cache)
- (let ((context (antlr-syntactic-context)))
- (not (and (numberp context)
- (or (zerop context)
- (memq last-command-event '(?\{ ?\}))))))))
- (self-insert-command (prefix-numeric-value arg))
- (self-insert-command (prefix-numeric-value arg))
- (antlr-indent-line)))
- ;;;===========================================================================
- ;;; Mode entry
- ;;;===========================================================================
- (defun antlr-c-init-language-vars ()
- "Like `c-init-language-vars-for' when using cc-mode before v5.29."
- (let ((settings ; (cdr '(setq...)) will be optimized
- (if (eq antlr-language 'c++-mode)
- (cdr '(setq ;' from `c++-mode' v5.20, v5.28
- c-keywords (c-identifier-re c-C++-keywords)
- c-conditional-key c-C++-conditional-key
- c-comment-start-regexp c-C++-comment-start-regexp
- c-class-key c-C++-class-key
- c-extra-toplevel-key c-C++-extra-toplevel-key
- c-access-key c-C++-access-key
- c-recognize-knr-p nil
- c-bitfield-key c-C-bitfield-key ; v5.28
- ))
- (cdr '(setq ; from `java-mode' v5.20, v5.28
- c-keywords (c-identifier-re c-Java-keywords)
- c-conditional-key c-Java-conditional-key
- c-comment-start-regexp c-Java-comment-start-regexp
- c-class-key c-Java-class-key
- c-method-key nil
- c-baseclass-key nil
- c-recognize-knr-p nil
- c-access-key c-Java-access-key ; v5.20
- c-inexpr-class-key c-Java-inexpr-class-key ; v5.28
- )))))
- (while settings
- (when (boundp (car settings))
- (ignore-errors
- (set (car settings) (eval (cadr settings)))))
- (setq settings (cddr settings)))))
- (defun antlr-language-option (search)
- "Find language in `antlr-language-alist' for language option.
- If SEARCH is non-nil, find element for language option. Otherwise, find
- the default language."
- (let ((value
- (and search
- (save-excursion
- (goto-char (point-min))
- (re-search-forward (cdr antlr-language-limit-n-regexp)
- (+ (point)
- (car antlr-language-limit-n-regexp))
- t))
- (match-string 1)))
- (seq antlr-language-alist)
- r)
- ;; Like (find VALUE antlr-language-alist :key 'cddr :test 'member)
- (while seq
- (setq r (pop seq))
- (if (member value (cddr r))
- (setq seq nil) ; stop
- (setq r nil))) ; no result yet
- (car r)))
- ;;;###autoload
- (define-derived-mode antlr-mode prog-mode
- ;; FIXME: Since it uses cc-mode, it bumps into c-update-modeline's
- ;; limitation to mode-name being a string.
- ;; '("Antlr." (:eval (cadr (assq antlr-language antlr-language-alist))))
- "Antlr"
- "Major mode for editing ANTLR grammar files."
- :abbrev-table antlr-mode-abbrev-table
- (c-initialize-cc-mode) ; cc-mode is required
- (unless (fboundp 'c-forward-sws) ; see above
- (fset 'antlr-c-forward-sws 'c-forward-syntactic-ws))
- ;; ANTLR specific ----------------------------------------------------------
- (unless antlr-language
- (set (make-local-variable 'antlr-language)
- (or (antlr-language-option t) (antlr-language-option nil))))
- (if (stringp (cadr (assq antlr-language antlr-language-alist)))
- (setq mode-name
- (concat "Antlr."
- (cadr (assq antlr-language antlr-language-alist)))))
- ;; indentation, for the C engine -------------------------------------------
- (setq c-buffer-is-cc-mode antlr-language)
- (cond ((fboundp 'c-init-language-vars-for) ; cc-mode 5.30.5+
- (c-init-language-vars-for antlr-language))
- ((fboundp 'c-init-c-language-vars) ; cc-mode 5.30 to 5.30.4
- (c-init-c-language-vars) ; not perfect, but OK
- (setq c-recognize-knr-p nil))
- ((fboundp 'c-init-language-vars) ; cc-mode 5.29
- (let ((init-fn 'c-init-language-vars))
- (funcall init-fn))) ; is a function in v5.29
- (t ; cc-mode upto 5.28
- (antlr-c-init-language-vars))) ; do it myself
- (c-basic-common-init antlr-language (or antlr-indent-style "gnu"))
- (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
- (set (make-local-variable 'outline-level) 'c-outline-level) ;TODO: define own
- (set (make-local-variable 'indent-line-function) 'antlr-indent-line)
- (set (make-local-variable 'indent-region-function) nil) ; too lazy
- (setq comment-start "// "
- comment-end ""
- comment-start-skip "/\\*+ *\\|// *")
- ;; various -----------------------------------------------------------------
- (set (make-local-variable 'font-lock-defaults) antlr-font-lock-defaults)
- (easy-menu-add antlr-mode-menu)
- (set (make-local-variable 'imenu-create-index-function)
- 'antlr-imenu-create-index-function)
- (set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test
- (and antlr-imenu-name ; there should be a global variable...
- (fboundp 'imenu-add-to-menubar)
- (imenu-add-to-menubar
- (if (stringp antlr-imenu-name) antlr-imenu-name "Index")))
- (antlr-set-tabs))
- ;; A smarter version of `group-buffers-menu-by-mode-then-alphabetically' (in
- ;; XEmacs) could use the following property. The header of the submenu would
- ;; be "Antlr" instead of "Antlr.C++" or (not and!) "Antlr.Java".
- (put 'antlr-mode 'mode-name "Antlr")
- ;;;###autoload
- (defun antlr-set-tabs ()
- "Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'.
- Used in `antlr-mode'. Also a useful function in `java-mode-hook'."
- (if buffer-file-name
- (let ((alist antlr-tab-offset-alist) elem)
- (while alist
- (setq elem (pop alist))
- (and (or (null (car elem)) (eq (car elem) major-mode))
- (or (null (cadr elem))
- (string-match (cadr elem) buffer-file-name))
- (setq tab-width (caddr elem)
- indent-tabs-mode (cadddr elem)
- alist nil))))))
- (provide 'antlr-mode)
- ;;; Local IspellPersDict: .ispell_antlr
- ;;; antlr-mode.el ends here
|