aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Wedler2025-12-08 20:02:33 +0100
committerChristoph Wedler2025-12-09 07:52:20 +0100
commit37468d244962dedc7ab760ffb19e15121975c1f0 (patch)
tree705fd02c3a8e4f93ef3caf7f0c8f78ac0f2233ab
parentd10a649e1b3737524f64e14e6a033eec5d0ab17d (diff)
downloademacs-feature/antlr-mode.tar.gz
emacs-feature/antlr-mode.zip
Update progmodes/antlr-mode.el from v2.2c to v3.2.0feature/antlr-mode
For the ChangeLog with timeline, see https://sourceforge.net/projects/antlr-mode/files/ The following is the ChangeLog between v2.2c to v3.2.0 without (intermediate) version numbers and changes already in the Emacs repository. * antlr-mode.el: Command `antlr-run-tool' now runs on the file for the current buffer by default. (antlr-run-tool-on-buffer-file): New user option. (antlr-run-tool-interactive): Use it. * antlr-mode.el: Allow `antlr-tool-version' and `antlr-language' be set in the Local Variables section of a file. (antlr-hack-local-variables-hook): New function. (antlr-set-tool-version-and-mode-line): Adapt (antlr-delayed-mode-hook): Renamed from `antlr-after-body-hook'. (antlr-font-lock-keywords): Correctly call `font-lock-value-in-major-mode'. * antlr-mode.el: Miscellaneous corrections and other changes. (antlr-insert-keyword-rule): Make it work in v2 and v4, too. (antlr-indent-line): Correctly calculate beginning of action. (antlr-grammar-header-regexp): Has a value which is valid for v3 and v4. (antlr-v4-grammar-header-regexp, antlr-v3-grammar-header-regexp): Delete. (antlr-tool-version-variables): tool-dependent variable for `antlr-grammar-header-regexp`' is optional. (antlr-upcase-p): Delete XEmacs bug workaround. * antlr-mode.el: Enhance options, add v4 language "Cpp". (antlr-v4-language-list): Add "Cpp". (antlr-v4-options-alists, antlr-v3-options-alists) (antlr-v2-options-alists): Do not hard-code languages. (antlr-read-language): New function used instead. (antlr-v4-options-alists): Add grammar option "contextSuperClass" and Cpp-only "exportMacro". (antlr-insert-option-do): Call the "right" antlr-mode for v4 grammars. (antlr-option-spec): Delete function. (antlr-insert-option-do): Do not use it. * antlr-mode.el: Correct command `antlr-insert-options'. (antlr-try-rule-or-grammar-option): New function. (antlr-option-level): Use it, correcting v3 and v4 behavior. (antlr-v2-options-alists): Correct "language" option. (antlr-syntactic-grammar-depth): Correct calculation (antlr-options-style): Make it really obsolete. (antlr-read-value): Do not use it. * antlr-mode.el: Disable command `antlr-show-makefile-rules' for ANTLR v3 and v4, these have "-depend" to show Makefile deps. (antlr-show-makefile-rules): User error when used with v3 or v4. * antlr-mode.el: Adapt command `antlr-run-tool' to ANTLR v3 and v4, do not calculate v2 option "-glib" for file dependencies. (antlr-tool-command): Make it tool-version dependent (antlr-v4-tool-command, antlr-v3-tool-command) (antlr-v2-tool-command): New user option. (antlr-run-tool-interactive): Only add "-glib" option with v2. (antlr-directory-dependencies): Only calculate deps with v2. (antlr-compilation-error-regexp-alist) (antlr-v4-compilation-error-regexp-alist): New variable. (antlr-tool-version-variables, antlr-run-tool): Use it. * antlr-mode.el: Cleanup, miscellaneous. Replace `match-string' by `match-string-no-properties' (see vc history). (antlr-grammar-file): New function. (antlr-insert-keyword-rule): New command. (antlr-mode-map): Use it. (antlr-font-lock-late-keywords): Correct face name. * antlr-mode.el: Allow to write a derived mode for grammars - like for PEG.js - whose rule header and body is separated by an operator other than ":" and other similar deviations. Also prepare for messages without file name in "*compilation*" buffer. (antlr-rule-body-start-op): New variable. (antlr-end-of-body, antlr-indent-line): Use it. (antlr-grammar-file): New variable. (antlr-run-tool): Set it local in *compilation*" to FILE. (antlr-font-lock-attribute-regexp, antlr-ruleref-assign-regexp): (antlr-v2-ruleref-assign-regexp, antlr-font-lock-negation-regexp): (antlr-font-lock-syntax-spec): New variables. (antlr-font-lock-additional-keywords): (antlr-font-lock-late-keywords): Use them here. (antlr-tool-version-variables): Add `antlr-ruleref-assign-regexp'. * antlr-mode.el: Adaptation to Emacs-25.1, cleanup. (antlr-insert-makefile-rules): Set variable properly. (antlr-syntax-propertize-template-literals): Using << inside an unclosed code block could lead to error during font-locking. (antlr-slow-cache-enabling-symbol): Delete variable. * antlr-mode.el: Adopt change below and other changes in the Emacs repository to current antlr-mode version. * antlr-mode.el: Use syntax-ppss. Check "are we in the grammar or action code?" does not use extra action syntax-table anymore, but 9th element of syntax-ppss / parse-partial-sexp, whose value is "subject to change" but has not changed since decades. (antlr-action-syntax-table): Delete variable. (antlr-font-lock-defaults): Do not give parentheses symbol syntax. (antlr-slow-context-cache): Delete variable. (antlr-invalidate-context-cache): Delete function. (antlr-syntactic-context): Use syntax-ppss, new optional arg PPSS. Now returns nil instead 0 if in normal grammar code. (antlr-syntax-propertize-template-literals, antlr-re-search-forward) (antlr-search-result, antlr-syntax-propertize-charsets) (antlr-electric-character): Simplify. (antlr-do-syntax-propertize): New variable. * antlr-mode.el: Code is not run under extra syntax table anymore. (antlr-syntax-propertize-wholerule, antlr-indent-at-bol-alist) (antlr-v4-grammar-header-regexp, antlr-v3-grammar-header-regexp) (antlr-v2-grammar-header-regexp, antlr-rule-postlude-skip-regexp) (antlr-skip-file-prelude, antlr-font-lock-additional-keywords) (antlr-imenu-create-index-function, antlr-inside-rule-p) (antlr-end-of-rule, antlr-beginning-of-rule antlr-end-of-body) (antlr-hide-actions, antlr-insert-option, antlr-option-level) (antlr-downcase-literals, antlr-file-dependencies) (antlr-guess-tool-version, antlr-indent-line): Do not call deleted function, do not use deleted variables, use regexp \\_> instead \\>., use both \\s_ and \\sw. * antlr-mode.el: Minor changes. (antlr-action-face, antlr-symbol-face): New face. (antlr-token-identifier-p): New variable. (antlr-font-lock-late-keywords): Use it, use antlr-grammar-header-regexp, use new faces. (antlr-syntax-propertize-charsets): Ignore @actionscope::name when searching for lexer rules. (antlr-syntax-propertize-template-literals): Change handling if the template literal does not end before eob. (antlr-font-lock-keywords): Use font-lock-eval-keywords. (antlr-rule-postlude-skip-regexp): Allow scope name to begin with underscore. * antlr-mode.el: Make antlr-mode more modular - allow to add new target languages without changing existing code. (antlr-language-variables, antlr-language-mode-name) (antlr-java-language-mode-name, antlr-action-mode) (antlr-java-action-mode, antlr-init-cc-mode) (antlr-java-init-cc-mode, antlr-init-submode) (antlr-indent-action-line, antlr-action-font-lock-keywords) (antlr-java-action-font-lock-keywords, antlr-action-scope-names) (antlr-action-names, antlr-java-action-names): New variables. (antlr-c-language-mode-name, antlr-cpp-language-mode-name) (antlr-objc-language-mode-name, antlr-c-action-mode) (antlr-cpp-action-mode, antlr-objc-action-mode) (antlr-c-init-cc-mode, antlr-cpp-init-cc-mode) (antlr-obj-init-cc-mode, antlr-cpp-action-font-lock-keywords) (antlr-c-action-font-lock-keywords) (antlr-objc-action-font-lock-keywords) (antlr-js-language-mode-name, antlr-js-action-mode) (antlr-js-init-submode, antlr-js-action-font-lock-keywords) (antlr-js-indent-action-line, antlr-delphi-language-mode-name) (antlr-delphi-action-mode, antlr-delphi-init-submode) (antlr-delphi-action-font-lock-keywords) (antlr-delphi-indent-action-line, antlr-ruby-language-mode-name) (antlr-ruby-action-mode, antlr-ruby-init-submode) (antlr-ruby-action-font-lock-keywords) (antlr-ruby-indent-action-line, antlr-python-language-mode-name) (antlr-python-action-mode, antlr-python-action-font-lock-keywords) (antlr-python-indent-action-line, antlr-python-init-submode): New variables. (antlr-init-js, antlr-js-indent-action-line, antlr-init-delphi) (antlr-delphi-indent-action-line, antlr-init-ruby) (antlr-ruby-indent-action-line, antlr-init-python) (antlr-python-indent-action-line): New functions. (antlr-font-lock-keywords-alist): Remove variable. (antlr-guess-language): Rename from anlr-language-option, use antlr-language-list, use cl function. * antlr-mode.el: Make antlr-mode more modular - allow to add new ANTLR versions/flavors without changing existing code. (antlr-tool-version): Is a symbol now, default to nil = automatic. For backward compatibility, numbers between 20000 and 29999 are set to antlr-v2 in antlr-set-tool-version-and-mode-line. This variable should not be customized anymore - change :type spec. (antlr-tool-version-variables, antlr-tool-mode-name) (antlr-v4-tool-mode-name, antlr-v3-tool-mode-name) (antlr-v2-tool-mode-name, antlr-language-list) (antlr-v4-language-list, antlr-v3-language-list) (antlr-v2-language-list, antlr-syntax-propertize) (antlr-v4-syntax-propertize, antlr-v3-syntax-propertize) (antlr-v2-syntax-propertize, antlr-v2-options-alist) (antlr-v4-skip-line-regexp, antlr-v3-skip-line-regexp) (antlr-font-lock-symbol-regexp) (antlr-v4-font-lock-symbol-regexp) (antlr-v3-font-lock-symbol-regexp) (antlr-v4-grammar-header-regexp, antlr-v3-grammar-header-regexp) New variables. (antlr-options-alist): Make it tool-dependent. Remove sub-version specific settings for ANTLR v2. Remove function. (antlr-v2-grammar-header-regexp): Rename from antlr-class-header-regexp. (antlr-grammar-header-regexp): Make it tool-version dependent. (antlr-mode-menu, antlr-insert-option-interactive) (antlr-options-menu-filter, antlr-option-level) (antlr-insert-option-do): Use tool specific variable. (antlr-option-spec): ...and do not support sub versions. (antlr-guess-tool-version): Rename from antlr-tool-version. (antlr-set-local-variables): New function (antlr-set-tool-version-and-mode-line): Use them. * antlr-mode.el: Remove XEmacs and old Emacs compatibility code. (require): require cl-lib instead cl at compile time. (antlr-run-tool-interactive, antlr-insert-makefile-rules) (antlr-set-tabs, antlr-next-rule, antlr-downcase-literals) (antlr-file-dependencies): Use cl- prefix for cXXXr, cXXXXr, incf, decf, list*. (cond-emacs-xemacs, cond-emacs-xemacs-macfn, defunx) (ignore-errors-x, save-buffer-state-x): Delete functions/macros. (antlr-skip-sexps, antlr-hide-actions, antlr-option-kind): Adopt. (antlr-mode-menu): Do not test for Emacs below 21.0. (antlr-with-syntax-table): Delete, use with-syntax-table instead. (antlr-imenu-create-index-function, antlr-inside-rule-p) (antlr-end-of-rule, antlr-beginning-of-rule, antlr-end-of-body) (antlr-downcase-literals, antlr-hide-actions) (antlr-option-level, antlr-file-dependencies, antlr-indent-line) (antlr-electric-character, antlr-tool-version): Adopt. (antlr-default-directory): Delete function. Actually XEmacs' default-directory as a function is quite useful... (antlr-run-tool-interactive, antlr-insert-makefile-rules): Adopt. (antlr-read-shell-command): Delete, use read-shell-command. (antlr-run-tool-interactive): Adopt. (antlr-with-displaying-help-buffer): Delete. (antlr-show-makefile-rules): Use with-output-to-temp-buffer. (antlr-invalidate-context-cache) (antlr-syntactic-context): Remove XEmacs code. (antlr-end-of-rule, antlr-beginning-of-rule, antlr-end-of-body) (antlr-beginning-of-body): use interactive "^" for "_" in XEmacs. (antlr-mode): Do not consider cc-mode below 5.30. * antlr-mode.el: Scope references inside a v3 rule and import statements in a v4 grammar do not confuse the navigation anymore. (antlr-skip-line-regexp): New variable, contains regexp for v3 "scope" / v4 "import" up to the semicolon. (antlr-set-tool-version-and-mode-line): Set it. (antlr-search-result): New function. (antlr-search-forward, antlr-search-backward): Use it. Add extra regexp parameter for occurrences which should be skipped. (antlr-imenu-create-index-function, antlr-next-rule) (antlr-beginning-of-rule, antlr-indent-line): Provide `antlr-skip-line-regexp' when searching for ";". (antlr-rule-postlude-skip-alist): Make it a `defconst', re-compilation would use previous value. Add "import". (antlr-skip-rule-postlude): Allow function as SKIP. (antlr-skip-import-statement): New function for postlude skip. * antlr-mode.el: Correctly recognize ANTLR v4 lexer charsets, [...], and v3 templates, <<...>>, as literals. (antlr-syntax-propertize-wholerule) (antlr-syntax-propertize-charsets) (antlr-syntax-propertize-template-literals): New function (antlr-set-tool-version-and-mode-line): Use them. (antlr-imenu-create-index-function): Call `syntax-propertize'. * antlr-mode.el (antlr-end-of-defun-is-next): New option. If non-nil, both `antlr-end-of-rule' and `antlr-end-of-rule' jump to beginning of a rule with no or positive prefix arg, and to the end of a rule with negative prefix arg. Default nil means: `antlr-end-of-rule' jumps to beginning of a rule, `antlr-end-of-rule' jumps to end of a rule. (antlr-end-of-rule): Use it. (antlr-beginning-of-rule): Use it * antlr-mode.el: Options support for ANTLR v3 and v4. (antlr-v3-options-alists): Correct prompts. (antlr-v4-options-alists): New variable. (antlr-options-alists): Use it. (antlr-read-boolean): Use `y-or-n-p' without TABLE. (antlr-mode-menu): Do not include empty option menus. (antlr-option-level): Consider non-existent file/subrule options. Correctly recognize v3/v4 grammar definitions. * antlr-mode.el: Imenu and syntax-highlighting corrections. (antlr-font-lock-late-keywords): Correct syntax-highlighting of rule definitions with modifiers in same line. (antlr-grammar-header-regexp): New regexp for v3 and v4. (antlr-class-header-regexp): New function. (antlr-imenu-create-index-function): Also collect v4 scanner modes. Correctly scan fragment rules. * antlr-mode.el: Correctly skip the part of the rule which comes after the semicolon. To simplify things, consider v2 class preamble actions as belonging to the previous definition. (antlr-skip-file-prelude): Skip final ACTION. (antlr-rule-postlude-skip-alist) (antlr-rule-postlude-skip-regexp): New variables. (antlr-skip-rule-postlude): Use them. Rename from `antlr-skip-exception-part'. (antlr-beginning-of-body): Tool version-dependent error message. (antlr-options-alists): Consider v4 options. * antlr-mode.el (antlr-indent-line): For indentation cycling in Python, do not require a patched python.el anymore, but prog-mode.el and python.el from Emacs-24.5. Do not touch multi-line python actions which do not start in its own line - they are a bad idea anyway. * antlr-mode.el: Experimental indentation cycling for Python actions. Requires a patched python.el. Note: this patch is just a first proposal by me - things will change. (antlr-indent-line): Bind `python-submode-indentation-context' while calling `python-indent-line'. * antlr-mode.el: Use much less intrusive face settings, some minor font-lock changes. (antlr-syntax): Just inherit from `font-lock-keyword-face', face is now only used for AST-relevant operators (!, ^, ->), not parentheses, colons etc anymore - see below. (antlr-keyword): Just inherit from `font-lock-keyword-face'. (antlr-ruledef): Just inherit from `font-lock-function-name-face'. (antlr-tokendef): Just inherit from `font-lock-function-name-face'. (antlr-ruleref): Just inherit from `font-lock-type-face'. (antlr-tokenref): Just inherit from `font-lock-constant-face'. (antlr-attribute): Just inherit from `font-lock-preprocessor-face'. (antlr-literal): Just inherit from `font-lock-string-face' and specify :weight bold. (antlr-grammardef-face): Delete variable introduced in v3.0.2. (antlr-grammardef): Delete face, use `font-lock-type-face'. (antlr-font-lock-late-keywords): Change according to semantic change of `antlr-syntax', properly highlight scope definitions. (antlr-font-lock-additional-keywords): Change highlighting according to ANTLR change concerning grammar element labels, ANTLR v3/v4 only. Use `font-lock-negation-char-face' for ~, single dot. * antlr-mode.el: Be more robust / fix bug introduced with v3.0.5 - class definitions in ANTLR v2 grammars would look strange, makefile dependencies would not work even with ANTLR v2 grammars. (antlr-class-header-regexp): Revert accidentally change in regexp. (antlr-insert-makefile-rules): Be more robust against incomplete grammar files, i.e. those without any extracted dependency. * antlr-mode.el: Indentation for non-cc-based languages: JavaScript, Delphi, Ruby - Python actions are left as they are. (antlr-indent-line): For a line starting with the closing brace of bracket of an action / parameter section, use our own indentation engine, not that of the grammar language. (antlr-indent-line): Run indentation functions of `js-mode', `opascal-mode' and `ruby-mode' with buffer restriction starts after the opening brace/bracket. (antlr-indent-command): Preparation for future support for indentation cycling used by Python - do not insert a TAB with repeated call of this command. (antlr-set-tool-version-and-mode-line): Locally set indentation offsets/levels of grammar language according to offset used in the ANTLR grammar. * antlr-mode.el: Correct indentation of rule headers. (antlr-indent-line): When looking for the end of a rule header, do not stop at colon if that is followed by another one, because this the scope name of a preceeding grammar action. * antlr-mode.el: Support more action languages. (antlr-language-alist): Add entries for C, Delphi, JavaScript, ObjC, Python and Ruby, additional to Java and Cpp. (antlr-language-limit-n-regexp): Allow language name to contain digits. (antlr-font-lock-keywords-alist): Add font-lock specifications for the newly supported languages. (antlr-set-tool-version-and-mode-line): Handle non-cc-based languages, currently hard-coded. * antlr-mode.el: Preparation for non-cc-mode-based indentation. (antlr-indent-line): With non-cc-based languages, do not touch lines in braces and brackets, i.e. mainly actions. * antlr-mode.el: Bug fixes and minor changes. (antlr-indent-line): Introduced 3.0.4: lines starting with a colon would be incorrectly indented. (antlr-tool-version): v3 grammars with a class definition in a header action or containing a rule called "header" or "class" would be incorrectly categorized as v2 grammar. (antlr-set-tool-version-and-mode-line, antlr-mode): Set `indent-line-function' and friends after initializing cc-mode. (antlr-java-action-names): Renamed from `antlr-action-names', only include action names used with language Java. (antlr-font-lock-late-keywords): Check action names only in Java. * antlr-mode.el: Preparation for v3/v4 options support. (antlr-v3-options-alists): New variable. (antlr-options-alists): New function. (antlr-insert-option-interactive, antlr-options-menu-filter) (antlr-insert-option-do): Use it. (antlr-option-spec): Allow options-alist not to specify ANTLR subversions. * antlr-mode.el: More flexible tool invocation. (antlr-tool-path): New variable. (antlr-run-tool): Use it. (antlr-tool-command): Can now be a function. (antlr-run-tool-interactive): Change accordingly. * antlr-mode.el: Emacs-corrected and more flexible indentation. (antlr-syntactic-context): Bind `parse-sexp-ignore-comments' to t, parentheses inside comments would bring Emacs out of sync. (antlr-base-offset-alist): New user option. (antlr-indent-line): Use it. * antlr-mode.el: Delay language recognition and tab settings. (antlr-tool-version): Correctly recognize v2 grammars without header{...}. (antlr-set-tool-version-and-mode-line): Set language here. (antlr-mode): Do not set language here. * antlr-mode.el: Bug fixes. (antlr-language-limit-n-regexp): Also recognize 'LANG'. (antlr-imenu-create-index-function): in ANTLR v2 grammars, `which-function-mode' would not work, classes would not appear. (antlr-font-lock-checked-face): action names would not be highlighted, the doc string was inserted at the wrong place... * antlr-mode.el: Use "Antlr2"/"Antlr3"/"Antlr4" in mode line. (antlr-tool-version): Set default value to nil = automatic. (antlr-tool-version): New function. (antlr-set-tool-version-and-mode-line): New function. (antlr-after-body-hook): New variable. (antlr-mode): Run it as mode hook. (antlr-v4-mode): Do not update mode line anymore. * antlr-mode.el: Minor font-lock changes. (antlr-font-lock-literal-regexp): Also match strings surrounded by single quotes, and symbols and punctuation. (antlr-font-lock-late-keywords): Highlight regexp group 2 of that. * antlr-mode.el: Preparation for further v3 and v4 support. (antlr-v4-mode): New major mode for file suffix "g4". * antlr-mode.el: Adopt imenu and navigation to ANTLR v3 and v4. (antlr-imenu-create-index-function): Recognize fragment specification and named actions. (antlr-skip-exception-part): With v3 and v4, there is no 'exception' keyword, but an additional optional 'finally'. * antlr-mode.el: Adopt font-lock to ANTLR v3 and v4. (antlr-grammardef, antlr-attribute): New faces. (antlr-action-names, antlr-action-scope-names): New variables (antlr-font-lock-late-keywords): Recognize new elements. (antlr-font-lock-additional-keywords): Changed font-lock for $attr constructs. * antlr-mode.el: Newer cc-mode fontification is very eager, i.e. would overwrite that of antlr-mode. (antlr-font-lock-late-keywords): New variable, also using OVERRIDE in MATCH-HIGHLIGHT. (antlr-font-lock-keywords): Add at end of keywords. (antlr-font-lock-additional-keywords): Delete keywords here. * antlr-mode.el: Checked ANTLR up to latest v2. (antlr-tool-version): Set for ANTLR v2.7.7. (antlr-options-alists): Added options introduced with ANTLR v2.7.2, "classHeaderPrefix" and "noConstructors". * antlr-mode.el: redisplay during font-lock could signal "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned label". (antlr-font-lock-defaults): Do not set `beginning-of-defun'. * antlr-mode.el: Delete support for old cc-mode versions. (antlr-c-init-language-vars): Delete function. (antlr-mode): Do not call it anymore. (antlr-mode-syntax-table): Adopt docstring to changed init. * antlr-mode.el: imenu creation could signal "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned label". (antlr-slow-cache-diff-threshold): Delete variable. (antlr-syntactic-context): Do not use it here, do not call `beginning-of-defun' anymore. (antlr-mode): Allow /// etc as `comment-start-skip'. Still set `require-final-newline'. * antlr-mode.el (antlr-electric-character): With Emacs, use `last-command-event' instead `last-command-char'. * antlr-mode.el: imenu creation could signal "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned label". (antlr-slow-cache-diff-threshold): Deletia. (antlr-syntactic-context): Do not use it here, do not call `beginning-of-defun' anymore.
-rw-r--r--lisp/progmodes/antlr-mode.el2838
1 files changed, 1890 insertions, 948 deletions
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index 4f17dd77b2a..d68476d9a64 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -1,10 +1,10 @@
1;;; antlr-mode.el --- major mode for ANTLR grammar files -*- lexical-binding: t; -*- 1;;; antlr-mode.el --- major mode for ANTLR grammar files -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 1999-2025 Free Software Foundation, Inc. 3;; Copyright (C) 1999-2025 Free Software Foundation, Inc.
4 4
5;; Author: Christoph Wedler <Christoph.Wedler@sap.com> 5;; Author: Christoph Wedler <Christoph.Wedler@sap.com>
6;; Keywords: languages, ANTLR, code generator 6;; Keywords: languages, ANTLR, code generator
7;; Version: 2.2c 7;; Version: 3.2.0
8;; URL: https://antlr-mode.sourceforge.net/ 8;; URL: https://antlr-mode.sourceforge.net/
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -27,58 +27,88 @@
27;; The Emacs package ANTLR-Mode provides: syntax highlighting for ANTLR grammar 27;; The Emacs package ANTLR-Mode provides: syntax highlighting for ANTLR grammar
28;; files, automatic indentation, menus containing rule/token definitions and 28;; files, automatic indentation, menus containing rule/token definitions and
29;; supported options and various other things like running ANTLR from within 29;; supported options and various other things like running ANTLR from within
30;; Emacs. 30;; Emacs. It works for ANTLR v2, v3 and v4.
31 31
32;; For details, check <https://antlr-mode.sourceforge.net/> or, if you prefer 32;; For details, check <https://antlr-mode.sourceforge.net/> or, if you prefer
33;; the manual style, follow all commands mentioned in the documentation of 33;; the manual style, follow all commands mentioned in the documentation of
34;; `antlr-mode'. ANTLR is a LL(k)-based recognition tool which generates 34;; `antlr-mode'. ANTLR is a LL(k)-based recognition tool which generates
35;; lexers, parsers and tree transformers in Java, C++ or Sather and can be 35;; lexers, parsers and tree transformers in Java, C++ or other languages and
36;; found at <https://www.antlr.org/>. 36;; can be found at <https://www.antlr.org/>.
37 37
38;; Bug fixes, bug reports, improvements, and suggestions for the newest version 38;; Topics for 3.2 or later:
39;; are strongly appreciated.
40
41;; To-do/Wish-list:
42;; 39;;
43;; * Next Version [C-c C-w]. Produce HTML document with syntax highlighted 40;; * Special support for `indent-region': faster and better for Python ELP
44;; and hyper-links (using htmlize).
45;; * Next Version [C-c C-u]. Insert/update special comments: each rule lists
46;; all rules which use the current rule. With font-lock update.
47;; * Next Version. Make hiding much more customizable.
48;; * Planned [C-c C-j]. Jump to generated coding.
49;; * Planned. Further support for imenu, i.e., include entries for method
50;; definitions at beginning of grammar class.
51;; * Planned [C-c C-p]. Pack/unpack rule/subrule & options (one/multi-line).
52;;
53;; * Probably. Show rules/dependencies for ANT like for Makefile (does ANT
54;; support vocabularies and grammar inheritance?), I have to look at
55;; jde-ant.el: https://jakarta.apache.org/ant/manual/OptionalTasks/antlr.html
56;; * Probably. Make `indent-region' faster, especially in actions. ELP
57;; profiling in a class init action shows half the time is spent in 41;; profiling in a class init action shows half the time is spent in
58;; `antlr-next-rule', the other half in `c-guess-basic-syntax'. 42;; `antlr-next-rule', the other half in `c-guess-basic-syntax'.
59;; * Unlikely. Sather as generated language with syntax highlighting etc/. 43;; Do not define a indent command, just a function to be put into
60;; Questions/problems: is sather-mode.el the standard mode for sather, is it 44;; indent-line/region-function.
61;; still supported, what is its relationship to eiffel3.el? Requirement: 45;; * In v4, highlight lexer commands after "->"
62;; this mode must not depend on a Sather mode. 46;; * Test: in `antlr-imenu-create-index-function', can we use
63;; * Unlikely. Faster syntax highlighting: sectionize the buffer into Antlr 47;; (or antlr-skip-line-regexp antlr-grammar-header-regexp)
64;; and action code and run special highlighting functions on these regions. 48;; * Use native menu bindings instead easymenu (and use :help)
65;; Problems: code size, this mode would depend on font-lock internals. 49;; * Support v4 rule element options
50;; * Define minor mode for `antlr-hide-actions' functionality.
51;; * [C-c C-u]. *Help* for current rule / all rules: used-By list (at least
52;; for single-file grammars)
53;; * [C-c C-j]. Jump to generated coding.
54
55;; Eventually:
56;;
57;; * Support for one of the multi-mode imenu extensions mentioned in
58;; https://www.emacswiki.org/emacs-test/ImenuMode - if necessary
59;; * [C-c C-w]. Produce HTML document with syntax highlighted and
60;; hyper-links. With htmfontify: invisible actions did not really work
61;; (only w/o spaces?, default invisible would be better anyway) - we need to
62;; set <a> tags afterwards ourselves... Firefox does not understand
63;; encoding via XML declaration - use HTML meta tag.
64;; * Support for outline-minor-mode.
65
66;; The following topics and suggestions are unlikely to be implemented:
67;;
68;; * Some constructs of languages (in actions) which are highly un-C-ish might
69;; bring Emacs (and ANTLR!) out of sync: e.g. regexp literals in Perl,
70;; character and percent literals in Ruby.
71;; * Faster syntax highlighting: sectionize the buffer into Antlr and action
72;; code and run special highlighting functions on these regions. UNLIKELY
73;; due to: code size, this mode would depend on font-lock internals.
74;; * Set the syntax-table of the inner mode before calling the indentation
75;; engine of the inner mode (possible? - BUT: actions should still end at
76;; the same place!). Probably not worth the effort.
77
78;; Bug fixes, bug reports, improvements, and suggestions for the newest version
79;; are strongly appreciated.
66 80
67;;; Installation: 81;;; Installation:
68 82
69;; If antlr-mode is not part of your distribution, put this file into your 83;; This file requires Emacs-24.3 or higher which already includes a version of
70;; load-path and the following into your init file: 84;; antlr-mode. If you want to use this (hopefully newer) version instead, put
71;; (autoload 'antlr-mode "antlr-mode" nil t) 85;; this file into a directory early in `load-path' (or `push' a new one to it)
72;; (setq auto-mode-alist (cons '("\\.g\\'" . antlr-mode) auto-mode-alist)) 86;; and M-x byte-compile-file this file file.
73;; (add-hook 'speedbar-load-hook ; would be too late in antlr-mode.el 87
74;; (lambda () (speedbar-add-supported-extension ".g"))) 88;; If you want to use this mode with ANTLR v4 files, put the following into
89;; your init file:
90;; (autoload 'antlr-v4-mode "antlr-mode" nil t)
91;; (push '("\\.g4\\'" . antlr-v4-mode) auto-mode-alist)
75 92
76;; To customize, use menu item "Antlr" -> "Customize Antlr". 93;; To customize, use menu item "Antlr" -> "Customize Antlr".
77 94
78;;; Code: 95;;; Development resources:
96
97;; Good examples for different action languages (for syntax coloring, ...), but
98;; there are almost no examples with rule parameters and return values...
79 99
80(eval-when-compile (require 'cl-lib)) 100;; * examples-v3-master/Delphi: C/C.g, IslandGrammar/Simple.g, Python/Python.g
101;; * examples-v3-master/JavaScript: island-grammar/Simple.g, python/Python.g
102;; * examples-v3-master/Python: C/C.g, island-grammar/Simple.g, python/Python.g
103;; * Ruby in antlr3-master/samples/standard: ../CPP.g, ../JavaScript.g, C/C.g,
104;; python/Python.g
105;; * grammars-v4-master/
81 106
107;;; Code:
108
109(eval-when-compile
110 (require 'cl-lib)
111 (require 'compile))
82(when (< emacs-major-version 28) ; preloaded in Emacs 28 112(when (< emacs-major-version 28) ; preloaded in Emacs 28
83 (require 'easymenu)) 113 (require 'easymenu))
84(require 'cc-mode) 114(require 'cc-mode)
@@ -87,13 +117,6 @@
87(defvar imenu-use-markers) 117(defvar imenu-use-markers)
88(defvar imenu-create-index-function) 118(defvar imenu-create-index-function)
89 119
90;; We cannot use `c-forward-syntactic-ws' directly since it is a macro since
91;; cc-mode-5.30 => antlr-mode compiled with older cc-mode would fail (macro
92;; call) when used with newer cc-mode. Also, antlr-mode compiled with newer
93;; cc-mode would fail (undefined `c-forward-sws') when used with older cc-mode.
94;; Additional to the `defalias' below, we must set `antlr-c-forward-sws' to
95;; `c-forward-syntactic-ws' when `c-forward-sws' is not defined after requiring
96;; cc-mode.
97(defalias 'antlr-c-forward-sws #'c-forward-sws) 120(defalias 'antlr-c-forward-sws #'c-forward-sws)
98 121
99 122
@@ -109,10 +132,97 @@
109 :link '(url-link "https://antlr-mode.sourceforge.net/") 132 :link '(url-link "https://antlr-mode.sourceforge.net/")
110 :prefix "antlr-") 133 :prefix "antlr-")
111 134
112(defconst antlr-version "2.2c" 135(defconst antlr-version "3.2.0"
113 "ANTLR major mode version number. 136 "ANTLR major mode version number.
114Check <https://antlr-mode.sourceforge.net/> for the newest.") 137Check <https://antlr-mode.sourceforge.net/> for the newest.")
115 138
139(defcustom antlr-language-limit-n-regexp ; TODO: rename? (also for tool-version)
140 ;; actually, it is in v2 "L" only, in v3/v4 'L' only
141 '(30000 . "\\<language[ \t]*=[ \t]*[\"']?\\([A-Z][A-Za-z_0-9]*\\)[\"']?")
142 "Used to set a reasonable value for `antlr-language'.
143Looks like \(LIMIT . REGEXP). Search for REGEXP from the beginning of
144the buffer to LIMIT and use the first group in the matched string to set
145the language according to `antlr-language-list'."
146 :type '(cons (choice :tag "Limit" (const :tag "No" nil) (integer :value 0))
147 regexp))
148
149
150;;;===========================================================================
151;;; Controlling the tool to use, automatically deduced
152;;;===========================================================================
153
154(defcustom antlr-tool-version nil
155 "The version symbol of the Antlr tool. DO NOT CUSTOMIZE.
156Set as buffer-local in buffers using `antlr-mode'. Supported local
157values are `antlr-v2', `antlr-v3' and`antlr-v4'. The value is used to
158set other variables, see `antlr-tool-version-variables'."
159 :type '(radio (const :tag "Automatic" nil)
160 (sexp :tag "Do not choose this" :value nil)))
161
162(defvar antlr-tool-version-variables
163 '(antlr-tool-mode-name
164 antlr-tool-command
165 antlr-language-list
166 antlr-syntax-propertize
167 antlr-options-alists
168 &optional
169 antlr-grammar-header-regexp
170 antlr-compilation-error-regexp-alist
171 antlr-skip-line-regexp
172 antlr-rule-postlude-skip-alist
173 antlr-rule-postlude-skip-regexp
174 antlr-ruleref-assign-regexp
175 antlr-font-lock-symbol-regexp)
176 "List of variables which have a tool-dependent value.
177For each antlr-VAR in this list, function `antlr-set-local-variables'
178makes it buffer-local and uses the variable VERSION-VAR, i.e.,
179antlr-v2-VAR, antlr-v3-VAR or antlr-v4-VAR to set its value,
180dependending on the value VERSION of `antlr-tool-version'.
181
182If that variable VERSION-VAR does not exist, ignore antlr-VAR if it is
183listed after the symbol &optional, or issue an error otherwise.")
184
185(defvar antlr-tool-mode-name nil
186 "The first part of the mode name used in the mode line.
187The value is tool-dependent, see `antlr-tool-version-variables'.")
188
189(defvar antlr-v4-tool-mode-name "Antlr4"
190 "Value for `antlr-tool-mode-name' when using ANTLR v4.")
191(defvar antlr-v3-tool-mode-name "Antlr3"
192 "Value for `antlr-tool-mode-name' when using ANTLR v3.")
193(defvar antlr-v2-tool-mode-name "Antlr2"
194 "Value for `antlr-tool-mode-name' when using ANTLR v2.")
195
196(defvar antlr-language-list nil
197 "Alist of supported action languages.
198Each element in this list looks like (LANG-SYMBOL STRING...) where
199LANG-SYMBOL is made the value of `antlr-language' and one of the STRINGs
200is used in ANTLR's `language` grammar/file option to specify that
201language.
202The value is tool-dependent, see `antlr-tool-version-variables'.")
203
204(defvar antlr-v4-language-list
205 '((antlr-java "Java") (antlr-cpp "Cpp") ; +CSharp
206 (antlr-js "JavaScript") (antlr-python "Python2" "Python3"))
207 ;; in ANTLR4-codegen/runtime, but not here
208 ;; - no standard Emacs major modes: CSharp, Go, Swift
209 "Value for `antlr-language-list' when using ANTLR v4.")
210
211(defvar antlr-v3-language-list
212 '((antlr-java "Java") (antlr-cpp "Cpp") (antlr-c "C")
213 (antlr-objc "ObjC") ; + CSharp
214 (antlr-js "JavaScript") (antlr-delphi "Delphi") ; + Perl
215 (antlr-python "Python" "Python3") (antlr-ruby "Ruby"))
216 ;; in ANTLR3-codegen/runtime, but not here
217 ;; - no standard Emacs major modes: ActionScript, CSharp2, CSharp3
218 ;; - I didn't spend time for it (and do not plan to do so): Perl5
219 "Value for `antlr-language-list' when using ANTLR v3.")
220
221(defvar antlr-v2-language-list
222 '((antlr-java "Java") (antlr-cpp "Cpp") (antlr-python "Python")
223 (nil "HTML") (nil "Diagnostic")) ; + CSharp
224 "Value for `antlr-language-list' when using ANTLR v2.")
225
116 226
117;;;=========================================================================== 227;;;===========================================================================
118;;; Controlling ANTLR's code generator (language option) 228;;; Controlling ANTLR's code generator (language option)
@@ -120,15 +230,62 @@ Check <https://antlr-mode.sourceforge.net/> for the newest.")
120 230
121(defvar antlr-language nil 231(defvar antlr-language nil
122 "Major mode corresponding to ANTLR's \"language\" option. 232 "Major mode corresponding to ANTLR's \"language\" option.
123Set via `antlr-language-alist'. The only useful place to change this 233Set via `antlr-language-list'. The only useful place to change this
124buffer-local variable yourself is in `antlr-mode-hook' or in the \"local 234buffer-local variable yourself is in `antlr-mode-hook' or in the \"local
125variable list\" near the end of the file, see 235variable list\" near the end of the file, see
126`enable-local-variables'.") 236`enable-local-variables'.
127 237The value is used to set other variables, see `antlr-language-variables'.")
128(defcustom antlr-language-alist 238
129 '((java-mode "Java" nil "\"Java\"" "Java") 239(defvar antlr-language-variables
130 (c++-mode "C++" "\"Cpp\"" "Cpp")) 240 '(antlr-language-mode-name
131 "List of ANTLR's supported languages. 241 antlr-action-mode
242 &optional
243 antlr-init-cc-mode
244 antlr-init-submode
245 antlr-indent-action-line
246 antlr-action-font-lock-keywords
247 antlr-action-names)
248 "List of variables which have a language-dependent value.
249For each antlr-VAR in this list, function `antlr-set-local-variables'
250makes it buffer-local and uses the variable LANGUAGE-VAR, i.e.,
251antlr-java-VAR, antlr-cpp-VAR, and so on to set its value,
252dependending on the value LANGUAGE of `antlr-language'.
253
254If that variable LANGUAGE-VAR does not exist, ignore antlr-VAR if it is
255listed after the symbol &optional, or issue an error otherwise.")
256
257;; Languages other than Java are defined at the end --------------------------
258
259(defvar antlr-language-mode-name "txt"
260 "The second part of the mode name used in the mode line.
261The value is language-dependent, see `antlr-language-variables'.")
262
263(defvar antlr-java-language-mode-name "Java"
264 "Value for `antlr-language-mode-name' when using language `antlr-java'.")
265
266(defvar antlr-action-mode nil
267 "Major-mode for code in actions of the grammar.
268The value is language-dependent, see `antlr-language-variables'.")
269
270(defvar antlr-java-action-mode 'java-mode
271 "Value for `antlr-action-mode' when using language `antlr-java'.")
272
273(defvar antlr-init-cc-mode 'java-mode
274 "Major-mode used to initialize the language variables of CC Mode.
275Used as argument for `c-init-language-vars-for'.
276The value is language-dependent, see `antlr-language-variables'.")
277
278(defvar antlr-java-init-cc-mode 'java-mode
279 "Value for `antlr-init-cc-mode' when using language `antlr-java'.")
280
281(defvar antlr-init-submode 'antlr-set-tabs
282 "Function used to initialize the action language.
283Important for languages which do not depend on CC Mode.
284The value is language-dependent, see `antlr-language-variables'.")
285
286(defcustom antlr-language-alist ; is obsolete now
287 nil
288 "List of ANTLR's supported languages. Variable is UNUSED.
132Each element in this list looks like 289Each element in this list looks like
133 (MAJOR-MODE MODELINE-STRING OPTION-VALUE...) 290 (MAJOR-MODE MODELINE-STRING OPTION-VALUE...)
134 291
@@ -137,21 +294,7 @@ value of `antlr-language' if the first group in the string matched by
137REGEXP in `antlr-language-limit-n-regexp' is one of the OPTION-VALUEs. 294REGEXP in `antlr-language-limit-n-regexp' is one of the OPTION-VALUEs.
138An OPTION-VALUE of nil denotes the fallback element. MODELINE-STRING is 295An OPTION-VALUE of nil denotes the fallback element. MODELINE-STRING is
139also displayed in the mode line next to \"Antlr\"." 296also displayed in the mode line next to \"Antlr\"."
140 :type '(repeat (group :value (java-mode "") 297 :type '(sexp :tag "DO NOT CUSTOMIZE" :value nil))
141 (function :tag "Major mode")
142 (string :tag "Mode line string")
143 (repeat :tag "ANTLR language option" :inline t
144 (choice (const :tag "Default" nil)
145 string )))))
146
147(defcustom antlr-language-limit-n-regexp
148 '(8192 . "language[ \t]*=[ \t]*\\(\"?[A-Z][A-Za-z_]*\"?\\)")
149 "Used to set a reasonable value for `antlr-language'.
150Looks like \(LIMIT . REGEXP). Search for REGEXP from the beginning of
151the buffer to LIMIT and use the first group in the matched string to set
152the language according to `antlr-language-alist'."
153 :type '(cons (choice :tag "Limit" (const :tag "No" nil) (integer :value 0))
154 regexp))
155 298
156 299
157;;;=========================================================================== 300;;;===========================================================================
@@ -175,7 +318,7 @@ they are only changed by \\[antlr-indent-command]."
175 (const :tag "Always" t) 318 (const :tag "Always" t)
176 (sexp :tag "With TAB" :format "%t" :value tab))) 319 (sexp :tag "With TAB" :format "%t" :value tab)))
177 320
178(defcustom antlr-tab-offset-alist 321(defcustom antlr-tab-offset-alist ; TODO: still advertise?
179 '((antlr-mode nil 4 nil) 322 '((antlr-mode nil 4 nil)
180 (java-mode "antlr" 4 nil)) 323 (java-mode "antlr" 4 nil))
181 "Alist to determine whether to use ANTLR's convention for TABs. 324 "Alist to determine whether to use ANTLR's convention for TABs.
@@ -197,26 +340,59 @@ See `c-set-style' and for details, where the most interesting part in
197`c-style-alist' is the value of `c-basic-offset'." 340`c-style-alist' is the value of `c-basic-offset'."
198 :type '(choice (const nil) regexp)) 341 :type '(choice (const nil) regexp))
199 342
343(defvar antlr-base-offset-alist ; TODO: make a defcustom?
344 '((:header . 0) (:body . 2) (:exception . 1))
345 "Influence the rule indentation of `antlr-indent-line'.
346The default indentation of grammar lines are calculated by
347`c-basic-offset', multiplied by:
348 - the level of the paren/brace/bracket depth,
349 - plus 0/2/1, depending on the position POS-SYMBOL inside the rule:
350 :header, :body, :exception part, customized by this variable.
351 - minus 1 if `antlr-indent-item-regexp' matches the beginning of the
352 line starting from the first non-whitespace.
353
354Each element in this list is an element (POS-SYMBOL . OFFSET).
355The following POS-SYMBOL can be:
356 - `:header', the rule header before `antlr-rule-body-start-op',
357 - `:colon' for `antlr-rule-body-start-op', the character starting
358 the rule body,
359 - `:body`, the rule body starting at `antlr-rule-body-start-op'
360 and ending with ';'
361 - `:exception', the part of the rule after the ';', see function
362 `antlr-skip-rule-postlude'.
363
364`:header', `:body` and `:exception' must appear in the alist,
365`:colon' is optional and its OFFSET defaults to the one from `:body`.")
366
200(defcustom antlr-indent-item-regexp 367(defcustom antlr-indent-item-regexp
201 "[]}):;|&]" ; & is local ANTLR extension (SGML's and-connector) 368 "[]}):;|]"
202 "Regexp matching lines which should be indented by one TAB less. 369 "Regexp matching lines which should be indented by one TAB less.
203See `antlr-indent-line' and command \\[antlr-indent-command]." 370See `antlr-indent-line' and command \\[antlr-indent-command]."
204 :type 'regexp) 371 :type 'regexp)
205 372
206(defcustom antlr-indent-at-bol-alist 373(defcustom antlr-indent-at-bol-alist ; TODO: make this pure custom option (define language-dependent vars as defaults)
207 ;; eval-when-compile not usable with defcustom... 374 ;; eval-when-compile not usable with defcustom...
208 '((java-mode . "\\(package\\|import\\)\\>") 375 '((java-mode . "\\(package\\|import\\)\\_>")
209 (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\\)\\>")) 376 (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\\)\\_>")
377 (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\\)\\_>"))
210 "Alist of regexps matching lines are indented at column 0. 378 "Alist of regexps matching lines are indented at column 0.
211Each element in this list looks like (MODE . REGEXP) where MODE is a 379Each element in this list looks like (MODE . REGEXP) where MODE is a
212function and REGEXP is a regular expression. 380function and REGEXP is a regular expression.
213 381
214If `antlr-language' equals to a MODE, the line starting at the first 382If the value of `antlr-action-mode' equals to a MODE, the line starting
215non-whitespace is matched by the corresponding REGEXP, and the line is 383at the first non-whitespace is matched by the corresponding REGEXP, and
216part of a header action, indent the line at column 0 instead according 384the line is part of a header action, indent the line at column 0 instead
217to the normal rules of `antlr-indent-line'." 385of according to the normal rules of `antlr-indent-line'."
218 :type '(repeat (cons (function :tag "Major mode") regexp))) 386 :type '(repeat (cons (function :tag "Major mode") regexp)))
219 387
388(defvar antlr-indent-action-line nil
389 ;; TODO: better call it with action start?
390 "Function which indents the current line in actions.
391The function is called with the character address of the '{' starting
392the action.
393If nil, use CC mode to indent the line.
394The value might be language-dependent, see `antlr-language-variables'.")
395
220;; adopt indentation to cc-engine 396;; adopt indentation to cc-engine
221(defvar antlr-disabling-cc-syntactic-symbols 397(defvar antlr-disabling-cc-syntactic-symbols
222 '(statement-block-intro 398 '(statement-block-intro
@@ -224,30 +400,30 @@ to the normal rules of `antlr-indent-line'."
224 arglist-intro brace-list-intro knr-argdecl-intro inher-intro 400 arglist-intro brace-list-intro knr-argdecl-intro inher-intro
225 objc-method-intro 401 objc-method-intro
226 block-close defun-close class-close brace-list-close arglist-close 402 block-close defun-close class-close brace-list-close arglist-close
227 inline-close extern-lang-close namespace-close)) 403 inline-close extern-lang-close namespace-close)
404 "CC Mode syntactic context symbols adopting the indentation by CC Mode.")
228 405
229 406
230;;;=========================================================================== 407;;;===========================================================================
231;;; Options: customization 408;;; Options: customization
232;;;=========================================================================== 409;;;===========================================================================
233 410
411(defcustom antlr-end-of-defun-is-next nil
412 "Non-nil, if rule movement commands normally jump to beginning of rule.
413If non-nil, both `antlr-end-of-rule' and `antlr-end-of-rule' jump
414to beginning of a rule with no or positive prefix arg, and to the
415end of a rule with negative prefix arg.
416
417Default nil means: `antlr-end-of-rule' jumps to beginning of a
418rule, `antlr-end-of-rule' jumps to end of a rule."
419 :type 'boolean)
420
234(defcustom antlr-options-use-submenus t 421(defcustom antlr-options-use-submenus t
235 "Non-nil, if the major mode menu should include option submenus. 422 "Non-nil, if the major mode menu should include option submenus.
236If nil, the menu just includes a command to insert options. Otherwise, 423If nil, the menu just includes a command to insert options. Otherwise,
237it includes four submenus to insert file/grammar/rule/subrule options." 424it includes four submenus to insert file/grammar/rule/subrule options."
238 :type 'boolean) 425 :type 'boolean)
239 426
240(defcustom antlr-tool-version 20701
241 "The version number of the Antlr tool.
242The value is an integer of the form XYYZZ which stands for vX.YY.ZZ.
243This variable is used to warn about non-supported options and to supply
244version correct option values when using \\[antlr-insert-option].
245
246Don't use a number smaller than 20600 since the stored history of
247Antlr's options starts with v2.06.00, see `antlr-options-alists'. You
248can make this variable buffer-local."
249 :type 'integer)
250
251(defcustom antlr-options-auto-colon t 427(defcustom antlr-options-auto-colon t
252 "Non-nil, if `:' is inserted with a rule or subrule options section. 428 "Non-nil, if `:' is inserted with a rule or subrule options section.
253A `:' is only inserted if this value is non-nil, if a rule or subrule 429A `:' is only inserted if this value is non-nil, if a rule or subrule
@@ -256,14 +432,8 @@ subrule options section before, and if a `:' is not already present
256after the section, ignoring whitespace, comments and the init action." 432after the section, ignoring whitespace, comments and the init action."
257 :type 'boolean) 433 :type 'boolean)
258 434
259(defcustom antlr-options-style nil 435(defcustom antlr-options-style nil ; TODO: obsolete
260 "List of symbols which determine the style of option values. 436 "Obsolete user option."
261If a style symbol is present, the corresponding option value is put into
262quotes, i.e., represented as a string, otherwise it is represented as an
263identifier.
264
265The only style symbol used in the default value of `antlr-options-alist'
266is `language-as-string'. See also `antlr-read-value'."
267 :type '(repeat (symbol :tag "Style symbol"))) 437 :type '(repeat (symbol :tag "Style symbol")))
268 438
269(defcustom antlr-options-push-mark t 439(defcustom antlr-options-push-mark t
@@ -296,178 +466,311 @@ existing `=' won't be changed when changing an option value."
296The standard value is (\"file\" \"grammar\" \"rule\" \"subrule\"). See 466The standard value is (\"file\" \"grammar\" \"rule\" \"subrule\"). See
297`antlr-options-alists'") 467`antlr-options-alists'")
298 468
299(defvar antlr-options-alists 469(defvar antlr-options-alists nil
470 ;; TODO: distinguish between "no known option" (options{} is allowed), and
471 ;; does not exist (file options in v3 and v4)
472 "Definitions for Antlr's options of all four different kinds.
473
474The value looks like \(FILE GRAMMAR RULE SUBRULE) where each FILE,
475GRAMMAR, RULE, and SUBRULE is a list of option definitions of the
476corresponding kind, i.e., looks like \(OPTION-DEF...).
477
478Each OPTION-DEF looks like \(OPTION-NAME EXTRA-FN VALUE-SPEC...) which
479defines a file/grammar/rule/subrule option with name OPTION-NAME. The
480OPTION-NAMEs are used for the creation of the \"Insert XXX Option\"
481submenus, see `antlr-options-use-submenus', and to allow the insertion
482of the option name with completion when using \\[antlr-insert-option].
483
484If EXTRA-FN is a function, it is called at different phases of the
485insertion with arguments \(PHASE OPTION-NAME). PHASE can have the
486values `before-input' or `after-insertion', additional phases might be
487defined in future versions of this mode. The phase `before-input'
488occurs before the user is asked to insert a value. The phase
489`after-insertion' occurs after the option value has been inserted.
490EXTRA-FN might be called with additional arguments in future versions of
491this mode.
492
493Each specification VALUE-SPEC looks like \(VERSION READ-FN ARG...). The
494last VALUE-SPEC in an OPTION-DEF whose VERSION is smaller or equal to
495`antlr-tool-version' specifies how the user is asked for the value of
496the option.
497
498If READ-FN is nil, the only ARG is a string which is printed at the echo
499area to guide the user what to insert at point. Otherwise, READ-FN is
500called with arguments \(INIT-VALUE ARG...) to get the new value of the
501option. INIT-VALUE is the old value of the option or nil.
502
503The standard value contains the following functions as READ-FN:
504`antlr-read-value' with ARGs = \(PROMPT AS-STRING TABLE) which reads a
505general value, or `antlr-read-boolean' with ARGs = \(PROMPT TABLE) which
506reads a boolean value or a member of TABLE. PROMPT is the prompt when
507asking for a new value. If non-nil, TABLE is a table for completion or
508a function evaluating to such a table. The return value is quoted if
509AS-STRING is non-nil.
510
511The value is tool-dependent, see `antlr-tool-version-variables'.")
512
513(defvar antlr-v4-options-alists
514 ;; see https://github.com/antlr/antlr4 - doc/options.md
515 '(() ; no file options
516 (;; grammar options ------------------------------------------------------
517 ("language"
518 ;; The target language for code generation. Default is Java. See Code
519 ;; Generation Targets for list of currently supported target languages.
520 antlr-language-option-extra antlr-read-language "Generated language: ")
521 ("tokenVocab"
522 ;; Where ANTLR should get predefined tokens and token types. Tree
523 ;; grammars need it to get the token types from the parser that creates
524 ;; its trees. Default value: Do not import token vocab.
525 nil antlr-read-value "Token vocabulary: ")
526 ("TokenLabelType" ; parser and tree only
527 ;; Set the type of all tree labels and tree-valued expressions. Without
528 ;; this option, trees are of type Object. TODO: Cross-reference default
529 ;; impl (org.antlr.runtime.tree.CommonTree in Java)?
530 nil antlr-read-value "Token type: ")
531 ("superClass" ; in combined grammar: for parser
532 ;; Set the superclass of the generated recognizer. Default value
533 ;; Lexer/Parser/TreeParser (org.antlr.runtime.Parser in Java)?
534 nil antlr-read-value "Super class: ")
535 ("contextSuperClass"
536 nil antlr-read-value "Rule context super class: ")
537 ("exportMacro" ; doc/cpp-target.md
538 antlr-c++-mode-extra antlr-read-value "Export macro: "))
539 nil ; no rule option yet
540 nil ; no subrule options
541 ;; use ??, *?, +? for non-greedy subrules
542 ;; (but there are some greedy options in grammars-v4-master/...)
543 ;; rule element options in v4 are actually different (and have a different
544 ;; syntax): <optionname = value> - not yet supported
545 ;; after op: <assoc=left|right>
546 ;; after sempred: <fail={expr}>
547 )
548 "Value for `antlr-options-alists' when using ANTLR v4.")
549
550;;; v3:
551;; https://theantlrguy.atlassian.net/wiki/display/ANTLR3/ANTLR+3+Wiki+Home
552
553;; $ANTLR3/tool/src/main/java/org/antlr/tool/Grammar.java
554;; https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Grammar+options
555;; https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Rule+and+subrule+options
556(defvar antlr-v3-options-alists
557 '(() ; no file options
558 (;; grammar options ------------------------------------------------------
559 ("language"
560 ;; The target language for code generation. Default is Java. See Code
561 ;; Generation Targets for list of currently supported target languages.
562 antlr-language-option-extra antlr-read-language "Generated language: ")
563 ("tokenVocab"
564 ;; Where ANTLR should get predefined tokens and token types. Tree
565 ;; grammars need it to get the token types from the parser that creates
566 ;; its trees. Default value: Do not import token vocab.
567 nil antlr-read-value "Token vocabulary: ")
568 ("output" ; parser and tree only
569 ;; The type of output the generated parser should return. Valid values
570 ;; are AST and template. TODO: Briefly, what are the interpretations of
571 ;; these values? Default value: nothing
572 nil antlr-read-value "Output type (AST or template): ") ; TODO: completion
573 ("TokenLabelType" ; parser and tree only
574 ;; Set the type of all tree labels and tree-valued expressions. Without
575 ;; this option, trees are of type Object. TODO: Cross-reference default
576 ;; impl (org.antlr.runtime.tree.CommonTree in Java)?
577 nil antlr-read-value "Token type: ")
578 ("superClass" ; in combined grammar: for parser
579 ;; Set the superclass of the generated recognizer. Default value
580 ;; Lexer/Parser/TreeParser (org.antlr.runtime.Parser in Java)?
581 nil antlr-read-value "Super class: ")
582 ("filter" ; lexer only
583 ;; In the lexer, this allows you to try a list of lexer rules in
584 ;; order. The first one that matches, wins. This is the token that
585 ;; nextToken() returns. If nothing matches, the lexer consumes a single
586 ;; character and tries the list of rules again. See Lexical filters for
587 ;; more., Default: false
588 nil antlr-read-boolean "Lexical filter? ")
589 ("rewrite" ; parser and tree only
590 ;; Valid values are true and false. Default is false. Use this option
591 ;; when your translator output looks very much like the input. Your
592 ;; actions can modify the TokenRewriteStream to insert, delete, or
593 ;; replace ranges of tokens with another object. Used in conjunction with
594 ;; output=template, you can very easily build translators that tweak
595 ;; input files.
596 nil antlr-read-value "Template rewrite: ")
597 ("k" ; parser and tree only
598 ;; Limit the lookahead depth for the recognizer to at most k
599 ;; symbols. This prevents the decision from using acyclic LL* DFA.
600 nil antlr-read-value "Lookahead depth: ")
601 ("backtrack" ; parser and tree only
602 ;; Valid values are true and false. Default is false. Taken from
603 ;; http://www.antlr.org:8080/pipermail/antlr-interest/2006-July/016818.html
604 ;; : The new feature (a big one) is the backtrack=true option for
605 ;; grammar, rule, and block that lets you type in any old crap and ANTLR
606 ;; will backtrack if it can't figure out what you meant. No errors are
607 ;; reported by antlr during analysis. It implicitly adds a syn pred in
608 ;; front of every production, using them only if static grammar LL*
609 ;; analysis fails. Syn pred code is not generated if the pred is not used
610 ;; in a decision. This is essentially a rapid prototyping mode. It is
611 ;; what I have used on the java.g. Oh, it doesn't memoize partial parses
612 ;; (i.e. rule parsing results) during backtracking automatically now. You
613 ;; must also say memoize=true. Can make a HUGE difference to turn on.
614 nil antlr-read-boolean "Use automatic backtracking if necessary? ")
615 ("memoize" ; parser and tree only
616 ;; Valid values are true and false. When backtracking, remember whether
617 ;; or not rule references succeed so that the same input position cannot
618 ;; be parsed more than once by the same rule. This effectively guarantees
619 ;; linear parsing when backtracking at the cost of more memory. TODO:
620 ;; Default value: false
621 nil antlr-read-boolean "Store backtracking calculations? "))
622 (;; rule options ---------------------------------------------------------
623 ("backtrack"
624 nil antlr-read-boolean "Use automatic backtracking if necessary? ")
625 ("memoize"
626 nil antlr-read-boolean "Store backtracking calculations? "))
627 (;; subrule options ------------------------------------------------------
628 ("k"
629 nil antlr-read-value "Lookahead depth: ")
630 ("greedy" ; default true
631 nil antlr-read-boolean "Make this optional/loop subrule greedy? ")))
632 "Value for `antlr-options-alists' when using ANTLR v3.")
633
634(defvar antlr-v2-options-alists
300 '(;; file options ---------------------------------------------------------- 635 '(;; file options ----------------------------------------------------------
301 (("language" antlr-language-option-extra 636 (("language"
302 (20600 antlr-read-value 637 antlr-language-option-extra antlr-read-language "Generated language: ")
303 "Generated language: " language-as-string
304 (("Java") ("Cpp") ("HTML") ("Diagnostic")))
305 (20700 antlr-read-value
306 "Generated language: " language-as-string
307 (("Java") ("Cpp") ("HTML") ("Diagnostic") ("Sather"))))
308 ("mangleLiteralPrefix" nil 638 ("mangleLiteralPrefix" nil
309 (20600 antlr-read-value 639 antlr-read-value "Prefix for literals (default LITERAL_): " t)
310 "Prefix for literals (default LITERAL_): " t))
311 ("namespace" antlr-c++-mode-extra 640 ("namespace" antlr-c++-mode-extra
312 (20700 antlr-read-value 641 antlr-read-value "Wrap generated C++ code in namespace: " t)
313 "Wrap generated C++ code in namespace: " t))
314 ("namespaceStd" antlr-c++-mode-extra 642 ("namespaceStd" antlr-c++-mode-extra
315 (20701 antlr-read-value 643 antlr-read-value "Replace ANTLR_USE_NAMESPACE(std) by: " t)
316 "Replace ANTLR_USE_NAMESPACE(std) by: " t))
317 ("namespaceAntlr" antlr-c++-mode-extra 644 ("namespaceAntlr" antlr-c++-mode-extra
318 (20701 antlr-read-value 645 antlr-read-value "Replace ANTLR_USE_NAMESPACE(antlr) by: " t)
319 "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
320 ("genHashLines" antlr-c++-mode-extra 646 ("genHashLines" antlr-c++-mode-extra
321 (20701 antlr-read-boolean 647 antlr-read-boolean "Include #line in generated C++ code? ")
322 "Include #line in generated C++ code? ")) 648 ("noConstructors" antlr-c++-mode-extra ; lexer only
649 antlr-read-boolean "Omit default constructors for generated classes? ")
323 ) 650 )
324 ;; grammar options -------------------------------------------------------- 651 ;; grammar options --------------------------------------------------------
325 (("k" nil 652 (("k" nil
326 (20600 antlr-read-value 653 antlr-read-value "Lookahead depth: ")
327 "Lookahead depth: "))
328 ("importVocab" nil 654 ("importVocab" nil
329 (20600 antlr-read-value 655 antlr-read-value "Import vocabulary: ")
330 "Import vocabulary: ")) 656 ("exportVocab" nil antlr-read-value
331 ("exportVocab" nil 657 "Export vocabulary: ")
332 (20600 antlr-read-value
333 "Export vocabulary: "))
334 ("testLiterals" nil ; lexer only 658 ("testLiterals" nil ; lexer only
335 (20600 antlr-read-boolean 659 antlr-read-boolean "Test each token against literals table? ")
336 "Test each token against literals table? "))
337 ("defaultErrorHandler" nil ; not for lexer 660 ("defaultErrorHandler" nil ; not for lexer
338 (20600 antlr-read-boolean 661 antlr-read-boolean "Generate default exception handler for each rule? ")
339 "Generate default exception handler for each rule? "))
340 ("codeGenMakeSwitchThreshold" nil 662 ("codeGenMakeSwitchThreshold" nil
341 (20600 antlr-read-value 663 antlr-read-value "Min number of alternatives for `switch': ")
342 "Min number of alternatives for `switch': "))
343 ("codeGenBitsetTestThreshold" nil 664 ("codeGenBitsetTestThreshold" nil
344 (20600 antlr-read-value 665 antlr-read-value "Min size of lookahead set for bitset test: ")
345 "Min size of lookahead set for bitset test: "))
346 ("analyzerDebug" nil 666 ("analyzerDebug" nil
347 (20600 antlr-read-boolean 667 antlr-read-boolean "Display debugging info during grammar analysis? ")
348 "Display debugging info during grammar analysis? "))
349 ("codeGenDebug" nil 668 ("codeGenDebug" nil
350 (20600 antlr-read-boolean 669 antlr-read-boolean "Display debugging info during code generation? ")
351 "Display debugging info during code generation? "))
352 ("buildAST" nil ; not for lexer 670 ("buildAST" nil ; not for lexer
353 (20600 antlr-read-boolean 671 antlr-read-boolean "Use automatic AST construction/transformation? ")
354 "Use automatic AST construction/transformation? "))
355 ("ASTLabelType" nil ; not for lexer 672 ("ASTLabelType" nil ; not for lexer
356 (20600 antlr-read-value 673 antlr-read-value "Class of user-defined AST node: " t)
357 "Class of user-defined AST node: " t))
358 ("charVocabulary" nil ; lexer only 674 ("charVocabulary" nil ; lexer only
359 (20600 nil 675 nil "Insert character vocabulary")
360 "Insert character vocabulary"))
361 ("interactive" nil 676 ("interactive" nil
362 (20600 antlr-read-boolean 677 antlr-read-boolean "Generate interactive lexer/parser? ")
363 "Generate interactive lexer/parser? "))
364 ("caseSensitive" nil ; lexer only 678 ("caseSensitive" nil ; lexer only
365 (20600 antlr-read-boolean 679 antlr-read-boolean "Case significant when matching characters? ")
366 "Case significant when matching characters? "))
367 ("caseSensitiveLiterals" nil ; lexer only 680 ("caseSensitiveLiterals" nil ; lexer only
368 (20600 antlr-read-boolean 681 antlr-read-boolean "Case significant when testing literals table? ")
369 "Case significant when testing literals table? ")) 682 ("classHeaderPrefix" nil
683 nil "Initial String for grammar class definition")
370 ("classHeaderSuffix" nil 684 ("classHeaderSuffix" nil
371 (20600 nil 685 nil "Additional string for grammar class definition")
372 "Additional string for grammar class definition"))
373 ("filter" nil ; lexer only 686 ("filter" nil ; lexer only
374 (20600 antlr-read-boolean 687 antlr-read-boolean "Skip rule (the name, true or false): "
375 "Skip rule (the name, true or false): " 688 antlr-grammar-tokens)
376 antlr-grammar-tokens))
377 ("namespace" antlr-c++-mode-extra 689 ("namespace" antlr-c++-mode-extra
378 (20700 antlr-read-value 690 antlr-read-value "Wrap generated C++ code for grammar in namespace: " t)
379 "Wrap generated C++ code for grammar in namespace: " t))
380 ("namespaceStd" antlr-c++-mode-extra 691 ("namespaceStd" antlr-c++-mode-extra
381 (20701 antlr-read-value 692 antlr-read-value "Replace ANTLR_USE_NAMESPACE(std) by: " t)
382 "Replace ANTLR_USE_NAMESPACE(std) by: " t))
383 ("namespaceAntlr" antlr-c++-mode-extra 693 ("namespaceAntlr" antlr-c++-mode-extra
384 (20701 antlr-read-value 694 antlr-read-value "Replace ANTLR_USE_NAMESPACE(antlr) by: " t)
385 "Replace ANTLR_USE_NAMESPACE(antlr) by: " t))
386 ("genHashLines" antlr-c++-mode-extra 695 ("genHashLines" antlr-c++-mode-extra
387 (20701 antlr-read-boolean 696 antlr-read-boolean "Include #line in generated C++ code? ")
388 "Include #line in generated C++ code? ")) 697 ("noConstructors" antlr-c++-mode-extra ; lexer only
389;;; ("autoTokenDef" nil ; parser only 698 antlr-read-boolean "Omit default constructors for generated classes? ")
390;;; (80000 antlr-read-boolean ; default: true
391;;; "Automatically define referenced token? "))
392;;; ("keywordsMeltTo" nil ; parser only
393;;; (80000 antlr-read-value
394;;; "Change non-matching keywords to token type: "))
395 ) 699 )
396 ;; rule options ---------------------------------------------------------- 700 ;; rule options ----------------------------------------------------------
397 (("testLiterals" nil ; lexer only 701 (("testLiterals" nil ; lexer only
398 (20600 antlr-read-boolean 702 antlr-read-boolean "Test this token against literals table? ")
399 "Test this token against literals table? "))
400 ("defaultErrorHandler" nil ; not for lexer 703 ("defaultErrorHandler" nil ; not for lexer
401 (20600 antlr-read-boolean 704 antlr-read-boolean "Generate default exception handler for this rule? ")
402 "Generate default exception handler for this rule? "))
403 ("ignore" nil ; lexer only 705 ("ignore" nil ; lexer only
404 (20600 antlr-read-value 706 antlr-read-value "In this rule, ignore tokens of type: " nil
405 "In this rule, ignore tokens of type: " nil 707 antlr-grammar-tokens)
406 antlr-grammar-tokens))
407 ("paraphrase" nil ; lexer only 708 ("paraphrase" nil ; lexer only
408 (20600 antlr-read-value 709 antlr-read-value "In messages, replace name of this token by: " t)
409 "In messages, replace name of this token by: " t))
410 ) 710 )
411 ;; subrule options ------------------------------------------------------- 711 ;; subrule options -------------------------------------------------------
412 (("warnWhenFollowAmbig" nil 712 (("warnWhenFollowAmbig" nil
413 (20600 antlr-read-boolean 713 antlr-read-boolean "Display warnings for ambiguities with FOLLOW? ")
414 "Display warnings for ambiguities with FOLLOW? "))
415 ("generateAmbigWarnings" nil 714 ("generateAmbigWarnings" nil
416 (20600 antlr-read-boolean 715 antlr-read-boolean "Display warnings for ambiguities? ")
417 "Display warnings for ambiguities? "))
418 ("greedy" nil 716 ("greedy" nil
419 (20700 antlr-read-boolean 717 antlr-read-boolean "Make this optional/loop subrule greedy? ")
420 "Make this optional/loop subrule greedy? "))
421 )) 718 ))
422 "Definitions for Antlr's options of all four different kinds. 719 "Value for `antlr-options-alist' when using ANTLR v2.")
423 720
424The value looks like \(FILE GRAMMAR RULE SUBRULE) where each FILE,
425GRAMMAR, RULE, and SUBRULE is a list of option definitions of the
426corresponding kind, i.e., looks like \(OPTION-DEF...).
427 721
428Each OPTION-DEF looks like \(OPTION-NAME EXTRA-FN VALUE-SPEC...) which 722;;;===========================================================================
429defines a file/grammar/rule/subrule option with name OPTION-NAME. The 723;;; Run tool
430OPTION-NAMEs are used for the creation of the \"Insert XXX Option\" 724;;;===========================================================================
431submenus, see `antlr-options-use-submenus', and to allow the insertion
432of the option name with completion when using \\[antlr-insert-option].
433 725
434If EXTRA-FN is a function, it is called at different phases of the 726(defvar antlr-tool-path nil ; TODO: make it a defcustom?
435insertion with arguments \(PHASE OPTION-NAME). PHASE can have the 727 "Extra settings for environment variables $PATH and $LD_LIBRARY_PATH.")
436values `before-input' or `after-insertion', additional phases might be
437defined in future versions of this mode. The phase `before-input'
438occurs before the user is asked to insert a value. The phase
439`after-insertion' occurs after the option value has been inserted.
440EXTRA-FN might be called with additional arguments in future versions of
441this mode.
442 728
443Each specification VALUE-SPEC looks like \(VERSION READ-FN ARG...). The 729(defvar antlr-compilation-mode nil
444last VALUE-SPEC in an OPTION-DEF whose VERSION is smaller or equal to 730 "Mode used for compile output of \\[antlr-run-tool].")
445`antlr-tool-version' specifies how the user is asked for the value of
446the option.
447 731
448If READ-FN is nil, the only ARG is a string which is printed at the echo 732(defvar antlr-compilation-error-regexp-alist nil
449area to guide the user what to insert at point. Otherwise, READ-FN is 733 "If non-nil, used instead `compilation-error-regexp-alist'`.
450called with arguments \(INIT-VALUE ARG...) to get the new value of the 734The value might be tool-dependent, see `antlr-tool-version-variables'.")
451option. INIT-VALUE is the old value of the option or nil.
452 735
453The standard value contains the following functions as READ-FN: 736(defvar antlr-v4-compilation-error-regexp-alist
454`antlr-read-value' with ARGs = \(PROMPT AS-STRING TABLE) which reads a 737 '(("\\(?:[eE]rror\\|\\([wW]arning\\)\\)[ \t]*([0-9]+):[ \t]*\
455general value, or `antlr-read-boolean' with ARGs = \(PROMPT TABLE) which 738\\([^\n:]+\\):\\([0-9]+\\):\\([0-9]+\\)" 2 3 4 (1))
456reads a boolean value or a member of TABLE. PROMPT is the prompt when 739 gnu)
457asking for a new value. If non-nil, TABLE is a table for completion or 740 "Value for `antlr-compilation-error-regexp-alist' when using ANTLR v4.")
458a function evaluating to such a table. The return value is quoted if
459AS-STRING is non-nil and is either t or a symbol which is a member of
460`antlr-options-style'.")
461 741
742(defcustom antlr-run-tool-on-buffer-file t ; was nil before 3.2.0
743 "Non-nil, if \\[antlr-run-tool] runs on the file for the current buffer.
744If nil, the provided tool command must include the file name."
745 :type 'boolean)
462 746
463;;;=========================================================================== 747(defcustom antlr-tool-command nil
464;;; Run tool, create Makefile dependencies 748 "Command used in \\[antlr-run-tool] to run the Antlr tool.
465;;;=========================================================================== 749This variable should include all options passed to Antlr except the
750option \"-glib\" which is automatically suggested if necessary.
751
752OBSOLETE as user option - customize version dependent user options."
753 :type 'string)
754
755(defcustom antlr-v4-tool-command "java org.antlr.v4.Tool"
756 ;; you probably also need to add s/th like
757 ;; "-cp /usr/local/lib/antlr-4.6-complete.jar" to the string
758 "Command used in \\[antlr-run-tool] to run the Antlr tool.
759This variable should include all options passed to Antlr.
760Value for `antlr-tool-command' when using ANTLR v4."
761 :type 'string)
762
763(defcustom antlr-v3-tool-command "java org.antlr.Tool"
764 "Command used in \\[antlr-run-tool] to run the Antlr tool.
765This variable should include all options passed to Antlr.
766Value for `antlr-tool-command' when using ANTLR v3."
767 :type 'string)
466 768
467(defcustom antlr-tool-command "java antlr.Tool" 769(defcustom antlr-v2-tool-command "java antlr.Tool"
468 "Command used in \\[antlr-run-tool] to run the Antlr tool. 770 "Command used in \\[antlr-run-tool] to run the Antlr tool.
469This variable should include all options passed to Antlr except the 771This variable should include all options passed to Antlr except the
470option \"-glib\" which is automatically suggested if necessary." 772option \"-glib\" which is automatically suggested if necessary.
773Value for `antlr-tool-command' when using ANTLR v2."
471 :type 'string) 774 :type 'string)
472 775
473(defcustom antlr-ask-about-save t 776(defcustom antlr-ask-about-save t
@@ -475,9 +778,18 @@ option \"-glib\" which is automatically suggested if necessary."
475Otherwise, it saves all modified buffers before running without asking." 778Otherwise, it saves all modified buffers before running without asking."
476 :type 'boolean) 779 :type 'boolean)
477 780
781
782;;;===========================================================================
783;;; Makefile creation (ANTLR v2 only)
784;;;===========================================================================
785
786;; TODO: make it a variable only (no `defcustom')
478(defcustom antlr-makefile-specification 787(defcustom antlr-makefile-specification
479 '("\n" ("GENS" "GENS%d" " \\\n\t") "$(ANTLR)") 788 '("\n" ("GENS" "GENS%d" " \\\n\t") "$(ANTLR)")
480 "Variable to specify the appearance of the generated makefile rules. 789 "Variable to specify the appearance of the generated makefile rules.
790This variable is only used or ANTLR v2 grammars. For v3 and v4
791grammars, run the ANTLR tool with option \"--depend\".
792
481This variable influences the output of \\[antlr-show-makefile-rules]. 793This variable influences the output of \\[antlr-show-makefile-rules].
482It looks like \(RULE-SEP GEN-VAR-SPEC COMMAND). 794It looks like \(RULE-SEP GEN-VAR-SPEC COMMAND).
483 795
@@ -507,6 +819,8 @@ COUNT starts with 1. GEN-SEP is used to separate long variable values."
507 '((java-mode ("%sTokenTypes.java") ("%s.java")) 819 '((java-mode ("%sTokenTypes.java") ("%s.java"))
508 (c++-mode ("%sTokenTypes.hpp") ("%s.cpp" "%s.hpp"))) 820 (c++-mode ("%sTokenTypes.hpp") ("%s.cpp" "%s.hpp")))
509 "Language dependent formats which specify generated files. 821 "Language dependent formats which specify generated files.
822This variable is only used or ANTLR v2 grammars.
823
510Each element in this list looks like 824Each element in this list looks like
511 (MAJOR-MODE (VOCAB-FILE-FORMAT...) (CLASS-FILE-FORMAT...)). 825 (MAJOR-MODE (VOCAB-FILE-FORMAT...) (CLASS-FILE-FORMAT...)).
512 826
@@ -521,6 +835,8 @@ CLASS/%s the generated file for each grammar class CLASS.")
521 835
522(defvar antlr-special-file-formats '("%sTokenTypes.txt" "expanded%s.g") 836(defvar antlr-special-file-formats '("%sTokenTypes.txt" "expanded%s.g")
523 "Language independent formats which specify generated files. 837 "Language independent formats which specify generated files.
838This variable is only used or ANTLR v2 grammars.
839
524The value looks like \(VOCAB-FILE-FORMAT EXPANDED-GRAMMAR-FORMAT). 840The value looks like \(VOCAB-FILE-FORMAT EXPANDED-GRAMMAR-FORMAT).
525 841
526VOCAB-FILE-FORMAT is a format string, it specifies with substitution 842VOCAB-FILE-FORMAT is a format string, it specifies with substitution
@@ -535,6 +851,8 @@ formats.")
535 851
536(defvar antlr-unknown-file-formats '("?%s?.g" "?%s?") 852(defvar antlr-unknown-file-formats '("?%s?.g" "?%s?")
537 "Formats which specify the names of unknown files. 853 "Formats which specify the names of unknown files.
854This variable is only used or ANTLR v2 grammars.
855
538The value looks like \(SUPER-GRAMMAR-FILE-FORMAT SUPER-EVOCAB-FORMAT). 856The value looks like \(SUPER-GRAMMAR-FILE-FORMAT SUPER-EVOCAB-FORMAT).
539 857
540SUPER-GRAMMAR-FORMAT is a format string, it specifies with substitution 858SUPER-GRAMMAR-FORMAT is a format string, it specifies with substitution
@@ -551,6 +869,8 @@ of above mentioned class SUPER.")
551## the current directory or is defined more than once. Please replace 869## the current directory or is defined more than once. Please replace
552## these filenames by the grammar files (and their exportVocab).\n\n" 870## these filenames by the grammar files (and their exportVocab).\n\n"
553 "String indicating the existence of unknown files in the Makefile. 871 "String indicating the existence of unknown files in the Makefile.
872This variable is only used or ANTLR v2 grammars.
873
554See \\[antlr-show-makefile-rules] and `antlr-unknown-file-formats'.") 874See \\[antlr-show-makefile-rules] and `antlr-unknown-file-formats'.")
555 875
556(defvar antlr-help-rules-intro 876(defvar antlr-help-rules-intro
@@ -560,6 +880,8 @@ They are stored in the kill-ring, i.e., you can insert them with C-y
560into your Makefile. You can also invoke \\[antlr-show-makefile-rules] 880into your Makefile. You can also invoke \\[antlr-show-makefile-rules]
561from within a Makefile to insert them directly.\n\n\n" 881from within a Makefile to insert them directly.\n\n\n"
562 "Introduction to use with \\[antlr-show-makefile-rules]. 882 "Introduction to use with \\[antlr-show-makefile-rules].
883This variable is only used or ANTLR v2 grammars.
884
563It is a format string and used with substitution DIRECTORY/%s where 885It is a format string and used with substitution DIRECTORY/%s where
564DIRECTORY is the name of the current directory.") 886DIRECTORY is the name of the current directory.")
565 887
@@ -568,10 +890,11 @@ DIRECTORY is the name of the current directory.")
568;;; Menu 890;;; Menu
569;;;=========================================================================== 891;;;===========================================================================
570 892
571(defcustom antlr-imenu-name t ; (featurep 'xemacs) ; TODO: Emacs-21 bug? 893(defcustom antlr-imenu-name t
572 "Non-nil, if a \"Index\" menu should be added to the menubar. 894 "Non-nil, if a \"Index\" menu should be added to the menubar.
573If it is a string, it is used instead \"Index\". Requires package 895If it is a string, it is used instead \"Index\". Requires package
574imenu." 896imenu. For sorted menu entries, customize variable
897`imenu-sort-function'."
575 :type '(choice (const :tag "No menu" nil) 898 :type '(choice (const :tag "No menu" nil)
576 (const :tag "Index menu" t) 899 (const :tag "Index menu" t)
577 (string :tag "Other menu name"))) 900 (string :tag "Other menu name")))
@@ -584,8 +907,9 @@ imenu."
584 (define-key map "\C-c\C-a" 'antlr-beginning-of-body) 907 (define-key map "\C-c\C-a" 'antlr-beginning-of-body)
585 (define-key map "\C-c\C-e" 'antlr-end-of-body) 908 (define-key map "\C-c\C-e" 'antlr-end-of-body)
586 (define-key map "\C-c\C-f" 'subword-forward) 909 (define-key map "\C-c\C-f" 'subword-forward)
587 (define-key map "\C-c\C-b" 'c-backward-into-nomenclature) 910 (define-key map "\C-c\C-b" 'subword-backward)
588 (define-key map "\C-c\C-c" 'comment-region) 911 (define-key map "\C-c\C-c" 'comment-region)
912 (define-key map "\C-c\C-k" 'antlr-insert-keyword-rule)
589 (define-key map "\C-c\C-v" 'antlr-hide-actions) 913 (define-key map "\C-c\C-v" 'antlr-hide-actions)
590 (define-key map "\C-c\C-r" 'antlr-run-tool) 914 (define-key map "\C-c\C-r" 'antlr-run-tool)
591 (define-key map "\C-c\C-o" 'antlr-insert-option) 915 (define-key map "\C-c\C-o" 'antlr-insert-option)
@@ -609,12 +933,16 @@ imenu."
609 `("Antlr" 933 `("Antlr"
610 ,@(if antlr-options-use-submenus 934 ,@(if antlr-options-use-submenus
611 `(("Insert File Option" 935 `(("Insert File Option"
936 :visible (elt antlr-options-alists 0)
612 :filter ,(lambda (x) (antlr-options-menu-filter 1 x))) 937 :filter ,(lambda (x) (antlr-options-menu-filter 1 x)))
613 ("Insert Grammar Option" 938 ("Insert Grammar Option"
939 :visible (elt antlr-options-alists 1)
614 :filter ,(lambda (x) (antlr-options-menu-filter 2 x))) 940 :filter ,(lambda (x) (antlr-options-menu-filter 2 x)))
615 ("Insert Rule Option" 941 ("Insert Rule Option"
942 :visible (elt antlr-options-alists 2)
616 :filter ,(lambda (x) (antlr-options-menu-filter 3 x))) 943 :filter ,(lambda (x) (antlr-options-menu-filter 3 x)))
617 ("Insert Subrule Option" 944 ("Insert Subrule Option"
945 :visible (elt antlr-options-alists 3)
618 :filter ,(lambda (x) (antlr-options-menu-filter 4 x))) 946 :filter ,(lambda (x) (antlr-options-menu-filter 4 x)))
619 "---") 947 "---")
620 '(["Insert Option" antlr-insert-option 948 '(["Insert Option" antlr-insert-option
@@ -629,8 +957,8 @@ imenu."
629 "---" 957 "---"
630 ["Backward Statement" c-beginning-of-statement t] 958 ["Backward Statement" c-beginning-of-statement t]
631 ["Forward Statement" c-end-of-statement t] 959 ["Forward Statement" c-end-of-statement t]
632 ["Backward Into Nomencl." c-backward-into-nomenclature t] 960 ["Backward Subword" subword-forward t]
633 ["Forward Into Nomencl." subword-forward t]) 961 ["Forward Subword" subword-backward t])
634 ["Indent Region" indent-region 962 ["Indent Region" indent-region
635 :active (and (not buffer-read-only) (c-region-is-active-p))] 963 :active (and (not buffer-read-only) (c-region-is-active-p))]
636 ["Comment Out Region" comment-region 964 ["Comment Out Region" comment-region
@@ -644,26 +972,177 @@ imenu."
644 ["Unhide All Actions" (antlr-hide-actions 0) t] 972 ["Unhide All Actions" (antlr-hide-actions 0) t]
645 "---" 973 "---"
646 ["Run Tool on Grammar" antlr-run-tool t] 974 ["Run Tool on Grammar" antlr-run-tool t]
647 ["Show Makefile Rules" antlr-show-makefile-rules t] 975 ["Show Makefile Rules" antlr-show-makefile-rules (eq antlr-tool-version 'antlr-v2)]
648 "---" 976 "---"
649 ["Customize Antlr" (customize-group 'antlr) t])) 977 ["Customize Antlr" (customize-group 'antlr) t]))
650 978
651 979
652;;;=========================================================================== 980;;;===========================================================================
653;;; font-lock 981;;; basic syntax
982;;;===========================================================================
983
984(defvar antlr-syntax-propertize nil
985 "Specification used to apply ‘syntax-table’ text properties.
986When non-nil, the value looks like \(MAIN EXTEND-REGION MULTILINE-CHAR).
987
988MAIN is used as value for `syntax-propertize-function'.
989
990EXTEND-REGION is for `syntax-propertize-extend-region-functions';
991it is appended to the existing value if it is a function, or
992replaces the value otherwise, t leaves the value untouched.
993
994MULTILINE-CHAR is for `c-multiline-string-start-char' if non-nil;
995if that variable already has a non-nil value, it is set to t.
996
997The value is tool-dependent, see `antlr-tool-version-variables'.")
998
999(defvar antlr-v4-syntax-propertize
1000 '(antlr-syntax-propertize-charsets (antlr-syntax-propertize-wholerule))
1001 "Value for `antlr-syntax-propertize' when using ANTLR v4.")
1002
1003(defvar antlr-v3-syntax-propertize
1004 '(antlr-syntax-propertize-template-literals syntax-propertize-multiline ?<)
1005 "Value for `antlr-syntax-propertize' when using ANTLR v3.")
1006
1007(defvar antlr-v2-syntax-propertize nil
1008 "Value for `antlr-syntax-propertize' when using ANTLR v2.")
1009
1010(defvar antlr-skip-line-regexp nil
1011 "Regexp matching special declarations after the grammar header.
1012The value is tool-dependent, see `antlr-tool-version-variables'.")
1013
1014(defvar antlr-v4-skip-line-regexp "[ \t]*import[ \t]+[^][}{)(^\n;]+;"
1015 "Value for `antlr-skip-line-regexp' when using ANTLR v4.")
1016
1017(defvar antlr-v3-skip-line-regexp "[ \t]*scope[ \t]+[^][}{)(^\n;]+;"
1018 "Value for `antlr-skip-line-regexp' when using ANTLR v3.")
1019
1020(defvar antlr-rule-body-start-op ":"
1021 "Single-character string which starts the rule body.")
1022
1023
1024;;;===========================================================================
1025;;; tool- and language-dependent font-lock
1026;;;===========================================================================
1027
1028(defvar antlr-font-lock-symbol-regexp nil
1029 "Regexp matching symbol declarations in the grammar, or nil.
1030If a regexp, the buffer content matched by the first regexp group
1031is highlighted with face `antlr-keyword' and the content matched
1032by the second regexp group is highlighted with face
1033`antlr-symbol'.
1034
1035The value is tool-dependent, see `antlr-tool-version-variables'.")
1036
1037(defvar antlr-v4-font-lock-symbol-regexp
1038 "^[ \t]*\\(mode\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)?"
1039 "Value for `antlr-font-lock-symbol-regexp' when using ANTLR v4.")
1040
1041(defvar antlr-v3-font-lock-symbol-regexp
1042 "^[ \t]*\\(scope\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)?"
1043 "Value for `antlr-font-lock-symbol-regexp' when using ANTLR v3.")
1044
1045(defcustom antlr-font-lock-literal-regexp
1046 ;; actually, in v3/v4 it is 'L' only
1047 "\\([\"']\\)\\(\\sw\\(\\sw\\|-\\)*\\|\\(\\s_\\|\\s.\\)+\\|\\s(\\|\\s)\\)\\1"
1048 "Regexp matching literals with special syntax highlighting, or nil.
1049If nil, there is no special syntax highlighting for some literals.
1050Otherwise, it should be a regular expression which must contain at least
1051two regexp groups. The string matched by the second group is highlighted
1052with face `antlr-literal'."
1053 :type '(choice (const :tag "None" nil) regexp))
1054
1055(defvar antlr-font-lock-attribute-regexp "\\(\\$\\sw+\\)"
1056 "Regexp matching attributes within actions with special syntax highlighting.
1057If nil, there is no special syntax highlighting for attributes.
1058Otherwise, it should be a regular expression which must contain at least
1059one regexp group. The string matched by the first group is highlighted
1060with face `antlr-attribute'.")
1061
1062(defvar antlr-font-lock-negation-regexp "\\.\\.\\|\\([.~]\\)"
1063 "Regexp whose first regexp group matches negation.
1064The negation is highlighted with face `font-lock-negation-char-face'.")
1065
1066(defvar antlr-font-lock-syntax-spec '("\\(->\\|[!^]\\)")
1067 "Specification for highlighting syntax symbols for AST creation: !, ^, ->.
1068If non-nil, the value looks like (REGEXP). Syntax symbols are matched
1069by the first regexp group in REGEXP, and are highlighted with face
1070`antlr-syntax'.")
1071;; TODO: in v4, highlight lexer commands after "->"
1072
1073(defvar antlr-grammar-header-regexp
1074 "\\<\\(lexer[ \t]+grammar\\|parser[ \t]+grammar\\|tree[ \t]+grammar\\|grammar\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)[ \t]*;"
1075 "Regexp matching class headers.
1076The value might be tool-dependent, see `antlr-tool-version-variables'.")
1077
1078(defvar antlr-v2-grammar-header-regexp
1079 "\\<\\(class\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)[ \t]*;"
1080 "Value for `antlr-grammar-header-regexp' when using ANTLR v2.")
1081
1082(defvar antlr-ruleref-assign-regexp "\\(\\sw+\\)[ \t]*\\(\\+?=\\)?"
1083 "Regexp matching rule references or their optional labels.
1084If the second regexp group does not match, the first regexp group
1085matches a rule reference, which is highlighted with face `antlr-tokenref'
1086for token rules, and face `antlr-ruleref' for other rules.
1087
1088If there is no third regexp group or it does not match, the first
1089regexp group matches a rule label, which is highlighted with face
1090`font-lock-variable-name-face'.
1091
1092The value might be tool-dependent, see `antlr-tool-version-variables'.")
1093
1094(defvar antlr-v2-ruleref-assign-regexp "\\(\\sw+\\)[ \t]*\\([:]\\|\\(=\\)\\)?"
1095 "Value for `antlr-ruleref-assign-regexp' when using ANTLR v2.")
1096
1097(defvar antlr-action-font-lock-keywords nil
1098 "Font Lock keywords used for the actions in the grammar.
1099The value should be like the first element of `font-lock-defaults.
1100See also `antlr-font-lock-maximum-decoration'.
1101The value might be language-dependent, see `antlr-language-variables'.")
1102
1103(defvar antlr-java-action-font-lock-keywords
1104 '(antlr-no-action-keywords
1105 java-font-lock-keywords-1 java-font-lock-keywords-2
1106 java-font-lock-keywords-3)
1107 "Value for `antlr-action-font-lock-keywords' when using language `antlr-java'.")
1108
1109(defvar antlr-action-scope-names '("lexer" "parser" "treeparser")
1110 "Valid ANTLR action scope names.")
1111
1112(defvar antlr-action-names t
1113 "Valid ANTLR action names.
1114This is a string list or t, which means that any name is valid.
1115The value might be language-dependent, see `antlr-language-variables'.")
1116
1117;; see $(ANTLR3)/tool/src/main/java/org/antlr/codegen/$(LANGUAGE)Target.java-isValidActionScope()
1118;; or $(ANTLR3.JAR)/antlr3-jar/org/antlr/codegen/templates/, fine-grep for "actions\."
1119(defvar antlr-java-action-names
1120 '("init" "after" "header" "members" "rulecatch" "synpredgate")
1121 "Valid ANTLR action names in Java.
1122Value for `antlr-action-names' when using language `antlr-java'.")
1123
1124(defvar antlr-token-identifier-p 'antlr-upcase-p
1125 "Function for syntax highlighting to distinguish token refs from rule refs.
1126Function is called with the first character of the identifier; it should
1127return non-nil if the identifier is a token reference.")
1128
1129
1130;;;===========================================================================
1131;;; general font-lock
654;;;=========================================================================== 1132;;;===========================================================================
655 1133
656(defcustom antlr-font-lock-maximum-decoration 'inherit 1134(defcustom antlr-font-lock-maximum-decoration 'inherit
657 "The maximum decoration level for fontifying actions. 1135 "The maximum decoration level for fontifying actions.
658Value `none' means, do not fontify actions, just normal grammar code 1136Value `none' means, do not fontify actions, just normal grammar
659according to `antlr-font-lock-additional-keywords'. Value `inherit' 1137code according to `antlr-font-lock-additional-keywords' and
660means, use value of `font-lock-maximum-decoration'. Any other value is 1138`antlr-font-lock-late-keywords'. Value `inherit' means, use
1139value of `font-lock-maximum-decoration'. Any other value is
661interpreted as in `font-lock-maximum-decoration' with no level-0 1140interpreted as in `font-lock-maximum-decoration' with no level-0
662fontification, see `antlr-font-lock-keywords-alist'. 1141fontification, see `antlr-font-lock-keywords-alist'.
663 1142
664While calculating the decoration level for actions, `major-mode' is 1143While calculating the decoration level for actions, `major-mode' is
665bound to `antlr-language'. For example, with value 1144bound to the value of `antlr-action-mode'. For example, with value
666 ((java-mode . 2) (c++-mode . 0)) 1145 ((java-mode \. 2) (c++-mode \. 0))
667Java actions are fontified with level 2 and C++ actions are not 1146Java actions are fontified with level 2 and C++ actions are not
668fontified at all." 1147fontified at all."
669 :type '(choice (const :tag "None" none) 1148 :type '(choice (const :tag "None" none)
@@ -689,145 +1168,137 @@ fontified at all."
689 "Empty font-lock keywords for actions. 1168 "Empty font-lock keywords for actions.
690Do not change the value of this constant.") 1169Do not change the value of this constant.")
691 1170
692(defvar antlr-font-lock-keywords-alist
693 '((java-mode
694 antlr-no-action-keywords
695 java-font-lock-keywords-1 java-font-lock-keywords-2
696 java-font-lock-keywords-3)
697 (c++-mode
698 antlr-no-action-keywords
699 c++-font-lock-keywords-1 c++-font-lock-keywords-2
700 c++-font-lock-keywords-3))
701 "List of font-lock keywords for actions in the grammar.
702Each element in this list looks like
703 (MAJOR-MODE KEYWORD...)
704
705If `antlr-language' is equal to MAJOR-MODE, the KEYWORDs are the
706font-lock keywords according to `font-lock-defaults' used for the code
707in the grammar's actions and semantic predicates, see
708`antlr-font-lock-maximum-decoration'.")
709
710(defface antlr-default '((t nil)) 1171(defface antlr-default '((t nil))
711 "Face to prevent strings from language dependent highlighting. 1172 "Face to prevent strings from language dependent highlighting.
712Do not change.") 1173Do not change.")
713 1174
714(defface antlr-keyword 1175(defface antlr-keyword
715 '((((class color) (background light)) 1176 '((t :inherit font-lock-keyword-face))
716 (:foreground "black" :weight bold))
717 (t :inherit font-lock-keyword-face))
718 "ANTLR keywords.") 1177 "ANTLR keywords.")
719 1178
720(defface antlr-syntax 1179(defface antlr-syntax
721 '((((class color) (background light)) 1180 '((t :inherit font-lock-keyword-face))
722 (:foreground "black" :weight bold)) 1181 "ANTLR syntax symbols for AST creation: !, ^, ->.")
723 (t :inherit font-lock-constant-face)) 1182
724 "ANTLR syntax symbols like :, |, (, ), ....") 1183(defface antlr-action
1184 '((t :inherit font-lock-builtin-face))
1185 "ANTLR action names: @ActionName, @ActionScope::ActionName.")
725 1186
726(defface antlr-ruledef 1187(defface antlr-ruledef
727 '((((class color) (background light)) 1188 '((t :inherit font-lock-function-name-face))
728 (:foreground "blue" :weight bold)) 1189 "ANTLR parser and treeparser rule symbols (definition).")
729 (t :inherit font-lock-function-name-face))
730 "ANTLR rule references (definition).")
731 1190
732(defface antlr-tokendef 1191(defface antlr-tokendef
733 '((((class color) (background light)) 1192 '((t :inherit font-lock-function-name-face))
734 (:foreground "blue" :weight bold)) 1193 "ANTLR scanner rule symbols (definition).")
735 (t :inherit font-lock-function-name-face))
736 "ANTLR token references (definition).")
737 1194
738(defface antlr-ruleref 1195(defface antlr-ruleref
739 '((((class color) (background light)) (:foreground "blue4")) 1196 '((t :inherit font-lock-type-face))
740 (t :inherit font-lock-type-face)) 1197 "ANTLR parser and treeparser rule symbols (usage).")
741 "ANTLR rule references (usage).")
742 1198
743(defface antlr-tokenref 1199(defface antlr-tokenref
744 '((((class color) (background light)) (:foreground "orange4")) 1200 '((t :inherit font-lock-constant-face))
745 (t :inherit font-lock-type-face)) 1201 "ANTLR scanner rule symbols (usage).")
746 "ANTLR token references (usage).") 1202
1203(defface antlr-symbol
1204 '((t :inherit font-lock-variable-name-face))
1205 "ANTLR symbols (definition and usage) for things other than rules.
1206Used for grammars, v3 scopes and v4 modes.")
747 1207
748(defface antlr-literal 1208(defface antlr-literal
749 '((((class color) (background light)) 1209 '((t :inherit font-lock-string-face :weight bold))
750 (:foreground "brown4" :weight bold))
751 (t :inherit font-lock-string-face))
752 "ANTLR special literal tokens. 1210 "ANTLR special literal tokens.
753It is used to highlight strings matched by the first regexp group of 1211It is used to highlight strings matched by the first regexp group of
754`antlr-font-lock-literal-regexp'.") 1212`antlr-font-lock-literal-regexp'.")
755 1213
756(defcustom antlr-font-lock-literal-regexp "\"\\(\\sw\\(\\sw\\|-\\)*\\)\"" 1214(defface antlr-attribute '((t :inherit font-lock-preprocessor-face))
757 "Regexp matching literals with special syntax highlighting, or nil. 1215 "ANTLR references to attributes within actions.")
758If nil, there is no special syntax highlighting for some literals. 1216
759Otherwise, it should be a regular expression which must contain a regexp 1217(defvar antlr-font-lock-late-keywords
760group. The string matched by the first group is highlighted with 1218 ;; The tokens are already fontified as string/docstrings. The extra
761`antlr-font-lock-literal-face'." 1219 ;; fontification of literals must come after the fontification from cc-mode;
762 :type '(choice (const :tag "None" nil) regexp)) 1220 ;; otherwise `c-font-lock-invalid-string' fontifies the final doublequote of
763 1221 ;; the last literal in a line with red (warning) - for whatever reason.
764(defvar antlr-class-header-regexp 1222 `((,(lambda (limit) ; v3, v4: literals are only '...'
765 "\\(class\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]+\\(extends\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\sw*\\)[ \t]*;" 1223 (if antlr-font-lock-literal-regexp
766 "Regexp matching class headers.") 1224 (antlr-re-search-forward antlr-font-lock-literal-regexp limit)))
767 1225 (2 'antlr-literal t))
768(defvar antlr-font-lock-additional-keywords
769 `((antlr-invalidate-context-cache)
770 ("\\$setType[ \t]*(\\([A-Za-z\300-\326\330-\337]\\sw*\\))"
771 (1 'antlr-tokendef))
772 ("\\$\\sw+" (0 'antlr-keyword))
773 ;; the tokens are already fontified as string/docstrings:
774 (,(lambda (limit) 1226 (,(lambda (limit)
775 (if antlr-font-lock-literal-regexp 1227 (antlr-re-search-forward "^\\(\\sw+\\)" limit))
776 (antlr-re-search-forward antlr-font-lock-literal-regexp limit))) 1228 (1 (if (funcall antlr-token-identifier-p (char-after (match-beginning 0)))
777 (1 'antlr-literal t)) 1229 'antlr-tokendef
1230 'antlr-ruledef)
1231 t))
778 (,(lambda (limit) 1232 (,(lambda (limit)
779 (antlr-re-search-forward antlr-class-header-regexp limit)) 1233 (antlr-re-search-forward antlr-grammar-header-regexp limit))
780 (1 'antlr-keyword) 1234 (1 'antlr-keyword t)
781 (2 'antlr-ruledef) 1235 (2 'antlr-symbol t)
782 (3 'antlr-keyword) 1236 (3 'antlr-keyword t t)
783 (4 (if (member (match-string 4) '("Lexer" "Parser" "TreeParser")) 1237 (4 (if (member (match-string-no-properties 4) '("Lexer" "Parser" "TreeParser"))
784 'antlr-keyword 1238 'antlr-keyword
785 'font-lock-type-face))) 1239 'font-lock-type-face)
1240 t t))
786 (,(lambda (limit) 1241 (,(lambda (limit)
787 (antlr-re-search-forward 1242 (antlr-re-search-forward
788 "\\<\\(header\\|options\\|tokens\\|exception\\|catch\\|returns\\)\\>" 1243 "\\<\\(header\\|options\\|tokens\\|channels\\|exception\\|catch\\|finally\\|returns\\|throws\\|import\\|locals\\)\\>"
789 limit)) 1244 limit))
790 (1 'antlr-keyword)) 1245 (1 'antlr-keyword t))
791 (,(lambda (limit) 1246 (,(lambda (limit)
792 (antlr-re-search-forward 1247 (when antlr-font-lock-symbol-regexp
793 "^\\(private\\|public\\|protected\\)\\>[ \t]*\\(\\(\\sw+[ \t]*\\(:\\)?\\)\\)?" 1248 (antlr-re-search-forward antlr-font-lock-symbol-regexp limit)))
794 limit)) 1249 (1 'antlr-keyword t)
795 (1 'font-lock-type-face) ; not XEmacs's java level-3 fruit salad 1250 (2 'antlr-symbol t t))
796 (3 (if (antlr-upcase-p (char-after (match-beginning 3)))
797 'antlr-tokendef
798 'antlr-ruledef)
799 nil t)
800 (4 'antlr-syntax nil t))
801 (,(lambda (limit) 1251 (,(lambda (limit)
802 (antlr-re-search-forward "^\\(\\sw+\\)[ \t]*\\(:\\)?" limit)) 1252 (antlr-re-search-forward
803 (1 (if (antlr-upcase-p (char-after (match-beginning 0))) 1253 "^\\(private\\|public\\|protected\\|fragment\\)\\>[ \t]*\\(\\sw+\\)?"
1254 limit))
1255 (1 'antlr-keyword t)
1256 (2 (if (funcall antlr-token-identifier-p (char-after (match-beginning 2)))
804 'antlr-tokendef 1257 'antlr-tokendef
805 'antlr-ruledef) 1258 'antlr-ruledef)
806 nil t) 1259 t t))
807 (2 'antlr-syntax nil t)) 1260 (,(lambda (limit) ; v3, v4
1261 (antlr-re-search-forward "@\\([A-Za-z\300-\326\330-\337_]\\sw*\\)\\(?:::\\([A-Za-z\300-\326\330-\337_]\\sw*\\)\\)?" limit))
1262 (1 (antlr-font-lock-checked-face (if (match-beginning 2)
1263 antlr-action-scope-names
1264 antlr-action-names)
1265 1 'antlr-action)
1266 t)
1267 (2 (antlr-font-lock-checked-face antlr-action-names 2 'antlr-action)
1268 t t))
808 (,(lambda (limit) 1269 (,(lambda (limit)
809 ;; v:ruleref and v:"literal" is allowed... 1270 (and antlr-font-lock-syntax-spec
810 (antlr-re-search-forward "\\(\\sw+\\)[ \t]*\\([=:]\\)?" limit)) 1271 (antlr-re-search-forward (car antlr-font-lock-syntax-spec) limit)))
1272 (1 'antlr-syntax t)))
1273 "Late font-lock keywords for ANTLR's normal grammar code.
1274See `antlr-font-lock-keywords-alist' for the keywords of actions.")
1275
1276(defvar antlr-font-lock-additional-keywords
1277 `((,(lambda (limit)
1278 (and antlr-font-lock-attribute-regexp
1279 (re-search-forward antlr-font-lock-attribute-regexp limit 'limit)))
1280 (1 'antlr-attribute))
1281 (,(lambda (limit)
1282 ;; v2: v:ruleref v:"literal", v=ruleref (no highlighting), v3: v=ruleref
1283 (antlr-re-search-forward antlr-ruleref-assign-regexp limit))
811 (1 (if (match-beginning 2) 1284 (1 (if (match-beginning 2)
812 (if (eq (char-after (match-beginning 2)) ?=) 1285 (if (match-beginning 3)
813 'antlr-default 1286 'antlr-default
814 'font-lock-variable-name-face) 1287 'font-lock-variable-name-face) ; yes, same as vars in [...]
815 (if (antlr-upcase-p (char-after (match-beginning 1))) 1288 (if (funcall antlr-token-identifier-p (char-after (match-beginning 1)))
816 'antlr-tokenref 1289 'antlr-tokenref
817 'antlr-ruleref))) 1290 'antlr-ruleref)))
818 (2 'antlr-default nil t)) 1291 (2 'antlr-default nil t))
819 (,(lambda (limit) 1292 (,(lambda (limit)
820 (antlr-re-search-forward "[|&:;(~]\\|)\\([*+?]\\|=>\\)?" limit)) 1293 (antlr-re-search-forward antlr-font-lock-negation-regexp limit))
821 (0 'antlr-syntax))) 1294 (1 'font-lock-negation-char-face t t)))
822 "Font-lock keywords for ANTLR's normal grammar code. 1295"Early font-lock keywords for ANTLR's normal grammar code.
823See `antlr-font-lock-keywords-alist' for the keywords of actions.") 1296See `antlr-font-lock-keywords-alist' for the keywords of actions.")
824 1297
825(defvar antlr-font-lock-defaults 1298(defvar antlr-font-lock-defaults
826 '(antlr-font-lock-keywords 1299 '(antlr-font-lock-keywords
827 nil nil ((?_ . "w") (?\( . ".") (?\) . ".")) beginning-of-defun) 1300 nil nil ((?_ . "w")))
828 "Font-lock defaults used for ANTLR syntax highlighting. 1301 "Font-lock defaults used for ANTLR syntax highlighting.")
829The SYNTAX-ALIST element is also used to initialize
830`antlr-action-syntax-table'.")
831 1302
832 1303
833;;;=========================================================================== 1304;;;===========================================================================
@@ -841,38 +1312,12 @@ The SYNTAX-ALIST element is also used to initialize
841 (let ((st (make-syntax-table))) 1312 (let ((st (make-syntax-table)))
842 (c-populate-syntax-table st) 1313 (c-populate-syntax-table st)
843 st) 1314 st)
844 "Syntax table used in `antlr-mode' buffers. 1315 "Syntax table used in `antlr-mode' buffers.")
845If non-nil, it will be initialized in `antlr-mode'.")
846
847;; used for "in Java/C++ code" = syntactic-depth>0
848(defvar antlr-action-syntax-table
849 (let ((st (copy-syntax-table antlr-mode-syntax-table))
850 (slist (nth 3 antlr-font-lock-defaults)))
851 (while slist
852 (modify-syntax-entry (caar slist) (cdar slist) st)
853 (setq slist (cdr slist)))
854 st)
855 "Syntax table used for ANTLR action parsing.
856Initialized by `antlr-mode-syntax-table', changed by SYNTAX-ALIST in
857`antlr-font-lock-defaults'. This table should be selected if you use
858`buffer-syntactic-context' and `buffer-syntactic-context-depth' in order
859not to confuse their context_cache.")
860 1316
861(defvar antlr-mode-abbrev-table nil 1317(defvar antlr-mode-abbrev-table nil
862 "Abbreviation table used in `antlr-mode' buffers.") 1318 "Abbreviation table used in `antlr-mode' buffers.")
863(define-abbrev-table 'antlr-mode-abbrev-table ()) 1319(define-abbrev-table 'antlr-mode-abbrev-table ())
864 1320
865(defvar antlr-slow-cache-enabling-symbol 'loudly
866;; Emacs's font-lock changes buffer's tick counter, therefore this value should
867;; be a parameter of a font-lock function, but not any other variable of
868;; functions which call `antlr-slow-syntactic-context'.
869 "If value is a bound symbol, cache will be used even with text changes.
870This is no user option. Used for `antlr-slow-syntactic-context'.")
871
872(defvar antlr-slow-cache-diff-threshold 5000
873 "Maximum distance between `point' and cache position for cache use.
874Used for `antlr-slow-syntactic-context'.")
875
876 1321
877;;;;########################################################################## 1322;;;;##########################################################################
878;;;; The Code 1323;;;; The Code
@@ -881,111 +1326,25 @@ Used for `antlr-slow-syntactic-context'.")
881 1326
882 1327
883;;;=========================================================================== 1328;;;===========================================================================
884;;; Syntax functions
885;;;===========================================================================
886
887;;;===========================================================================
888;;; Context cache 1329;;; Context cache
889;;;=========================================================================== 1330;;;===========================================================================
890 1331
891(defvar antlr-slow-context-cache nil "Internal.") 1332(defun antlr-syntactic-context (&optional ppss)
892
893;;;(defvar antlr-statistics-full-neg 0)
894;;;(defvar antlr-statistics-full-diff 0)
895;;;(defvar antlr-statistics-full-other 0)
896;;;(defvar antlr-statistics-cache 0)
897;;;(defvar antlr-statistics-inval 0)
898
899(defun antlr-invalidate-context-cache (&rest _dummies)
900;; checkdoc-params: (dummies)
901 "Invalidate context cache for syntactical context information."
902;;; (cl-incf antlr-statistics-inval)
903 (setq antlr-slow-context-cache nil))
904
905(defun antlr-syntactic-context ()
906 "Return some syntactic context information. 1333 "Return some syntactic context information.
907Return `string' if point is within a string, `block-comment' or 1334Return `string' if point is within a string, `block-comment' or
908`comment' is point is within a comment or the depth within all 1335`comment' if point is within a comment or the depth within all
909parenthesis-syntax delimiters at point otherwise. 1336parenthesis-syntax delimiters at point otherwise.
910WARNING: this may alter `match-data'." 1337WARNING: this may alter `match-data'.
911 (let ((orig (point)) diff state 1338Optional argument PPSS" ; TODO: warning this valid?
912 ;; Arg, Emacs's (buffer-modified-tick) changes with font-lock. Use 1339 ;; does not work for negative depth
913 ;; hack that `loudly' is bound during font-locking => cache use will 1340 (or ppss (setq ppss (syntax-ppss)))
914 ;; increase from 7% to 99.99% during font-locking. 1341 (cond ((nth 3 ppss) 'string)
915 (tick (or (boundp antlr-slow-cache-enabling-symbol) 1342 ((nth 4 ppss) 'comment)
916 (buffer-modified-tick)))) 1343 (t
917 (if (and (cdr antlr-slow-context-cache) 1344 (let ((poss (nth 9 ppss))) ; TODO Emacs: syntax-ppss-open-positions
918 (>= (setq diff (- orig (cadr antlr-slow-context-cache))) 0) 1345 (while (and poss (memq (char-after (car poss)) '(nil ?\()))
919 (< diff antlr-slow-cache-diff-threshold) 1346 (setq poss (cdr poss)))
920 (eq (current-buffer) (caar antlr-slow-context-cache)) 1347 (and poss (length poss)))))) ; depth if inside {} or []
921 (eq tick (cdar antlr-slow-context-cache)))
922 ;; (setq antlr-statistics-cache (1+ antlr-statistics-cache) ...)
923 (setq state (parse-partial-sexp (cadr antlr-slow-context-cache) orig
924 nil nil
925 (cddr antlr-slow-context-cache)))
926 (if (>= orig antlr-slow-cache-diff-threshold)
927 (beginning-of-defun)
928 (goto-char (point-min)))
929 ;; (cond ((and diff (< diff 0)) (cl-incf antlr-statistics-full-neg))
930 ;; ((and diff (>= diff 3000)) (cl-incf antlr-statistics-full-diff))
931 ;; (t (cl-incf antlr-statistics-full-other)))
932 (setq state (parse-partial-sexp (point) orig)))
933 (goto-char orig)
934 (if antlr-slow-context-cache
935 (setcdr antlr-slow-context-cache (cons orig state))
936 (setq antlr-slow-context-cache
937 (cons (cons (current-buffer) tick)
938 (cons orig state))))
939 (cond ((nth 3 state) 'string)
940 ((nth 4 state) 'comment) ; block-comment? -- we don't care
941 (t (car state)))))
942
943;; (cl-incf (aref antlr-statistics 2))
944;; (unless (and (eq (current-buffer)
945;; (caar antlr-slow-context-cache))
946;; (eq (buffer-modified-tick)
947;; (cdar antlr-slow-context-cache)))
948;; (cl-incf (aref antlr-statistics 1))
949;; (setq antlr-slow-context-cache nil))
950;; (let* ((orig (point))
951;; (base (cadr antlr-slow-context-cache))
952;; (curr (cddr antlr-slow-context-cache))
953;; (state (cond ((eq orig (car curr)) (cdr curr))
954;; ((eq orig (car base)) (cdr base))))
955;; diff diff2)
956;; (unless state
957;; (cl-incf (aref antlr-statistics 3))
958;; (when curr
959;; (if (< (setq diff (abs (- orig (car curr))))
960;; (setq diff2 (abs (- orig (car base)))))
961;; (setq state curr)
962;; (setq state base
963;; diff diff2))
964;; (if (or (>= (1+ diff) (point)) (>= diff 3000))
965;; (setq state nil))) ; start from bod/bob
966;; (if state
967;; (setq state
968;; (parse-partial-sexp (car state) orig nil nil (cdr state)))
969;; (if (>= orig 3000) (beginning-of-defun) (goto-char (point-min)))
970;; (cl-incf (aref antlr-statistics 4))
971;; (setq cw (list orig (point) base curr))
972;; (setq state (parse-partial-sexp (point) orig)))
973;; (goto-char orig)
974;; (if antlr-slow-context-cache
975;; (setcdr (cdr antlr-slow-context-cache) (cons orig state))
976;; (setq antlr-slow-context-cache
977;; (cons (cons (current-buffer) (buffer-modified-tick))
978;; (cons (cons orig state) (cons orig state))))))
979;; (cond ((nth 3 state) 'string)
980;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
981;; (t (car state)))))
982
983;; (beginning-of-defun)
984;; (let ((state (parse-partial-sexp (point) orig)))
985;; (goto-char orig)
986;; (cond ((nth 3 state) 'string)
987;; ((nth 4 state) 'comment) ; block-comment? -- we don't care
988;; (t (car state))))))
989 1348
990 1349
991;;;=========================================================================== 1350;;;===========================================================================
@@ -994,9 +1353,8 @@ WARNING: this may alter `match-data'."
994 1353
995(defun antlr-upcase-p (char) 1354(defun antlr-upcase-p (char)
996 "Non-nil, if CHAR is an uppercase character (if CHAR was a char)." 1355 "Non-nil, if CHAR is an uppercase character (if CHAR was a char)."
997 ;; in XEmacs, upcase only works for ASCII 1356 ;; (get-char-code-property char 'lowercase)
998 (or (and (<= ?A char) (<= char ?Z)) 1357 (not (eq (downcase char) char)))
999 (and (<= ?\300 char) (<= char ?\337)))) ; ?\327 is no letter
1000 1358
1001(defun antlr-re-search-forward (regexp bound) 1359(defun antlr-re-search-forward (regexp bound)
1002 "Search forward from point for regular expression REGEXP. 1360 "Search forward from point for regular expression REGEXP.
@@ -1005,36 +1363,47 @@ nil if no occurrence was found. Do not search within comments, strings
1005and actions/semantic predicates. BOUND bounds the search; it is a 1363and actions/semantic predicates. BOUND bounds the search; it is a
1006buffer position. See also the functions `match-beginning', `match-end' 1364buffer position. See also the functions `match-beginning', `match-end'
1007and `replace-match'." 1365and `replace-match'."
1008 ;; WARNING: Should only be used with `antlr-action-syntax-table'!
1009 (let ((continue t)) 1366 (let ((continue t))
1010 (while (and (re-search-forward regexp bound 'limit) 1367 (while (and (re-search-forward regexp bound 'limit)
1011 (save-match-data 1368 (save-match-data
1012 (if (eq (antlr-syntactic-context) 0) 1369 (or (antlr-syntactic-context) (setq continue nil)))))
1013 (setq continue nil)
1014 t))))
1015 (if continue nil (point)))) 1370 (if continue nil (point))))
1016 1371
1017(defun antlr-search-forward (string) 1372(defsubst antlr-search-result (line-regexp)
1373 "Return `point' if last search is valid, or nil otherwise.
1374The search is not considered valid if point is inside actions, comments
1375or strings, or if the beginning of the current line matches LINE-REGEXP
1376if that is non-nil."
1377 (unless (antlr-syntactic-context)
1378 (if (and line-regexp
1379 (save-excursion
1380 (beginning-of-line)
1381 (looking-at line-regexp))
1382 (<= (point) (match-end 0) (1+ (point))))
1383 nil
1384 (point))))
1385
1386(defun antlr-search-forward (string &optional line-regexp)
1018 "Search forward from point for STRING. 1387 "Search forward from point for STRING.
1019Set point to the end of the occurrence found, and return point. Return 1388Set point to the end of the occurrence found, and return point. Return
1020nil if no occurrence was found. Do not search within comments, strings 1389nil if no occurrence was found. Do not search within comments, strings
1021and actions/semantic predicates." 1390and actions/semantic predicates.
1022 ;; WARNING: Should only be used with `antlr-action-syntax-table'! 1391See function `antlr-search-result' for the optional arg LINE-REGEXP."
1023 (let ((continue t)) 1392 (let ((result nil))
1024 (while (and (search-forward string nil 'limit) 1393 (while (and (null result) (search-forward string nil 'limit))
1025 (if (eq (antlr-syntactic-context) 0) (setq continue nil) t))) 1394 (setq result (antlr-search-result line-regexp)))
1026 (if continue nil (point)))) 1395 result))
1027 1396
1028(defun antlr-search-backward (string) 1397(defun antlr-search-backward (string &optional line-regexp)
1029 "Search backward from point for STRING. 1398 "Search backward from point for STRING.
1030Set point to the beginning of the occurrence found, and return point. 1399Set point to the beginning of the occurrence found, and return point.
1031Return nil if no occurrence was found. Do not search within comments, 1400Return nil if no occurrence was found. Do not search within comments,
1032strings and actions/semantic predicates." 1401strings and actions/semantic predicates.
1033 ;; WARNING: Should only be used with `antlr-action-syntax-table'! 1402See function `antlr-search-result' for the optional arg LINE-REGEXP."
1034 (let ((continue t)) 1403 (let ((result nil))
1035 (while (and (search-backward string nil 'limit) 1404 (while (and (null result) (search-backward string nil 'limit))
1036 (if (eq (antlr-syntactic-context) 0) (setq continue nil) t))) 1405 (setq result (antlr-search-result line-regexp)))
1037 (if continue nil (point)))) 1406 result))
1038 1407
1039(defsubst antlr-skip-sexps (count) 1408(defsubst antlr-skip-sexps (count)
1040 "Skip the next COUNT balanced expressions and the comments after it. 1409 "Skip the next COUNT balanced expressions and the comments after it.
@@ -1043,6 +1412,117 @@ Return position before the comments after the last expression."
1043 (prog1 (point) 1412 (prog1 (point)
1044 (antlr-c-forward-sws))) 1413 (antlr-c-forward-sws)))
1045 1414
1415(defun antlr-syntax-propertize-wholerule (start end)
1416 ;; checkdoc-params: (start end)
1417 "Function used to properly highlight ANTLR v4 charsets.
1418This function is used in `syntax-propertize-extend-region-functions' to
1419make sure that the propertized region starts at the beginning of a rule."
1420 (goto-char start)
1421 (beginning-of-line)
1422 (while (if (bobp) nil (looking-at "[ \t\n}]\\|@init\\_>\\|options\\_>"))
1423 (beginning-of-line 0))
1424 ;; no need to find the real end of a rule... end-of-line is good
1425 (cons (point)
1426 (progn (goto-char end)
1427 (if (bolp) (point) (line-beginning-position 2)))))
1428
1429;; font-lock.el and/or syntax.el should say something about the use of
1430;; `syntax-ppss' when `font-lock-syntax-table' is set - we should not use the
1431;; same cache for calls inside and outside font-lock, don't we?
1432
1433(defun antlr-syntax-propertize-charsets (start end)
1434 ;; checkdoc-params: (start end)
1435 "Function used to properly highlight ANTLR v4 charsets.
1436This function is as value for `syntax-propertize-function' and makes
1437sure that charsets like [a-z] in token rule bodies are considered
1438literals."
1439 (goto-char start)
1440 (let ((mode (if (bolp) :start :next)))
1441 (while (< (point) end)
1442 (let ((context (antlr-syntactic-context)))
1443 (cond ((numberp context)
1444 (goto-char (or (ignore-errors (scan-lists (point) 1 context))
1445 end)))
1446 ((eq mode :start) ; TODO: only if context = 0
1447 (when (looking-at "fragment\\_>")
1448 (forward-char 8)
1449 (skip-chars-forward " \t\n"))
1450 (setq mode (if (antlr-upcase-p (char-after))
1451 :scanner
1452 (if (eq (char-syntax (char-after)) ?w)
1453 :end
1454 :next))))
1455 ((eq mode :end)
1456 (skip-chars-forward "^;" end)
1457 (while (and (< (point) end) (antlr-syntactic-context))
1458 (forward-char)
1459 (skip-chars-forward "^;" end))
1460 (setq mode :next))
1461 ((eq mode :next)
1462 (beginning-of-line 2)
1463 (while (and (< (point) end) (looking-at "[ \t\n@}]"))
1464 (beginning-of-line 2))
1465 (setq mode :start))
1466 ((eq mode :scanner)
1467 (skip-chars-forward "^:;" end)
1468 (while (and (< (point) end) (antlr-syntactic-context))
1469 (forward-char)
1470 (skip-chars-forward "^:;" end))
1471 (if (eq (char-after) ?:)
1472 (if (eq (char-after (1+ (point))) ?:)
1473 (forward-char 2) ; "::" for namespace
1474 (setq mode :charset))
1475 (setq mode :next)))
1476 ((eq mode :charset)
1477 ;; LEXER_CHAR_SET :
1478 ;; '[' ( '\\' ~('\r'|'\n') | ~('\r'|'\n'|'\\'|']') )* ']'
1479 (skip-chars-forward "^;[" end)
1480 (while (and (< (point) end) (antlr-syntactic-context))
1481 (forward-char)
1482 (skip-chars-forward "^;[" end))
1483 (if (not (eq (char-after) ?\[))
1484 (setq mode :next)
1485 (put-text-property (point) (progn (forward-char) (point))
1486 'syntax-table
1487 (eval-when-compile
1488 (string-to-syntax "|")))
1489 (let (char (esc nil))
1490 (while (and (setq char (char-after))
1491 (not (eq char ?\n))
1492 (or esc (not (eq char ?\]))))
1493 (setq esc (if esc nil (eq char ?\\)))
1494 (forward-char)))
1495 (put-text-property (point) (1+ (point))
1496 'syntax-table
1497 (eval-when-compile
1498 (string-to-syntax "|"))))))))))
1499
1500(defun antlr-syntax-propertize-template-literals (start end)
1501 ;; checkdoc-params: (start end)
1502 "Function used to properly highlight ANTLR v3 template literals.
1503This function is as value for `syntax-propertize-function' and makes
1504sure that templates like <<...>> outside actions, strings or comments
1505are considered literals."
1506 (goto-char start)
1507 (while (search-forward "<<" end t)
1508 (let ((context (antlr-syntactic-context)))
1509 (if context
1510 (when (numberp context)
1511 (goto-char (min (or (ignore-errors (scan-lists (point) 1 context))
1512 end)
1513 end)))
1514 (let ((pos (- (point) 2)))
1515 ;; put the text property on the inner "<>", since multi-line is set
1516 ;; to be ok with `c-multiline-string-start-char'
1517 (put-text-property (1+ pos) (point) 'syntax-table
1518 (eval-when-compile
1519 (string-to-syntax "|")))
1520 (when (search-forward ">>" end 'move)
1521 (put-text-property (- (point) 2) (1- (point)) 'syntax-table
1522 (eval-when-compile
1523 (string-to-syntax "|"))))
1524 (put-text-property pos (point) 'syntax-multiline t))))))
1525
1046 1526
1047;;;=========================================================================== 1527;;;===========================================================================
1048;;; font-lock 1528;;; font-lock
@@ -1052,63 +1532,82 @@ Return position before the comments after the last expression."
1052 "Return font-lock keywords for current buffer. 1532 "Return font-lock keywords for current buffer.
1053See `antlr-font-lock-additional-keywords', `antlr-language' and 1533See `antlr-font-lock-additional-keywords', `antlr-language' and
1054`antlr-font-lock-maximum-decoration'." 1534`antlr-font-lock-maximum-decoration'."
1055 (if (eq antlr-font-lock-maximum-decoration 'none) 1535 (append antlr-font-lock-additional-keywords
1056 antlr-font-lock-additional-keywords 1536 (unless (eq antlr-font-lock-maximum-decoration 'none)
1057 (append antlr-font-lock-additional-keywords 1537 (let* ((major-mode antlr-action-mode) ;#dynamic
1058 (eval (let ((major-mode antlr-language)) ; dynamic 1538 (level (font-lock-value-in-major-mode
1059 (font-lock-choose-keywords 1539 (if (eq antlr-font-lock-maximum-decoration 'inherit)
1060 (cdr (assq antlr-language 1540 font-lock-maximum-decoration
1061 antlr-font-lock-keywords-alist)) 1541 antlr-font-lock-maximum-decoration))))
1062 (if (eq antlr-font-lock-maximum-decoration 'inherit) 1542 (font-lock-eval-keywords
1063 font-lock-maximum-decoration 1543 (font-lock-choose-keywords antlr-action-font-lock-keywords
1064 antlr-font-lock-maximum-decoration))) 1544 level))))
1065 t)))) 1545 antlr-font-lock-late-keywords))
1546
1547(defun antlr-font-lock-checked-face (strings group face) ; checkdoc-order: nil
1548 "Return font-lock face for regexp group GROUP.
1549If the matched string is an element of STRINGS (or STRINGS is not a list),
1550return FACE, otherwise return `font-lock-warning-face'."
1551 (if (if (consp strings) (member (match-string-no-properties group) strings) strings)
1552 face
1553 font-lock-warning-face))
1066 1554
1067 1555
1068;;;=========================================================================== 1556;;;===========================================================================
1069;;; imenu support 1557;;; imenu support
1070;;;=========================================================================== 1558;;;===========================================================================
1071 1559
1560;; Actually, issues in the "Index" (at least with sorted entries) menu are
1561;; imenu-induced. If entries are missing in the menu (as are sometimes for me
1562;; on Emacs-25.1.1), try M-x imenu RET -> you see all. This might not be the
1563;; case anymore with the reordering of `imenu-add-to-menubar'...
1564(defvar antlr-do-syntax-propertize (version< emacs-version "25")
1565 "Whether \\[antlr-mode] runs `syntax-propertize' on the complete buffer.
1566Running it explicitly at the beginning of the mode might be
1567necessary for a correct Index menu and motion commands.")
1568
1072(defun antlr-grammar-tokens () 1569(defun antlr-grammar-tokens ()
1073 "Return alist for tokens defined in current buffer." 1570 "Return alist for tokens defined in current buffer."
1074 (save-excursion (antlr-imenu-create-index-function t))) 1571 (save-excursion (antlr-imenu-create-index-function 'upcase)))
1075 1572
1076(defun antlr-imenu-create-index-function (&optional tokenrefs-only) 1573;; TODO: version dependent?
1574(defun antlr-imenu-create-index-function (&optional refs-only)
1077 "Return imenu index-alist for ANTLR grammar files. 1575 "Return imenu index-alist for ANTLR grammar files.
1078IF TOKENREFS-ONLY is non-nil, just return alist with tokenref names." 1576IF REFS-ONLY is non-nil, just return alist with ref names,
1577with value 'upcase, only return alist with tokenref names."
1079 (let ((items nil) 1578 (let ((items nil)
1080 (classes nil) 1579 (classes nil)
1081 (continue t)) 1580 (continue t))
1082 ;; The generic imenu function searches backward, which is slower 1581 ;; Using `imenu-progress-message' would require imenu for compilation, but
1083 ;; and more likely not to work during editing. 1582 ;; nobody is missing these messages. The generic imenu function searches
1084 (with-syntax-table antlr-action-syntax-table 1583 ;; backward, which is slower and more likely not to work during editing.
1085 (antlr-invalidate-context-cache) 1584 (goto-char (point-min))
1086 (goto-char (point-min)) 1585 (antlr-skip-file-prelude t)
1087 (antlr-skip-file-prelude t) 1586 (while continue
1088 (while continue 1587 (if (looking-at "\\(class\\|lexer[ \t]+grammar\\|parser[ \t]+grammar\\|tree[ \t]+grammar\\|grammar\\|mode\\|import\\)[ \t]+\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)") ; TODO: import is (hopefully) temp
1089 (if (looking-at "{") (antlr-skip-sexps 1)) 1588 (and (not refs-only)
1090 (if (looking-at antlr-class-header-regexp) 1589 (memq (char-after (match-beginning 1)) '(?c ?m)) ;class, mode
1091 (or tokenrefs-only 1590 (push (cons (match-string-no-properties 2)
1092 (push (cons (match-string 2) 1591 (if imenu-use-markers
1093 (if imenu-use-markers 1592 (copy-marker (match-beginning 2))
1094 (copy-marker (match-beginning 2)) 1593 (match-beginning 2)))
1095 (match-beginning 2))) 1594 classes))
1096 classes)) 1595 (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)\\_>\\|fragment\\_>")
1097 (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)") 1596 (antlr-skip-sexps 1))
1098 (antlr-skip-sexps 1)) 1597 (when (looking-at "\\(?:\\sw\\|\\s_\\)+")
1099 (when (looking-at "\\sw+") 1598 (when (or (not (eq refs-only 'upcase))
1100 (if tokenrefs-only 1599 (antlr-upcase-p (char-after (point))))
1101 (if (antlr-upcase-p (char-after (point))) 1600 (push (cons (match-string-no-properties 0)
1102 (push (list (match-string 0)) items)) 1601 (if (and imenu-use-markers (not refs-only))
1103 (push (cons (match-string 0) 1602 (copy-marker (match-beginning 0))
1104 (if imenu-use-markers 1603 (match-beginning 0)))
1105 (copy-marker (match-beginning 0)) 1604 items))))
1106 (match-beginning 0))) 1605 (if (setq continue (antlr-search-forward ";" antlr-skip-line-regexp))
1107 items)))) 1606 (antlr-skip-rule-postlude t)))
1108 (if (setq continue (antlr-search-forward ";"))
1109 (antlr-skip-exception-part t))))
1110 (if classes 1607 (if classes
1111 (cons (cons "Classes" (nreverse classes)) (nreverse items)) 1608 (cons (cons (if (eq antlr-tool-version 'antlr-v2) "Classes" "Modes")
1609 (nreverse classes))
1610 (nreverse items))
1112 (nreverse items)))) 1611 (nreverse items))))
1113 1612
1114 1613
@@ -1116,28 +1615,95 @@ IF TOKENREFS-ONLY is non-nil, just return alist with tokenref names."
1116;;; Parse grammar files (internal functions) 1615;;; Parse grammar files (internal functions)
1117;;;=========================================================================== 1616;;;===========================================================================
1118 1617
1119(defun antlr-skip-exception-part (skip-comment) 1618;; --- simplified v2 grammar -------------------------------------------------
1120 "Skip exception part of current rule, i.e., everything after `;'. 1619;; file: ("header" STRING? ACTION)? OPTIONS? ACTION? class*
1121This also includes the options and tokens part of a grammar class 1620;; class: "class" ID // moved preable action to file rule
1122header. If SKIP-COMMENT is non-nil, also skip the comment after that 1621;; ("extends" ("Lexer"|"Parser"|"TreeParser") ID?)? ";"
1123part." 1622;; OPTIONS? TOKENS? ACTION? rule*
1124 (let ((pos (point)) 1623;; rule: ("protected"|"public"|"private")? ID "!"?
1125 (class nil)) 1624;; (ARGS)? ('returns' ARGS)? ('throws' IDs )? OPTIONS? ACTION?
1625;; ":" alts ";" ("exception" ARGS? ("catch" ARGS ACTION)* )*
1626
1627;; --- simplified v3/v4 grammar ----------------------------------------------
1628;; grammar: ('lexer'|'parser'|'tree')? 'grammar' id ';'
1629;; < OPTIONS? TOKENS? (grammar3only|grammar4only) action* >
1630;; rule* ('mode' ID ';' rule* )* // lexer MODE is v4 only
1631;; grammar3only: ('scope' id ACTION)* // strict sequence in <...>
1632;; grammar4only: ('import' IDs ';')? ('channels' ACTION)? // any sequence in <...>
1633;; action: '@' (ID '::')? ID ACTION
1634;; rule: ('protected'|'public'|'private'|'fragment')? ID '!'?
1635;; (ARGS)? ('returns' ARGS)? ('throws' IDs )? ('locals' ARGS)?
1636;; < OPTIONS? scope3only action* >
1637;; ':' alts ';' ('catch' ARGS ACTION)* ('finally' ACTION)?
1638;; scope3only: ('scope' ACTION)? ('scope' IDs ';' )?
1639
1640(eval-and-compile
1641 (defconst antlr-rule-postlude-skip-alist--const ; const for eval-when-compile safety
1642 '(("exception" 1 . t) ("import" antlr-skip-import-statement)
1643 ("options" 2) ("tokens" 2) ("finally" 2) ("channels" 2)
1644 ("catch" 3) ("scope" 3))
1645 "Constant for `antlr-rule-postlude-skip-alist'."))
1646
1647(defvar antlr-rule-postlude-skip-alist antlr-rule-postlude-skip-alist--const
1648 "Alist of keywords after the ';' which still belong to the grammar rule.
1649Each element looks like
1650 (KEYWORD FUNCTION ARGS...)
1651or
1652 (KEYWORD SEXPS-COUNT OPTIONALP)
1653
1654After the ';' ending a rule body, function `antlr-skip-rule-postlude'
1655skips whitespace and comments, and check the text after point against
1656`antlr-rule-postlude-skip-regexp'. While there is a match,
1657
1658- if regexp group 1 has not been matched: we set point the end of the,
1659 match, and skip the next sexpr, whitespace and comments
1660
1661- if the string matched by regexp group 1 is not the car of an element
1662 of `antlr-rule-postlude-skip-alist': we skip one sexpr - which should
1663 move point to the end of the whole match,
1664
1665- when the corresponding element of `antlr-rule-postlude-skip-alist'
1666 is of the first form, we call FUNCTION with arguments ARGS - this
1667 the function should return the position after a match and move
1668 point to the non whitespace/comment position after that
1669
1670- when the corresponding element of `antlr-rule-postlude-skip-alist'
1671 is of the second form, we skip SEXPS-COUNT balanced expression
1672 (including the keyword itself)
1673
1674The value might be tool-dependent, see `antlr-tool-version-variables'.")
1675
1676(defvar antlr-rule-postlude-skip-regexp
1677 (eval-when-compile
1678 (concat (regexp-opt (mapcar #'car antlr-rule-postlude-skip-alist--const) t)
1679 "\\_>\\|@[A-Za-z\300-\326\330-\337_]\\(?:\\sw\\|\\s_\\)*\\(?:::[A-Za-z\300-\326\330-\337_]\\(?:\\sw\\|\\s_\\)*\\)?"))
1680 "Regexp matching things after ';' which still belong to the grammar rule.
1681See `antlr-rule-postlude-skip-alist' for details.
1682The value might be tool-dependent, see `antlr-tool-version-variables'.")
1683
1684(defun antlr-skip-rule-postlude (skip-comment)
1685 "Skip the postlude of a definition, i.e. everything after `;'.
1686Definitions are rules, grammar/class and v4 mode definition. If
1687SKIP-COMMENT is non-nil, also skip the whitespace and comment
1688after that part. See `antlr-rule-postlude-skip-alist'.
1689
1690Point is assumed to be after the `;'. Always return end position
1691before trailing whitespaces and comments"
1692 (let ((pos (point)))
1126 (antlr-c-forward-sws) 1693 (antlr-c-forward-sws)
1127 (while (looking-at "options\\>\\|tokens\\>") 1694 (while (looking-at antlr-rule-postlude-skip-regexp)
1128 (setq class t) 1695 (if (match-end 1)
1129 (setq pos (antlr-skip-sexps 2))) 1696 (let ((skip (cdr (assoc (match-string-no-properties 1)
1130 (if class 1697 antlr-rule-postlude-skip-alist))))
1131 ;; Problem: an action only belongs to a class def, not a normal rule. 1698 (if (functionp (car skip))
1132 ;; But checking the current rule type is too expensive => only expect 1699 (setq pos (apply (car skip) (cdr skip)))
1133 ;; an action if we have found an option or tokens part. 1700 (setq pos (antlr-skip-sexps (or (car skip) 1)))
1134 (if (looking-at "{") (setq pos (antlr-skip-sexps 1))) 1701 (when (and (cdr skip) (eq (char-after) ?\[))
1135 (while (looking-at "exception\\>") 1702 (setq pos (antlr-skip-sexps 1)))))
1136 (setq pos (antlr-skip-sexps 1)) 1703 (goto-char (match-end 0)) ; to end of @action / @scope::action
1137 (when (looking-at "\\[") 1704 (antlr-c-forward-sws)
1138 (setq pos (antlr-skip-sexps 1))) 1705 (setq pos (antlr-skip-sexps 1))))
1139 (while (looking-at "catch\\>") 1706 (if (eq (char-after) ?\{) (setq pos (antlr-skip-sexps 1))) ; v2
1140 (setq pos (antlr-skip-sexps 3)))))
1141 (or skip-comment (goto-char pos)))) 1707 (or skip-comment (goto-char pos))))
1142 1708
1143(defun antlr-skip-file-prelude (skip-comment) 1709(defun antlr-skip-file-prelude (skip-comment)
@@ -1147,46 +1713,47 @@ Return the start position of the file prelude.
1147 1713
1148Hack: if SKIP-COMMENT is `header-only' only skip header and return 1714Hack: if SKIP-COMMENT is `header-only' only skip header and return
1149position before the comment after the header." 1715position before the comment after the header."
1150 (let* ((pos (point)) 1716 (let* ((pos (point)) ; should be (point-min)
1151 (pos0 pos)) 1717 (pos0 pos))
1152 (antlr-c-forward-sws) 1718 (antlr-c-forward-sws)
1153 (if skip-comment (setq pos0 (point))) 1719 (if skip-comment (setq pos0 (point)))
1154 (while (looking-at "header\\>[ \t]*\\(\"\\)?") 1720 (while (looking-at "header\\_>[ \t]*\\(\"\\)?")
1155 (setq pos (antlr-skip-sexps (if (match-beginning 1) 3 2)))) 1721 (setq pos (antlr-skip-sexps (if (match-beginning 1) 3 2))))
1156 (if (eq skip-comment 'header-only) ; a hack... 1722 (if (eq skip-comment 'header-only) ; a hack...
1157 pos 1723 pos
1158 (when (looking-at "options\\>") 1724 (when (looking-at "options\\_>")
1159 (setq pos (antlr-skip-sexps 2))) 1725 (setq pos (antlr-skip-sexps 2)))
1726 (if (eq (char-after) ?\{) (setq pos (antlr-skip-sexps 1)))
1160 (or skip-comment (goto-char pos)) 1727 (or skip-comment (goto-char pos))
1161 pos0))) 1728 pos0)))
1162 1729
1163(defun antlr-next-rule (arg skip-comment) 1730(defun antlr-next-rule (arg skip-comment)
1164 "Move forward to next end of rule. Do it ARG many times. 1731 "Move forward to next end of rule. Do it ARG many times.
1165A grammar class header and the file prelude are also considered as a 1732A grammar/class definition and the file prelude of Antlr v2
1166rule. Negative argument ARG means move back to ARGth preceding end of 1733grammars are also considered as a rule. Negative argument ARG
1167rule. The behavior is not defined when ARG is zero. If SKIP-COMMENT 1734means move back to ARGth preceding end of rule. The behavior is
1168is non-nil, move to beginning of the rule." 1735not defined when ARG is zero. If SKIP-COMMENT is non-nil, move
1169 ;; WARNING: Should only be used with `antlr-action-syntax-table'! 1736to beginning of the rule."
1170 ;; PRE: ARG<>0 1737 ;; PRE: ARG<>0
1171 (let ((pos (point)) 1738 (let ((pos (point))
1172 (beg (point))) 1739 (beg (point)))
1173 ;; first look whether point is in exception part 1740 ;; first look whether point is in rule postlude
1174 (if (antlr-search-backward ";") 1741 (if (antlr-search-backward ";" antlr-skip-line-regexp)
1175 (progn 1742 (progn
1176 (setq beg (point)) 1743 (setq beg (point))
1177 (forward-char) 1744 (forward-char)
1178 (antlr-skip-exception-part skip-comment)) 1745 (antlr-skip-rule-postlude skip-comment))
1179 (antlr-skip-file-prelude skip-comment)) 1746 (antlr-skip-file-prelude skip-comment))
1180 (if (< arg 0) 1747 (if (< arg 0)
1181 (unless (and (< (point) pos) (zerop (cl-incf arg))) 1748 (unless (and (< (point) pos) (zerop (cl-incf arg)))
1182 ;; if we have moved backward, we already moved one defun backward 1749 ;; if we have moved backward, we already moved one defun backward
1183 (goto-char beg) ; rewind (to ";" / point) 1750 (goto-char beg) ; rewind (to ";" / point)
1184 (while (and arg (<= (cl-incf arg) 0)) 1751 (while (and arg (<= (cl-incf arg) 0))
1185 (if (antlr-search-backward ";") 1752 (if (antlr-search-backward ";" antlr-skip-line-regexp)
1186 (setq beg (point)) 1753 (setq beg (point))
1187 (when (>= arg -1) 1754 (when (>= arg -1)
1188 ;; try file prelude: 1755 ;; try file prelude:
1189 (setq pos (antlr-skip-file-prelude skip-comment)) 1756 (setq pos (antlr-skip-file-prelude skip-comment)) ; header pos
1190 (if (zerop arg) 1757 (if (zerop arg)
1191 (if (>= (point) beg) 1758 (if (>= (point) beg)
1192 (goto-char (if (>= pos beg) (point-min) pos))) 1759 (goto-char (if (>= pos beg) (point-min) pos)))
@@ -1195,21 +1762,20 @@ is non-nil, move to beginning of the rule."
1195 (setq arg nil))) 1762 (setq arg nil)))
1196 (when arg ; always found a ";" 1763 (when arg ; always found a ";"
1197 (forward-char) 1764 (forward-char)
1198 (antlr-skip-exception-part skip-comment))) 1765 (antlr-skip-rule-postlude skip-comment)))
1199 (if (<= (point) pos) ; moved backward? 1766 (if (<= (point) pos) ; moved backward?
1200 (goto-char pos) ; rewind 1767 (goto-char pos) ; rewind
1201 (decf arg)) ; already moved one defun forward 1768 (decf arg)) ; already moved one defun forward
1202 (unless (zerop arg) 1769 (unless (zerop arg)
1203 (while (>= (decf arg) 0) 1770 (while (>= (decf arg) 0)
1204 (antlr-search-forward ";")) 1771 (antlr-search-forward ";" antlr-skip-line-regexp))
1205 (antlr-skip-exception-part skip-comment))))) 1772 (antlr-skip-rule-postlude skip-comment)))))
1206 1773
1207(defun antlr-outside-rule-p () 1774(defun antlr-outside-rule-p ()
1208 "Non-nil if point is outside a grammar rule. 1775 "Non-nil if point is outside a grammar rule.
1209Move to the beginning of the current rule if point is inside a rule." 1776Move to the beginning of the current rule if point is inside a rule."
1210 ;; WARNING: Should only be used with `antlr-action-syntax-table'!
1211 (let ((pos (point))) 1777 (let ((pos (point)))
1212 (antlr-next-rule -1 nil) 1778 (antlr-next-rule -1 nil) ; to end of previous rule
1213 (let ((between (or (bobp) (< (point) pos)))) 1779 (let ((between (or (bobp) (< (point) pos))))
1214 (antlr-c-forward-sws) 1780 (antlr-c-forward-sws)
1215 (and between (> (point) pos) (goto-char pos))))) 1781 (and between (> (point) pos) (goto-char pos)))))
@@ -1225,58 +1791,70 @@ Move to the beginning of the current rule if point is inside a rule."
1225A grammar class header and the file prelude are also considered as a 1791A grammar class header and the file prelude are also considered as a
1226rule." 1792rule."
1227 (save-excursion 1793 (save-excursion
1228 (with-syntax-table antlr-action-syntax-table 1794 (not (antlr-outside-rule-p))))
1229 (not (antlr-outside-rule-p)))))
1230 1795
1231(defun antlr-end-of-rule (&optional arg) 1796(defun antlr-end-of-rule (&optional arg)
1232 "Move forward to next end of rule. Do it ARG [default: 1] many times. 1797 "Move forward to next/end of rule. Do it ARG [default: 1] many times.
1233A grammar class header and the file prelude are also considered as a 1798A grammar/class header and the file prelude are also considered a
1234rule. Negative argument ARG means move back to ARGth preceding end of 1799rule.
1800
1801If `antlr-end-of-defun-is-next' is nil, move to next end of rule,
1802i.e. the end of the current rule with ARG = 1. Otherwise move
1803forward to the ARGth next rule.
1804
1805Negative argument ARG means move back to ARGth preceding end of
1235rule. If ARG is zero, run `antlr-end-of-body'." 1806rule. If ARG is zero, run `antlr-end-of-body'."
1236 (interactive "^p") 1807 (interactive "^p")
1808 ;; yes, there is a variable `end-of-defun-function', but `end-of-defun' does
1809 ;; far too much around the funcall of that variable (Emacs-24.4)
1237 (if (zerop arg) 1810 (if (zerop arg)
1238 (antlr-end-of-body) 1811 (antlr-end-of-body)
1239 (with-syntax-table antlr-action-syntax-table 1812 (antlr-next-rule arg (and antlr-end-of-defun-is-next (> arg 0)))))
1240 (antlr-next-rule arg nil))))
1241 1813
1242(defun antlr-beginning-of-rule (&optional arg) 1814(defun antlr-beginning-of-rule (&optional arg)
1243 "Move backward to preceding beginning of rule. Do it ARG many times. 1815 "Move backward to preceding beginning of rule. Do it ARG many times.
1244A grammar class header and the file prelude are also considered as a 1816A grammar/class header and the file prelude are also considered a
1245rule. Negative argument ARG means move forward to ARGth next beginning 1817rule.
1246of rule. If ARG is zero, run `antlr-beginning-of-body'." 1818
1819Negative argument ARG means move forward to abs(ARG)th next rule:
1820beginning of rule if `antlr-end-of-defun-is-next' is nil, and end
1821of rule otherwise.
1822
1823If ARG is zero, run `antlr-beginning-of-body'."
1247 (interactive "^p") 1824 (interactive "^p")
1248 (if (zerop arg) 1825 (if (zerop arg)
1249 (antlr-beginning-of-body) 1826 (antlr-beginning-of-body)
1250 (with-syntax-table antlr-action-syntax-table 1827 (antlr-next-rule (- arg) (if antlr-end-of-defun-is-next (> arg 0) t))))
1251 (antlr-next-rule (- arg) t))))
1252 1828
1253(defun antlr-end-of-body (&optional msg) 1829(defun antlr-end-of-body (&optional msg)
1254 "Move to position after the `;' of the current rule. 1830 "Move to position after the `;' of the current rule.
1255A grammar class header is also considered as a rule. With optional 1831A grammar class header is also considered as a rule. With optional
1256prefix arg MSG, move to `:'." 1832prefix arg MSG, move to `:'."
1257 (interactive "^") 1833 (interactive "^")
1258 (with-syntax-table antlr-action-syntax-table 1834 (let ((orig (point)))
1259 (let ((orig (point))) 1835 (if (antlr-outside-rule-p)
1260 (if (antlr-outside-rule-p) 1836 (error "Outside an ANTLR rule"))
1261 (error "Outside an ANTLR rule")) 1837 (let ((bor (point))) ; beginning of current rule
1262 (let ((bor (point))) 1838 (when (< (antlr-skip-file-prelude t) (point))
1263 (when (< (antlr-skip-file-prelude t) (point)) 1839 ;; Yes, we are in the file prelude
1264 ;; Yes, we are in the file prelude 1840 (goto-char orig)
1265 (goto-char orig) 1841 (error (or msg "The file prelude is without `;'")))
1266 (error (or msg "The file prelude is without `;'"))) 1842 (antlr-search-forward ";" antlr-skip-line-regexp)
1267 (antlr-search-forward ";") 1843 (when msg
1268 (when msg 1844 (when (< (point)
1269 (when (< (point) 1845 (progn (goto-char bor)
1270 (progn (goto-char bor) 1846 (or (antlr-search-forward antlr-rule-body-start-op)
1271 (or (antlr-search-forward ":") (point-max)))) 1847 (point-max))))
1272 (goto-char orig) 1848 (goto-char orig)
1273 (error msg)) 1849 (error msg))
1274 (antlr-c-forward-sws)))))) 1850 (antlr-c-forward-sws)))))
1275 1851
1276(defun antlr-beginning-of-body () 1852(defun antlr-beginning-of-body ()
1277 "Move to the first element after the `:' of the current rule." 1853 "Move to the first element after the `:' of the current rule."
1278 (interactive "^") 1854 (interactive "^")
1279 (antlr-end-of-body "Class headers and the file prelude are without `:'")) 1855 (antlr-end-of-body (if (eq antlr-tool-version 'antlr-v2)
1856 "Class definitions and the file prelude are without `:'"
1857 "Grammar and mode definitions are without `:'")))
1280 1858
1281 1859
1282;;;=========================================================================== 1860;;;===========================================================================
@@ -1291,11 +1869,9 @@ If non-nil, TRANSFORM is used on literals instead of `downcase-region'."
1291 (let ((literals 0)) 1869 (let ((literals 0))
1292 (save-excursion 1870 (save-excursion
1293 (goto-char (point-min)) 1871 (goto-char (point-min))
1294 (with-syntax-table antlr-action-syntax-table 1872 (while (antlr-re-search-forward "\"\\(\\sw\\(\\sw\\|\\s_\\|-\\)*\\)\"" nil) ; TODO: '...'
1295 (antlr-invalidate-context-cache) 1873 (funcall transform (match-beginning 0) (match-end 0))
1296 (while (antlr-re-search-forward "\"\\(\\sw\\(\\sw\\|-\\)*\\)\"" nil) 1874 (cl-incf literals)))
1297 (funcall transform (match-beginning 0) (match-end 0))
1298 (cl-incf literals))))
1299 (message "Transformed %d literals" literals))) 1875 (message "Transformed %d literals" literals)))
1300 1876
1301(defun antlr-upcase-literals () 1877(defun antlr-upcase-literals ()
@@ -1303,6 +1879,9 @@ If non-nil, TRANSFORM is used on literals instead of `downcase-region'."
1303 (interactive) 1879 (interactive)
1304 (antlr-downcase-literals 'upcase-region)) 1880 (antlr-downcase-literals 'upcase-region))
1305 1881
1882;; TODO: `antlr-hide-actions' should probably be a minor mode like
1883;; `hide-ifdef-mode'. Whether to exclude arguments (of limited use) should be
1884;; controlled by `antlr-action-visibility' (negative value)
1306(defun antlr-hide-actions (arg &optional silent) 1885(defun antlr-hide-actions (arg &optional silent)
1307 "Hide or unhide all actions in buffer. 1886 "Hide or unhide all actions in buffer.
1308Hide all actions including arguments in brackets if ARG is 1 or if 1887Hide all actions including arguments in brackets if ARG is 1 or if
@@ -1320,24 +1899,22 @@ Display a message unless optional argument SILENT is non-nil."
1320 (antlr-hide-actions 0 t) 1899 (antlr-hide-actions 0 t)
1321 (save-excursion 1900 (save-excursion
1322 (goto-char (point-min)) 1901 (goto-char (point-min))
1323 (with-syntax-table antlr-action-syntax-table 1902 (while (antlr-re-search-forward regexp nil)
1324 (antlr-invalidate-context-cache) 1903 (let ((beg (ignore-errors (scan-sexps (point) -1))))
1325 (while (antlr-re-search-forward regexp nil) 1904 (when beg
1326 (let ((beg (ignore-errors (scan-sexps (point) -1)))) 1905 (if diff ; braces are visible
1327 (when beg 1906 (if (> (point) (+ beg diff))
1328 (if diff ; braces are visible 1907 (add-text-properties (1+ beg) (1- (point))
1329 (if (> (point) (+ beg diff)) 1908 '(invisible t intangible t)))
1330 (add-text-properties (1+ beg) (1- (point)) 1909 ;; if actions is on line(s) of its own, hide WS
1331 '(invisible t intangible t))) 1910 (and (looking-at "[ \t]*$")
1332 ;; if actions is on line(s) of its own, hide WS 1911 (save-excursion
1333 (and (looking-at "[ \t]*$") 1912 (goto-char beg)
1334 (save-excursion 1913 (skip-chars-backward " \t")
1335 (goto-char beg) 1914 (and (bolp) (setq beg (point))))
1336 (skip-chars-backward " \t") 1915 (beginning-of-line 2)) ; beginning of next line
1337 (and (bolp) (setq beg (point)))) 1916 (add-text-properties beg (point)
1338 (beginning-of-line 2)) ; beginning of next line 1917 '(invisible t intangible t)))))))
1339 (add-text-properties beg (point)
1340 '(invisible t intangible t))))))))
1341 (or silent 1918 (or silent
1342 (message "Hide all actions (%s arguments)...done" 1919 (message "Hide all actions (%s arguments)...done"
1343 (if (= arg 1) "including" "excluding")))) 1920 (if (= arg 1) "including" "excluding"))))
@@ -1379,10 +1956,7 @@ Inserting an option with this command works as follows:
1379 according to a newly inserted language option. 1956 according to a newly inserted language option.
1380 1957
1381The name of all options with a specification for their values are stored 1958The name of all options with a specification for their values are stored
1382in `antlr-options-alists'. The used specification also depends on the 1959in `antlr-options-alists' which depends on `antlr-tool-version'.
1383value of `antlr-tool-version', i.e., step 4 will warn you if you use an
1384option that has been introduced in newer version of ANTLR, and step 5
1385will offer completion using version-correct values.
1386 1960
1387If the option already exists inside the visible part of the buffer, this 1961If the option already exists inside the visible part of the buffer, this
1388command can be used to change the value of that option. Otherwise, find 1962command can be used to change the value of that option. Otherwise, find
@@ -1410,6 +1984,7 @@ This command might also set the mark like \\[set-mark-command] does, see
1410 (barf-if-buffer-read-only) 1984 (barf-if-buffer-read-only)
1411 (or location (setq location (cdr (antlr-option-kind level)))) 1985 (or location (setq location (cdr (antlr-option-kind level))))
1412 (cond ((null level) 1986 (cond ((null level)
1987 ;; TODO: better msg if there is (currently) no such option
1413 (error "Cannot deduce what kind of option to insert")) 1988 (error "Cannot deduce what kind of option to insert"))
1414 ((atom location) 1989 ((atom location)
1415 (error "Cannot insert any %s options around here" 1990 (error "Cannot insert any %s options around here"
@@ -1430,7 +2005,7 @@ This command might also set the mark like \\[set-mark-command] does, see
1430 (goto-char (max (point-min) (car area))) 2005 (goto-char (max (point-min) (car area)))
1431 (re-search-forward (concat "\\(^\\|;\\)[ \t]*\\(\\<" 2006 (re-search-forward (concat "\\(^\\|;\\)[ \t]*\\(\\<"
1432 (regexp-quote option) 2007 (regexp-quote option)
1433 "\\>\\)[ \t\n]*\\(\\(=[ \t]?\\)[ \t]*\\(\\(\\sw\\|\\s_\\)+\\|\"\\([^\n\"\\]\\|[\\][^\n]\\)*\"\\)?\\)?") 2008 "\\_>\\)[ \t\n]*\\(\\(=[ \t]?\\)[ \t]*\\(\\(\\sw\\|\\s_\\)+\\|\"\\([^\n\"\\]\\|[\\][^\n]\\)*\"\\)?\\)?")
1434 ;; 2=name, 3=4+5, 4="=", 5=value 2009 ;; 2=name, 3=4+5, 4="=", 5=value
1435 (min (point-max) (cdr area)) 2010 (min (point-max) (cdr area))
1436 t)) 2011 t))
@@ -1449,7 +2024,7 @@ This command might also set the mark like \\[set-mark-command] does, see
1449 2024
1450(defun antlr-insert-option-interactive (arg) 2025(defun antlr-insert-option-interactive (arg)
1451 "Interactive specification for `antlr-insert-option'. 2026 "Interactive specification for `antlr-insert-option'.
1452Return \(LEVEL OPTION LOCATION)." 2027Use `current-prefix-arg' for ARG. Return \(LEVEL OPTION LOCATION)."
1453 (barf-if-buffer-read-only) 2028 (barf-if-buffer-read-only)
1454 (if arg (setq arg (prefix-numeric-value arg))) 2029 (if arg (setq arg (prefix-numeric-value arg)))
1455 (unless (memq arg '(nil 1 2 3 4)) 2030 (unless (memq arg '(nil 1 2 3 4))
@@ -1468,7 +2043,6 @@ Return \(LEVEL OPTION LOCATION)."
1468 2043
1469(defun antlr-options-menu-filter (level _menu-items) 2044(defun antlr-options-menu-filter (level _menu-items)
1470 "Return items for options submenu of level LEVEL." 2045 "Return items for options submenu of level LEVEL."
1471 ;; checkdoc-params: (menu-items)
1472 (let ((active (if buffer-read-only 2046 (let ((active (if buffer-read-only
1473 nil 2047 nil
1474 (consp (cdr-safe (cdr (antlr-option-kind level))))))) 2048 (consp (cdr-safe (cdr (antlr-option-kind level)))))))
@@ -1505,7 +2079,7 @@ like \(AREA . PLACE), see `antlr-option-location'."
1505 ((not (eq level 3)) ; grammar or subrule options 2079 ((not (eq level 3)) ; grammar or subrule options
1506 (setq pos (point)) 2080 (setq pos (point))
1507 (antlr-c-forward-sws)) 2081 (antlr-c-forward-sws))
1508 ((looking-at "^\\(private[ \t\n]\\|public[ \t\n]\\|protected[ \t\n]\\)?[ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)[ \t\n]*\\(!\\)?[ \t\n]*\\(\\[\\)?") 2082 ((looking-at "^\\(private[ \t\n]\\|public[ \t\n]\\|protected[ \t\n]\\|fragment[ \t\n]\\)?[ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)[ \t\n]*\\(!\\)?[ \t\n]*\\(\\[\\)?")
1509 ;; rule options, with complete rule header 2083 ;; rule options, with complete rule header
1510 (goto-char (or (match-end 4) (match-end 3))) 2084 (goto-char (or (match-end 4) (match-end 3)))
1511 (setq pos (antlr-skip-sexps (if (match-end 5) 1 0))) 2085 (setq pos (antlr-skip-sexps (if (match-end 5) 1 0)))
@@ -1540,51 +2114,51 @@ the rule/subrule after the init action. Otherwise, the point position
1540is undefined." 2114is undefined."
1541 (widen) 2115 (widen)
1542 (if (eq requested 1) 2116 (if (eq requested 1)
1543 1 2117 (and (car antlr-options-alists) 1)
1544 (with-syntax-table antlr-action-syntax-table 2118 (let* ((orig (point))
1545 (antlr-invalidate-context-cache) 2119 (outsidep (antlr-outside-rule-p))
1546 (let* ((orig (point)) 2120 bor)
1547 (outsidep (antlr-outside-rule-p)) 2121 (setq bor (point)) ; beginning of rule
1548 bor depth) 2122 (cond ((eq requested 2) ; grammar options required?
1549 (if (eq (char-after) ?\{) (antlr-skip-sexps 1)) 2123 (antlr-try-rule-or-grammar-option requested bor))
1550 (setq bor (point)) ; beginning of rule (after init action) 2124 ((and (car antlr-options-alists) ; file options available (v2)
1551 (cond ((eq requested 2) ; grammar options required? 2125 (save-excursion ; in region of file options?
1552 (let (boc) ; beginning of class 2126 (goto-char (point-min))
1553 (goto-char (point-min)) 2127 (antlr-skip-file-prelude t) ; ws/comment after: OK
1554 (while (and (<= (point) bor) 2128 (< orig (point))))
1555 (antlr-re-search-forward antlr-class-header-regexp 2129 (and (null requested) 1))
1556 nil)) 2130 (outsidep ; outside -> grammar option
1557 (if (<= (match-beginning 0) bor) 2131 (when (memq requested '(nil 2))
1558 (setq boc (match-end 0)))) 2132 (antlr-try-rule-or-grammar-option 2 bor)))
1559 (when boc 2133 ((looking-at antlr-grammar-header-regexp) ; rule = class def?
1560 (goto-char boc) 2134 (goto-char (match-end 0))
1561 2))) 2135 (and (null requested) 2))
1562 ((save-excursion ; in region of file options? 2136 ((or (eq requested 3) (null (elt antlr-options-alists 3)))
1563 (goto-char (point-min)) 2137 (antlr-try-rule-or-grammar-option requested bor))
1564 (antlr-skip-file-prelude t) ; ws/comment after: OK 2138 ((antlr-syntactic-grammar-depth orig bor t)
1565 (< orig (point))) 2139 4)
1566 (and (null requested) 1)) 2140 (t
1567 (outsidep ; outside rule not OK 2141 (antlr-try-rule-or-grammar-option requested bor))))))
1568 nil) 2142
1569 ((looking-at antlr-class-header-regexp) ; rule = class def? 2143(defun antlr-try-rule-or-grammar-option (requested bor)
1570 (goto-char (match-end 0)) 2144 "Try whether rule or grammar option can be applied.
1571 (and (null requested) 2)) 2145Called by function `antlr-option-level' with arguments REQUESTED,
1572 ((eq requested 3) ; rule options required? 2146and BOR poiting to the beginning of the current rule."
1573 (goto-char bor) 2147 (or (and (memq requested '(nil 3)) (elt antlr-options-alists 2)
1574 3) 2148 (progn (goto-char bor) 3))
1575 ((setq depth (antlr-syntactic-grammar-depth orig bor)) 2149 (and (memq requested '(nil 2)) (cadr antlr-options-alists)
1576 (if (> depth 0) ; move out of actions 2150 (let (boc) ; beginning of class
1577 (goto-char (scan-lists (point) -1 depth))) 2151 (goto-char (point-min))
1578 (set-syntax-table antlr-mode-syntax-table) 2152 (while (and (<= (point) bor)
1579 (antlr-invalidate-context-cache) 2153 (antlr-re-search-forward antlr-grammar-header-regexp nil))
1580 (if (eq (antlr-syntactic-context) 0) ; not in subrule? 2154 (if (<= (match-beginning 0) bor)
1581 (unless (eq requested 4) 2155 (setq boc (match-end 0))))
1582 (goto-char bor) 2156 (when boc
1583 3) 2157 (goto-char boc)
1584 (goto-char (1+ (scan-lists (point) -1 1))) 2158 2)))))
1585 4)))))))
1586 2159
1587(defun antlr-option-location (orig min-vis max-vis min-area max-area withp) 2160(defun antlr-option-location (orig min-vis max-vis min-area max-area withp)
2161 ;; checkdoc-order: nil
1588 "Return location for the options area. 2162 "Return location for the options area.
1589ORIG is the original position of `point', MIN-VIS is `point-min' and 2163ORIG is the original position of `point', MIN-VIS is `point-min' and
1590MAX-VIS is `point-max'. If WITHP is non-nil, there exists an option 2164MAX-VIS is `point-max'. If WITHP is non-nil, there exists an option
@@ -1616,26 +2190,25 @@ non-nil."
1616 ;; use start of options area (only if `withp') 2190 ;; use start of options area (only if `withp')
1617 (cons min-area 'beginning))))) 2191 (cons min-area 'beginning)))))
1618 2192
1619(defun antlr-syntactic-grammar-depth (pos beg) 2193(defun antlr-syntactic-grammar-depth (pos beg &optional outside-action)
1620 "Return syntactic context depth at POS. 2194 "Return syntactic context depth at POS.
1621Move to POS and from there on to the beginning of the string or comment 2195Move to POS and from there on to the beginning of the string or comment
1622if POS is inside such a construct. Then, return the syntactic context 2196if POS is inside such a construct. Then, return the syntactic context
1623depth at point if the point position is smaller than BEG. 2197depth at point if the point position is smaller than BEG.
1624WARNING: this may alter `match-data'." 2198WARNING: this may alter `match-data'.
2199With optional argument OUTSIDE-ACTION, move to beginning of action."
1625 (goto-char pos) 2200 (goto-char pos)
1626 (let ((context (or (antlr-syntactic-context) 0))) 2201 (let ((ppss (syntax-ppss)))
1627 (while (and context (not (integerp context))) 2202 (when (or (nth 3 ppss) (nth 4 ppss)) ; string or comment -> to beginning
1628 (cond ((eq context 'string) 2203 (goto-char (nth 8 ppss)))
1629 (setq context 2204 (when outside-action
1630 (and (search-backward "\"" nil t) 2205 (let ((poss (nth 9 ppss)) ; TODO: syntax-ppss-open-positions
1631 (>= (point) beg) 2206 open)
1632 (or (antlr-syntactic-context) 0)))) 2207 (while (and poss (eq (char-after (car poss)) ?\())
1633 ((memq context '(comment block-comment)) 2208 (setq open (pop poss)))
1634 (setq context 2209 (when open
1635 (and (re-search-backward "/[/*]" nil t) 2210 (goto-char (1+ open))
1636 (>= (point) beg) 2211 (>= open beg))))))
1637 (or (antlr-syntactic-context) 0))))))
1638 context))
1639 2212
1640 2213
1641;;;=========================================================================== 2214;;;===========================================================================
@@ -1643,6 +2216,7 @@ WARNING: this may alter `match-data'."
1643;;;=========================================================================== 2216;;;===========================================================================
1644 2217
1645(defun antlr-insert-option-do (level option old area pos) 2218(defun antlr-insert-option-do (level option old area pos)
2219 ;; checkdoc-order: nil
1646 "Insert option into buffer at position POS. 2220 "Insert option into buffer at position POS.
1647Insert option of level LEVEL and name OPTION. If OLD is non-nil, an 2221Insert option of level LEVEL and name OPTION. If OLD is non-nil, an
1648options area is already exists. If OLD looks like \(BEG . END), the 2222options area is already exists. If OLD looks like \(BEG . END), the
@@ -1654,7 +2228,7 @@ If the original point position was outside an options area, AREA is nil.
1654Otherwise, and if an option specification already exists, AREA is a cons 2228Otherwise, and if an option specification already exists, AREA is a cons
1655cell where the two values determine the area inside the braces." 2229cell where the two values determine the area inside the braces."
1656 (let* ((spec (cdr (assoc option (elt antlr-options-alists (1- level))))) 2230 (let* ((spec (cdr (assoc option (elt antlr-options-alists (1- level)))))
1657 (value (antlr-option-spec level option (cdr spec) (consp old)))) 2231 (value (cdr spec)))
1658 (if (fboundp (car spec)) (funcall (car spec) 'before-input option)) 2232 (if (fboundp (car spec)) (funcall (car spec) 'before-input option))
1659 ;; set mark (unless point was inside options area before) 2233 ;; set mark (unless point was inside options area before)
1660 (if (cond (area (eq antlr-options-push-mark t)) 2234 (if (cond (area (eq antlr-options-push-mark t))
@@ -1677,7 +2251,6 @@ cell where the two values determine the area inside the braces."
1677 (elt antlr-options-headings (1- level)) 2251 (elt antlr-options-headings (1- level))
1678 option)) 2252 option))
1679 ;; option specification found 2253 ;; option specification found
1680 (setq value (cdr value))
1681 (if (car value) 2254 (if (car value)
1682 (let ((initial (and (consp old) (cdr old) 2255 (let ((initial (and (consp old) (cdr old)
1683 (buffer-substring (car old) (cdr old))))) 2256 (buffer-substring (car old) (cdr old)))))
@@ -1703,42 +2276,13 @@ cell where the two values determine the area inside the braces."
1703 ;; final ----------------------------------------------------------------- 2276 ;; final -----------------------------------------------------------------
1704 (if (fboundp (car spec)) (funcall (car spec) 'after-insertion option)))) 2277 (if (fboundp (car spec)) (funcall (car spec) 'after-insertion option))))
1705 2278
1706(defun antlr-option-spec (level option specs existsp)
1707 "Return version correct option value specification.
1708Return specification for option OPTION of kind level LEVEL. SPECS
1709should correspond to the VALUE-SPEC... in `antlr-options-alists'.
1710EXISTSP determines whether the option already exists."
1711 (let (value)
1712 (while (and specs (>= antlr-tool-version (caar specs)))
1713 (setq value (pop specs)))
1714 (cond (value) ; found correct spec
1715 ((null specs) nil) ; didn't find any specs
1716 (existsp (car specs)) ; wrong version, but already present
1717 ((y-or-n-p (format "Insert v%s %s option %s in v%s? "
1718 (antlr-version-string (caar specs))
1719 (elt antlr-options-headings (1- level))
1720 option
1721 (antlr-version-string antlr-tool-version)))
1722 (car specs))
1723 (t
1724 (error "Didn't insert v%s %s option %s in v%s"
1725 (antlr-version-string (caar specs))
1726 (elt antlr-options-headings (1- level))
1727 option
1728 (antlr-version-string antlr-tool-version))))))
1729
1730(defun antlr-version-string (version)
1731 "Format the Antlr version number VERSION, see `antlr-tool-version'."
1732 (let ((version100 (/ version 100)))
1733 (format "%d.%d.%d"
1734 (/ version100 100) (mod version100 100) (mod version 100))))
1735
1736 2279
1737;;;=========================================================================== 2280;;;===========================================================================
1738;;; Insert options: the details (used by `antlr-insert-option-do') 2281;;; Insert options: the details (used by `antlr-insert-option-do')
1739;;;=========================================================================== 2282;;;===========================================================================
1740 2283
1741(defun antlr-insert-option-existing (old value) 2284(defun antlr-insert-option-existing (old value)
2285 ;; checkdoc-order: nil
1742 "Insert option value VALUE at point for existing option. 2286 "Insert option value VALUE at point for existing option.
1743For OLD, see `antlr-insert-option-do'." 2287For OLD, see `antlr-insert-option-do'."
1744 ;; no = => insert = 2288 ;; no = => insert =
@@ -1777,7 +2321,7 @@ For AREA and OLD, see `antlr-insert-option-do'."
1777 (skip-chars-forward " \t") 2321 (skip-chars-forward " \t")
1778 2322
1779 (if (looking-at "$\\|//") 2323 (if (looking-at "$\\|//")
1780 ;; just comment after point => skip (+ lines with same col comment) 2324 ;; just comment after point => skip (+ lines with same col comment)
1781 (let ((same (if (> (match-end 0) (match-beginning 0)) 2325 (let ((same (if (> (match-end 0) (match-beginning 0))
1782 (current-column)))) 2326 (current-column))))
1783 (beginning-of-line 2) 2327 (beginning-of-line 2)
@@ -1831,9 +2375,8 @@ Used by `antlr-insert-option-do'."
1831 "Read a string from the minibuffer, possibly with completion. 2375 "Read a string from the minibuffer, possibly with completion.
1832If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially. 2376If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
1833PROMPT is a string to prompt with, normally it ends in a colon and a 2377PROMPT is a string to prompt with, normally it ends in a colon and a
1834space. If AS-STRING is t or is a member \(comparison done with `eq') of 2378space. If AS-STRING is non-nil, return printed representation of the user
1835`antlr-options-style', return printed representation of the user input, 2379input, otherwise return the user input directly.
1836otherwise return the user input directly.
1837 2380
1838If TABLE or TABLE-X is non-nil, read with completion. The completion 2381If TABLE or TABLE-X is non-nil, read with completion. The completion
1839table is the resulting alist of TABLE-X concatenated with TABLE where 2382table is the resulting alist of TABLE-X concatenated with TABLE where
@@ -1847,10 +2390,10 @@ Used inside `antlr-options-alists'."
1847 (input (if table0 2390 (input (if table0
1848 (completing-read prompt table0 nil nil initial-contents) 2391 (completing-read prompt table0 nil nil initial-contents)
1849 (read-from-minibuffer prompt initial-contents)))) 2392 (read-from-minibuffer prompt initial-contents))))
1850 (if (and as-string 2393 (if as-string
1851 (or (eq as-string t) 2394 ;; if necessary, `use print-escape-newlines', `print-escape-nonascii'
1852 (cdr (assq as-string antlr-options-style)))) 2395 ;; if strings should be used in v3/v4, write our own (single quote)
1853 (format "%S" input) 2396 (format "%S" input)
1854 input))) 2397 input)))
1855 2398
1856(defun antlr-read-boolean (initial-contents prompt &optional table) 2399(defun antlr-read-boolean (initial-contents prompt &optional table)
@@ -1859,52 +2402,67 @@ If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
1859PROMPT is a string to prompt with, normally it ends in a question mark 2402PROMPT is a string to prompt with, normally it ends in a question mark
1860and a space. \"(true or false) \" is appended if TABLE is nil. 2403and a space. \"(true or false) \" is appended if TABLE is nil.
1861 2404
1862Read with completion over \"true\", \"false\" and the keys in TABLE, see 2405Without TABLE, use `y-or-n-p', otherwise read with completion
1863also `antlr-read-value'. 2406over \"true\", \"false\" and the keys in TABLE, see also
2407`antlr-read-value'.
1864 2408
1865Used inside `antlr-options-alists'." 2409Used inside `antlr-options-alists'."
1866 (antlr-read-value initial-contents 2410 (if table
1867 (if table prompt (concat prompt "(true or false) ")) 2411 (antlr-read-value initial-contents prompt
1868 nil 2412 nil table '(("false") ("true")))
1869 table '(("false") ("true")))) 2413 (if (y-or-n-p prompt) "true" "false")))
2414
2415(defun antlr-read-language (initial-contents prompt)
2416 "Read an action language from the minibuffer, with completion.
2417If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
2418PROMPT is a string to prompt with, normally it ends in a colon and a
2419space.
2420
2421Used inside `antlr-options-alists'."
2422 (let ((table (apply 'nconc
2423 (mapcar (lambda (l) (mapcar #'list (cdr l)))
2424 antlr-language-list))))
2425 (antlr-read-value initial-contents prompt nil table)))
1870 2426
1871(defun antlr-language-option-extra (phase &rest _dummies) 2427(defun antlr-language-option-extra (phase &rest _dummies)
1872;; checkdoc-params: (dummies)
1873 "Change language according to the new value of the \"language\" option. 2428 "Change language according to the new value of the \"language\" option.
1874Call `antlr-mode' if the new language would be different from the value 2429Call `antlr-mode' if the new language would be different from the value
1875of `antlr-language', keeping the value of variable `font-lock-mode'. 2430of `antlr-language', keeping the value of variable `font-lock-mode'.
1876 2431
1877Called in PHASE `after-insertion', see `antlr-options-alists'." 2432Called in PHASE `after-insertion', see `antlr-options-alists'."
1878 (when (eq phase 'after-insertion) 2433 (when (eq phase 'after-insertion)
1879 (let ((new-language (antlr-language-option t))) 2434 (let ((new-language (antlr-guess-language)))
1880 (or (null new-language) 2435 (or (null new-language)
1881 (eq new-language antlr-language) 2436 (eq new-language antlr-language)
1882 (let ((font-lock font-lock-mode)) 2437 (let ((font-lock (and (boundp 'font-lock-mode) font-lock-mode)))
1883 (if font-lock (font-lock-mode 0)) 2438 (if font-lock (font-lock-mode 0))
1884 (antlr-mode) 2439 (funcall major-mode) ; TODO: do differently?
1885 (and font-lock (null font-lock-mode) (font-lock-mode 1))))))) 2440 (and font-lock (null font-lock-mode) (font-lock-mode 1)))))))
1886 2441
1887(defun antlr-c++-mode-extra (phase option &rest _dummies) 2442(defun antlr-c++-mode-extra (phase option &rest _dummies)
1888;; checkdoc-params: (option dummies) 2443 ;; checkdoc-order: nil
1889 "Warn if C++ option is used with the wrong language. 2444 "Warn if C++ option OPTION is used with the wrong language.
1890Ask user \(\"y or n\"), if a C++ only option is going to be inserted but 2445Ask user \(\"y or n\"), if a C++ only option is going to be inserted but
1891`antlr-language' has not the value `c++-mode'. 2446`antlr-language' has not the value `antlr-cpp'.
1892 2447
1893Called in PHASE `before-input', see `antlr-options-alists'." 2448Called in PHASE `before-input', see `antlr-options-alists'."
1894 (and (eq phase 'before-input) 2449 (and (eq phase 'before-input)
1895 (not (eq antlr-language 'c++-mode)) 2450 (not (eq antlr-language 'antlr-cpp))
1896 (not (y-or-n-p (format "Insert C++ %s option? " option))) 2451 (not (y-or-n-p (format "Insert C++ %s option? " option)))
1897 (error "Didn't insert C++ %s option with language %s" 2452 (error "Didn't insert Cpp %s option with language %s"
1898 option (cadr (assq antlr-language antlr-language-alist))))) 2453 option antlr-language-mode-name)))
1899 2454
1900 2455
1901;;;=========================================================================== 2456;;;===========================================================================
1902;;; Compute dependencies 2457;;; Compute dependencies
1903;;;=========================================================================== 2458;;;===========================================================================
2459;; This whole section is ANTLR-v2 specific. It is not used in v3 and v4.
1904 2460
1905(defun antlr-file-dependencies () 2461(defun antlr-file-dependencies ()
1906 "Return dependencies for grammar in current buffer. 2462 "Return dependencies for grammar in current buffer.
1907The result looks like \(FILE \(CLASSES . SUPERS) VOCABS . LANGUAGE) 2463This function is for ANTLR v2 grammars only.
2464
2465The result looks like \(FILE \(CLASSES . SUPERS) VOCABS . LANGUAGE)
1908 where CLASSES = ((CLASS . CLASS-EVOCAB) ...), 2466 where CLASSES = ((CLASS . CLASS-EVOCAB) ...),
1909 SUPERS = ((SUPER . USE-EVOCAB-P) ...), and 2467 SUPERS = ((SUPER . USE-EVOCAB-P) ...), and
1910 VOCABS = ((EVOCAB ...) . (IVOCAB ...)) 2468 VOCABS = ((EVOCAB ...) . (IVOCAB ...))
@@ -1919,55 +2477,56 @@ its export vocabulary is used as an import vocabulary."
1919 (unless buffer-file-name 2477 (unless buffer-file-name
1920 (error "Grammar buffer does not visit a file")) 2478 (error "Grammar buffer does not visit a file"))
1921 (let (classes export-vocabs import-vocabs superclasses default-vocab) 2479 (let (classes export-vocabs import-vocabs superclasses default-vocab)
1922 (with-syntax-table antlr-action-syntax-table 2480 (goto-char (point-min))
1923 (goto-char (point-min)) 2481 (while (antlr-re-search-forward antlr-grammar-header-regexp nil)
1924 (while (antlr-re-search-forward antlr-class-header-regexp nil) 2482 ;; parse class definition --------------------------------------------
1925 ;; parse class definition -------------------------------------------- 2483 (let* ((class (match-string-no-properties 2))
1926 (let* ((class (match-string 2)) 2484 (sclass (match-string-no-properties 4))
1927 (sclass (match-string 4)) 2485 ;; export vocab defaults to class name (first grammar in file)
1928 ;; export vocab defaults to class name (first grammar in file) 2486 ;; or to the export vocab of the first grammar in file:
1929 ;; or to the export vocab of the first grammar in file: 2487 (evocab (or default-vocab class))
1930 (evocab (or default-vocab class)) 2488 (ivocab nil))
1931 (ivocab nil)) 2489 (goto-char (match-end 0))
1932 (goto-char (match-end 0)) 2490 (antlr-c-forward-sws)
1933 (antlr-c-forward-sws) 2491 (while (looking-at "options\\_>\\|\\(tokens\\)\\_>")
1934 (while (looking-at "options\\>\\|\\(tokens\\)\\>") 2492 (if (match-beginning 1)
1935 (if (match-beginning 1) 2493 (antlr-skip-sexps 2)
1936 (antlr-skip-sexps 2) 2494 (goto-char (match-end 0))
1937 (goto-char (match-end 0)) 2495 (antlr-c-forward-sws)
1938 (antlr-c-forward-sws) 2496 ;; parse grammar option sections -------------------------------
1939 ;; parse grammar option sections ------------------------------- 2497 (when (eq (char-after (point)) ?\{)
1940 (when (eq (char-after (point)) ?\{) 2498 (let* ((beg (1+ (point)))
1941 (let* ((beg (1+ (point))) 2499 (end (1- (antlr-skip-sexps 1)))
1942 (end (1- (antlr-skip-sexps 1))) 2500 (cont (point)))
1943 (cont (point)))
1944 (goto-char beg) 2501 (goto-char beg)
1945 (if (re-search-forward "\\<exportVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t) 2502 (if (re-search-forward "\\<exportVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)" end t)
1946 (setq evocab (match-string 1))) 2503 (setq evocab (match-string-no-properties 1)))
1947 (goto-char beg) 2504 (goto-char beg)
1948 (if (re-search-forward "\\<importVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\sw*\\)" end t) 2505 (if (re-search-forward "\\<importVocab[ \t]*=[ \t]*\\([A-Za-z\300-\326\330-\337]\\(?:\\sw\\|\\s_\\)*\\)" end t)
1949 (setq ivocab (match-string 1))) 2506 (setq ivocab (match-string-no-properties 1)))
1950 (goto-char cont))))) 2507 (goto-char cont)))))
1951 (unless (member sclass '("Parser" "Lexer" "TreeParser")) 2508 (unless (member sclass '("Parser" "Lexer" "TreeParser"))
1952 (let ((super (assoc sclass superclasses))) 2509 (let ((super (assoc sclass superclasses)))
1953 (if super 2510 (if super
1954 (or ivocab (setcdr super t)) 2511 (or ivocab (setcdr super t))
1955 (push (cons sclass (null ivocab)) superclasses)))) 2512 (push (cons sclass (null ivocab)) superclasses))))
1956 ;; remember class with export vocabulary: 2513 ;; remember class with export vocabulary:
1957 (push (cons class evocab) classes) 2514 (push (cons class evocab) classes)
1958 ;; default export vocab is export vocab of first grammar in file: 2515 ;; default export vocab is export vocab of first grammar in file:
1959 (or default-vocab (setq default-vocab evocab)) 2516 (or default-vocab (setq default-vocab evocab))
1960 (or (member evocab export-vocabs) (push evocab export-vocabs)) 2517 (or (member evocab export-vocabs) (push evocab export-vocabs))
1961 (or (null ivocab) 2518 (or (null ivocab)
1962 (member ivocab import-vocabs) (push ivocab import-vocabs))))) 2519 (member ivocab import-vocabs) (push ivocab import-vocabs))))
1963 (if classes 2520 (if classes
1964 (cl-list* (file-name-nondirectory buffer-file-name) 2521 (cl-list* (file-name-nondirectory buffer-file-name)
1965 (cons (nreverse classes) (nreverse superclasses)) 2522 (cons (nreverse classes) (nreverse superclasses))
1966 (cons (nreverse export-vocabs) (nreverse import-vocabs)) 2523 (cons (nreverse export-vocabs) (nreverse import-vocabs))
1967 antlr-language)))) 2524 antlr-action-mode))))
1968 2525
1969(defun antlr-directory-dependencies (dirname) 2526(defun antlr-directory-dependencies (dirname)
1970 "Return dependencies for all grammar files in directory DIRNAME. 2527 "Return dependencies for all grammar files in directory DIRNAME.
2528This function is for ANTLR v2 grammars only.
2529
1971The result looks like \((CLASS-SPEC ...) . \(FILE-DEP ...)) 2530The result looks like \((CLASS-SPEC ...) . \(FILE-DEP ...))
1972 where CLASS-SPEC = (CLASS (FILE . EVOCAB) ...). 2531 where CLASS-SPEC = (CLASS (FILE . EVOCAB) ...).
1973 2532
@@ -1991,11 +2550,12 @@ export vocabulary specified in that file."
1991 (insert-file-contents file t nil nil t) 2550 (insert-file-contents file t nil nil t)
1992 (normal-mode t) ; necessary for major-mode, syntax 2551 (normal-mode t) ; necessary for major-mode, syntax
1993 ; table and `antlr-language' 2552 ; table and `antlr-language'
1994 (when (derived-mode-p 'antlr-mode) 2553 (when (and (derived-mode-p 'antlr-mode)
2554 (eq antlr-tool-version 'antlr-v2))
1995 (let* ((file-deps (antlr-file-dependencies)) 2555 (let* ((file-deps (antlr-file-dependencies))
1996 (file (car file-deps))) 2556 (file (car file-deps)))
1997 (when file-deps 2557 (when file-deps
1998 (dolist (class-def (caadr file-deps)) 2558 (dolist (class-def (cl-caadr file-deps))
1999 (let ((file-evocab (cons file (cdr class-def))) 2559 (let ((file-evocab (cons file (cdr class-def)))
2000 (class-spec (assoc (car class-def) classes))) 2560 (class-spec (assoc (car class-def) classes)))
2001 (if class-spec 2561 (if class-spec
@@ -2005,13 +2565,10 @@ export vocabulary specified in that file."
2005 (push file-deps dependencies))))))) 2565 (push file-deps dependencies)))))))
2006 (cons (nreverse classes) (nreverse dependencies)))))) 2566 (cons (nreverse classes) (nreverse dependencies))))))
2007 2567
2008
2009;;;===========================================================================
2010;;; Compilation: run ANTLR tool
2011;;;===========================================================================
2012
2013(defun antlr-superclasses-glibs (supers classes) 2568(defun antlr-superclasses-glibs (supers classes)
2014 "Compute the grammar lib option for the super grammars SUPERS. 2569 "Compute the grammar lib option for the super grammars SUPERS.
2570This function is for ANTLR v2 grammars only.
2571
2015Look in CLASSES for the right grammar lib files for SUPERS. SUPERS is 2572Look in CLASSES for the right grammar lib files for SUPERS. SUPERS is
2016part SUPER in the result of `antlr-file-dependencies'. CLASSES is the 2573part SUPER in the result of `antlr-file-dependencies'. CLASSES is the
2017part \(CLASS-SPEC ...) in the result of `antlr-directory-dependencies'. 2574part \(CLASS-SPEC ...) in the result of `antlr-directory-dependencies'.
@@ -2043,45 +2600,86 @@ vocabulary of the super-grammar or nil if it is not needed."
2043 (cons (if glibs (concat " -glib " (mapconcat 'car glibs ";")) "") 2600 (cons (if glibs (concat " -glib " (mapconcat 'car glibs ";")) "")
2044 (cons unknown glibs)))) 2601 (cons unknown glibs))))
2045 2602
2603
2604;;;===========================================================================
2605;;; Compilation: run ANTLR tool
2606;;;===========================================================================
2607
2608(defvar antlr-grammar-file nil
2609 "Grammar file processed in *compilation* buffer.
2610Set by command `antlr-run-tool’.")
2611
2612(defun antlr-grammar-file ()
2613 "Return the current grammar file.
2614This function could be useful in `antlr-compilation-error-regexp-alist'
2615for certain tools."
2616 antlr-grammar-file)
2617
2046(defun antlr-run-tool (command file &optional saved) 2618(defun antlr-run-tool (command file &optional saved)
2047 "Run Antlr took COMMAND on grammar FILE. 2619 "Run Antlr took COMMAND on grammar FILE.
2048When called interactively, COMMAND is read from the minibuffer and 2620When called interactively, COMMAND is read from the minibuffer and
2049defaults to `antlr-tool-command' with a computed \"-glib\" option if 2621defaults to `antlr-tool-command', with a computed \"-glib\" option for
2050necessary. 2622ANTLR v2 grammars if necessary.
2623See also variable `antlr-run-tool-on-buffer-file'.
2051 2624
2052Save all buffers first unless optional value SAVED is non-nil. When 2625Save all buffers first unless optional value SAVED is non-nil. When
2053called interactively, the buffers are always saved, see also variable 2626called interactively, the buffers are always saved, see also variable
2054`antlr-ask-about-save'." 2627`antlr-ask-about-save'."
2055 (interactive (antlr-run-tool-interactive)) 2628 (interactive (antlr-run-tool-interactive))
2056 (or saved (save-some-buffers (not antlr-ask-about-save))) 2629 (or saved (save-some-buffers (not antlr-ask-about-save)))
2057 (let ((default-directory (file-name-directory file))) 2630 (let ((default-directory (file-name-directory file))
2058 (compilation-start (concat command " " (file-name-nondirectory file)) 2631 (error-regexp-alist antlr-compilation-error-regexp-alist)
2059 nil (lambda (_mode-name) "*Antlr-Run*")))) 2632 (process-environment
2633 (if antlr-tool-path
2634 (let ((path (mapconcat 'substitute-env-vars
2635 antlr-tool-path path-separator)))
2636 (cons (concat "PATH=" path path-separator
2637 (getenv "PATH"))
2638 (cons (concat "LD_LIBRARY_PATH=" path path-separator
2639 (getenv "LD_LIBRARY_PATH"))
2640 process-environment)))
2641 process-environment))) ;#dynamic
2642 ;; the MODE argument of `compilation-start' is quite a hack...
2643 (with-current-buffer
2644 (compilation-start command antlr-compilation-mode
2645 (lambda (_mode-name) "*Antlr-Run*"))
2646 (when error-regexp-alist
2647 (setq-local compilation-error-regexp-alist error-regexp-alist))
2648 (setq-local antlr-grammar-file file))))
2060 2649
2061(defun antlr-run-tool-interactive () 2650(defun antlr-run-tool-interactive ()
2062 ;; code in `interactive' is not compiled 2651 ;; code in `interactive' is not compiled
2063 "Interactive specification for `antlr-run-tool'. 2652 "Interactive specification for `antlr-run-tool'.
2064Use prefix argument ARG to return \(COMMAND FILE SAVED)." 2653Use prefix argument ARG to return \(COMMAND FILE SAVED)."
2065 (let* ((supers (cdadr (save-excursion 2654 (let* ((supers (and (eq antlr-tool-version 'antlr-v2)
2066 (save-restriction 2655 (cl-cdadr (save-excursion
2067 (widen) 2656 (save-restriction
2068 (antlr-file-dependencies))))) 2657 (widen)
2069 (glibs "")) 2658 (antlr-file-dependencies))))))
2070 (when supers 2659 (prompt (if (functionp antlr-tool-command)
2071 (save-some-buffers (not antlr-ask-about-save) nil) 2660 (funcall antlr-tool-command buffer-file-name supers)
2072 (setq glibs (car (antlr-superclasses-glibs 2661 (if (null supers)
2073 supers 2662 antlr-tool-command
2074 (car (antlr-directory-dependencies 2663 (save-some-buffers (not antlr-ask-about-save) nil)
2075 default-directory)))))) 2664 (concat antlr-tool-command
2076 (list (read-shell-command "Run Antlr on current file with: " 2665 (car (antlr-superclasses-glibs
2077 (concat antlr-tool-command glibs " ")) 2666 supers
2078 buffer-file-name 2667 (car (antlr-directory-dependencies
2079 supers))) 2668 default-directory)))))))))
2669 (list (if antlr-run-tool-on-buffer-file
2670 (concat (read-shell-command "Run Antlr with: " prompt)
2671 " " (file-name-nondirectory buffer-file-name))
2672 (read-shell-command "Run Antlr with: "
2673 (concat prompt " "
2674 (file-name-nondirectory buffer-file-name))))
2675 buffer-file-name
2676 supers)))
2080 2677
2081 2678
2082;;;=========================================================================== 2679;;;===========================================================================
2083;;; Makefile creation 2680;;; Makefile creation
2084;;;=========================================================================== 2681;;;===========================================================================
2682;; This whole section is ANTLR-v2 specific.
2085 2683
2086(defun antlr-makefile-insert-variable (number pre post) 2684(defun antlr-makefile-insert-variable (number pre post)
2087 "Insert Makefile variable numbered NUMBER according to specification. 2685 "Insert Makefile variable numbered NUMBER according to specification.
@@ -2094,6 +2692,8 @@ Also insert strings PRE and POST before and after the variable."
2094 2692
2095(defun antlr-insert-makefile-rules (&optional in-makefile) 2693(defun antlr-insert-makefile-rules (&optional in-makefile)
2096 "Insert Makefile rules in the current buffer at point. 2694 "Insert Makefile rules in the current buffer at point.
2695This function is for ANTLR v2 grammars only.
2696
2097IN-MAKEFILE is non-nil, if the current buffer is the Makefile. See 2697IN-MAKEFILE is non-nil, if the current buffer is the Makefile. See
2098command `antlr-show-makefile-rules' for detail." 2698command `antlr-show-makefile-rules' for detail."
2099 (let* ((dirname default-directory) 2699 (let* ((dirname default-directory)
@@ -2101,24 +2701,24 @@ command `antlr-show-makefile-rules' for detail."
2101 (classes (car deps0)) ; CLASS -> (FILE . EVOCAB) ... 2701 (classes (car deps0)) ; CLASS -> (FILE . EVOCAB) ...
2102 (deps (cdr deps0)) ; FILE -> (c . s) (ev . iv) . LANGUAGE 2702 (deps (cdr deps0)) ; FILE -> (c . s) (ev . iv) . LANGUAGE
2103 (with-error nil) 2703 (with-error nil)
2104 (gen-sep (or (caddr (cadr antlr-makefile-specification)) " ")) 2704 (gen-sep (or (cl-caddr (cadr antlr-makefile-specification)) " "))
2105 (n (and (cdr deps) (cadr antlr-makefile-specification) 0))) 2705 (n (and (cdr deps) (cadr antlr-makefile-specification) 0)))
2106 (or in-makefile (set-buffer standard-output)) 2706 (or in-makefile (set-buffer standard-output))
2107 (dolist (dep deps) 2707 (dolist (dep deps)
2108 (let ((supers (cdadr dep)) 2708 (let ((supers (cl-cdadr dep))
2109 (lang (cdr (assoc (cdddr dep) antlr-file-formats-alist)))) 2709 (lang (cdr (assoc (cl-cdddr dep) antlr-file-formats-alist))))
2110 (if n (cl-incf n)) 2710 (if n (cl-incf n))
2111 (antlr-makefile-insert-variable n "" " =") 2711 (antlr-makefile-insert-variable n "" " =")
2112 (if supers 2712 (if supers
2113 (insert " " 2713 (insert " "
2114 (format (cadr antlr-special-file-formats) 2714 (format (cadr antlr-special-file-formats)
2115 (file-name-sans-extension (car dep))))) 2715 (file-name-sans-extension (car dep)))))
2116 (dolist (class-def (caadr dep)) 2716 (dolist (class-def (cl-caadr dep))
2117 (let ((sep gen-sep)) 2717 (let ((sep gen-sep))
2118 (dolist (class-file (cadr lang)) 2718 (dolist (class-file (cadr lang))
2119 (insert sep (format class-file (car class-def))) 2719 (insert sep (format class-file (car class-def)))
2120 (setq sep " ")))) 2720 (setq sep " "))))
2121 (dolist (evocab (caaddr dep)) 2721 (dolist (evocab (cl-caaddr dep))
2122 (let ((sep gen-sep)) 2722 (let ((sep gen-sep))
2123 (dolist (vocab-file (cons (car antlr-special-file-formats) 2723 (dolist (vocab-file (cons (car antlr-special-file-formats)
2124 (car lang))) 2724 (car lang)))
@@ -2126,7 +2726,7 @@ command `antlr-show-makefile-rules' for detail."
2126 (setq sep " ")))) 2726 (setq sep " "))))
2127 (antlr-makefile-insert-variable n "\n$(" ")") 2727 (antlr-makefile-insert-variable n "\n$(" ")")
2128 (insert ": " (car dep)) 2728 (insert ": " (car dep))
2129 (dolist (ivocab (cdaddr dep)) 2729 (dolist (ivocab (cl-cdaddr dep))
2130 (insert " " (format (car antlr-special-file-formats) ivocab))) 2730 (insert " " (format (car antlr-special-file-formats) ivocab)))
2131 (let ((glibs (antlr-superclasses-glibs supers classes))) 2731 (let ((glibs (antlr-superclasses-glibs supers classes)))
2132 (if (cadr glibs) (setq with-error t)) 2732 (if (cadr glibs) (setq with-error t))
@@ -2136,7 +2736,7 @@ command `antlr-show-makefile-rules' for detail."
2136 (insert " " (format (car antlr-special-file-formats) 2736 (insert " " (format (car antlr-special-file-formats)
2137 (cdr super))))) 2737 (cdr super)))))
2138 (insert "\n\t" 2738 (insert "\n\t"
2139 (caddr antlr-makefile-specification) 2739 (cl-caddr antlr-makefile-specification)
2140 (car glibs) 2740 (car glibs)
2141 " $<\n" 2741 " $<\n"
2142 (car antlr-makefile-specification))))) 2742 (car antlr-makefile-specification)))))
@@ -2146,8 +2746,10 @@ command `antlr-show-makefile-rules' for detail."
2146 (while (<= (cl-incf i) n) 2746 (while (<= (cl-incf i) n)
2147 (antlr-makefile-insert-variable i " $(" ")")) 2747 (antlr-makefile-insert-variable i " $(" ")"))
2148 (insert "\n" (car antlr-makefile-specification)))) 2748 (insert "\n" (car antlr-makefile-specification))))
2149 (if (string-equal (car antlr-makefile-specification) "\n") 2749 (if (bobp)
2150 (delete-char -1)) 2750 (setq with-error t)
2751 (if (string-equal (car antlr-makefile-specification) "\n")
2752 (delete-char -1)))
2151 (when with-error 2753 (when with-error
2152 (goto-char (point-min)) 2754 (goto-char (point-min))
2153 (insert antlr-help-unknown-file-text)) 2755 (insert antlr-help-unknown-file-text))
@@ -2160,6 +2762,8 @@ command `antlr-show-makefile-rules' for detail."
2160;;;###autoload 2762;;;###autoload
2161(defun antlr-show-makefile-rules () 2763(defun antlr-show-makefile-rules ()
2162 "Show Makefile rules for all grammar files in the current directory. 2764 "Show Makefile rules for all grammar files in the current directory.
2765This command is for ANTLR v2 grammars only.
2766
2163If the `major-mode' of the current buffer has the value `makefile-mode', 2767If the `major-mode' of the current buffer has the value `makefile-mode',
2164the rules are directory inserted at point. Otherwise, a *Help* buffer 2768the rules are directory inserted at point. Otherwise, a *Help* buffer
2165is shown with the rules which are also put into the `kill-ring' for 2769is shown with the rules which are also put into the `kill-ring' for
@@ -2175,10 +2779,12 @@ are used according to variable `antlr-unknown-file-formats' and a
2175commentary with value `antlr-help-unknown-file-text' is added. The 2779commentary with value `antlr-help-unknown-file-text' is added. The
2176*Help* buffer always starts with the text in `antlr-help-rules-intro'." 2780*Help* buffer always starts with the text in `antlr-help-rules-intro'."
2177 (interactive) 2781 (interactive)
2782 (unless (eq antlr-tool-version 'antlr-v2)
2783 (user-error (substitute-command-keys
2784 "Run \\[antlr-run-tool] with option \"-depend\" instead")))
2178 (if (null (derived-mode-p 'makefile-mode)) 2785 (if (null (derived-mode-p 'makefile-mode))
2179 (with-output-to-temp-buffer "*Help*" 2786 (with-output-to-temp-buffer (help-buffer)
2180 (save-excursion 2787 (save-excursion (antlr-insert-makefile-rules)))
2181 (antlr-insert-makefile-rules)))
2182 (push-mark) 2788 (push-mark)
2183 (antlr-insert-makefile-rules t))) 2789 (antlr-insert-makefile-rules t)))
2184 2790
@@ -2189,18 +2795,18 @@ commentary with value `antlr-help-unknown-file-text' is added. The
2189 2795
2190(defun antlr-indent-line () 2796(defun antlr-indent-line ()
2191 "Indent the current line as ANTLR grammar code. 2797 "Indent the current line as ANTLR grammar code.
2192The indentation of grammar lines are calculated by `c-basic-offset', 2798The default indentation of grammar lines are calculated by
2193multiplied by: 2799`c-basic-offset', multiplied by:
2194 - the level of the paren/brace/bracket depth, 2800 - the level of the paren/brace/bracket depth,
2195 - plus 0/2/1, depending on the position inside the rule: header, body, 2801 - plus 0/2/1, depending on the position inside the rule: header, body,
2196 exception part, 2802 exception part, customized by `antlr-base-offset-alist',
2197 - minus 1 if `antlr-indent-item-regexp' matches the beginning of the 2803 - minus 1 if `antlr-indent-item-regexp' matches the beginning of the
2198 line starting from the first non-whitespace. 2804 line starting from the first non-whitespace.
2199 2805
2200Lines inside block comments are indented by `c-indent-line' according to 2806Lines inside block comments are indented by `c-indent-line' according to
2201`antlr-indent-comment'. 2807`antlr-indent-comment'.
2202 2808
2203Lines in actions except top-level actions in a header part or an option 2809Lines in actions except top level actions in a header part or an option
2204area are indented by `c-indent-line'. 2810area are indented by `c-indent-line'.
2205 2811
2206Lines in header actions are indented at column 0 if `antlr-language' 2812Lines in header actions are indented at column 0 if `antlr-language'
@@ -2209,10 +2815,11 @@ the first non-whitespace is matched by the corresponding value.
2209 2815
2210For the initialization of `c-basic-offset', see `antlr-indent-style' and, 2816For the initialization of `c-basic-offset', see `antlr-indent-style' and,
2211to a lesser extent, `antlr-tab-offset-alist'." 2817to a lesser extent, `antlr-tab-offset-alist'."
2818 ;; TODO: this function needs to be rewritten
2212 (save-restriction 2819 (save-restriction
2213 (let ((orig (point)) 2820 (let ((orig (point))
2214 (min0 (point-min)) 2821 (min0 (point-min))
2215 bol boi indent syntax cc-syntax) 2822 bol boi indent syntax cc-syntax boa pdepth)
2216 (widen) 2823 (widen)
2217 (beginning-of-line) 2824 (beginning-of-line)
2218 (setq bol (point)) 2825 (setq bol (point))
@@ -2221,32 +2828,64 @@ to a lesser extent, `antlr-tab-offset-alist'."
2221 (skip-chars-forward " \t") 2828 (skip-chars-forward " \t")
2222 (setq boi (point)) 2829 (setq boi (point))
2223 ;; check syntax at beginning of indentation ---------------------------- 2830 ;; check syntax at beginning of indentation ----------------------------
2224 (with-syntax-table antlr-action-syntax-table 2831 (let* ((ppss (syntax-ppss))
2225 (antlr-invalidate-context-cache) 2832 (context (antlr-syntactic-context ppss))
2226 (setq syntax (antlr-syntactic-context)) 2833 (open (nth 9 ppss))) ; TODO Emacs: syntax-ppss-open-positions
2227 (cond ((symbolp syntax) 2834 (setq syntax (or context 0))
2228 (setq indent nil)) ; block-comments, strings, (comments) 2835 (setq pdepth (car ppss))
2229 ((progn 2836 ;; TODO: should boa = first non-?\( in (nth 9 ppss) ?
2230 (antlr-next-rule -1 t) 2837 (when (numberp context) ; boa = beginning of action
2231 (if (antlr-search-forward ":") (< boi (1- (point))) t)) 2838 (setq boa (nth (- (length open) context) open))))
2232 (setq indent 0)) ; in rule header 2839 (cond ((symbolp syntax)
2233 ((if (antlr-search-forward ";") (< boi (point)) t) 2840 (setq indent nil)) ; block-comments, strings, (comments) -> cc engine
2234 (setq indent 2)) ; in rule body 2841 ((progn
2235 (t 2842 (antlr-next-rule -1 t) ; to start of rule
2236 (forward-char) 2843 (= (point) boi))
2237 (antlr-skip-exception-part nil) 2844 (setq indent 0)) ; rule start always at 0
2238 (setq indent (if (> (point) boi) 1 0))))) ; in exception part? 2845 ;; TODO: use antlr-skip-to-colon-or-semi
2846
2847 ((if (let ((r (antlr-search-forward antlr-rule-body-start-op)))
2848 (while (and r (eq (char-after) ?:)) ; skip double-colon
2849 (forward-char)
2850 (setq r (antlr-search-forward antlr-rule-body-start-op)))
2851 r)
2852 (< boi (1- (point)))
2853 t)
2854 (setq indent
2855 (or (cdr (assq :header antlr-base-offset-alist)) 0)))
2856 ((eq (char-after boi) ?:)
2857 (setq indent
2858 (or (cdr (assq :colon antlr-base-offset-alist))
2859 (cdr (assq :body antlr-base-offset-alist))
2860 2)))
2861 ((if (antlr-search-forward ";" antlr-skip-line-regexp)
2862 (< boi (point))
2863 t)
2864 (setq indent
2865 (or (cdr (assq :body antlr-base-offset-alist)) 2)))
2866 (t
2867 (forward-char)
2868 (antlr-skip-rule-postlude nil)
2869 (setq indent
2870 (if (> (point) boi)
2871 (or (cdr (assq :exception antlr-base-offset-alist)) 1)
2872 0)))) ; in exception part?
2239 ;; check whether to use indentation engine of cc-mode ------------------ 2873 ;; check whether to use indentation engine of cc-mode ------------------
2240 (antlr-invalidate-context-cache)
2241 (goto-char boi) 2874 (goto-char boi)
2242 (when (and indent (> syntax 0)) 2875 (when (and indent (> syntax 0))
2243 (cond ((> syntax 1) ; block in action => use cc-mode 2876 (cond ((> syntax 1) ; block in action => use cc-mode (or nothing)
2244 (setq indent nil)) 2877 (setq indent nil)
2245 ((and (= indent 0) 2878 (when antlr-indent-action-line
2246 (assq antlr-language antlr-indent-at-bol-alist) 2879 (setq syntax 'non-cc)))
2247 (looking-at (cdr (assq antlr-language 2880 ((and (= indent 0) ; TODO: recheck
2881 (assq antlr-action-mode antlr-indent-at-bol-alist)
2882 (looking-at (cdr (assq antlr-action-mode
2248 antlr-indent-at-bol-alist)))) 2883 antlr-indent-at-bol-alist))))
2249 (setq syntax 'bol)) 2884 (setq syntax 'bol))
2885 ((memq (char-after) '(?\} ?\]))) ; close the block -> usual grammar indent
2886 (antlr-indent-action-line
2887 ;; TODO: parameters, and mode-specific - should we handle options{} and tokens{} extra?
2888 (setq indent nil syntax 'non-cc))
2250 ((setq cc-syntax (c-guess-basic-syntax)) 2889 ((setq cc-syntax (c-guess-basic-syntax))
2251 (let ((cc cc-syntax) symbol) 2890 (let ((cc cc-syntax) symbol)
2252 (while (setq symbol (pop cc)) 2891 (while (setq symbol (pop cc))
@@ -2255,30 +2894,29 @@ to a lesser extent, `antlr-tab-offset-alist'."
2255 antlr-disabling-cc-syntactic-symbols) 2894 antlr-disabling-cc-syntactic-symbols)
2256 (setq indent nil)) 2895 (setq indent nil))
2257 (setq cc nil))))))) 2896 (setq cc nil)))))))
2258;;; ((= indent 1) ; exception part => use cc-mode 2897 ;; compute the corresponding indentation and indent --------------------
2259;;; (setq indent nil))
2260;;; ((save-restriction ; not in option part => cc-mode
2261;;; (goto-char (scan-lists (point) -1 1))
2262;;; (skip-chars-backward " \t\n")
2263;;; (narrow-to-region (point-min) (point))
2264;;; (not (re-search-backward "\\<options\\'" nil t)))
2265;;; (setq indent nil)))))
2266 ;; compute the corresponding indentation and indent --------------------
2267 (if (null indent) 2898 (if (null indent)
2268 ;; Use the indentation engine of cc-mode 2899 ;; Use the indentation engine of cc-mode
2269 (progn 2900 (progn
2270 (goto-char orig) 2901 (goto-char orig)
2271 (if (or (numberp syntax) 2902 (cond ((eq syntax 'non-cc)
2272 (if (eq syntax 'string) nil (eq antlr-indent-comment t))) 2903 ;; TODO: we might check whether the current line is the
2273 (c-indent-line cc-syntax))) 2904 ;; first code in the action -> then we simply indent
2905 ;; according to indent-level (then we do not have to check
2906 ;; whether the LANGUAGE indents at col 0 (and use C indent)
2907 (funcall antlr-indent-action-line boa))
2908 ((or (numberp syntax)
2909 (if (eq syntax 'string) nil (eq antlr-indent-comment t)))
2910 (c-indent-line cc-syntax))))
2274 ;; do it ourselves 2911 ;; do it ourselves
2275 (goto-char boi) 2912 (goto-char boi)
2276 (unless (symbolp syntax) ; direct indentation 2913 (unless (symbolp syntax) ; direct indentation
2277 ;;(antlr-invalidate-context-cache) 2914 (cl-incf indent pdepth)
2278 (cl-incf indent (antlr-syntactic-context)) 2915 (and (> indent 0) (looking-at antlr-indent-item-regexp)
2279 (and (> indent 0) (looking-at antlr-indent-item-regexp) (decf indent)) 2916 (cl-decf indent))
2280 (setq indent (* indent c-basic-offset))) 2917 (setq indent (* indent c-basic-offset)))
2281 ;; the usual major-mode indent stuff --------------------------------- 2918 ;; the usual major-mode indent stuff ---------------------------------
2919 ;; TODO: use `indent-line-to' instead?
2282 (setq orig (- (point-max) orig)) 2920 (setq orig (- (point-max) orig))
2283 (unless (= (current-column) indent) 2921 (unless (= (current-column) indent)
2284 (delete-region bol boi) 2922 (delete-region bol boi)
@@ -2290,12 +2928,13 @@ to a lesser extent, `antlr-tab-offset-alist'."
2290 (goto-char (- (point-max) orig))))))) 2928 (goto-char (- (point-max) orig)))))))
2291 2929
2292(defun antlr-indent-command (&optional arg) 2930(defun antlr-indent-command (&optional arg)
2931 ;; TODO: drop this command if there is a extra function for `indent-region'
2293 "Indent the current line or insert tabs/spaces. 2932 "Indent the current line or insert tabs/spaces.
2294With optional prefix argument ARG or if the previous command was this 2933With optional prefix argument ARG, insert ARG tabs or spaces according
2295command, insert ARG tabs or spaces according to `indent-tabs-mode'. 2934to `indent-tabs-mode'.
2296Otherwise, indent the current line with `antlr-indent-line'." 2935Otherwise, indent the current line with `antlr-indent-line'."
2297 (interactive "*P") 2936 (interactive "*P")
2298 (if (or arg (eq last-command 'antlr-indent-command)) 2937 (if arg
2299 (insert-tab arg) 2938 (insert-tab arg)
2300 (let ((antlr-indent-comment (and antlr-indent-comment t))) ; dynamic 2939 (let ((antlr-indent-comment (and antlr-indent-comment t))) ; dynamic
2301 (antlr-indent-line)))) 2940 (antlr-indent-line))))
@@ -2317,114 +2956,183 @@ ANTLR's syntax and influences the auto indentation, see
2317 (interactive "*P") 2956 (interactive "*P")
2318 (if (or arg 2957 (if (or arg
2319 (save-excursion (skip-chars-backward " \t") (not (bolp))) 2958 (save-excursion (skip-chars-backward " \t") (not (bolp)))
2320 (with-syntax-table antlr-action-syntax-table 2959 (let ((context (antlr-syntactic-context)))
2321 (antlr-invalidate-context-cache) 2960 (and context
2322 (let ((context (antlr-syntactic-context))) 2961 (not (and (numberp context)
2323 (not (and (numberp context) 2962 (memq last-command-event '(?\{ ?\})))))))
2324 (or (zerop context)
2325 (memq last-command-event '(?\{ ?\}))))))))
2326 (self-insert-command (prefix-numeric-value arg)) 2963 (self-insert-command (prefix-numeric-value arg))
2327 (self-insert-command (prefix-numeric-value arg)) 2964 (self-insert-command (prefix-numeric-value arg))
2328 (antlr-indent-line))) 2965 (antlr-indent-line)))
2329 2966
2967(defun antlr-insert-keyword-rule (&optional keyword)
2968 "Insert token rule for an case-insensitive keyword KEYWORD at point."
2969 (interactive "sKeyword: ")
2970 ;; Should be probably made a bit customizable...
2971 (insert (upcase keyword) " : "
2972 (mapconcat (lambda (c)
2973 (let ((d (downcase c)) (u (upcase c)))
2974 (cond ((eq d u) (string ?\' c ?\'))
2975 ((eq antlr-tool-version 'antlr-v4)
2976 (string ?\[ d u ?\]))
2977 (t (string ?\( ?\' d ?\' ?| ?\' u ?\' ?\))))))
2978 keyword "")
2979 " ;\n"))
2980
2330 2981
2331;;;=========================================================================== 2982;;;===========================================================================
2332;;; Mode entry 2983;;; Mode entry
2333;;;=========================================================================== 2984;;;===========================================================================
2334 2985
2335(defun antlr-c-init-language-vars () 2986(defun antlr-guess-language ()
2336 "Like `c-init-language-vars-for' when using cc-mode before v5.29." 2987 "Find language in `antlr-language-list' for language option.
2337 (let ((settings ; (cdr '(setq...)) will be optimized 2988If not found, use the default, which is the first element."
2338 (if (eq antlr-language 'c++-mode) 2989 ;; TODO: think about save-restriction & widen
2339 (cdr '(setq ;' from `c++-mode' v5.20, v5.28 2990 (save-excursion
2340 c-keywords (c-identifier-re c-C++-keywords) 2991 (goto-char (point-min))
2341 c-conditional-key c-C++-conditional-key 2992 (when (re-search-forward (cdr antlr-language-limit-n-regexp)
2342 c-comment-start-regexp c-C++-comment-start-regexp 2993 (+ (point)
2343 c-class-key c-C++-class-key 2994 (car antlr-language-limit-n-regexp))
2344 c-extra-toplevel-key c-C++-extra-toplevel-key 2995 t)
2345 c-access-key c-C++-access-key 2996 (car (cl-find (match-string-no-properties 1) antlr-language-list
2346 c-recognize-knr-p nil 2997 :key 'cdr :test 'member)))))
2347 c-bitfield-key c-C-bitfield-key ; v5.28 2998
2348 )) 2999(defun antlr-guess-tool-version ()
2349 (cdr '(setq ; from `java-mode' v5.20, v5.28 3000 "Guess whether current grammar is for ANTLR v2 or v3.
2350 c-keywords (c-identifier-re c-Java-keywords) 3001By default, we assume v3. Only if we find a keyword 'class' or
2351 c-conditional-key c-Java-conditional-key 3002'header' at the beginning of a line before any 'grammar' keyword,
2352 c-comment-start-regexp c-Java-comment-start-regexp 3003we assume v2."
2353 c-class-key c-Java-class-key 3004 (save-excursion
2354 c-method-key nil 3005 (goto-char (point-min))
2355 c-baseclass-key nil 3006 (if (and (antlr-re-search-forward "^\\(lexer[ \t]+grammar\\|parser[ \t]+grammar\\|tree[ \t]+grammar\\|grammar\\|\\(class\\|header\\)\\)\\_>" (+ (point) (car antlr-language-limit-n-regexp)))
2356 c-recognize-knr-p nil 3007 (match-beginning 2)) ; class or header
2357 c-access-key c-Java-access-key ; v5.20 3008 'antlr-v2
2358 c-inexpr-class-key c-Java-inexpr-class-key ; v5.28 3009 'antlr-v3)))
2359 ))))) 3010
2360 (while settings 3011(defun antlr-skip-import-statement ()
2361 (when (boundp (car settings)) 3012 "Skip whitespaces, comments and special declarations after the header.
2362 (ignore-errors 3013See `antlr-skip-line-regexp', which skips the 'scope' declaration in
2363 (set (car settings) (eval (cadr settings) t)))) 3014ANTLR v3, and the 'import' declaration in ANTLR v4."
2364 (setq settings (cddr settings))))) 3015 (if (not (and antlr-skip-line-regexp (looking-at antlr-skip-line-regexp)))
2365 3016 (antlr-skip-sexps 1)
2366(defun antlr-language-option (search) 3017 (goto-char (match-end 0))
2367 "Find language in `antlr-language-alist' for language option. 3018 (prog1 (point)
2368If SEARCH is non-nil, find element for language option. Otherwise, find 3019 (antlr-c-forward-sws))))
2369the default language." 3020
2370 (let ((value 3021(defun antlr-set-local-variables (selector-symbol selector variables)
2371 (and search 3022 ;; checkdoc-order: nil
2372 (save-excursion 3023 "Set SELECTOR dependent local variables for VARIABLES.
2373 (goto-char (point-min)) 3024Also set SELECTOR-SYMBOL to SELECTOR.
2374 (re-search-forward (cdr antlr-language-limit-n-regexp) 3025See `antlr-tool-version-variables' and `antlr-language-variables'."
2375 (+ (point) 3026 (unless (symbolp selector)
2376 (car antlr-language-limit-n-regexp)) 3027 (error "Illegal selector %s" selector))
2377 t)) 3028 (let ((required t) (prefix (symbol-name selector)))
2378 (match-string 1))) 3029 (dolist (var variables)
2379 (seq antlr-language-alist) 3030 (if (eq var '&optional)
2380 r) 3031 (setq required nil)
2381 ;; Like (find VALUE antlr-language-alist :key 'cddr :test 'member) 3032 (let ((name (symbol-name var)))
2382 (while seq 3033 (unless (and (string-match "\\`antlr-" name) (boundp var))
2383 (setq r (pop seq)) 3034 (error "Illegal element %s" var))
2384 (if (member value (cddr r)) 3035 (let ((valsym (intern (concat prefix (substring name 5)))))
2385 (setq seq nil) ; stop 3036 (when (or (boundp valsym) required)
2386 (setq r nil))) ; no result yet 3037 (set (make-local-variable var) (symbol-value valsym)))))))
2387 (car r))) 3038 (set (make-local-variable selector-symbol) selector)
3039 nil))
3040
3041;; I would have guessed that there is a possibility to run code at the end of
3042;; initializing a major mode which is definitely run at the end (with or
3043;; without local variables enabled). That is not the case... (only hard-coded
3044;; for font-lock). Hence, we run some code twice with local variables...
3045
3046(defun antlr-hack-local-variables-hook ()
3047 "Late setup for buffers with a local variables spec.
3048This function is used in `hack-local-variables-hook'."
3049 (and (derived-mode-p 'antlr-mode)
3050 (or (assq 'antlr-tool-version file-local-variables-alist)
3051 (assq 'antlr-language file-local-variables-alist))
3052 (antlr-set-tool-version-and-mode-line)))
3053
3054(add-hook 'hack-local-variables-hook 'antlr-hack-local-variables-hook)
3055
3056(defun antlr-set-tool-version-and-mode-line ()
3057 "Late setup for `antlr-mode' and sub modes."
3058 ;; tool and language version and dependent variables -----------------------
3059 (let ((guess (if (local-variable-p 'antlr-tool-version)
3060 ;; backward-compatibility:
3061 (if (numberp antlr-tool-version) 'antlr-v2 antlr-tool-version)
3062 (antlr-guess-tool-version))))
3063 (when (with-demoted-errors "File mode error for `antlr-tool-version': %s"
3064 (antlr-set-local-variables 'antlr-tool-version guess
3065 antlr-tool-version-variables))
3066 (antlr-set-local-variables 'antlr-tool-version 'antlr-v3
3067 antlr-tool-version-variables)))
3068 (let ((guess (if (local-variable-p 'antlr-language)
3069 (or (cdr (assq antlr-language ; backward compatibility
3070 '((java-mode . antlr-java) (c++-mode . antlr-cpp))))
3071 antlr-language)
3072 (antlr-guess-language))))
3073 (when (with-demoted-errors "File mode error for `antlr-language': %s"
3074 (antlr-set-local-variables 'antlr-language
3075 (or guess (caar antlr-language-list))
3076 antlr-language-variables))
3077 (antlr-set-local-variables 'antlr-language 'antlr-java
3078 antlr-language-variables)))
3079 ;; language-dependent initializations --------------------------------------
3080 (c-init-language-vars-for antlr-init-cc-mode)
3081 (c-basic-common-init antlr-init-cc-mode ; sets `indent-line-function' etc
3082 (or antlr-indent-style "gnu"))
3083 (funcall antlr-init-submode)
3084 (set (make-local-variable 'indent-line-function) #'antlr-indent-line)
3085 (set (make-local-variable 'indent-region-function) nil) ; TODO
3086 ;; syntax-propertize -------------------------------------------------------
3087 (when antlr-syntax-propertize
3088 (setq-local syntax-propertize-function (car antlr-syntax-propertize))
3089 (unless (eq (cadr antlr-syntax-propertize) t)
3090 (if (functionp (cadr antlr-syntax-propertize))
3091 (add-hook 'syntax-propertize-extend-region-functions
3092 (cadr antlr-syntax-propertize) 'append 'local)
3093 (setq-local syntax-propertize-extend-region-functions
3094 (cadr antlr-syntax-propertize))))
3095 (when (nth 2 antlr-syntax-propertize)
3096 (setq-local c-multiline-string-start-char
3097 (if c-multiline-string-start-char t
3098 (nth 2 antlr-syntax-propertize))))
3099 (when antlr-do-syntax-propertize ; at least for imenu in Emacs-24.5
3100 (syntax-propertize (point-max))))
3101 ;; Before I had moved `imenu-add-to-menubar' from function `antlr-mode', it
3102 ;; had already scanned the buffer before I have set `antlr-tool-version' here
3103 ;; (variables which depend on it). Thus, I move the imenu function to this
3104 ;; function, too... (do we need to explicitly call `imenu-update-menubar' to
3105 ;; be on the safe side?)
3106 (and antlr-imenu-name ; there should be a global variable...
3107 (fboundp 'imenu-add-to-menubar)
3108 (imenu-add-to-menubar
3109 (if (stringp antlr-imenu-name) antlr-imenu-name "Index")))
3110 (setq mode-name ; TODO: or use ("" ...)?
3111 (concat antlr-tool-mode-name "." antlr-language-mode-name)))
3112
3113
3114(defvar antlr-delayed-mode-hook '(antlr-set-tool-version-and-mode-line)
3115 "Hook run after entering Antlr mode or a derived mode.")
2388 3116
2389;;;###autoload 3117;;;###autoload
2390(define-derived-mode antlr-mode prog-mode 3118(define-derived-mode antlr-mode prog-mode
2391 ;; FIXME: Since it uses cc-mode, it bumps into c-update-modeline's
2392 ;; limitation to mode-name being a string.
2393 ;; '("Antlr." (:eval (cadr (assq antlr-language antlr-language-alist))))
2394 "Antlr" 3119 "Antlr"
2395 "Major mode for editing ANTLR grammar files." 3120 "Major mode for editing ANTLR grammar files."
2396 :abbrev-table antlr-mode-abbrev-table 3121 :abbrev-table antlr-mode-abbrev-table
2397 (c-initialize-cc-mode) ; cc-mode is required 3122 (c-initialize-cc-mode) ; cc-mode is required
2398 (unless (fboundp 'c-forward-sws) ; see above 3123 (set (make-local-variable 'require-final-newline) mode-require-final-newline)
2399 (fset 'antlr-c-forward-sws 'c-forward-syntactic-ws))
2400 ;; ANTLR specific ----------------------------------------------------------
2401 (unless antlr-language
2402 (set (make-local-variable 'antlr-language)
2403 (or (antlr-language-option t) (antlr-language-option nil))))
2404 (if (stringp (cadr (assq antlr-language antlr-language-alist)))
2405 (setq mode-name
2406 (concat "Antlr."
2407 (cadr (assq antlr-language antlr-language-alist)))))
2408 ;; indentation, for the C engine -------------------------------------------
2409 (setq c-buffer-is-cc-mode antlr-language)
2410 (c-init-language-vars-for antlr-language)
2411 (c-basic-common-init antlr-language (or antlr-indent-style "gnu"))
2412 (set (make-local-variable 'outline-regexp) "[^#\n\^M]") 3124 (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
2413 (set (make-local-variable 'outline-level) #'c-outline-level) ;TODO: define own 3125 (set (make-local-variable 'outline-level) #'c-outline-level) ;TODO: define own
2414 (set (make-local-variable 'indent-line-function) #'antlr-indent-line)
2415 (set (make-local-variable 'indent-region-function) nil) ; too lazy
2416 (setq comment-start "// " 3126 (setq comment-start "// "
2417 comment-end "" 3127 comment-end ""
2418 comment-start-skip "/\\*+ *\\|// *") 3128 comment-start-skip "/\\*+ *\\|//+ *")
2419 ;; various ----------------------------------------------------------------- 3129 ;; various -----------------------------------------------------------------
2420 (set (make-local-variable 'font-lock-defaults) antlr-font-lock-defaults) 3130 (set (make-local-variable 'font-lock-defaults) antlr-font-lock-defaults)
2421 (set (make-local-variable 'imenu-create-index-function) 3131 (set (make-local-variable 'imenu-create-index-function)
2422 #'antlr-imenu-create-index-function) 3132 #'antlr-imenu-create-index-function)
2423 (set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test 3133 (set (make-local-variable 'imenu-generic-expression) t) ; fool stupid test
2424 (and antlr-imenu-name ; there should be a global variable... 3134 (easy-menu-add antlr-mode-menu)
2425 (imenu-add-to-menubar 3135 (run-mode-hooks 'antlr-delayed-mode-hook))
2426 (if (stringp antlr-imenu-name) antlr-imenu-name "Index")))
2427 (antlr-set-tabs))
2428 3136
2429;; A smarter version of `group-buffers-menu-by-mode-then-alphabetically' (in 3137;; A smarter version of `group-buffers-menu-by-mode-then-alphabetically' (in
2430;; XEmacs) could use the following property. The header of the submenu would 3138;; XEmacs) could use the following property. The header of the submenu would
@@ -2432,9 +3140,18 @@ the default language."
2432(put 'antlr-mode 'mode-name "Antlr") 3140(put 'antlr-mode 'mode-name "Antlr")
2433 3141
2434;;;###autoload 3142;;;###autoload
3143(define-derived-mode antlr-v4-mode antlr-mode
3144 "Antlr" ; use this in the menubar, see below for the mode line
3145 "Major mode for editing ANTLR v4 grammar files."
3146 :syntax-table nil
3147 :abbrev-table nil
3148 (set (make-local-variable 'antlr-tool-version) 'antlr-v4))
3149
3150;;;###autoload
2435(defun antlr-set-tabs () 3151(defun antlr-set-tabs ()
2436 "Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'. 3152 "Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'.
2437Used in `antlr-mode'. Also a useful function in `java-mode-hook'." 3153Used in `antlr-mode' for cc-mode-based languages.
3154It is probably better to automatically deduce the TAB setting."
2438 (if buffer-file-name 3155 (if buffer-file-name
2439 (let ((alist antlr-tab-offset-alist) elem) 3156 (let ((alist antlr-tab-offset-alist) elem)
2440 (while alist 3157 (while alist
@@ -2442,12 +3159,237 @@ Used in `antlr-mode'. Also a useful function in `java-mode-hook'."
2442 (and (or (null (car elem)) (eq (car elem) major-mode)) 3159 (and (or (null (car elem)) (eq (car elem) major-mode))
2443 (or (null (cadr elem)) 3160 (or (null (cadr elem))
2444 (string-match (cadr elem) buffer-file-name)) 3161 (string-match (cadr elem) buffer-file-name))
2445 (setq tab-width (caddr elem) 3162 (setq tab-width (cl-caddr elem)
2446 indent-tabs-mode (cadddr elem) 3163 indent-tabs-mode (cl-cadddr elem)
2447 alist nil)))))) 3164 alist nil))))))
2448 3165
2449(provide 'antlr-mode)
2450 3166
2451;; Local IspellPersDict: .ispell_antlr 3167;;;===========================================================================
3168;;; CC-mode languages
3169;;;===========================================================================
3170
3171(defvar antlr-c-language-mode-name "C"
3172 "Value for `antlr-language-mode-name' when using language `antlr-c'.")
3173(defvar antlr-cpp-language-mode-name "Cpp"
3174 "Value for `antlr-language-mode-name' when using language `antlr-cpp'.")
3175(defvar antlr-objc-language-mode-name "ObjC"
3176 "Value for `antlr-language-mode-name' when using language `antlr-objc'.")
3177
3178(defvar antlr-c-action-mode 'c-mode
3179 "Value for `antlr-action-mode' when using language `antlr-c'.")
3180(defvar antlr-cpp-action-mode 'c++-mode
3181 "Value for `antlr-action-mode' when using language `antlr-cpp'.")
3182(defvar antlr-objc-action-mode 'objc-mode
3183 "Value for `antlr-action-mode' when using language `antlr-objc'.")
3184
3185(defvar antlr-c-init-cc-mode 'c-mode
3186 "Value for `antlr-init-cc-mode' when using language `antlr-c'.")
3187(defvar antlr-cpp-init-cc-mode 'c++-mode
3188 "Value for `antlr-init-cc-mode' when using language `antlr-cpp'.")
3189(defvar antlr-obj-init-cc-mode 'objc-mode
3190 "Value for `antlr-init-cc-mode' when using language `antlr-objc'.")
3191
3192(defvar antlr-c-action-font-lock-keywords
3193 '(antlr-no-action-keywords
3194 c-font-lock-keywords-1 c-font-lock-keywords-2
3195 c-font-lock-keywords-3)
3196 "Value for `antlr-action-font-lock-keywords' when using language `antlr-c'.")
3197(defvar antlr-cpp-action-font-lock-keywords
3198 '(antlr-no-action-keywords
3199 c++-font-lock-keywords-1 c++-font-lock-keywords-2
3200 c++-font-lock-keywords-3)
3201 "Value for `antlr-action-font-lock-keywords' when using language `antlr-cpp'.")
3202(defvar antlr-objc-action-font-lock-keywords
3203 '(antlr-no-action-keywords
3204 objc-font-lock-keywords-1 objc-font-lock-keywords-2
3205 objc-font-lock-keywords-3)
3206 "Value for `antlr-action-font-lock-keywords' when using language `antlr-objc'.")
3207
3208
3209;;;===========================================================================
3210;;; JavaScript
3211;;;===========================================================================
3212
3213(declare-function js-indent-line "js")
3214;; TODO: better support for js2-mode?
3215
3216(defvar antlr-js-language-mode-name "Js"
3217 "Value for `antlr-language-mode-name' when using language `antlr-js'.")
3218
3219(defvar antlr-js-action-mode 'js-mode
3220 "Value for `antlr-action-mode' when using language `antlr-js'.")
3221
3222(defvar antlr-js-init-submode 'antlr-init-js
3223 "Value for `antlr-init-submode' when using language `antlr-js'.")
3224
3225(defvar antlr-js-action-font-lock-keywords
3226 '(antlr-no-action-keywords
3227 ;; do not use `js--font-lock-keywords-3' !
3228 js--font-lock-keywords-1 js--font-lock-keywords-2)
3229 "Value for `antlr-action-font-lock-keywords' when using language `antlr-js'.")
2452 3230
3231(defvar antlr-js-indent-action-line 'antlr-js-indent-action-line
3232 "Value for `antlr-indent-action-line' when using language `antlr-js'.")
3233
3234(defun antlr-init-js ()
3235 "Initialize action language `antlr-js'."
3236 (require 'js))
3237
3238(defun antlr-js-indent-action-line (_boa)
3239 "Indent the current line in an JavaScript action."
3240 (js-indent-line))
3241
3242
3243;;;===========================================================================
3244;;; Delphi (opascal)
3245;;;===========================================================================
3246
3247(declare-function opascal-indent-line "opascal")
3248(defvar opascal-compound-block-indent)
3249(defvar opascal-indent-level)
3250(defvar opascal-case-label-indent)
3251
3252(defvar antlr-delphi-language-mode-name "Delphi"
3253 "Value for `antlr-language-mode-name' when using language `antlr-delphi'.")
3254
3255(defvar antlr-delphi-action-mode 'opascal-mode
3256 "Value for `antlr-action-mode' when using language `antlr-delphi'.")
3257
3258(defvar antlr-delphi-init-submode 'antlr-init-delphi
3259 "Value for `antlr-init-submode' when using language `antlr-delphi'.")
3260
3261(defvar antlr-delphi-action-font-lock-keywords
3262 '(antlr-no-action-keywords
3263 opascal-font-lock-keywords)
3264 "Value for `antlr-action-font-lock-keywords' when using language `antlr-delphi'.")
3265
3266(defvar antlr-delphi-indent-action-line 'antlr-delphi-indent-action-line
3267 "Value for `antlr-indent-action-line' when using language `antlr-delphi'.")
3268
3269(defun antlr-init-delphi ()
3270 "Initialize action language `antlr-delphi'."
3271 (require 'opascal)
3272 (when (integerp c-basic-offset)
3273 (when (equal opascal-compound-block-indent opascal-indent-level)
3274 (setq-local opascal-compound-block-indent c-basic-offset))
3275 (when (equal opascal-case-label-indent opascal-indent-level)
3276 (setq-local opascal-case-label-indent c-basic-offset))
3277 (setq-local opascal-indent-level c-basic-offset)))
3278
3279(defun antlr-delphi-indent-action-line (boa)
3280 "Indent the current line in a Delphi (opascal) action.
3281Argument BOA is the start position of the action."
3282 (narrow-to-region (1+ boa) (point-at-eol))
3283 ;; make Pascal mode only checks the code fragment after the opening brace,
3284 ;; otherwise its indentation gets confused as {...} are block comments
3285 (opascal-indent-line)
3286 ;; or use low-level `opascal-corrected-indentation' - but that does not have
3287 ;; a docstring, i.e. not really official ?
3288 (widen)
3289 (unless (memq (char-after (point-at-bol)) '(?\ ?\t))
3290 ;; no indentation -> considered top-level -> indentation can also be
3291 ;; performed by c-mode
3292 (c-indent-line)))
3293
3294
3295;;;===========================================================================
3296;;; Ruby
3297;;;===========================================================================
3298
3299(declare-function ruby-indent-line "ruby-mode")
3300(defvar ruby-indent-level)
3301(defvar ruby-use-smie)
3302
3303(defvar antlr-ruby-language-mode-name "Ruby"
3304 "Value for `antlr-language-mode-name' when using language `antlr-ruby'.")
3305
3306(defvar antlr-ruby-action-mode 'ruby-mode
3307 "Value for `antlr-action-mode' when using language `antlr-ruby'.")
3308
3309(defvar antlr-ruby-init-submode 'antlr-init-ruby
3310 "Value for `antlr-init-submode' when using language `antlr-ruby'.")
3311
3312(defvar antlr-ruby-action-font-lock-keywords
3313 '(antlr-no-action-keywords
3314 ruby-font-lock-keywords)
3315 "Value for `antlr-action-font-lock-keywords' when using language `antlr-ruby'.")
3316
3317(defvar antlr-ruby-indent-action-line 'antlr-ruby-indent-action-line
3318 "Value for `antlr-indent-action-line' when using language `antlr-ruby'.")
3319
3320(defun antlr-init-ruby ()
3321 "Initialize action language `antlr-ruby'."
3322 (require 'ruby-mode)
3323 (setq-local ruby-indent-level c-basic-offset)
3324 ;; Disable smie as long as we do not have a function for a part of
3325 ;; `ruby-mode-variables'
3326 (setq-local ruby-use-smie nil))
3327
3328(defun antlr-ruby-indent-action-line (boa)
3329 "Indent the current line in a Ruby action.
3330Argument BOA is the start position of the action."
3331 (narrow-to-region (1+ boa) (point-at-eol))
3332 (ruby-indent-line)
3333 (widen)
3334 (unless (memq (char-after (point-at-bol)) '(?\ ?\t))
3335 ;; no indentation -> considered top-level -> indentation can also be
3336 ;; performed by cc-mode
3337 (c-indent-line)))
3338
3339
3340;;;===========================================================================
3341;;; Python
3342;;;===========================================================================
3343
3344(declare-function python-indent-line "python")
3345(defvar prog-indentation-context)
3346
3347(defvar antlr-python-language-mode-name "Python"
3348 "Value for `antlr-language-mode-name' when using language `antlr-python'.")
3349
3350(defvar antlr-python-action-mode 'python-mode
3351 "Value for `antlr-action-mode' when using language `antlr-python'.")
3352
3353(defvar antlr-python-init-submode 'antlr-init-python
3354 "Value for `antlr-init-submode' when using language `antlr-python'.")
3355
3356(defvar antlr-python-action-font-lock-keywords
3357 '(antlr-no-action-keywords
3358 python-font-lock-keywords)
3359 "Value for `antlr-action-font-lock-keywords' when using language `antlr-python'.")
3360
3361(defvar antlr-python-indent-action-line 'antlr-python-indent-action-line
3362 "Value for `antlr-indent-action-line' when using language `antlr-python'.")
3363
3364(defun antlr-init-python ()
3365 "Initialize action language `antlr-python'."
3366 (require 'python))
3367
3368(defun antlr-python-indent-action-line (boa)
3369 "Indent the current line in a Python action.
3370Argument BOA is the start position of the action."
3371 (let (leftouter)
3372 (save-excursion
3373 (goto-char boa)
3374 (setq leftouter (current-indentation))
3375 (forward-char)
3376 (skip-chars-forward " \t")
3377 (setq boa (and (eq (char-after) ?\n) (point))))
3378 ;; a multi-line Python action does not start in its own line: this is a bad
3379 ;; idea -> we do not touch those actions
3380 (when (and boa
3381 (eq antlr-indent-comment t) ; indent-region
3382 (boundp 'prog-indentation-context)) ; Emacs 24.5 or later
3383 (let ((syntax-ppss-cache nil) ;#dynamic, in older Emacs...
3384 (syntax-ppss-last nil) ;#dynamic, in older Emacs...
3385 ;; TODO: do we also need to call `syntax-propertize' or
3386 ;; `syntax-ppss-flush-cache'? and/or bind
3387 ;; `syntax-propertize-function'?
3388 (prog-indentation-context ;#dynamic
3389 (list (+ leftouter c-basic-offset) (list (1+ boa)))))
3390 (narrow-to-region (1+ boa) (point-max))
3391 (python-indent-line (eq this-command 'antlr-indent-command))))))
3392
3393
3394(provide 'antlr-mode)
2453;;; antlr-mode.el ends here 3395;;; antlr-mode.el ends here