From 7c66d04999ce21b5ddedb22593832aa738e0a4aa Mon Sep 17 00:00:00 2001 From: Gerd Moellmann Date: Wed, 29 Nov 2000 16:55:47 +0000 Subject: [PATCH] New commands to run ANTLR from within Emacs and to create Makefile rules. (antlr-tool-command): New user option. (antlr-ask-about-save): New user option. (antlr-makefile-specification): New user option. (antlr-file-formats-alist): New variable. (antlr-special-file-formats): New variable. (antlr-unknown-file-formats): New user option. (antlr-help-unknown-file-text): New variable. (antlr-help-rules-intro): New variable. (antlr-mode-map): Add [C-c C-r] for `antlr-run-tool'. (antlr-mode-menu): Add entries. (antlr-file-dependencies): New function. (antlr-directory-dependencies): New function. (antlr-superclasses-glibs): New function. (antlr-run-tool): New command. (antlr-makefile-insert-variable): New function. (antlr-insert-makefile-rules): New function. (antlr-show-makefile-rules): New command. More Emacs/XEmacs stuff. (antlr-no-action-keywords): New constant with value nil. (antlr-font-lock-keywords-alist): Use it. Old value would break syntax highlighting in Emacs-21.0. (antlr-default-directory): Emacs/XEmacs dependend function. (antlr-read-shell-command): Ditto. (antlr-with-displaying-help-buffer): Ditto. imenu, parsing and highlighting changes. (antlr-imenu-create-index-function): Don't create extra submenus for definitions in different grammar classes. It is not necessary for the menu and would make command `imenu' awkward to use. (antlr-skip-file-prelude): With ANTLR-2.7+, you can specify named header actions and more than one. (antlr-font-lock-tokendef-face): Changed color. (antlr-font-lock-tokenref-face): Changed color. (antlr-font-lock-additional-keywords): Also highlight lowercase. (antlr-mode-syntax-table): New variable. (antlr-mode): Populate and use it instead `java-mode-syntax-table'. (antlr-with-syntax-table): Don't copy syntax table. Minor changes: language setting. (antlr-language-alist): The value for file option "language" can be both an identifier and a string. Reported by Rajesh Radhakrishnan . (antlr-language-limit-n-regexp): Change accordingly. Minor changes: tabs, hiding. (antlr-tab-offset-alist): Set `indent-tabs-mode' to nil instead t. (antlr-action-visibility): Also allow value nil to also hide the braces. Renamed from `antlr-tiny-action-length'. Suggested by Jay@aol.com. (antlr-hide-actions): Change accordingly. Hide line if completely hidden action is on a line of its own. --- lisp/progmodes/antlr-mode.el | 638 +++++++++++++++++++++++++++++------ 1 file changed, 536 insertions(+), 102 deletions(-) diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el index 32d32cc5fca..3f1d735b535 100644 --- a/lisp/progmodes/antlr-mode.el +++ b/lisp/progmodes/antlr-mode.el @@ -1,9 +1,9 @@ ;;; antlr-mode.el --- Major mode for ANTLR grammar files -;; Copyright (C) 1999-2000 Free Software Foundation, Inc. +;; Copyright (C) 1999, 2000 Free Software Foundation, Inc. ;; ;; Author: Christoph.Wedler@sap.com -;; Version: $Id: antlr-mode.el,v 1.2 1999/12/16 19:30:34 wedler Exp $ +;; Version: 1.4 ;; X-URL: http://www.fmi.uni-passau.de/~wedler/antlr-mode/ ;; This file is part of GNU Emacs. @@ -29,42 +29,58 @@ ;; ANTLR is ANother Tool for Language Recognition (an excellent alternative to ;; lex/yacc), see and . -;; Variable `antlr-language' is set according to the language in actions and -;; semantic predicates of the grammar (see ANTLR's file option "language"). -;; The supported languages are "Java" (java-mode) and "Cpp" (c++-mode). This -;; package uses features of the Emacs package cc-mode. - ;; This package provides the following features: +;; * Syntax coloring (via font-lock) for grammar symbols and the code in +;; actions. The latter depends on the language settings. ;; * Indentation for the current line (TAB) and selected region (C-M-\). -;; * Syntax coloring (via font-lock) with language dependent coloring. ;; * Support for imenu/speedbar: menu "Index" (Parser, Lexer, TreeParser). -;; * Direct move to previous/next rule, beginning/end of rule body etc. +;; * Commands to move to previous/next rule, beginning/end of rule body etc. +;; * Commands to hide/unhide actions, upcase/downcase literals. +;; * Run ANTLR from within Emacs, create Makefile dependencies. + +;; LANGUAGE SETTINGS. This mode needs to know which language is used in +;; actions and semantic predicated of the grammar. This information is used +;; for syntax coloring and the creation of the Makefile dependencies. It is +;; stored in variable `antlr-language' and automatically set according to +;; ANTLR's file option "language", see `antlr-language-alist'. The supported +;; languages are "Java" (java-mode) and "Cpp" (c++-mode). ;; INDENTATION. This package supports ANTLR's (intended) indentation style ;; which is based on a simple paren/brace/bracket depth-level calculation, see ;; `antlr-indent-line'. The indentation engine of cc-mode is only used inside ;; block comments (it is not easy to use it for actions, esp if they come early -;; in the rule body). By default, this package uses TABs for a basic offset of -;; 4 to be consistent to both ANTLR's conventions (TABs usage) and the +;; in the rule body). By default, this package defines a tab width of 4 to be +;; consistent to both ANTLR's conventions (TABs usage) and the ;; `c-indentation-style' "java" which sets `c-basic-offset' to 4, see ;; `antlr-tab-offset-alist'. You might want to set this variable to nil. ;; SYNTAX COLORING comes in three phases. First, comments and strings are ;; highlighted. Second, the grammar code is highlighted according to -;; `antlr-font-lock-additional-keywords' (rule refs: blue, token refs: brown, -;; definition: ditto+bold). Third, actions, semantic predicates and arguments -;; are highlighted according to the usual font-lock keywords of +;; `antlr-font-lock-additional-keywords' (rule refs: dark blue, token refs: +;; dark orange, definition: bold blue). Third, actions, semantic predicates +;; and arguments are highlighted according to the usual font-lock keywords of ;; `antlr-language', see also `antlr-font-lock-maximum-decoration'. We define ;; special font-lock faces for the grammar code to allow you to distinguish ;; ANTLR keywords from Java/C++ keywords. +;; MAKEFILE CREATION. Command \\[antlr-show-makefile-rules] shows/inserts the +;; dependencies for all grammar files in the current directory. It considers +;; import/export vocabularies and grammar inheritance and provides a value for +;; the -glib option if necessary (which you have to edit if the super-grammar +;; is not in the same directory). + +;; TODO. Support to insert/change file/grammar/rule/subrule options. imenu +;; support for method definitions in actions is not really planned (you can +;; send be a patch, though). This mode would become too dependent on cc-mode +;; or I would have to do a lot of language-dependent things myself... + ;; Bug fixes, bug reports, improvements, and suggestions are strongly ;; appreciated. Please check the newest version first: ;; http://www.fmi.uni-passau.de/~wedler/antlr-mode/changes.html ;;; Installation: -;; This file requires Emacs-20.3, XEmacs-20.4 or higher. +;; 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: @@ -86,19 +102,33 @@ ;;; Code: (provide 'antlr-mode) -(eval-when-compile (require 'cc-mode)) ; shut up most warnings -(require 'easymenu) ; Emacs -(eval-when-compile ; optional libraries - (defvar outline-level) (defvar imenu-use-markers)) -(eval-when-compile ; Emacs: cl, XEmacs vars - (require 'cl)) +(eval-when-compile ; required and optional libraries + (require 'cc-mode) + (defvar outline-level) (defvar imenu-use-markers) + (defvar imenu-create-index-function)) +(eval-when-compile ; Emacs: cl, easymenu + (require 'cl) + (require 'easymenu)) (eval-when-compile ; XEmacs: Emacs vars (defvar inhibit-point-motion-hooks) (defvar deactivate-mark)) -(eval-and-compile - (if (string-match "XEmacs" emacs-version) +(eval-and-compile ; XEmacs functions, simplified + (if (featurep 'xemacs) (defalias 'antlr-scan-sexps 'scan-sexps) (defalias 'antlr-scan-sexps 'antlr-scan-sexps-internal)) + (if (fboundp 'default-directory) + (defalias 'antlr-default-directory 'default-directory) + (defun antlr-default-directory () default-directory)) + (if (fboundp 'read-shell-command) + (defalias 'antlr-read-shell-command 'read-shell-command) + (defun antlr-read-shell-command (prompt &optional initial-input history) + (read-from-minibuffer prompt initial-input nil nil + (or history 'shell-command-history)))) + (if (fboundp 'with-displaying-help-buffer) + (defalias 'antlr-with-displaying-help-buffer 'with-displaying-help-buffer) + (defun antlr-with-displaying-help-buffer (thunk &optional name) + (with-output-to-temp-buffer "*Help*" + (save-excursion (funcall thunk))))) (if (and (fboundp 'buffer-syntactic-context) (fboundp 'buffer-syntactic-context-depth)) (progn @@ -121,7 +151,7 @@ :link '(url-link "http://www.fmi.uni-passau.de/~wedler/antlr-mode/") :prefix "antlr-") -(defconst antlr-version "1.3" +(defconst antlr-version "1.4" "ANTLR major mode version number.") @@ -137,16 +167,16 @@ variable list\" near the end of the file, see `enable-local-variables'.") (defcustom antlr-language-alist - '((java-mode "Java" nil "Java") - (c++-mode "C++" "Cpp")) + '((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 regexp group 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 +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 "") @@ -157,25 +187,28 @@ also displayed in the modeline next to \"Antlr\"." string ))))) (defcustom antlr-language-limit-n-regexp - '(3000 . "language[ \t]*=[ \t]*\"\\([A-Z][A-Za-z_]*\\)\"") + '(3000 . "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 to set the language according to -`antlr-language-alist'." +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)) ;;;=========================================================================== -;;; Indent/Tabs +;;; Hide/Unhide, Indent/Tabs ;;;=========================================================================== -(defcustom antlr-tiny-action-length 3 - "Maximal number of characters in actions never to hide. -See command `antlr-hide-actions'." +(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 'integer) + :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. @@ -188,8 +221,8 @@ they are only changed by \\[antlr-indent-command]." (sexp :tag "With TAB" :format "%t" :value tab))) (defcustom antlr-tab-offset-alist - '((antlr-mode nil 4 t) - (java-mode "antlr" 4 t)) + '((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 @@ -210,6 +243,113 @@ ANTLR's and Java's indentation styles. Used by `antlr-set-tabs'." See command \\[antlr-indent-command].") +;;;=========================================================================== +;;; 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 ;;;=========================================================================== @@ -234,6 +374,7 @@ imenu." (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) ;; I'm too lazy to define my own: (define-key map "\ea" 'c-beginning-of-statement) (define-key map "\ee" 'c-end-of-statement) @@ -270,7 +411,10 @@ imenu." "---" ["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])) + ["Unhide All Actions" (antlr-hide-actions 0) t] + "---" + ["Run Tool on Grammar" antlr-run-tool t] + ["Show Makefile Rules" antlr-show-makefile-rules t])) ;;;=========================================================================== @@ -306,13 +450,20 @@ fontified at all." (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 - (list) ; nil won't work (would use level-3) + antlr-no-action-keywords java-font-lock-keywords-1 java-font-lock-keywords-2 java-font-lock-keywords-3) (c++-mode - (list) ; nil won't work (would use level-3) + 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. @@ -338,7 +489,7 @@ in the grammar's actions and semantic predicates, see (defvar antlr-font-lock-tokendef-face 'antlr-font-lock-tokendef-face) (defface antlr-font-lock-tokendef-face - '((((class color) (background light)) (:foreground "brown3" :bold t))) + '((((class color) (background light)) (:foreground "blue" :bold t))) "ANTLR token references (definition)." :group 'antlr) @@ -350,7 +501,7 @@ in the grammar's actions and semantic predicates, see (defvar antlr-font-lock-tokenref-face 'antlr-font-lock-tokenref-face) (defface antlr-font-lock-tokenref-face - '((((class color) (background light)) (:foreground "brown4"))) + '((((class color) (background light)) (:foreground "orange4"))) "ANTLR token references (usage)." :group 'antlr) @@ -362,7 +513,7 @@ in the grammar's actions and semantic predicates, see (defvar antlr-font-lock-additional-keywords `((antlr-invalidate-context-cache) - ("\\$setType[ \t]*(\\([A-Z\300-\326\330-\337]\\sw*\\))" + ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))" (1 antlr-font-lock-tokendef-face)) ("\\$\\sw+" (0 font-lock-keyword-face)) ;; the tokens are already fontified as string/docstrings: @@ -373,7 +524,7 @@ in the grammar's actions and semantic predicates, see '((0 nil)))) ; XEmacs bug workaround (,(lambda (limit) (antlr-re-search-forward - "^\\(class\\)[ \t]+\\([A-Z\300-\326\330-\337]\\sw*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Z\300-\326\330-\337]\\sw*\\)[ \t]*;" limit)) + "^\\(class\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;" limit)) (1 antlr-font-lock-keyword-face) (2 antlr-font-lock-ruledef-face) (3 antlr-font-lock-keyword-face) @@ -426,14 +577,17 @@ The SYNTAX-ALIST element is also used to initialize (defvar antlr-mode-hook nil "Hook called by `antlr-mode'.") +(defvar antlr-mode-syntax-table nil + "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 nil "Syntax table used for ANTLR action parsing. -Initialized by `java-mode-syntax-table', i.e., the syntax table used for -grammar files, 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.") +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.") @@ -450,11 +604,12 @@ context_cache.") ;;; Syntax functions -- Emacs vs XEmacs dependent ;;;=========================================================================== -;; From help.el (XEmacs-21.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 (copy-syntax-table ,syntab)) ,@body) + (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)) @@ -585,10 +740,6 @@ See `antlr-font-lock-additional-keywords', `antlr-language' and (defun antlr-imenu-create-index-function () "Return imenu index-alist for ANTLR grammar files." (let ((items nil) - (lexer nil) - (parser nil) - (treeparser nil) - (misc nil) (classes nil) (semi (point-max))) ;; Using `imenu-progress-message' would require imenu for compilation -- @@ -603,24 +754,12 @@ See `antlr-font-lock-additional-keywords', `antlr-language' and (progn (forward-char) (antlr-skip-exception-part t)) (antlr-skip-file-prelude t)) (if (looking-at "{") (antlr-skip-sexps 1)) - (if (looking-at "class[ \t]+\\([A-Z\300-\326\330-\337]\\sw*\\)[ \t]+extends[ \t]+\\([A-Z\300-\326\330-\337]\\sw*\\)[ \t]*;") - (progn - (push (cons (match-string 1) - (if imenu-use-markers - (copy-marker (match-beginning 1)) - (match-beginning 1))) - classes) - (if items - (let ((super (match-string 2))) - (cond ((string-equal super "Parser") - (setq parser (nconc items parser))) - ((string-equal super "Lexer") - (setq lexer (nconc items lexer))) - ((string-equal super "TreeParser") - (setq treeparser (nconc items treeparser))) - (t - (setq misc (nconc items misc)))) - (setq items nil)))) + (if (looking-at "class[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+extends[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;") + (push (cons (match-string 1) + (if imenu-use-markers + (copy-marker (match-beginning 1)) + (match-beginning 1))) + classes) (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)") (antlr-skip-sexps 1)) (when (looking-at "\\sw+") @@ -629,15 +768,6 @@ See `antlr-font-lock-additional-keywords', `antlr-language' and (copy-marker (match-beginning 0)) (match-beginning 0))) items))))) - (or items ; outside any class - (prog1 (setq items misc) (setq misc nil)) - (prog1 (setq items parser) (setq parser nil)) - (prog1 (setq items lexer) (setq lexer nil)) - (prog1 (setq items treeparser) (setq treeparser nil))) - (if misc (push (cons "Miscellaneous" misc) items)) - (if treeparser (push (cons "TreeParser" treeparser) items)) - (if lexer (push (cons "Lexer" lexer) items)) - (if parser (push (cons "Parser" parser) items)) (if classes (cons (cons "Classes" classes) items) items))) @@ -670,12 +800,14 @@ part." (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." +If SKIP-COMMENT is non-nil, also skip the comment after that part. +Return the start position of the file prelude." (let* ((pos (point)) (pos0 pos)) (c-forward-syntactic-ws) (if skip-comment (setq pos0 (point))) - (if (looking-at "header\\>") (setq pos (antlr-skip-sexps 2))) + (while (looking-at "header\\>[ \t]*\\(\"\\)?") + (setq pos (antlr-skip-sexps (if (match-beginning 1) 3 2)))) (if (looking-at "options\\>") (setq pos (antlr-skip-sexps 2))) (or skip-comment (goto-char pos)) pos0)) @@ -831,8 +963,9 @@ If non-nil, TRANSFORM is used on literals instead of `downcase-region'." 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. Never hide actions whose character -length is shorter or equal to `antlr-tiny-action-length'." +actions if ARG is 0 or negative. See `antlr-action-visibility'. + +Display a message unless optional argument SILENT is non-nil." (interactive "p") ;; from Emacs/lazy-lock: `save-buffer-state' (let ((modified (buffer-modified-p)) @@ -842,18 +975,29 @@ length is shorter or equal to `antlr-tiny-action-length'." buffer-file-name buffer-file-truename) (if (> arg 0) (let ((regexp (if (= arg 1) "[]}]" "}")) - (diff (+ (max antlr-tiny-action-length 0) 2))) + (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* ((end (point)) - (beg (antlr-scan-sexps (point) -1 nil t))) - (and beg (> end (+ beg diff)) - (add-text-properties (1+ beg) (1- end) - '(invisible t intangible t))))))) + (let ((beg (antlr-scan-sexps (point) -1 nil t))) + (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")))) @@ -865,6 +1009,290 @@ length is shorter or equal to `antlr-tiny-action-length'." (set-buffer-modified-p nil)))) +;;;=========================================================================== +;;; 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 exportVocabs importVocabs superclasses default-vocab) + (antlr-with-syntax-table antlr-action-syntax-table + (goto-char (point-min)) + (while (antlr-re-search-forward "class[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+extends[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;" nil) + ;; parse class definition -------------------------------------------- + (let* ((class (match-string 1)) + (sclass (match-string 2)) + ;; 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)) + (c-forward-syntactic-ws) + (while (looking-at "options\\>\\|\\(tokens\\)\\>") + (if (match-beginning 1) + (antlr-skip-sexps 2) + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + ;; parse grammar option section -------------------------------- + (when (eq (char-after (point)) ?\{) + (let* ((beg (1+ (point))) + (end (1- (antlr-skip-sexps 1))) + (cont (point))) + (goto-char beg) + (if (re-search-forward "\\ (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 (eq major-mode 'makefile-mode)) + (antlr-with-displaying-help-buffer 'antlr-insert-makefile-rules) + (push-mark) + (antlr-insert-makefile-rules t))) + + ;;;=========================================================================== ;;; Indentation ;;;=========================================================================== @@ -918,7 +1346,7 @@ Lines inside block comments are not changed or indented by (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: + ;; the usual major-mode indent stuff ----------------------------------- (setq orig (- (point-max) orig)) (unless (= (current-column) indent) (delete-region bol boi) @@ -1019,11 +1447,14 @@ Otherwise, indent the current line with `antlr-indent-line'." (setq major-mode 'antlr-mode mode-name "Antlr") (setq local-abbrev-table antlr-mode-abbrev-table) - (set-syntax-table java-mode-syntax-table) + (unless antlr-mode-syntax-table + (setq antlr-mode-syntax-table (make-syntax-table)) + (c-populate-syntax-table antlr-mode-syntax-table)) + (set-syntax-table antlr-mode-syntax-table) (unless antlr-action-syntax-table (let ((slist (nth 3 antlr-font-lock-defaults))) (setq antlr-action-syntax-table - (copy-syntax-table java-mode-syntax-table)) + (copy-syntax-table antlr-mode-syntax-table)) (while slist (modify-syntax-entry (caar slist) (cdar slist) antlr-action-syntax-table) @@ -1081,9 +1512,9 @@ Otherwise, indent the current line with `antlr-indent-line'." (antlr-set-tabs) (run-hooks 'antlr-mode-hook)) -;; In XEmacs, a smarter version of `buffers-menu-grouping-function' could use -;; the following property. The header of the submenu would be "Antlr" instead -;; of "Antlr/C++" or "Antlr/Java" (depending on the buffer ordering). +;; 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 @@ -1104,6 +1535,9 @@ Used in `antlr-mode'. Also a useful function in `java-mode-hook'." ;;; antlr-mode.el ends here ; LocalWords: antlr ANother ANTLR's Cpp Lexer TreeParser esp refs VALUEs ea ee -; LocalWords: Java's Nomencl ruledef tokendef ruleref tokenref setType ader +; LocalWords: Java's Nomencl ruledef tokendef ruleref tokenref setType ader ev ; LocalWords: ivate syntab lexer treeparser lic rotected rivate bor boi AFAIK -; LocalWords: slist knr inexpr +; LocalWords: slist knr inexpr unhide jit GENS SEP GEN sTokenTypes hpp cpp DEP +; LocalWords: VOCAB EVOCAB Antlr's TokenTypes exportVocab incl excl SUPERS gen +; LocalWords: VOCABS IVOCAB exportVocabs importVocabs superclasses vocab kens +; LocalWords: sclass evocab ivocab importVocab deps glibs supers sep dep lang -- 2.39.2