diff options
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 23 | ||||
| -rw-r--r-- | lisp/cedet/cedet.el | 4 | ||||
| -rw-r--r-- | lisp/cedet/ede.el | 12 | ||||
| -rw-r--r-- | lisp/cedet/ede/proj-elisp.el | 2 | ||||
| -rw-r--r-- | lisp/cedet/ede/system.el | 8 | ||||
| -rw-r--r-- | lisp/cedet/semantic.el | 54 | ||||
| -rw-r--r-- | lisp/cedet/semantic/db-mode.el | 67 | ||||
| -rw-r--r-- | lisp/cedet/semantic/ede-grammar.el | 202 | ||||
| -rw-r--r-- | lisp/cedet/semantic/grammar-wy.el | 478 | ||||
| -rw-r--r-- | lisp/cedet/semantic/grammar.el | 1912 |
10 files changed, 2674 insertions, 88 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 43f36484ab8..0739e79cf7a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,28 @@ | |||
| 1 | 2009-09-27 Chong Yidong <cyd@stupidchicken.com> | 1 | 2009-09-27 Chong Yidong <cyd@stupidchicken.com> |
| 2 | 2 | ||
| 3 | * cedet/ede/system.el (ede-upload-html-documentation) | ||
| 4 | (ede-upload-distribution, ede-edit-web-page) | ||
| 5 | (ede-web-browse-home): Autoload. | ||
| 6 | |||
| 7 | * cedet/ede/proj-elisp.el: Add autoload for | ||
| 8 | semantic-ede-proj-target-grammar. | ||
| 9 | |||
| 10 | * cedet/semantic.el (navigate-menu): Show menu items only if | ||
| 11 | semantic-mode is enabled. | ||
| 12 | |||
| 13 | * cedet/ede.el: Remove comments. | ||
| 14 | |||
| 15 | * cedet/cedet.el (cedet-menu-map): Minor doc fix. | ||
| 16 | |||
| 17 | * cedet/semantic/grammar.el: | ||
| 18 | * cedet/semantic/grammar-wy.el: | ||
| 19 | * cedet/semantic/ede-grammar.el: New files. | ||
| 20 | |||
| 21 | * cedet/semantic/db-mode.el (global-semanticdb-minor-mode): Define | ||
| 22 | using define-minor-mode, so that the usual mode variable exists. | ||
| 23 | |||
| 24 | 2009-09-27 Chong Yidong <cyd@stupidchicken.com> | ||
| 25 | |||
| 3 | * cedet/ede.el (global-ede-mode-map): Move menu to | 26 | * cedet/ede.el (global-ede-mode-map): Move menu to |
| 4 | global-ede-mode-map. | 27 | global-ede-mode-map. |
| 5 | (ede-minor-mode, global-ede-mode): Use define-minor-mode. | 28 | (ede-minor-mode, global-ede-mode): Use define-minor-mode. |
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el index 8dcbfd6a414..c98dc9b8893 100644 --- a/lisp/cedet/cedet.el +++ b/lisp/cedet/cedet.el | |||
| @@ -65,12 +65,12 @@ | |||
| 65 | (define-key map [global-semantic-idle-scheduler-mode] 'undefined) | 65 | (define-key map [global-semantic-idle-scheduler-mode] 'undefined) |
| 66 | (define-key map [semantic-menu-separator] '("--")) | 66 | (define-key map [semantic-menu-separator] '("--")) |
| 67 | (define-key map [semantic-mode] | 67 | (define-key map [semantic-mode] |
| 68 | '(menu-item "Enable parsers (Semantic)" semantic-mode | 68 | '(menu-item "Enable Parsers (Semantic)" semantic-mode |
| 69 | :help "Enable language parsers (Semantic)" | 69 | :help "Enable language parsers (Semantic)" |
| 70 | :visible (not (bound-and-true-p semantic-mode)))) | 70 | :visible (not (bound-and-true-p semantic-mode)))) |
| 71 | (define-key map [cedet-menu-separator] 'undefined) | 71 | (define-key map [cedet-menu-separator] 'undefined) |
| 72 | (define-key map [ede-mode] | 72 | (define-key map [ede-mode] |
| 73 | '(menu-item "Enable Projects (EDE)" global-ede-mode | 73 | '(menu-item "Enable Project Support (EDE)" global-ede-mode |
| 74 | :help "Enable the Emacs Development Environment (EDE)" | 74 | :help "Enable the Emacs Development Environment (EDE)" |
| 75 | :visible (not (bound-and-true-p global-ede-mode)))) | 75 | :visible (not (bound-and-true-p global-ede-mode)))) |
| 76 | (define-key map [ede-menu-separator] '("--")) | 76 | (define-key map [ede-menu-separator] '("--")) |
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el index 8240961c257..65da831660e 100644 --- a/lisp/cedet/ede.el +++ b/lisp/cedet/ede.el | |||
| @@ -1981,18 +1981,6 @@ Display the results as a debug list." | |||
| 1981 | ;; (def-edebug-spec ede-with-projectfile | 1981 | ;; (def-edebug-spec ede-with-projectfile |
| 1982 | ;; (form def-body)))) | 1982 | ;; (form def-body)))) |
| 1983 | 1983 | ||
| 1984 | ;; (autoload 'ede-web-browse-home "ede-system" t | ||
| 1985 | ;; "Web browse this project's home page.") | ||
| 1986 | |||
| 1987 | ;; (autoload 'ede-edit-web-page "ede-system" t | ||
| 1988 | ;; "Edit the web site for this project.") | ||
| 1989 | |||
| 1990 | ;; (autoload 'ede-upload-distribution "ede-system" t | ||
| 1991 | ;; "Upload the dist for this project to the upload site.") | ||
| 1992 | |||
| 1993 | ;; (autoload 'ede-upload-html-documentation "ede-system" t | ||
| 1994 | ;; "Upload auto-generated HTML to the web site.") | ||
| 1995 | |||
| 1996 | (provide 'ede) | 1984 | (provide 'ede) |
| 1997 | 1985 | ||
| 1998 | ;; Include this last because it depends on ede. | 1986 | ;; Include this last because it depends on ede. |
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el index 068daae44de..1838bad00e0 100644 --- a/lisp/cedet/ede/proj-elisp.el +++ b/lisp/cedet/ede/proj-elisp.el | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | (require 'ede/pmake) | 29 | (require 'ede/pmake) |
| 30 | (require 'ede/pconf) | 30 | (require 'ede/pconf) |
| 31 | 31 | ||
| 32 | (autoload 'semantic-ede-proj-target-grammar "semantic/ede-grammar") | ||
| 33 | |||
| 32 | ;;; Code: | 34 | ;;; Code: |
| 33 | (defclass ede-proj-target-elisp (ede-proj-target-makefile) | 35 | (defclass ede-proj-target-elisp (ede-proj-target-makefile) |
| 34 | ((menu :initform nil) | 36 | ((menu :initform nil) |
diff --git a/lisp/cedet/ede/system.el b/lisp/cedet/ede/system.el index ad917cf6b1b..db2b9a2c9a4 100644 --- a/lisp/cedet/ede/system.el +++ b/lisp/cedet/ede/system.el | |||
| @@ -31,7 +31,8 @@ | |||
| 31 | ;;; Code: | 31 | ;;; Code: |
| 32 | 32 | ||
| 33 | ;;; Web/FTP site node. | 33 | ;;; Web/FTP site node. |
| 34 | ;; | 34 | |
| 35 | ;;;###autoload | ||
| 35 | (defun ede-web-browse-home () | 36 | (defun ede-web-browse-home () |
| 36 | "Browse the home page of the current project." | 37 | "Browse the home page of the current project." |
| 37 | (interactive) | 38 | (interactive) |
| @@ -44,7 +45,7 @@ | |||
| 44 | (browse-url home) | 45 | (browse-url home) |
| 45 | )) | 46 | )) |
| 46 | 47 | ||
| 47 | 48 | ;;;###autoload | |
| 48 | (defun ede-edit-web-page () | 49 | (defun ede-edit-web-page () |
| 49 | "Edit the web site for this project." | 50 | "Edit the web site for this project." |
| 50 | (interactive) | 51 | (interactive) |
| @@ -62,7 +63,7 @@ | |||
| 62 | (error "No project file found"))) | 63 | (error "No project file found"))) |
| 63 | (find-file endfile))) | 64 | (find-file endfile))) |
| 64 | 65 | ||
| 65 | 66 | ;;;###autoload | |
| 66 | (defun ede-upload-distribution () | 67 | (defun ede-upload-distribution () |
| 67 | "Upload the current distribution to the correct location. | 68 | "Upload the current distribution to the correct location. |
| 68 | Use /user@ftp.site.com: file names for FTP sites. | 69 | Use /user@ftp.site.com: file names for FTP sites. |
| @@ -95,6 +96,7 @@ Download tramp, and use /r:machine: for names on remote sites w/out FTP access." | |||
| 95 | (message "Done uploading files...") | 96 | (message "Done uploading files...") |
| 96 | ) | 97 | ) |
| 97 | 98 | ||
| 99 | ;;;###autoload | ||
| 98 | (defun ede-upload-html-documentation () | 100 | (defun ede-upload-html-documentation () |
| 99 | "Upload the current distributions documentation as HTML. | 101 | "Upload the current distributions documentation as HTML. |
| 100 | Use /user@ftp.site.com: file names for FTP sites. | 102 | Use /user@ftp.site.com: file names for FTP sites. |
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el index 81214b4b63f..dfed8a8c194 100644 --- a/lisp/cedet/semantic.el +++ b/lisp/cedet/semantic.el | |||
| @@ -934,42 +934,47 @@ Throw away all the old tags, and recreate the tag database." | |||
| 934 | ;; Top level menu items: | 934 | ;; Top level menu items: |
| 935 | (define-key cedet-menu-map [semantic-force-refresh] | 935 | (define-key cedet-menu-map [semantic-force-refresh] |
| 936 | '(menu-item "Reparse Buffer" semantic-force-refresh | 936 | '(menu-item "Reparse Buffer" semantic-force-refresh |
| 937 | :help "Force a full reparse of the current buffer.")) | 937 | :help "Force a full reparse of the current buffer." |
| 938 | :visible semantic-mode)) | ||
| 938 | (define-key cedet-menu-map [semantic-edit-menu] | 939 | (define-key cedet-menu-map [semantic-edit-menu] |
| 939 | (cons "Edit Tags" edit-menu)) | 940 | `(menu-item "Edit Tags" ,edit-menu |
| 941 | :visible semantic-mode)) | ||
| 940 | (define-key cedet-menu-map [navigate-menu] | 942 | (define-key cedet-menu-map [navigate-menu] |
| 941 | (cons "Navigate Tags" navigate-menu)) | 943 | `(menu-item "Navigate Tags" ,navigate-menu |
| 944 | :visible semantic-mode)) | ||
| 942 | (define-key cedet-menu-map [semantic-options-separator] | 945 | (define-key cedet-menu-map [semantic-options-separator] |
| 943 | '("--")) | 946 | '("--")) |
| 944 | (define-key cedet-menu-map [global-semantic-highlight-func-mode] | 947 | (define-key cedet-menu-map [global-semantic-highlight-func-mode] |
| 945 | (menu-bar-make-mm-toggle | 948 | '(menu-item "Highlight Current Function" global-semantic-highlight-func-mode |
| 946 | global-semantic-highlight-func-mode | 949 | :help "Highlight the tag at point" |
| 947 | "Highlight Current Function" | 950 | :visible semantic-mode |
| 948 | "Highlight the tag at point")) | 951 | :button (:toggle . global-semantic-highlight-func-mode))) |
| 949 | (define-key cedet-menu-map [global-semantic-decoration-mode] | 952 | (define-key cedet-menu-map [global-semantic-decoration-mode] |
| 950 | (menu-bar-make-mm-toggle | 953 | '(menu-item "Decorate Tags" global-semantic-decoration-mode |
| 951 | global-semantic-decoration-mode | 954 | :help "Decorate tags based on tag attributes" |
| 952 | "Decorate Tags" | 955 | :visible semantic-mode |
| 953 | "Decorate tags based on various attributes")) | 956 | :button (:toggle . (bound-and-true-p |
| 957 | global-semantic-decoration-mode)))) | ||
| 954 | (define-key cedet-menu-map [global-semantic-idle-completions-mode] | 958 | (define-key cedet-menu-map [global-semantic-idle-completions-mode] |
| 955 | (menu-bar-make-mm-toggle | 959 | '(menu-item "Show Tag Completions" global-semantic-idle-completions-mode |
| 956 | global-semantic-idle-completions-mode | 960 | :help "Show tag completions when idle" |
| 957 | "Show Tag Completions" | 961 | :visible semantic-mode |
| 958 | "Show tag completions when idle")) | 962 | :button (:toggle . global-semantic-idle-completions-mode))) |
| 959 | (define-key cedet-menu-map [global-semantic-idle-summary-mode] | 963 | (define-key cedet-menu-map [global-semantic-idle-summary-mode] |
| 960 | (menu-bar-make-mm-toggle | 964 | '(menu-item "Show Tag Summaries" global-semantic-idle-summary-mode |
| 961 | global-semantic-idle-summary-mode | 965 | :help "Show tag summaries when idle" |
| 962 | "Show Tag Summaries" | 966 | :visible semantic-mode |
| 963 | "Show tag summaries when idle")) | 967 | :button (:toggle . global-semantic-idle-summary-mode))) |
| 964 | (define-key cedet-menu-map [global-semanticdb-minor-mode] | 968 | (define-key cedet-menu-map [global-semanticdb-minor-mode] |
| 965 | '(menu-item "Semantic Database" global-semanticdb-minor-mode | 969 | '(menu-item "Semantic Database" global-semanticdb-minor-mode |
| 966 | :help "Store tag information in a database" | 970 | :help "Store tag information in a database" |
| 967 | :button (:toggle . (semanticdb-minor-mode-p)))) | 971 | :visible semantic-mode |
| 972 | :button (:toggle . global-semanticdb-minor-mode))) | ||
| 968 | (define-key cedet-menu-map [global-semantic-idle-scheduler-mode] | 973 | (define-key cedet-menu-map [global-semantic-idle-scheduler-mode] |
| 969 | (menu-bar-make-mm-toggle | 974 | '(menu-item "Reparse When Idle" global-semantic-idle-scheduler-mode |
| 970 | global-semantic-idle-scheduler-mode | 975 | :help "Keep a buffer's parse tree up to date when idle" |
| 971 | "Reparse When Idle" | 976 | :visible semantic-mode |
| 972 | "Keep a buffer's parse tree up to date when idle")) | 977 | :button (:toggle . global-semantic-idle-scheduler-mode))) |
| 973 | (define-key cedet-menu-map [ede-menu-separator] 'undefined) | 978 | (define-key cedet-menu-map [ede-menu-separator] 'undefined) |
| 974 | (define-key cedet-menu-map [cedet-menu-separator] 'undefined) | 979 | (define-key cedet-menu-map [cedet-menu-separator] 'undefined) |
| 975 | (define-key cedet-menu-map [semantic-menu-separator] '("--"))) | 980 | (define-key cedet-menu-map [semantic-menu-separator] '("--"))) |
| @@ -1064,7 +1069,6 @@ Semantic mode. | |||
| 1064 | (remove-hook 'html-mode-hook 'semantic-default-html-setup) | 1069 | (remove-hook 'html-mode-hook 'semantic-default-html-setup) |
| 1065 | 1070 | ||
| 1066 | ;; FIXME: handle semanticdb-load-ebrowse-caches | 1071 | ;; FIXME: handle semanticdb-load-ebrowse-caches |
| 1067 | |||
| 1068 | (dolist (mode semantic-submode-list) | 1072 | (dolist (mode semantic-submode-list) |
| 1069 | (if (and (boundp mode) (eval mode)) | 1073 | (if (and (boundp mode) (eval mode)) |
| 1070 | (funcall mode -1))))) | 1074 | (funcall mode -1))))) |
diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el index 697a87dac13..ae612217232 100644 --- a/lisp/cedet/semantic/db-mode.el +++ b/lisp/cedet/semantic/db-mode.el | |||
| @@ -37,26 +37,6 @@ | |||
| 37 | 37 | ||
| 38 | (declare-function semantic-lex-spp-set-dynamic-table "semantic/lex-spp") | 38 | (declare-function semantic-lex-spp-set-dynamic-table "semantic/lex-spp") |
| 39 | 39 | ||
| 40 | (defcustom semanticdb-global-mode nil | ||
| 41 | "*If non-nil enable the use of `semanticdb-minor-mode'." | ||
| 42 | :group 'semantic | ||
| 43 | :type 'boolean | ||
| 44 | :require 'semantic/db | ||
| 45 | :initialize 'custom-initialize-default | ||
| 46 | :set (lambda (sym val) | ||
| 47 | (global-semanticdb-minor-mode (if val 1 -1)) | ||
| 48 | (custom-set-default sym val))) | ||
| 49 | |||
| 50 | (defcustom semanticdb-mode-hook nil | ||
| 51 | "Hook run whenever `global-semanticdb-minor-mode' is run. | ||
| 52 | Use `semanticdb-minor-mode-p' to determine if the mode has been turned | ||
| 53 | on or off." | ||
| 54 | :group 'semanticdb | ||
| 55 | :type 'hook) | ||
| 56 | |||
| 57 | (semantic-varalias-obsolete 'semanticdb-mode-hooks | ||
| 58 | 'semanticdb-mode-hook) | ||
| 59 | |||
| 60 | ;;; Start/Stop database use | 40 | ;;; Start/Stop database use |
| 61 | ;; | 41 | ;; |
| 62 | (defvar semanticdb-hooks | 42 | (defvar semanticdb-hooks |
| @@ -80,32 +60,27 @@ on or off." | |||
| 80 | (symbol-value (car (cdr (car semanticdb-hooks)))))) | 60 | (symbol-value (car (cdr (car semanticdb-hooks)))))) |
| 81 | 61 | ||
| 82 | ;;;###autoload | 62 | ;;;###autoload |
| 83 | (defun global-semanticdb-minor-mode (&optional arg) | 63 | (define-minor-mode global-semanticdb-minor-mode |
| 84 | "Toggle the use of `semanticdb-minor-mode'. | 64 | "Toggle Semantic DB mode. |
| 85 | If ARG is positive, enable, if it is negative, disable. | 65 | With ARG, turn Semantic DB mode on if ARG is positive, off otherwise. |
| 86 | If ARG is nil, then toggle." | 66 | |
| 87 | (interactive "P") | 67 | In Semantic DB mode, Semantic parsers store results in a |
| 88 | (if (not arg) | 68 | database, which can be saved for future Emacs sessions." |
| 89 | (if (semanticdb-minor-mode-p) | 69 | :global t |
| 90 | (setq arg -1) | 70 | :group 'semantic |
| 91 | (setq arg 1))) | 71 | (if global-semanticdb-minor-mode |
| 92 | (let ((fn 'add-hook) | 72 | ;; Enable |
| 93 | (h semanticdb-hooks) | 73 | (dolist (elt semanticdb-hooks) |
| 94 | (changed nil)) | 74 | (add-hook (cadr elt) (car elt))) |
| 95 | (if (< arg 0) | 75 | ;; Disable |
| 96 | (setq changed semanticdb-global-mode | 76 | (dolist (elt semanticdb-hooks) |
| 97 | semanticdb-global-mode nil | 77 | (add-hook (cadr elt) (car elt))))) |
| 98 | fn 'remove-hook) | 78 | |
| 99 | (setq changed (not semanticdb-global-mode) | 79 | (defvaralias 'semanticdb-mode-hook 'global-semanticdb-minor-mode-hook) |
| 100 | semanticdb-global-mode t)) | 80 | (defvaralias 'semanticdb-global-mode 'global-semanticdb-minor-mode) |
| 101 | ;(message "ARG = %d" arg) | 81 | (semantic-varalias-obsolete 'semanticdb-mode-hooks |
| 102 | (when changed | 82 | 'global-semanticdb-minor-mode-hook) |
| 103 | (while h | 83 | |
| 104 | (funcall fn (car (cdr (car h))) (car (car h))) | ||
| 105 | (setq h (cdr h))) | ||
| 106 | ;; Call a hook | ||
| 107 | (run-hooks 'semanticdb-mode-hook)) | ||
| 108 | )) | ||
| 109 | 84 | ||
| 110 | (defun semanticdb-toggle-global-mode () | 85 | (defun semanticdb-toggle-global-mode () |
| 111 | "Toggle use of the Semantic Database feature. | 86 | "Toggle use of the Semantic Database feature. |
diff --git a/lisp/cedet/semantic/ede-grammar.el b/lisp/cedet/semantic/ede-grammar.el new file mode 100644 index 00000000000..c23b489c837 --- /dev/null +++ b/lisp/cedet/semantic/ede-grammar.el | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | ;;; semantic/ede-grammar.el --- EDE support for Semantic Grammar Files | ||
| 2 | |||
| 3 | ;;; Copyright (C) 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | ||
| 6 | ;; Keywords: project, make | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | ;; | ||
| 25 | ;; Handle .by or .wy files. | ||
| 26 | |||
| 27 | (require 'semantic) | ||
| 28 | (require 'ede/proj) | ||
| 29 | (require 'ede/pmake) | ||
| 30 | (require 'ede/pconf) | ||
| 31 | (require 'ede/proj-elisp) | ||
| 32 | (require 'semantic/grammar) | ||
| 33 | |||
| 34 | ;;; Code: | ||
| 35 | (defclass semantic-ede-proj-target-grammar (ede-proj-target-makefile) | ||
| 36 | ((menu :initform nil) | ||
| 37 | (keybindings :initform nil) | ||
| 38 | (phony :initform t) | ||
| 39 | (sourcetype :initform | ||
| 40 | (semantic-ede-source-grammar-wisent | ||
| 41 | semantic-ede-source-grammar-bovine | ||
| 42 | )) | ||
| 43 | (availablecompilers :initform | ||
| 44 | (semantic-ede-grammar-compiler-wisent | ||
| 45 | semantic-ede-grammar-compiler-bovine | ||
| 46 | )) | ||
| 47 | ) | ||
| 48 | "This target consists of a group of grammar files. | ||
| 49 | A grammar target consists of grammar files that build Emacs Lisp programs for | ||
| 50 | parsing different languages.") | ||
| 51 | |||
| 52 | (defvar semantic-ede-source-grammar-wisent | ||
| 53 | (ede-sourcecode "semantic-ede-grammar-source-wisent" | ||
| 54 | :name "Wisent Grammar" | ||
| 55 | :sourcepattern "\\.wy$" | ||
| 56 | ) | ||
| 57 | "Semantic Grammar source code definition for wisent.") | ||
| 58 | |||
| 59 | (defclass semantic-ede-grammar-compiler-class (ede-compiler) | ||
| 60 | nil | ||
| 61 | "Specialized compiler for semantic grammars.") | ||
| 62 | |||
| 63 | (defvar semantic-ede-grammar-compiler-wisent | ||
| 64 | (semantic-ede-grammar-compiler-class | ||
| 65 | "ede-emacs-wisent-compiler" | ||
| 66 | :name "emacs" | ||
| 67 | :variables '(("EMACS" . "emacs")) | ||
| 68 | :commands | ||
| 69 | '( | ||
| 70 | "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script" | ||
| 71 | "@for loadpath in . ${LOADPATH}; do \\" | ||
| 72 | " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\" | ||
| 73 | "done;" | ||
| 74 | "@echo \"(require 'semantic-load)\" >> grammar-make-script" | ||
| 75 | "@echo \"(require 'semantic-grammar)\" >> grammar-make-script" | ||
| 76 | ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script" | ||
| 77 | "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^" | ||
| 78 | ) | ||
| 79 | ;; :autoconf '("AM_PATH_LISPDIR") | ||
| 80 | :sourcetype '(semantic-ede-source-grammar-wisent) | ||
| 81 | :objectextention "-wy.elc" | ||
| 82 | ) | ||
| 83 | "Compile Emacs Lisp programs.") | ||
| 84 | |||
| 85 | |||
| 86 | (defvar semantic-ede-source-grammar-bovine | ||
| 87 | (ede-sourcecode "semantic-ede-grammar-source-bovine" | ||
| 88 | :name "Bovine Grammar" | ||
| 89 | :sourcepattern "\\.by$" | ||
| 90 | ) | ||
| 91 | "Semantic Grammar source code definition for the bovinator.") | ||
| 92 | |||
| 93 | (defvar semantic-ede-grammar-compiler-bovine | ||
| 94 | (semantic-ede-grammar-compiler-class | ||
| 95 | "ede-emacs-wisent-compiler" | ||
| 96 | :name "emacs" | ||
| 97 | :variables '(("EMACS" . "emacs")) | ||
| 98 | :commands | ||
| 99 | '( | ||
| 100 | "@echo \"(add-to-list 'load-path nil)\" > grammar-make-script" | ||
| 101 | "@for loadpath in . ${LOADPATH}; do \\" | ||
| 102 | " echo \"(add-to-list 'load-path \\\"$$loadpath\\\")\" >> grammar-make-script; \\" | ||
| 103 | "done;" | ||
| 104 | "@echo \"(require 'semantic-load)\" >> grammar-make-script" | ||
| 105 | "@echo \"(require 'semantic-grammar)\" >> grammar-make-script" | ||
| 106 | ;; "@echo \"(setq debug-on-error t)\" >> grammar-make-script" | ||
| 107 | "\"$(EMACS)\" -batch --no-site-file -l grammar-make-script -f semantic-grammar-batch-build-packages $^" | ||
| 108 | ) | ||
| 109 | ;; :autoconf '("AM_PATH_LISPDIR") | ||
| 110 | :sourcetype '(semantic-ede-source-grammar-bovine) | ||
| 111 | :objectextention "-by.elc" | ||
| 112 | ) | ||
| 113 | "Compile Emacs Lisp programs.") | ||
| 114 | |||
| 115 | ;;; Target options. | ||
| 116 | (defmethod ede-buffer-mine ((this semantic-ede-proj-target-grammar) buffer) | ||
| 117 | "Return t if object THIS lays claim to the file in BUFFER. | ||
| 118 | Lays claim to all -by.el, and -wy.el files." | ||
| 119 | ;; We need to be a little more careful than this, but at the moment it | ||
| 120 | ;; is common to have only one target of this class per directory. | ||
| 121 | (if (string-match "-[bw]y\\.elc?$" (buffer-file-name buffer)) | ||
| 122 | t | ||
| 123 | (call-next-method) ; The usual thing. | ||
| 124 | )) | ||
| 125 | |||
| 126 | (defmethod project-compile-target ((obj semantic-ede-proj-target-grammar)) | ||
| 127 | "Compile all sources in a Lisp target OBJ." | ||
| 128 | (let* ((cb (current-buffer)) | ||
| 129 | (proj (ede-target-parent obj)) | ||
| 130 | (default-directory (oref proj directory))) | ||
| 131 | (mapc (lambda (src) | ||
| 132 | (save-excursion | ||
| 133 | (set-buffer (find-file-noselect src)) | ||
| 134 | (save-excursion | ||
| 135 | (semantic-grammar-create-package)) | ||
| 136 | (save-buffer) | ||
| 137 | (let ((cf (concat (semantic-grammar-package) ".el"))) | ||
| 138 | (if (or (not (file-exists-p cf)) | ||
| 139 | (file-newer-than-file-p src cf)) | ||
| 140 | (byte-compile-file cf))))) | ||
| 141 | (oref obj source))) | ||
| 142 | (message "All Semantic Grammar sources are up to date in %s" (object-name obj))) | ||
| 143 | |||
| 144 | ;;; Makefile generation functions | ||
| 145 | ;; | ||
| 146 | (defmethod ede-proj-makefile-sourcevar ((this semantic-ede-proj-target-grammar)) | ||
| 147 | "Return the variable name for THIS's sources." | ||
| 148 | (cond ((ede-proj-automake-p) | ||
| 149 | (error "No Automake support for Semantic Grammars")) | ||
| 150 | (t (concat (ede-pmake-varname this) "_SEMANTIC_GRAMMAR")))) | ||
| 151 | |||
| 152 | (defmethod ede-proj-makefile-insert-variables :AFTER ((this semantic-ede-proj-target-grammar)) | ||
| 153 | "Insert variables needed by target THIS." | ||
| 154 | (ede-proj-makefile-insert-loadpath-items | ||
| 155 | (ede-proj-elisp-packages-to-loadpath | ||
| 156 | (list "eieio" "semantic" "inversion" "ede"))) | ||
| 157 | ;; eieio for object system needed in ede | ||
| 158 | ;; semantic because it is | ||
| 159 | ;; Inversion for versioning system. | ||
| 160 | ;; ede for project regeneration | ||
| 161 | (ede-pmake-insert-variable-shared | ||
| 162 | (concat (ede-pmake-varname this) "_SEMANTIC_GRAMMAR_EL") | ||
| 163 | (insert | ||
| 164 | (mapconcat (lambda (src) | ||
| 165 | (save-excursion | ||
| 166 | (set-buffer (find-file-noselect src)) | ||
| 167 | (concat (semantic-grammar-package) ".el"))) | ||
| 168 | (oref this source) | ||
| 169 | " "))) | ||
| 170 | ) | ||
| 171 | |||
| 172 | (defmethod ede-proj-makefile-insert-rules ((this semantic-ede-proj-target-grammar)) | ||
| 173 | "Insert rules needed by THIS target." | ||
| 174 | ;; Add in some dependencies. | ||
| 175 | ;; (mapc (lambda (src) | ||
| 176 | ;; (let ((nm (file-name-sans-extension src))) | ||
| 177 | ;; (insert nm "-wy.el: " src "\n" | ||
| 178 | ;; nm "-wy.elc: " nm "-wy.el\n\n") | ||
| 179 | ;; )) | ||
| 180 | ;; (oref this source)) | ||
| 181 | ;; Call the normal insertion of rules. | ||
| 182 | (call-next-method) | ||
| 183 | ) | ||
| 184 | |||
| 185 | (defmethod ede-proj-makefile-insert-dist-dependencies ((this semantic-ede-proj-target-grammar)) | ||
| 186 | "Insert dist dependencies, or intermediate targets. | ||
| 187 | This makes sure that all grammar lisp files are created before the dist | ||
| 188 | runs, so they are always up to date. | ||
| 189 | Argument THIS is the target that should insert stuff." | ||
| 190 | (call-next-method) | ||
| 191 | (insert " $(" (ede-pmake-varname this) "_SEMANTIC_GRAMMAR_EL)") | ||
| 192 | ) | ||
| 193 | |||
| 194 | ;; (autoload 'ede-proj-target-elisp "ede/proj-elisp" | ||
| 195 | ;; "Target class for Emacs/Semantic grammar files." nil nil) | ||
| 196 | |||
| 197 | (ede-proj-register-target "semantic grammar" | ||
| 198 | semantic-ede-proj-target-grammar) | ||
| 199 | |||
| 200 | (provide 'semantic/ede-grammar) | ||
| 201 | |||
| 202 | ;;; semantic/ede-grammar.el ends here | ||
diff --git a/lisp/cedet/semantic/grammar-wy.el b/lisp/cedet/semantic/grammar-wy.el new file mode 100644 index 00000000000..ae1aec7b466 --- /dev/null +++ b/lisp/cedet/semantic/grammar-wy.el | |||
| @@ -0,0 +1,478 @@ | |||
| 1 | ;;; semantic/grammar-wy.el --- Generated parser support file | ||
| 2 | |||
| 3 | ;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: David Ponce <david@dponce.com> | ||
| 6 | ;; Keywords: syntax | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | ;; | ||
| 25 | ;; This file is generated from the grammar file semantic-grammar.wy in | ||
| 26 | ;; the upstream CEDET repository. | ||
| 27 | |||
| 28 | ;;; Code: | ||
| 29 | |||
| 30 | (require 'semantic/lex) | ||
| 31 | (defvar semantic-grammar-lex-c-char-re) | ||
| 32 | |||
| 33 | ;; Current parsed nonterminal name. | ||
| 34 | (defvar semantic-grammar-wy--nterm nil) | ||
| 35 | ;; Index of rule in a nonterminal clause. | ||
| 36 | (defvar semantic-grammar-wy--rindx nil) | ||
| 37 | |||
| 38 | ;;; Declarations | ||
| 39 | ;; | ||
| 40 | (defconst semantic-grammar-wy--keyword-table | ||
| 41 | (semantic-lex-make-keyword-table | ||
| 42 | '(("%default-prec" . DEFAULT-PREC) | ||
| 43 | ("%no-default-prec" . NO-DEFAULT-PREC) | ||
| 44 | ("%keyword" . KEYWORD) | ||
| 45 | ("%languagemode" . LANGUAGEMODE) | ||
| 46 | ("%left" . LEFT) | ||
| 47 | ("%nonassoc" . NONASSOC) | ||
| 48 | ("%package" . PACKAGE) | ||
| 49 | ("%prec" . PREC) | ||
| 50 | ("%put" . PUT) | ||
| 51 | ("%quotemode" . QUOTEMODE) | ||
| 52 | ("%right" . RIGHT) | ||
| 53 | ("%scopestart" . SCOPESTART) | ||
| 54 | ("%start" . START) | ||
| 55 | ("%token" . TOKEN) | ||
| 56 | ("%type" . TYPE) | ||
| 57 | ("%use-macros" . USE-MACROS)) | ||
| 58 | 'nil) | ||
| 59 | "Table of language keywords.") | ||
| 60 | |||
| 61 | (defconst semantic-grammar-wy--token-table | ||
| 62 | (semantic-lex-make-type-table | ||
| 63 | '(("punctuation" | ||
| 64 | (GT . ">") | ||
| 65 | (LT . "<") | ||
| 66 | (OR . "|") | ||
| 67 | (SEMI . ";") | ||
| 68 | (COLON . ":")) | ||
| 69 | ("close-paren" | ||
| 70 | (RBRACE . "}") | ||
| 71 | (RPAREN . ")")) | ||
| 72 | ("open-paren" | ||
| 73 | (LBRACE . "{") | ||
| 74 | (LPAREN . "(")) | ||
| 75 | ("block" | ||
| 76 | (BRACE_BLOCK . "(LBRACE RBRACE)") | ||
| 77 | (PAREN_BLOCK . "(LPAREN RPAREN)")) | ||
| 78 | ("code" | ||
| 79 | (EPILOGUE . "%%...EOF") | ||
| 80 | (PROLOGUE . "%{...%}")) | ||
| 81 | ("sexp" | ||
| 82 | (SEXP)) | ||
| 83 | ("qlist" | ||
| 84 | (PREFIXED_LIST)) | ||
| 85 | ("char" | ||
| 86 | (CHARACTER)) | ||
| 87 | ("symbol" | ||
| 88 | (PERCENT_PERCENT . "\\`%%\\'") | ||
| 89 | (SYMBOL)) | ||
| 90 | ("string" | ||
| 91 | (STRING))) | ||
| 92 | '(("punctuation" :declared t) | ||
| 93 | ("block" :declared t) | ||
| 94 | ("sexp" matchdatatype sexp) | ||
| 95 | ("sexp" syntax "\\=") | ||
| 96 | ("sexp" :declared t) | ||
| 97 | ("qlist" matchdatatype sexp) | ||
| 98 | ("qlist" syntax "\\s'\\s-*(") | ||
| 99 | ("qlist" :declared t) | ||
| 100 | ("char" syntax semantic-grammar-lex-c-char-re) | ||
| 101 | ("char" :declared t) | ||
| 102 | ("symbol" syntax ":?\\(\\sw\\|\\s_\\)+") | ||
| 103 | ("symbol" :declared t) | ||
| 104 | ("string" :declared t) | ||
| 105 | ("keyword" :declared t))) | ||
| 106 | "Table of lexical tokens.") | ||
| 107 | |||
| 108 | (defconst semantic-grammar-wy--parse-table | ||
| 109 | (progn | ||
| 110 | (eval-when-compile | ||
| 111 | (require 'semantic/wisent/comp)) | ||
| 112 | (wisent-compile-grammar | ||
| 113 | '((DEFAULT-PREC NO-DEFAULT-PREC KEYWORD LANGUAGEMODE LEFT NONASSOC PACKAGE PREC PUT QUOTEMODE RIGHT SCOPESTART START TOKEN TYPE USE-MACROS STRING SYMBOL PERCENT_PERCENT CHARACTER PREFIXED_LIST SEXP PROLOGUE EPILOGUE PAREN_BLOCK BRACE_BLOCK LPAREN RPAREN LBRACE RBRACE COLON SEMI OR LT GT) | ||
| 114 | nil | ||
| 115 | (grammar | ||
| 116 | ((prologue)) | ||
| 117 | ((epilogue)) | ||
| 118 | ((declaration)) | ||
| 119 | ((nonterminal)) | ||
| 120 | ((PERCENT_PERCENT))) | ||
| 121 | (prologue | ||
| 122 | ((PROLOGUE) | ||
| 123 | (wisent-raw-tag | ||
| 124 | (semantic-tag-new-code "prologue" nil)))) | ||
| 125 | (epilogue | ||
| 126 | ((EPILOGUE) | ||
| 127 | (wisent-raw-tag | ||
| 128 | (semantic-tag-new-code "epilogue" nil)))) | ||
| 129 | (declaration | ||
| 130 | ((decl) | ||
| 131 | (eval $1))) | ||
| 132 | (decl | ||
| 133 | ((default_prec_decl)) | ||
| 134 | ((no_default_prec_decl)) | ||
| 135 | ((languagemode_decl)) | ||
| 136 | ((package_decl)) | ||
| 137 | ((precedence_decl)) | ||
| 138 | ((put_decl)) | ||
| 139 | ((quotemode_decl)) | ||
| 140 | ((scopestart_decl)) | ||
| 141 | ((start_decl)) | ||
| 142 | ((keyword_decl)) | ||
| 143 | ((token_decl)) | ||
| 144 | ((type_decl)) | ||
| 145 | ((use_macros_decl))) | ||
| 146 | (default_prec_decl | ||
| 147 | ((DEFAULT-PREC) | ||
| 148 | `(wisent-raw-tag | ||
| 149 | (semantic-tag "default-prec" 'assoc :value | ||
| 150 | '("t"))))) | ||
| 151 | (no_default_prec_decl | ||
| 152 | ((NO-DEFAULT-PREC) | ||
| 153 | `(wisent-raw-tag | ||
| 154 | (semantic-tag "default-prec" 'assoc :value | ||
| 155 | '("nil"))))) | ||
| 156 | (languagemode_decl | ||
| 157 | ((LANGUAGEMODE symbols) | ||
| 158 | `(wisent-raw-tag | ||
| 159 | (semantic-tag ',(car $2) | ||
| 160 | 'languagemode :rest ',(cdr $2))))) | ||
| 161 | (package_decl | ||
| 162 | ((PACKAGE SYMBOL) | ||
| 163 | `(wisent-raw-tag | ||
| 164 | (semantic-tag-new-package ',$2 nil)))) | ||
| 165 | (precedence_decl | ||
| 166 | ((associativity token_type_opt items) | ||
| 167 | `(wisent-raw-tag | ||
| 168 | (semantic-tag ',$1 'assoc :type ',$2 :value ',$3)))) | ||
| 169 | (associativity | ||
| 170 | ((LEFT) | ||
| 171 | (progn "left")) | ||
| 172 | ((RIGHT) | ||
| 173 | (progn "right")) | ||
| 174 | ((NONASSOC) | ||
| 175 | (progn "nonassoc"))) | ||
| 176 | (put_decl | ||
| 177 | ((PUT put_name put_value) | ||
| 178 | `(wisent-raw-tag | ||
| 179 | (semantic-tag ',$2 'put :value ',(list $3)))) | ||
| 180 | ((PUT put_name put_value_list) | ||
| 181 | `(wisent-raw-tag | ||
| 182 | (semantic-tag ',$2 'put :value ',$3))) | ||
| 183 | ((PUT put_name_list put_value) | ||
| 184 | `(wisent-raw-tag | ||
| 185 | (semantic-tag ',(car $2) | ||
| 186 | 'put :rest ',(cdr $2) | ||
| 187 | :value ',(list $3)))) | ||
| 188 | ((PUT put_name_list put_value_list) | ||
| 189 | `(wisent-raw-tag | ||
| 190 | (semantic-tag ',(car $2) | ||
| 191 | 'put :rest ',(cdr $2) | ||
| 192 | :value ',$3)))) | ||
| 193 | (put_name_list | ||
| 194 | ((BRACE_BLOCK) | ||
| 195 | (mapcar 'semantic-tag-name | ||
| 196 | (semantic-parse-region | ||
| 197 | (car $region1) | ||
| 198 | (cdr $region1) | ||
| 199 | 'put_names 1)))) | ||
| 200 | (put_names | ||
| 201 | ((LBRACE) | ||
| 202 | nil) | ||
| 203 | ((RBRACE) | ||
| 204 | nil) | ||
| 205 | ((put_name) | ||
| 206 | (wisent-raw-tag | ||
| 207 | (semantic-tag $1 'put-name)))) | ||
| 208 | (put_name | ||
| 209 | ((SYMBOL)) | ||
| 210 | ((token_type))) | ||
| 211 | (put_value_list | ||
| 212 | ((BRACE_BLOCK) | ||
| 213 | (mapcar 'semantic-tag-code-detail | ||
| 214 | (semantic-parse-region | ||
| 215 | (car $region1) | ||
| 216 | (cdr $region1) | ||
| 217 | 'put_values 1)))) | ||
| 218 | (put_values | ||
| 219 | ((LBRACE) | ||
| 220 | nil) | ||
| 221 | ((RBRACE) | ||
| 222 | nil) | ||
| 223 | ((put_value) | ||
| 224 | (wisent-raw-tag | ||
| 225 | (semantic-tag-new-code "put-value" $1)))) | ||
| 226 | (put_value | ||
| 227 | ((SYMBOL any_value) | ||
| 228 | (cons $1 $2))) | ||
| 229 | (scopestart_decl | ||
| 230 | ((SCOPESTART SYMBOL) | ||
| 231 | `(wisent-raw-tag | ||
| 232 | (semantic-tag ',$2 'scopestart)))) | ||
| 233 | (quotemode_decl | ||
| 234 | ((QUOTEMODE SYMBOL) | ||
| 235 | `(wisent-raw-tag | ||
| 236 | (semantic-tag ',$2 'quotemode)))) | ||
| 237 | (start_decl | ||
| 238 | ((START symbols) | ||
| 239 | `(wisent-raw-tag | ||
| 240 | (semantic-tag ',(car $2) | ||
| 241 | 'start :rest ',(cdr $2))))) | ||
| 242 | (keyword_decl | ||
| 243 | ((KEYWORD SYMBOL string_value) | ||
| 244 | `(wisent-raw-tag | ||
| 245 | (semantic-tag ',$2 'keyword :value ',$3)))) | ||
| 246 | (token_decl | ||
| 247 | ((TOKEN token_type_opt SYMBOL string_value) | ||
| 248 | `(wisent-raw-tag | ||
| 249 | (semantic-tag ',$3 ',(if $2 'token 'keyword) | ||
| 250 | :type ',$2 :value ',$4))) | ||
| 251 | ((TOKEN token_type_opt symbols) | ||
| 252 | `(wisent-raw-tag | ||
| 253 | (semantic-tag ',(car $3) | ||
| 254 | 'token :type ',$2 :rest ',(cdr $3))))) | ||
| 255 | (token_type_opt | ||
| 256 | (nil) | ||
| 257 | ((token_type))) | ||
| 258 | (token_type | ||
| 259 | ((LT SYMBOL GT) | ||
| 260 | (progn $2))) | ||
| 261 | (type_decl | ||
| 262 | ((TYPE token_type plist_opt) | ||
| 263 | `(wisent-raw-tag | ||
| 264 | (semantic-tag ',$2 'type :value ',$3)))) | ||
| 265 | (plist_opt | ||
| 266 | (nil) | ||
| 267 | ((plist))) | ||
| 268 | (plist | ||
| 269 | ((plist put_value) | ||
| 270 | (append | ||
| 271 | (list $2) | ||
| 272 | $1)) | ||
| 273 | ((put_value) | ||
| 274 | (list $1))) | ||
| 275 | (use_name_list | ||
| 276 | ((BRACE_BLOCK) | ||
| 277 | (mapcar 'semantic-tag-name | ||
| 278 | (semantic-parse-region | ||
| 279 | (car $region1) | ||
| 280 | (cdr $region1) | ||
| 281 | 'use_names 1)))) | ||
| 282 | (use_names | ||
| 283 | ((LBRACE) | ||
| 284 | nil) | ||
| 285 | ((RBRACE) | ||
| 286 | nil) | ||
| 287 | ((SYMBOL) | ||
| 288 | (wisent-raw-tag | ||
| 289 | (semantic-tag $1 'use-name)))) | ||
| 290 | (use_macros_decl | ||
| 291 | ((USE-MACROS SYMBOL use_name_list) | ||
| 292 | `(wisent-raw-tag | ||
| 293 | (semantic-tag "macro" 'macro :type ',$2 :value ',$3)))) | ||
| 294 | (string_value | ||
| 295 | ((STRING) | ||
| 296 | (read $1))) | ||
| 297 | (any_value | ||
| 298 | ((SYMBOL)) | ||
| 299 | ((STRING)) | ||
| 300 | ((PAREN_BLOCK)) | ||
| 301 | ((PREFIXED_LIST)) | ||
| 302 | ((SEXP))) | ||
| 303 | (symbols | ||
| 304 | ((lifo_symbols) | ||
| 305 | (nreverse $1))) | ||
| 306 | (lifo_symbols | ||
| 307 | ((lifo_symbols SYMBOL) | ||
| 308 | (cons $2 $1)) | ||
| 309 | ((SYMBOL) | ||
| 310 | (list $1))) | ||
| 311 | (nonterminal | ||
| 312 | ((SYMBOL | ||
| 313 | (setq semantic-grammar-wy--nterm $1 semantic-grammar-wy--rindx 0) | ||
| 314 | COLON rules SEMI) | ||
| 315 | (wisent-raw-tag | ||
| 316 | (semantic-tag $1 'nonterminal :children $4)))) | ||
| 317 | (rules | ||
| 318 | ((lifo_rules) | ||
| 319 | (apply 'nconc | ||
| 320 | (nreverse $1)))) | ||
| 321 | (lifo_rules | ||
| 322 | ((lifo_rules OR rule) | ||
| 323 | (cons $3 $1)) | ||
| 324 | ((rule) | ||
| 325 | (list $1))) | ||
| 326 | (rule | ||
| 327 | ((rhs) | ||
| 328 | (let* | ||
| 329 | ((nterm semantic-grammar-wy--nterm) | ||
| 330 | (rindx semantic-grammar-wy--rindx) | ||
| 331 | (rhs $1) | ||
| 332 | comps prec action elt) | ||
| 333 | (setq semantic-grammar-wy--rindx | ||
| 334 | (1+ semantic-grammar-wy--rindx)) | ||
| 335 | (while rhs | ||
| 336 | (setq elt | ||
| 337 | (car rhs) | ||
| 338 | rhs | ||
| 339 | (cdr rhs)) | ||
| 340 | (cond | ||
| 341 | ((vectorp elt) | ||
| 342 | (if prec | ||
| 343 | (error "duplicate %%prec in `%s:%d' rule" nterm rindx)) | ||
| 344 | (setq prec | ||
| 345 | (aref elt 0))) | ||
| 346 | ((consp elt) | ||
| 347 | (if | ||
| 348 | (or action comps) | ||
| 349 | (setq comps | ||
| 350 | (cons elt comps) | ||
| 351 | semantic-grammar-wy--rindx | ||
| 352 | (1+ semantic-grammar-wy--rindx)) | ||
| 353 | (setq action | ||
| 354 | (car elt)))) | ||
| 355 | (t | ||
| 356 | (setq comps | ||
| 357 | (cons elt comps))))) | ||
| 358 | (wisent-cook-tag | ||
| 359 | (wisent-raw-tag | ||
| 360 | (semantic-tag | ||
| 361 | (format "%s:%d" nterm rindx) | ||
| 362 | 'rule :type | ||
| 363 | (if comps "group" "empty") | ||
| 364 | :value comps :prec prec :expr action)))))) | ||
| 365 | (rhs | ||
| 366 | (nil) | ||
| 367 | ((rhs item) | ||
| 368 | (cons $2 $1)) | ||
| 369 | ((rhs action) | ||
| 370 | (cons | ||
| 371 | (list $2) | ||
| 372 | $1)) | ||
| 373 | ((rhs PREC item) | ||
| 374 | (cons | ||
| 375 | (vector $3) | ||
| 376 | $1))) | ||
| 377 | (action | ||
| 378 | ((PAREN_BLOCK)) | ||
| 379 | ((PREFIXED_LIST)) | ||
| 380 | ((BRACE_BLOCK) | ||
| 381 | (format "(progn\n%s)" | ||
| 382 | (let | ||
| 383 | ((s $1)) | ||
| 384 | (if | ||
| 385 | (string-match "^{[ \n ]*" s) | ||
| 386 | (setq s | ||
| 387 | (substring s | ||
| 388 | (match-end 0)))) | ||
| 389 | (if | ||
| 390 | (string-match "[ \n ]*}$" s) | ||
| 391 | (setq s | ||
| 392 | (substring s 0 | ||
| 393 | (match-beginning 0)))) | ||
| 394 | s)))) | ||
| 395 | (items | ||
| 396 | ((lifo_items) | ||
| 397 | (nreverse $1))) | ||
| 398 | (lifo_items | ||
| 399 | ((lifo_items item) | ||
| 400 | (cons $2 $1)) | ||
| 401 | ((item) | ||
| 402 | (list $1))) | ||
| 403 | (item | ||
| 404 | ((SYMBOL)) | ||
| 405 | ((CHARACTER)))) | ||
| 406 | '(grammar prologue epilogue declaration nonterminal rule put_names put_values use_names))) | ||
| 407 | "Parser table.") | ||
| 408 | |||
| 409 | (defun semantic-grammar-wy--install-parser () | ||
| 410 | "Setup the Semantic Parser." | ||
| 411 | (semantic-install-function-overrides | ||
| 412 | '((parse-stream . wisent-parse-stream))) | ||
| 413 | (setq semantic-parser-name "LALR" | ||
| 414 | semantic--parse-table semantic-grammar-wy--parse-table | ||
| 415 | semantic-debug-parser-source "semantic-grammar.wy" | ||
| 416 | semantic-flex-keywords-obarray semantic-grammar-wy--keyword-table | ||
| 417 | semantic-lex-types-obarray semantic-grammar-wy--token-table) | ||
| 418 | ;; Collect unmatched syntax lexical tokens | ||
| 419 | (semantic-make-local-hook 'wisent-discarding-token-functions) | ||
| 420 | (add-hook 'wisent-discarding-token-functions | ||
| 421 | 'wisent-collect-unmatched-syntax nil t)) | ||
| 422 | |||
| 423 | |||
| 424 | ;;; Analyzers | ||
| 425 | |||
| 426 | (define-lex-sexp-type-analyzer semantic-grammar-wy--<sexp>-sexp-analyzer | ||
| 427 | "sexp analyzer for <sexp> tokens." | ||
| 428 | "\\=" | ||
| 429 | 'SEXP) | ||
| 430 | |||
| 431 | (define-lex-sexp-type-analyzer semantic-grammar-wy--<qlist>-sexp-analyzer | ||
| 432 | "sexp analyzer for <qlist> tokens." | ||
| 433 | "\\s'\\s-*(" | ||
| 434 | 'PREFIXED_LIST) | ||
| 435 | |||
| 436 | (define-lex-keyword-type-analyzer semantic-grammar-wy--<keyword>-keyword-analyzer | ||
| 437 | "keyword analyzer for <keyword> tokens." | ||
| 438 | "\\(\\sw\\|\\s_\\)+") | ||
| 439 | |||
| 440 | (define-lex-block-type-analyzer semantic-grammar-wy--<block>-block-analyzer | ||
| 441 | "block analyzer for <block> tokens." | ||
| 442 | "\\s(\\|\\s)" | ||
| 443 | '((("(" LPAREN PAREN_BLOCK) | ||
| 444 | ("{" LBRACE BRACE_BLOCK)) | ||
| 445 | (")" RPAREN) | ||
| 446 | ("}" RBRACE)) | ||
| 447 | ) | ||
| 448 | |||
| 449 | (define-lex-regex-type-analyzer semantic-grammar-wy--<char>-regexp-analyzer | ||
| 450 | "regexp analyzer for <char> tokens." | ||
| 451 | semantic-grammar-lex-c-char-re | ||
| 452 | nil | ||
| 453 | 'CHARACTER) | ||
| 454 | |||
| 455 | (define-lex-sexp-type-analyzer semantic-grammar-wy--<string>-sexp-analyzer | ||
| 456 | "sexp analyzer for <string> tokens." | ||
| 457 | "\\s\"" | ||
| 458 | 'STRING) | ||
| 459 | |||
| 460 | (define-lex-regex-type-analyzer semantic-grammar-wy--<symbol>-regexp-analyzer | ||
| 461 | "regexp analyzer for <symbol> tokens." | ||
| 462 | ":?\\(\\sw\\|\\s_\\)+" | ||
| 463 | '((PERCENT_PERCENT . "\\`%%\\'")) | ||
| 464 | 'SYMBOL) | ||
| 465 | |||
| 466 | (define-lex-string-type-analyzer semantic-grammar-wy--<punctuation>-string-analyzer | ||
| 467 | "string analyzer for <punctuation> tokens." | ||
| 468 | "\\(\\s.\\|\\s$\\|\\s'\\)+" | ||
| 469 | '((GT . ">") | ||
| 470 | (LT . "<") | ||
| 471 | (OR . "|") | ||
| 472 | (SEMI . ";") | ||
| 473 | (COLON . ":")) | ||
| 474 | 'punctuation) | ||
| 475 | |||
| 476 | (provide 'semantic/grammar-wy) | ||
| 477 | |||
| 478 | ;;; semantic/grammar-wy.el ends here | ||
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el new file mode 100644 index 00000000000..5d947551d48 --- /dev/null +++ b/lisp/cedet/semantic/grammar.el | |||
| @@ -0,0 +1,1912 @@ | |||
| 1 | ;;; semantic/grammar.el --- Major mode framework for Semantic grammars | ||
| 2 | |||
| 3 | ;;; Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 | ||
| 4 | ;;; Free Software Foundation, Inc. | ||
| 5 | |||
| 6 | ;; Author: David Ponce <david@dponce.com> | ||
| 7 | ;; Maintainer: David Ponce <david@dponce.com> | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 14 | ;; (at your option) any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | ;; | ||
| 26 | ;; Major mode framework for editing Semantic's input grammar files. | ||
| 27 | |||
| 28 | ;;; History: | ||
| 29 | ;; | ||
| 30 | |||
| 31 | ;;; Code: | ||
| 32 | |||
| 33 | (require 'semantic) | ||
| 34 | (require 'semantic/ctxt) | ||
| 35 | (require 'semantic/format) | ||
| 36 | (require 'semantic/grammar-wy) | ||
| 37 | (require 'semantic/idle) | ||
| 38 | (declare-function semantic-momentary-highlight-tag "semantic/decorate") | ||
| 39 | (declare-function semantic-analyze-context "semantic/analyze") | ||
| 40 | (declare-function semantic-analyze-tags-of-class-list | ||
| 41 | "semantic/analyze/complete") | ||
| 42 | |||
| 43 | |||
| 44 | ;; (eval-when-compile | ||
| 45 | ;; (require 'semantic/analyze)) | ||
| 46 | |||
| 47 | (eval-when-compile | ||
| 48 | (require 'eldoc) | ||
| 49 | (require 'semantic/edit) | ||
| 50 | (require 'semantic/find)) | ||
| 51 | |||
| 52 | ;;(require 'semantic/wisent) | ||
| 53 | ;; (require 'font-lock) | ||
| 54 | ;; (require 'pp) | ||
| 55 | |||
| 56 | ;; (eval-when-compile | ||
| 57 | ;; ;; (require 'senator) | ||
| 58 | ;; (require 'semantic/edit) | ||
| 59 | ;; (require 'semantic/find) | ||
| 60 | ;; (require 'semantic/format) | ||
| 61 | ;; (require 'semantic/idle)) | ||
| 62 | |||
| 63 | |||
| 64 | ;;;; | ||
| 65 | ;;;; Set up lexer | ||
| 66 | ;;;; | ||
| 67 | |||
| 68 | (defconst semantic-grammar-lex-c-char-re "'\\s\\?.'" | ||
| 69 | "Regexp matching C-like character literals.") | ||
| 70 | |||
| 71 | ;; Most of the analyzers are auto-generated from the grammar, but the | ||
| 72 | ;; following which need special handling code. | ||
| 73 | ;; | ||
| 74 | (define-lex-regex-analyzer semantic-grammar-lex-prologue | ||
| 75 | "Detect and create a prologue token." | ||
| 76 | "\\<%{" | ||
| 77 | ;; Zing to the end of this brace block. | ||
| 78 | (semantic-lex-push-token | ||
| 79 | (semantic-lex-token | ||
| 80 | 'PROLOGUE (point) | ||
| 81 | (save-excursion | ||
| 82 | (semantic-lex-unterminated-syntax-protection 'PROLOGUE | ||
| 83 | (forward-char) | ||
| 84 | (forward-sexp 1) | ||
| 85 | (point)))))) | ||
| 86 | |||
| 87 | (defsubst semantic-grammar-epilogue-start () | ||
| 88 | "Return the start position of the grammar epilogue." | ||
| 89 | (save-excursion | ||
| 90 | (goto-char (point-min)) | ||
| 91 | (if (re-search-forward "^\\s-*\\<%%\\>\\s-*$" nil t 2) | ||
| 92 | (match-beginning 0) | ||
| 93 | (1+ (point-max))))) | ||
| 94 | |||
| 95 | (define-lex-regex-analyzer semantic-grammar-lex-epilogue | ||
| 96 | "Detect and create an epilogue or percent-percent token." | ||
| 97 | "\\<%%\\>" | ||
| 98 | (let ((start (match-beginning 0)) | ||
| 99 | (end (match-end 0)) | ||
| 100 | (class 'PERCENT_PERCENT)) | ||
| 101 | (when (>= start (semantic-grammar-epilogue-start)) | ||
| 102 | (setq class 'EPILOGUE | ||
| 103 | end (point-max))) | ||
| 104 | (semantic-lex-push-token | ||
| 105 | (semantic-lex-token class start end)))) | ||
| 106 | |||
| 107 | (define-lex semantic-grammar-lexer | ||
| 108 | "Lexical analyzer that handles Semantic grammar buffers. | ||
| 109 | It ignores whitespaces, newlines and comments." | ||
| 110 | semantic-lex-ignore-newline | ||
| 111 | semantic-lex-ignore-whitespace | ||
| 112 | ;; Must detect prologue/epilogue before other symbols/keywords! | ||
| 113 | semantic-grammar-lex-prologue | ||
| 114 | semantic-grammar-lex-epilogue | ||
| 115 | semantic-grammar-wy--<keyword>-keyword-analyzer | ||
| 116 | semantic-grammar-wy--<symbol>-regexp-analyzer | ||
| 117 | semantic-grammar-wy--<char>-regexp-analyzer | ||
| 118 | semantic-grammar-wy--<string>-sexp-analyzer | ||
| 119 | ;; Must detect comments after strings because `comment-start-skip' | ||
| 120 | ;; regexp match semicolons inside strings! | ||
| 121 | semantic-lex-ignore-comments | ||
| 122 | ;; Must detect prefixed list before punctuation because prefix chars | ||
| 123 | ;; are also punctuations! | ||
| 124 | semantic-grammar-wy--<qlist>-sexp-analyzer | ||
| 125 | ;; Must detect punctuations after comments because the semicolon can | ||
| 126 | ;; be a punctuation or a comment start! | ||
| 127 | semantic-grammar-wy--<punctuation>-string-analyzer | ||
| 128 | semantic-grammar-wy--<block>-block-analyzer | ||
| 129 | semantic-grammar-wy--<sexp>-sexp-analyzer) | ||
| 130 | |||
| 131 | ;;; Test the lexer | ||
| 132 | ;; | ||
| 133 | (defun semantic-grammar-lex-buffer () | ||
| 134 | "Run `semantic-grammar-lex' on current buffer." | ||
| 135 | (interactive) | ||
| 136 | (semantic-lex-init) | ||
| 137 | (setq semantic-lex-analyzer 'semantic-grammar-lexer) | ||
| 138 | (let ((token-stream | ||
| 139 | (semantic-lex (point-min) (point-max)))) | ||
| 140 | (with-current-buffer (get-buffer-create "*semantic-grammar-lex*") | ||
| 141 | (erase-buffer) | ||
| 142 | (pp token-stream (current-buffer)) | ||
| 143 | (goto-char (point-min)) | ||
| 144 | (pop-to-buffer (current-buffer))))) | ||
| 145 | |||
| 146 | ;;;; | ||
| 147 | ;;;; Semantic action expansion | ||
| 148 | ;;;; | ||
| 149 | |||
| 150 | (defun semantic-grammar-ASSOC (&rest args) | ||
| 151 | "Return expansion of built-in ASSOC expression. | ||
| 152 | ARGS are ASSOC's key value list." | ||
| 153 | (let ((key t)) | ||
| 154 | `(semantic-tag-make-assoc-list | ||
| 155 | ,@(mapcar #'(lambda (i) | ||
| 156 | (prog1 | ||
| 157 | (if key | ||
| 158 | (list 'quote i) | ||
| 159 | i) | ||
| 160 | (setq key (not key)))) | ||
| 161 | args)))) | ||
| 162 | |||
| 163 | (defsubst semantic-grammar-quote-p (sym) | ||
| 164 | "Return non-nil if SYM is bound to the `quote' function." | ||
| 165 | (condition-case nil | ||
| 166 | (eq (indirect-function sym) | ||
| 167 | (indirect-function 'quote)) | ||
| 168 | (error nil))) | ||
| 169 | |||
| 170 | (defsubst semantic-grammar-backquote-p (sym) | ||
| 171 | "Return non-nil if SYM is bound to the `backquote' function." | ||
| 172 | (condition-case nil | ||
| 173 | (eq (indirect-function sym) | ||
| 174 | (indirect-function 'backquote)) | ||
| 175 | (error nil))) | ||
| 176 | |||
| 177 | ;;;; | ||
| 178 | ;;;; API to access grammar tags | ||
| 179 | ;;;; | ||
| 180 | |||
| 181 | (define-mode-local-override semantic-tag-components | ||
| 182 | semantic-grammar-mode (tag) | ||
| 183 | "Return the children of tag TAG." | ||
| 184 | (semantic-tag-get-attribute tag :children)) | ||
| 185 | |||
| 186 | (defun semantic-grammar-first-tag-name (class) | ||
| 187 | "Return the name of the first tag of class CLASS found. | ||
| 188 | Warn if other tags of class CLASS exist." | ||
| 189 | (let* ((tags (semantic-find-tags-by-class | ||
| 190 | class (current-buffer)))) | ||
| 191 | (if tags | ||
| 192 | (prog1 | ||
| 193 | (semantic-tag-name (car tags)) | ||
| 194 | (if (cdr tags) | ||
| 195 | (message "*** Ignore all but first declared %s" | ||
| 196 | class)))))) | ||
| 197 | |||
| 198 | (defun semantic-grammar-tag-symbols (class) | ||
| 199 | "Return the list of symbols defined in tags of class CLASS. | ||
| 200 | That is tag names plus names defined in tag attribute `:rest'." | ||
| 201 | (let* ((tags (semantic-find-tags-by-class | ||
| 202 | class (current-buffer)))) | ||
| 203 | (apply 'append | ||
| 204 | (mapcar | ||
| 205 | #'(lambda (tag) | ||
| 206 | (mapcar | ||
| 207 | 'intern | ||
| 208 | (cons (semantic-tag-name tag) | ||
| 209 | (semantic-tag-get-attribute tag :rest)))) | ||
| 210 | tags)))) | ||
| 211 | |||
| 212 | (defsubst semantic-grammar-item-text (item) | ||
| 213 | "Return the readable string form of ITEM." | ||
| 214 | (if (string-match semantic-grammar-lex-c-char-re item) | ||
| 215 | (concat "?" (substring item 1 -1)) | ||
| 216 | item)) | ||
| 217 | |||
| 218 | (defsubst semantic-grammar-item-value (item) | ||
| 219 | "Return symbol or character value of ITEM string." | ||
| 220 | (if (string-match semantic-grammar-lex-c-char-re item) | ||
| 221 | (let ((c (read (concat "?" (substring item 1 -1))))) | ||
| 222 | (if (featurep 'xemacs) | ||
| 223 | ;; Handle characters as integers in XEmacs like in GNU Emacs. | ||
| 224 | (char-int c) | ||
| 225 | c)) | ||
| 226 | (intern item))) | ||
| 227 | |||
| 228 | (defun semantic-grammar-prologue () | ||
| 229 | "Return grammar prologue code as a string value." | ||
| 230 | (let ((tag (semantic-find-first-tag-by-name | ||
| 231 | "prologue" | ||
| 232 | (semantic-find-tags-by-class 'code (current-buffer))))) | ||
| 233 | (if tag | ||
| 234 | (save-excursion | ||
| 235 | (concat | ||
| 236 | (buffer-substring | ||
| 237 | (progn | ||
| 238 | (goto-char (semantic-tag-start tag)) | ||
| 239 | (skip-chars-forward "%{\r\n\t ") | ||
| 240 | (point)) | ||
| 241 | (progn | ||
| 242 | (goto-char (semantic-tag-end tag)) | ||
| 243 | (skip-chars-backward "\r\n\t %}") | ||
| 244 | (point))) | ||
| 245 | "\n")) | ||
| 246 | ""))) | ||
| 247 | |||
| 248 | (defun semantic-grammar-epilogue () | ||
| 249 | "Return grammar epilogue code as a string value." | ||
| 250 | (let ((tag (semantic-find-first-tag-by-name | ||
| 251 | "epilogue" | ||
| 252 | (semantic-find-tags-by-class 'code (current-buffer))))) | ||
| 253 | (if tag | ||
| 254 | (save-excursion | ||
| 255 | (concat | ||
| 256 | (buffer-substring | ||
| 257 | (progn | ||
| 258 | (goto-char (semantic-tag-start tag)) | ||
| 259 | (skip-chars-forward "%\r\n\t ") | ||
| 260 | (point)) | ||
| 261 | (progn | ||
| 262 | (goto-char (semantic-tag-end tag)) | ||
| 263 | (skip-chars-backward "\r\n\t") | ||
| 264 | ;; If a grammar footer is found, skip it. | ||
| 265 | (re-search-backward "^;;;\\s-+\\S-+\\s-+ends here" | ||
| 266 | (save-excursion | ||
| 267 | (beginning-of-line) | ||
| 268 | (point)) | ||
| 269 | t) | ||
| 270 | (skip-chars-backward "\r\n\t") | ||
| 271 | (point))) | ||
| 272 | "\n")) | ||
| 273 | ""))) | ||
| 274 | |||
| 275 | (defsubst semantic-grammar-buffer-file (&optional buffer) | ||
| 276 | "Return name of file sans directory BUFFER is visiting. | ||
| 277 | No argument or nil as argument means use the current buffer." | ||
| 278 | (file-name-nondirectory (buffer-file-name buffer))) | ||
| 279 | |||
| 280 | (defun semantic-grammar-package () | ||
| 281 | "Return the %package value as a string. | ||
| 282 | If there is no %package statement in the grammar, return a default | ||
| 283 | package name derived from the grammar file name. For example, the | ||
| 284 | default package name for the grammar file foo.wy is foo-wy, and for | ||
| 285 | foo.by it is foo-by." | ||
| 286 | (or (semantic-grammar-first-tag-name 'package) | ||
| 287 | (let* ((file (semantic-grammar-buffer-file)) | ||
| 288 | (ext (file-name-extension file)) | ||
| 289 | (i (string-match (format "\\([.]\\)%s\\'" ext) file))) | ||
| 290 | (concat (substring file 0 i) "-" ext)))) | ||
| 291 | |||
| 292 | (defsubst semantic-grammar-languagemode () | ||
| 293 | "Return the %languagemode value as a list of symbols or nil." | ||
| 294 | (semantic-grammar-tag-symbols 'languagemode)) | ||
| 295 | |||
| 296 | (defsubst semantic-grammar-start () | ||
| 297 | "Return the %start value as a list of symbols or nil." | ||
| 298 | (semantic-grammar-tag-symbols 'start)) | ||
| 299 | |||
| 300 | (defsubst semantic-grammar-scopestart () | ||
| 301 | "Return the %scopestart value as a symbol or nil." | ||
| 302 | (intern (or (semantic-grammar-first-tag-name 'scopestart) "nil"))) | ||
| 303 | |||
| 304 | (defsubst semantic-grammar-quotemode () | ||
| 305 | "Return the %quotemode value as a symbol or nil." | ||
| 306 | (intern (or (semantic-grammar-first-tag-name 'quotemode) "nil"))) | ||
| 307 | |||
| 308 | (defsubst semantic-grammar-keywords () | ||
| 309 | "Return the language keywords. | ||
| 310 | That is an alist of (VALUE . TOKEN) where VALUE is the string value of | ||
| 311 | the keyword and TOKEN is the terminal symbol identifying the keyword." | ||
| 312 | (mapcar | ||
| 313 | #'(lambda (key) | ||
| 314 | (cons (semantic-tag-get-attribute key :value) | ||
| 315 | (intern (semantic-tag-name key)))) | ||
| 316 | (semantic-find-tags-by-class 'keyword (current-buffer)))) | ||
| 317 | |||
| 318 | (defun semantic-grammar-keyword-properties (keywords) | ||
| 319 | "Return the list of KEYWORDS properties." | ||
| 320 | (let ((puts (semantic-find-tags-by-class | ||
| 321 | 'put (current-buffer))) | ||
| 322 | put keys key plist assoc pkey pval props) | ||
| 323 | (while puts | ||
| 324 | (setq put (car puts) | ||
| 325 | puts (cdr puts) | ||
| 326 | keys (mapcar | ||
| 327 | 'intern | ||
| 328 | (cons (semantic-tag-name put) | ||
| 329 | (semantic-tag-get-attribute put :rest)))) | ||
| 330 | (while keys | ||
| 331 | (setq key (car keys) | ||
| 332 | keys (cdr keys) | ||
| 333 | assoc (rassq key keywords)) | ||
| 334 | (if (null assoc) | ||
| 335 | nil ;;(message "*** %%put to undefined keyword %s ignored" key) | ||
| 336 | (setq key (car assoc) | ||
| 337 | plist (semantic-tag-get-attribute put :value)) | ||
| 338 | (while plist | ||
| 339 | (setq pkey (intern (caar plist)) | ||
| 340 | pval (read (cdar plist)) | ||
| 341 | props (cons (list key pkey pval) props) | ||
| 342 | plist (cdr plist)))))) | ||
| 343 | props)) | ||
| 344 | |||
| 345 | (defun semantic-grammar-tokens () | ||
| 346 | "Return defined lexical tokens. | ||
| 347 | That is an alist (TYPE . DEFS) where type is a %token <type> symbol | ||
| 348 | and DEFS is an alist of (TOKEN . VALUE). TOKEN is the terminal symbol | ||
| 349 | identifying the token and VALUE is the string value of the token or | ||
| 350 | nil." | ||
| 351 | (let (tags alist assoc tag type term names value) | ||
| 352 | |||
| 353 | ;; Check for <type> in %left, %right & %nonassoc declarations | ||
| 354 | (setq tags (semantic-find-tags-by-class | ||
| 355 | 'assoc (current-buffer))) | ||
| 356 | (while tags | ||
| 357 | (setq tag (car tags) | ||
| 358 | tags (cdr tags)) | ||
| 359 | (when (setq type (semantic-tag-type tag)) | ||
| 360 | (setq names (semantic-tag-get-attribute tag :value) | ||
| 361 | assoc (assoc type alist)) | ||
| 362 | (or assoc (setq assoc (list type) | ||
| 363 | alist (cons assoc alist))) | ||
| 364 | (while names | ||
| 365 | (setq term (car names) | ||
| 366 | names (cdr names)) | ||
| 367 | (or (string-match semantic-grammar-lex-c-char-re term) | ||
| 368 | (setcdr assoc (cons (list (intern term)) | ||
| 369 | (cdr assoc))))))) | ||
| 370 | |||
| 371 | ;; Then process %token declarations so they can override any | ||
| 372 | ;; previous specifications | ||
| 373 | (setq tags (semantic-find-tags-by-class | ||
| 374 | 'token (current-buffer))) | ||
| 375 | (while tags | ||
| 376 | (setq tag (car tags) | ||
| 377 | tags (cdr tags)) | ||
| 378 | (setq names (cons (semantic-tag-name tag) | ||
| 379 | (semantic-tag-get-attribute tag :rest)) | ||
| 380 | type (or (semantic-tag-type tag) "<no-type>") | ||
| 381 | value (semantic-tag-get-attribute tag :value) | ||
| 382 | assoc (assoc type alist)) | ||
| 383 | (or assoc (setq assoc (list type) | ||
| 384 | alist (cons assoc alist))) | ||
| 385 | (while names | ||
| 386 | (setq term (intern (car names)) | ||
| 387 | names (cdr names)) | ||
| 388 | (setcdr assoc (cons (cons term value) (cdr assoc))))) | ||
| 389 | alist)) | ||
| 390 | |||
| 391 | (defun semantic-grammar-token-%type-properties (&optional props) | ||
| 392 | "Return properties set by %type statements. | ||
| 393 | This declare a new type if necessary. | ||
| 394 | If optional argument PROPS is non-nil, it is an existing list of | ||
| 395 | properties where to add new properties." | ||
| 396 | (let (type) | ||
| 397 | (dolist (tag (semantic-find-tags-by-class 'type (current-buffer))) | ||
| 398 | (setq type (semantic-tag-name tag)) | ||
| 399 | ;; Indicate to auto-generate the analyzer for this type | ||
| 400 | (push (list type :declared t) props) | ||
| 401 | (dolist (e (semantic-tag-get-attribute tag :value)) | ||
| 402 | (push (list type (intern (car e)) (read (or (cdr e) "nil"))) | ||
| 403 | props))) | ||
| 404 | props)) | ||
| 405 | |||
| 406 | (defun semantic-grammar-token-%put-properties (tokens) | ||
| 407 | "For types found in TOKENS, return properties set by %put statements." | ||
| 408 | (let (found props) | ||
| 409 | (dolist (put (semantic-find-tags-by-class 'put (current-buffer))) | ||
| 410 | (dolist (type (cons (semantic-tag-name put) | ||
| 411 | (semantic-tag-get-attribute put :rest))) | ||
| 412 | (setq found (assoc type tokens)) | ||
| 413 | (if (null found) | ||
| 414 | nil ;; %put <type> ignored, no token defined | ||
| 415 | (setq type (car found)) | ||
| 416 | (dolist (e (semantic-tag-get-attribute put :value)) | ||
| 417 | (push (list type (intern (car e)) (read (or (cdr e) "nil"))) | ||
| 418 | props))))) | ||
| 419 | props)) | ||
| 420 | |||
| 421 | (defsubst semantic-grammar-token-properties (tokens) | ||
| 422 | "Return properties of declared types. | ||
| 423 | Types are explicitly declared by %type statements. Types found in | ||
| 424 | TOKENS are those declared implicitly by %token statements. | ||
| 425 | Properties can be set by %put and %type statements. | ||
| 426 | Properties set by %type statements take precedence over those set by | ||
| 427 | %put statements." | ||
| 428 | (let ((props (semantic-grammar-token-%put-properties tokens))) | ||
| 429 | (semantic-grammar-token-%type-properties props))) | ||
| 430 | |||
| 431 | (defun semantic-grammar-use-macros () | ||
| 432 | "Return macro definitions from %use-macros statements. | ||
| 433 | Also load the specified macro libraries." | ||
| 434 | (let (lib defs) | ||
| 435 | (dolist (tag (semantic-find-tags-by-class 'macro (current-buffer))) | ||
| 436 | (setq lib (intern (semantic-tag-type tag))) | ||
| 437 | (condition-case nil | ||
| 438 | ;;(load lib) ;; Be sure to use the latest macro library. | ||
| 439 | (require lib) | ||
| 440 | (error nil)) | ||
| 441 | (dolist (mac (semantic-tag-get-attribute tag :value)) | ||
| 442 | (push (cons (intern mac) | ||
| 443 | (intern (format "%s-%s" lib mac))) | ||
| 444 | defs))) | ||
| 445 | (nreverse defs))) | ||
| 446 | |||
| 447 | (defvar semantic-grammar-macros nil | ||
| 448 | "List of associations (MACRO-NAME . EXPANDER).") | ||
| 449 | (make-variable-buffer-local 'semantic-grammar-macros) | ||
| 450 | |||
| 451 | (defun semantic-grammar-macros () | ||
| 452 | "Build and return the alist of defined macros." | ||
| 453 | (append | ||
| 454 | ;; Definitions found in tags. | ||
| 455 | (semantic-grammar-use-macros) | ||
| 456 | ;; Other pre-installed definitions. | ||
| 457 | semantic-grammar-macros)) | ||
| 458 | |||
| 459 | ;;;; | ||
| 460 | ;;;; Overloaded functions that build parser data. | ||
| 461 | ;;;; | ||
| 462 | |||
| 463 | ;;; Keyword table builder | ||
| 464 | ;; | ||
| 465 | (defun semantic-grammar-keywordtable-builder-default () | ||
| 466 | "Return the default value of the keyword table." | ||
| 467 | (let ((keywords (semantic-grammar-keywords))) | ||
| 468 | `(semantic-lex-make-keyword-table | ||
| 469 | ',keywords | ||
| 470 | ',(semantic-grammar-keyword-properties keywords)))) | ||
| 471 | |||
| 472 | (define-overloadable-function semantic-grammar-keywordtable-builder () | ||
| 473 | "Return the keyword table table value.") | ||
| 474 | |||
| 475 | ;;; Token table builder | ||
| 476 | ;; | ||
| 477 | (defun semantic-grammar-tokentable-builder-default () | ||
| 478 | "Return the default value of the table of lexical tokens." | ||
| 479 | (let ((tokens (semantic-grammar-tokens))) | ||
| 480 | `(semantic-lex-make-type-table | ||
| 481 | ',tokens | ||
| 482 | ',(semantic-grammar-token-properties tokens)))) | ||
| 483 | |||
| 484 | (define-overloadable-function semantic-grammar-tokentable-builder () | ||
| 485 | "Return the value of the table of lexical tokens.") | ||
| 486 | |||
| 487 | ;;; Parser table builder | ||
| 488 | ;; | ||
| 489 | (defun semantic-grammar-parsetable-builder-default () | ||
| 490 | "Return the default value of the parse table." | ||
| 491 | (error "`semantic-grammar-parsetable-builder' not defined")) | ||
| 492 | |||
| 493 | (define-overloadable-function semantic-grammar-parsetable-builder () | ||
| 494 | "Return the parser table value.") | ||
| 495 | |||
| 496 | ;;; Parser setup code builder | ||
| 497 | ;; | ||
| 498 | (defun semantic-grammar-setupcode-builder-default () | ||
| 499 | "Return the default value of the setup code form." | ||
| 500 | (error "`semantic-grammar-setupcode-builder' not defined")) | ||
| 501 | |||
| 502 | (define-overloadable-function semantic-grammar-setupcode-builder () | ||
| 503 | "Return the parser setup code form.") | ||
| 504 | |||
| 505 | ;;;; | ||
| 506 | ;;;; Lisp code generation | ||
| 507 | ;;;; | ||
| 508 | (defvar semantic--grammar-input-buffer nil) | ||
| 509 | (defvar semantic--grammar-output-buffer nil) | ||
| 510 | |||
| 511 | (defsubst semantic-grammar-keywordtable () | ||
| 512 | "Return the variable name of the keyword table." | ||
| 513 | (concat (file-name-sans-extension | ||
| 514 | (semantic-grammar-buffer-file | ||
| 515 | semantic--grammar-output-buffer)) | ||
| 516 | "--keyword-table")) | ||
| 517 | |||
| 518 | (defsubst semantic-grammar-tokentable () | ||
| 519 | "Return the variable name of the token table." | ||
| 520 | (concat (file-name-sans-extension | ||
| 521 | (semantic-grammar-buffer-file | ||
| 522 | semantic--grammar-output-buffer)) | ||
| 523 | "--token-table")) | ||
| 524 | |||
| 525 | (defsubst semantic-grammar-parsetable () | ||
| 526 | "Return the variable name of the parse table." | ||
| 527 | (concat (file-name-sans-extension | ||
| 528 | (semantic-grammar-buffer-file | ||
| 529 | semantic--grammar-output-buffer)) | ||
| 530 | "--parse-table")) | ||
| 531 | |||
| 532 | (defsubst semantic-grammar-setupfunction () | ||
| 533 | "Return the name of the parser setup function." | ||
| 534 | (concat (file-name-sans-extension | ||
| 535 | (semantic-grammar-buffer-file | ||
| 536 | semantic--grammar-output-buffer)) | ||
| 537 | "--install-parser")) | ||
| 538 | |||
| 539 | (defmacro semantic-grammar-as-string (object) | ||
| 540 | "Return OBJECT as a string value." | ||
| 541 | `(if (stringp ,object) | ||
| 542 | ,object | ||
| 543 | ;;(require 'pp) | ||
| 544 | (pp-to-string ,object))) | ||
| 545 | |||
| 546 | (defun semantic-grammar-insert-defconst (name value docstring) | ||
| 547 | "Insert declaration of constant NAME with VALUE and DOCSTRING." | ||
| 548 | (let ((start (point))) | ||
| 549 | (insert (format "(defconst %s\n%s%S)\n\n" name value docstring)) | ||
| 550 | (save-excursion | ||
| 551 | (goto-char start) | ||
| 552 | (indent-sexp)))) | ||
| 553 | |||
| 554 | (defun semantic-grammar-insert-defun (name body docstring) | ||
| 555 | "Insert declaration of function NAME with BODY and DOCSTRING." | ||
| 556 | (let ((start (point))) | ||
| 557 | (insert (format "(defun %s ()\n%S\n%s)\n\n" name docstring body)) | ||
| 558 | (save-excursion | ||
| 559 | (goto-char start) | ||
| 560 | (indent-sexp)))) | ||
| 561 | |||
| 562 | (defun semantic-grammar-insert-define (define) | ||
| 563 | "Insert the declaration specified by DEFINE expression. | ||
| 564 | Typically a DEFINE expression should look like this: | ||
| 565 | |||
| 566 | \(define-thing name docstring expression1 ...)" | ||
| 567 | ;;(require 'pp) | ||
| 568 | (let ((start (point))) | ||
| 569 | (insert (format "(%S %S" (car define) (nth 1 define))) | ||
| 570 | (dolist (item (nthcdr 2 define)) | ||
| 571 | (insert "\n") | ||
| 572 | (delete-blank-lines) | ||
| 573 | (pp item (current-buffer))) | ||
| 574 | (insert ")\n\n") | ||
| 575 | (save-excursion | ||
| 576 | (goto-char start) | ||
| 577 | (indent-sexp)))) | ||
| 578 | |||
| 579 | (defconst semantic-grammar-header-template | ||
| 580 | '("\ | ||
| 581 | ;;; " file " --- Generated parser support file | ||
| 582 | |||
| 583 | " copy " | ||
| 584 | |||
| 585 | ;; Author: " user-full-name " <" user-mail-address "> | ||
| 586 | ;; Created: " date " | ||
| 587 | ;; Keywords: syntax | ||
| 588 | ;; X-RCS: " vcid " | ||
| 589 | |||
| 590 | ;; This file is not part of GNU Emacs. | ||
| 591 | ;; | ||
| 592 | ;; This program is free software; you can redistribute it and/or | ||
| 593 | ;; modify it under the terms of the GNU General Public License as | ||
| 594 | ;; published by the Free Software Foundation; either version 2, or (at | ||
| 595 | ;; your option) any later version. | ||
| 596 | ;; | ||
| 597 | ;; This software is distributed in the hope that it will be useful, | ||
| 598 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 599 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 600 | ;; General Public License for more details. | ||
| 601 | ;; | ||
| 602 | ;; You should have received a copy of the GNU General Public License | ||
| 603 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 604 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 605 | ;; Boston, MA 02110-1301, USA. | ||
| 606 | |||
| 607 | ;;; Commentary: | ||
| 608 | ;; | ||
| 609 | ;; PLEASE DO NOT MANUALLY EDIT THIS FILE! It is automatically | ||
| 610 | ;; generated from the grammar file " gram ". | ||
| 611 | |||
| 612 | ;;; History: | ||
| 613 | ;; | ||
| 614 | |||
| 615 | ;;; Code: | ||
| 616 | ") | ||
| 617 | "Generated header template. | ||
| 618 | The symbols in the template are local variables in | ||
| 619 | `semantic-grammar-header'") | ||
| 620 | |||
| 621 | (defconst semantic-grammar-footer-template | ||
| 622 | '("\ | ||
| 623 | |||
| 624 | \(provide '" libr ") | ||
| 625 | |||
| 626 | ;;; " file " ends here | ||
| 627 | ") | ||
| 628 | "Generated footer template. | ||
| 629 | The symbols in the list are local variables in | ||
| 630 | `semantic-grammar-footer'.") | ||
| 631 | |||
| 632 | (defun semantic-grammar-copyright-line () | ||
| 633 | "Return the grammar copyright line, or nil if not found." | ||
| 634 | (save-excursion | ||
| 635 | (goto-char (point-min)) | ||
| 636 | (when (re-search-forward "^;;+[ \t]+Copyright (C) .*$" | ||
| 637 | ;; Search only in the four top lines | ||
| 638 | (save-excursion (forward-line 4) (point)) | ||
| 639 | t) | ||
| 640 | (match-string 0)))) | ||
| 641 | |||
| 642 | (defun semantic-grammar-header () | ||
| 643 | "Return text of a generated standard header." | ||
| 644 | (let ((file (semantic-grammar-buffer-file | ||
| 645 | semantic--grammar-output-buffer)) | ||
| 646 | (gram (semantic-grammar-buffer-file)) | ||
| 647 | (date (format-time-string "%Y-%m-%d %T%z")) | ||
| 648 | (vcid (concat "$" "Id" "$")) ;; Avoid expansion | ||
| 649 | ;; Try to get the copyright from the input grammar, or | ||
| 650 | ;; generate a new one if not found. | ||
| 651 | (copy (or (semantic-grammar-copyright-line) | ||
| 652 | (concat (format-time-string ";; Copyright (C) %Y ") | ||
| 653 | user-full-name))) | ||
| 654 | (out "")) | ||
| 655 | (dolist (S semantic-grammar-header-template) | ||
| 656 | (cond ((stringp S) | ||
| 657 | (setq out (concat out S))) | ||
| 658 | ((symbolp S) | ||
| 659 | (setq out (concat out (symbol-value S)))))) | ||
| 660 | out)) | ||
| 661 | |||
| 662 | (defun semantic-grammar-footer () | ||
| 663 | "Return text of a generated standard footer." | ||
| 664 | (let* ((file (semantic-grammar-buffer-file | ||
| 665 | semantic--grammar-output-buffer)) | ||
| 666 | (libr (file-name-sans-extension file)) | ||
| 667 | (out "")) | ||
| 668 | (dolist (S semantic-grammar-footer-template) | ||
| 669 | (cond ((stringp S) | ||
| 670 | (setq out (concat out S))) | ||
| 671 | ((symbolp S) | ||
| 672 | (setq out (concat out (symbol-value S)))))) | ||
| 673 | out)) | ||
| 674 | |||
| 675 | (defun semantic-grammar-token-data () | ||
| 676 | "Return the string value of the table of lexical tokens." | ||
| 677 | (semantic-grammar-as-string | ||
| 678 | (semantic-grammar-tokentable-builder))) | ||
| 679 | |||
| 680 | (defun semantic-grammar-keyword-data () | ||
| 681 | "Return the string value of the table of keywords." | ||
| 682 | (semantic-grammar-as-string | ||
| 683 | (semantic-grammar-keywordtable-builder))) | ||
| 684 | |||
| 685 | (defun semantic-grammar-parser-data () | ||
| 686 | "Return the parser table as a string value." | ||
| 687 | (semantic-grammar-as-string | ||
| 688 | (semantic-grammar-parsetable-builder))) | ||
| 689 | |||
| 690 | (defun semantic-grammar-setup-data () | ||
| 691 | "Return the parser setup code form as a string value." | ||
| 692 | (semantic-grammar-as-string | ||
| 693 | (semantic-grammar-setupcode-builder))) | ||
| 694 | |||
| 695 | ;;; Generation of lexical analyzers. | ||
| 696 | ;; | ||
| 697 | (defvar semantic-grammar--lex-block-specs) | ||
| 698 | |||
| 699 | (defsubst semantic-grammar--lex-delim-spec (block-spec) | ||
| 700 | "Return delimiters specification from BLOCK-SPEC." | ||
| 701 | (condition-case nil | ||
| 702 | (let* ((standard-input (cdr block-spec)) | ||
| 703 | (delim-spec (read))) | ||
| 704 | (if (and (consp delim-spec) | ||
| 705 | (car delim-spec) (symbolp (car delim-spec)) | ||
| 706 | (cadr delim-spec) (symbolp (cadr delim-spec))) | ||
| 707 | delim-spec | ||
| 708 | (error))) | ||
| 709 | (error | ||
| 710 | (error "Invalid delimiters specification %s in block token %s" | ||
| 711 | (cdr block-spec) (car block-spec))))) | ||
| 712 | |||
| 713 | (defun semantic-grammar--lex-block-specs () | ||
| 714 | "Compute lexical block specifications for the current buffer. | ||
| 715 | Block definitions are read from the current table of lexical types." | ||
| 716 | (cond | ||
| 717 | ;; Block specifications have been parsed and are invalid. | ||
| 718 | ((eq semantic-grammar--lex-block-specs 'error) | ||
| 719 | nil | ||
| 720 | ) | ||
| 721 | ;; Parse block specifications. | ||
| 722 | ((null semantic-grammar--lex-block-specs) | ||
| 723 | (condition-case err | ||
| 724 | (let* ((blocks (cdr (semantic-lex-type-value "block" t))) | ||
| 725 | (open-delims (cdr (semantic-lex-type-value "open-paren" t))) | ||
| 726 | (close-delims (cdr (semantic-lex-type-value "close-paren" t))) | ||
| 727 | olist clist block-spec delim-spec open-spec close-spec) | ||
| 728 | (dolist (block-spec blocks) | ||
| 729 | (setq delim-spec (semantic-grammar--lex-delim-spec block-spec) | ||
| 730 | open-spec (assq (car delim-spec) open-delims) | ||
| 731 | close-spec (assq (cadr delim-spec) close-delims)) | ||
| 732 | (or open-spec | ||
| 733 | (error "Missing open-paren token %s required by block %s" | ||
| 734 | (car delim-spec) (car block-spec))) | ||
| 735 | (or close-spec | ||
| 736 | (error "Missing close-paren token %s required by block %s" | ||
| 737 | (cdr delim-spec) (car block-spec))) | ||
| 738 | ;; build alist ((OPEN-DELIM OPEN-SYM BLOCK-SYM) ...) | ||
| 739 | (push (list (cdr open-spec) (car open-spec) (car block-spec)) | ||
| 740 | olist) | ||
| 741 | ;; build alist ((CLOSE-DELIM CLOSE-SYM) ...) | ||
| 742 | (push (list (cdr close-spec) (car close-spec)) | ||
| 743 | clist)) | ||
| 744 | (setq semantic-grammar--lex-block-specs (cons olist clist))) | ||
| 745 | (error | ||
| 746 | (setq semantic-grammar--lex-block-specs 'error) | ||
| 747 | (message "%s" (error-message-string err)) | ||
| 748 | nil)) | ||
| 749 | ) | ||
| 750 | ;; Block specifications already parsed. | ||
| 751 | (t | ||
| 752 | semantic-grammar--lex-block-specs))) | ||
| 753 | |||
| 754 | (defsubst semantic-grammar-quoted-form (exp) | ||
| 755 | "Return a quoted form of EXP if it isn't a self evaluating form." | ||
| 756 | (if (and (not (null exp)) | ||
| 757 | (or (listp exp) (symbolp exp))) | ||
| 758 | (list 'quote exp) | ||
| 759 | exp)) | ||
| 760 | |||
| 761 | (defun semantic-grammar-insert-defanalyzer (type) | ||
| 762 | "Insert declaration of the lexical analyzer defined with TYPE." | ||
| 763 | (let* ((type-name (symbol-name type)) | ||
| 764 | (type-value (symbol-value type)) | ||
| 765 | (syntax (get type 'syntax)) | ||
| 766 | (declared (get type :declared)) | ||
| 767 | spec mtype prefix name doc) | ||
| 768 | ;; Generate an analyzer if the corresponding type has been | ||
| 769 | ;; explicitly declared in a %type statement, and if at least the | ||
| 770 | ;; syntax property has been provided. | ||
| 771 | (when (and declared syntax) | ||
| 772 | (setq prefix (file-name-sans-extension | ||
| 773 | (semantic-grammar-buffer-file | ||
| 774 | semantic--grammar-output-buffer)) | ||
| 775 | mtype (or (get type 'matchdatatype) 'regexp) | ||
| 776 | name (intern (format "%s--<%s>-%s-analyzer" prefix type mtype)) | ||
| 777 | doc (format "%s analyzer for <%s> tokens." mtype type)) | ||
| 778 | (cond | ||
| 779 | ;; Regexp match analyzer | ||
| 780 | ((eq mtype 'regexp) | ||
| 781 | (semantic-grammar-insert-define | ||
| 782 | `(define-lex-regex-type-analyzer ,name | ||
| 783 | ,doc ,syntax | ||
| 784 | ,(semantic-grammar-quoted-form (cdr type-value)) | ||
| 785 | ',(or (car type-value) (intern type-name)))) | ||
| 786 | ) | ||
| 787 | ;; String compare analyzer | ||
| 788 | ((eq mtype 'string) | ||
| 789 | (semantic-grammar-insert-define | ||
| 790 | `(define-lex-string-type-analyzer ,name | ||
| 791 | ,doc ,syntax | ||
| 792 | ,(semantic-grammar-quoted-form (cdr type-value)) | ||
| 793 | ',(or (car type-value) (intern type-name)))) | ||
| 794 | ) | ||
| 795 | ;; Block analyzer | ||
| 796 | ((and (eq mtype 'block) | ||
| 797 | (setq spec (semantic-grammar--lex-block-specs))) | ||
| 798 | (semantic-grammar-insert-define | ||
| 799 | `(define-lex-block-type-analyzer ,name | ||
| 800 | ,doc ,syntax | ||
| 801 | ,(semantic-grammar-quoted-form spec))) | ||
| 802 | ) | ||
| 803 | ;; Sexp analyzer | ||
| 804 | ((eq mtype 'sexp) | ||
| 805 | (semantic-grammar-insert-define | ||
| 806 | `(define-lex-sexp-type-analyzer ,name | ||
| 807 | ,doc ,syntax | ||
| 808 | ',(or (car type-value) (intern type-name)))) | ||
| 809 | ) | ||
| 810 | ;; keyword analyzer | ||
| 811 | ((eq mtype 'keyword) | ||
| 812 | (semantic-grammar-insert-define | ||
| 813 | `(define-lex-keyword-type-analyzer ,name | ||
| 814 | ,doc ,syntax)) | ||
| 815 | ) | ||
| 816 | )) | ||
| 817 | )) | ||
| 818 | |||
| 819 | (defun semantic-grammar-insert-defanalyzers () | ||
| 820 | "Insert declarations of lexical analyzers." | ||
| 821 | (let (tokens props) | ||
| 822 | (with-current-buffer semantic--grammar-input-buffer | ||
| 823 | (setq tokens (semantic-grammar-tokens) | ||
| 824 | props (semantic-grammar-token-properties tokens))) | ||
| 825 | (insert "(require 'semantic-lex)\n\n") | ||
| 826 | (let ((semantic-lex-types-obarray | ||
| 827 | (semantic-lex-make-type-table tokens props)) | ||
| 828 | semantic-grammar--lex-block-specs) | ||
| 829 | (mapatoms 'semantic-grammar-insert-defanalyzer | ||
| 830 | semantic-lex-types-obarray)))) | ||
| 831 | |||
| 832 | ;;; Generation of the grammar support file. | ||
| 833 | ;; | ||
| 834 | (defcustom semantic-grammar-file-regexp "\\.[wb]y$" | ||
| 835 | "Regexp which matches grammar source files." | ||
| 836 | :group 'semantic | ||
| 837 | :type 'regexp) | ||
| 838 | |||
| 839 | (defsubst semantic-grammar-noninteractive () | ||
| 840 | "Return non-nil if running without interactive terminal." | ||
| 841 | (if (featurep 'xemacs) | ||
| 842 | (noninteractive) | ||
| 843 | noninteractive)) | ||
| 844 | |||
| 845 | (defun semantic-grammar-create-package (&optional force) | ||
| 846 | "Create package Lisp code from grammar in current buffer. | ||
| 847 | Does nothing if the Lisp code seems up to date. | ||
| 848 | If optional argument FORCE is non-nil, unconditionally re-generate the | ||
| 849 | Lisp code." | ||
| 850 | (interactive "P") | ||
| 851 | (setq force (or force current-prefix-arg)) | ||
| 852 | (semantic-fetch-tags) | ||
| 853 | (let* ( | ||
| 854 | ;; Values of the following local variables are obtained from | ||
| 855 | ;; the grammar parsed tree in current buffer, that is before | ||
| 856 | ;; switching to the output file. | ||
| 857 | (package (semantic-grammar-package)) | ||
| 858 | (output (concat package ".el")) | ||
| 859 | (semantic--grammar-input-buffer (current-buffer)) | ||
| 860 | (semantic--grammar-output-buffer (find-file-noselect output)) | ||
| 861 | (header (semantic-grammar-header)) | ||
| 862 | (prologue (semantic-grammar-prologue)) | ||
| 863 | (epilogue (semantic-grammar-epilogue)) | ||
| 864 | (footer (semantic-grammar-footer)) | ||
| 865 | ) | ||
| 866 | (if (and (not force) | ||
| 867 | (not (buffer-modified-p)) | ||
| 868 | (file-newer-than-file-p | ||
| 869 | (buffer-file-name semantic--grammar-output-buffer) | ||
| 870 | (buffer-file-name semantic--grammar-input-buffer))) | ||
| 871 | (message "Package `%s' is up to date." package) | ||
| 872 | ;; Create the package | ||
| 873 | (set-buffer semantic--grammar-output-buffer) | ||
| 874 | ;; Use Unix EOLs, so that the file is portable to all platforms. | ||
| 875 | (setq buffer-file-coding-system 'raw-text-unix) | ||
| 876 | (erase-buffer) | ||
| 877 | (unless (eq major-mode 'emacs-lisp-mode) | ||
| 878 | (emacs-lisp-mode)) | ||
| 879 | |||
| 880 | ;;;; Header + Prologue | ||
| 881 | |||
| 882 | (insert header | ||
| 883 | "\n;;; Prologue\n;;\n" | ||
| 884 | prologue | ||
| 885 | ) | ||
| 886 | ;; Evaluate the prologue now, because it might provide definition | ||
| 887 | ;; of grammar macro expanders. | ||
| 888 | (eval-region (point-min) (point)) | ||
| 889 | |||
| 890 | (save-excursion | ||
| 891 | |||
| 892 | ;;;; Declarations | ||
| 893 | |||
| 894 | (insert "\n;;; Declarations\n;;\n") | ||
| 895 | |||
| 896 | ;; `eval-defun' is not necessary to reset `defconst' values. | ||
| 897 | (semantic-grammar-insert-defconst | ||
| 898 | (semantic-grammar-keywordtable) | ||
| 899 | (with-current-buffer semantic--grammar-input-buffer | ||
| 900 | (semantic-grammar-keyword-data)) | ||
| 901 | "Table of language keywords.") | ||
| 902 | |||
| 903 | (semantic-grammar-insert-defconst | ||
| 904 | (semantic-grammar-tokentable) | ||
| 905 | (with-current-buffer semantic--grammar-input-buffer | ||
| 906 | (semantic-grammar-token-data)) | ||
| 907 | "Table of lexical tokens.") | ||
| 908 | |||
| 909 | (semantic-grammar-insert-defconst | ||
| 910 | (semantic-grammar-parsetable) | ||
| 911 | (with-current-buffer semantic--grammar-input-buffer | ||
| 912 | (semantic-grammar-parser-data)) | ||
| 913 | "Parser table.") | ||
| 914 | |||
| 915 | (semantic-grammar-insert-defun | ||
| 916 | (semantic-grammar-setupfunction) | ||
| 917 | (with-current-buffer semantic--grammar-input-buffer | ||
| 918 | (semantic-grammar-setup-data)) | ||
| 919 | "Setup the Semantic Parser.") | ||
| 920 | |||
| 921 | ;;;; Analyzers | ||
| 922 | (insert "\n;;; Analyzers\n;;\n") | ||
| 923 | |||
| 924 | (semantic-grammar-insert-defanalyzers) | ||
| 925 | |||
| 926 | ;;;; Epilogue & Footer | ||
| 927 | |||
| 928 | (insert "\n;;; Epilogue\n;;\n" | ||
| 929 | epilogue | ||
| 930 | footer | ||
| 931 | ) | ||
| 932 | |||
| 933 | ) | ||
| 934 | |||
| 935 | (save-buffer 16) | ||
| 936 | |||
| 937 | ;; If running in batch mode, there is nothing more to do. | ||
| 938 | ;; Save the generated file and quit. | ||
| 939 | (if (semantic-grammar-noninteractive) | ||
| 940 | (let ((version-control t) | ||
| 941 | (delete-old-versions t) | ||
| 942 | (make-backup-files t) | ||
| 943 | (vc-make-backup-files t)) | ||
| 944 | (kill-buffer (current-buffer))) | ||
| 945 | ;; If running interactively, eval declarations and epilogue | ||
| 946 | ;; code, then pop to the buffer visiting the generated file. | ||
| 947 | (eval-region (point) (point-max)) | ||
| 948 | (goto-char (point-min)) | ||
| 949 | (pop-to-buffer (current-buffer)) | ||
| 950 | ;; The generated code has been evaluated and updated into | ||
| 951 | ;; memory. Now find all buffers that match the major modes we | ||
| 952 | ;; have created this language for, and force them to call our | ||
| 953 | ;; setup function again, refreshing all semantic data, and | ||
| 954 | ;; enabling them to work with the new code just created. | ||
| 955 | ;;;; FIXME? | ||
| 956 | ;; At this point, I don't know any user's defined setup code :-( | ||
| 957 | ;; At least, what I can do for now, is to run the generated | ||
| 958 | ;; parser-install function. | ||
| 959 | (semantic-map-mode-buffers | ||
| 960 | (semantic-grammar-setupfunction) | ||
| 961 | (semantic-grammar-languagemode))) | ||
| 962 | ) | ||
| 963 | ;; Return the name of the generated package file. | ||
| 964 | output)) | ||
| 965 | |||
| 966 | (defun semantic-grammar-recreate-package () | ||
| 967 | "Unconditionnaly create Lisp code from grammar in current buffer. | ||
| 968 | Like \\[universal-argument] \\[semantic-grammar-create-package]." | ||
| 969 | (interactive) | ||
| 970 | (semantic-grammar-create-package t)) | ||
| 971 | |||
| 972 | (defun semantic-grammar-batch-build-one-package (file) | ||
| 973 | "Build a Lisp package from the grammar in FILE. | ||
| 974 | That is, generate Lisp code from FILE, and `byte-compile' it. | ||
| 975 | Return non-nil if there were no errors, nil if errors." | ||
| 976 | ;; We need this require so that we can find `byte-compile-dest-file'. | ||
| 977 | (require 'bytecomp) | ||
| 978 | (unless (auto-save-file-name-p file) | ||
| 979 | ;; Create the package | ||
| 980 | (let ((packagename | ||
| 981 | (condition-case err | ||
| 982 | (with-current-buffer (find-file-noselect file) | ||
| 983 | (semantic-grammar-create-package)) | ||
| 984 | (error | ||
| 985 | (message "%s" (error-message-string err)) | ||
| 986 | nil)))) | ||
| 987 | (when packagename | ||
| 988 | ;; Only byte compile if out of date | ||
| 989 | (if (file-newer-than-file-p | ||
| 990 | packagename (byte-compile-dest-file packagename)) | ||
| 991 | (let (;; Some complex grammar table expressions need a few | ||
| 992 | ;; more resources than the default. | ||
| 993 | (max-specpdl-size (max 3000 max-specpdl-size)) | ||
| 994 | (max-lisp-eval-depth (max 1000 max-lisp-eval-depth)) | ||
| 995 | ) | ||
| 996 | ;; byte compile the resultant file | ||
| 997 | (byte-compile-file packagename)) | ||
| 998 | t))))) | ||
| 999 | |||
| 1000 | (defun semantic-grammar-batch-build-packages () | ||
| 1001 | "Build Lisp packages from grammar files on the command line. | ||
| 1002 | That is, run `semantic-grammar-batch-build-one-package' for each file. | ||
| 1003 | Each file is processed even if an error occurred previously. | ||
| 1004 | Must be used from the command line, with `-batch'. | ||
| 1005 | For example, to process grammar files in current directory, invoke: | ||
| 1006 | |||
| 1007 | \"emacs -batch -f semantic-grammar-batch-build-packages .\". | ||
| 1008 | |||
| 1009 | See also the variable `semantic-grammar-file-regexp'." | ||
| 1010 | (or (semantic-grammar-noninteractive) | ||
| 1011 | (error "\ | ||
| 1012 | `semantic-grammar-batch-build-packages' must be used with -batch" | ||
| 1013 | )) | ||
| 1014 | (let ((status 0) | ||
| 1015 | ;; Remove vc from find-file-hook. It causes bad stuff to | ||
| 1016 | ;; happen in Emacs 20. | ||
| 1017 | (find-file-hook (delete 'vc-find-file-hook find-file-hook))) | ||
| 1018 | (message "Compiling Grammars from: %s" (locate-library "semantic-grammar")) | ||
| 1019 | (dolist (arg command-line-args-left) | ||
| 1020 | (unless (and arg (file-exists-p arg)) | ||
| 1021 | (error "Argument %s is not a valid file name" arg)) | ||
| 1022 | (setq arg (expand-file-name arg)) | ||
| 1023 | (if (file-directory-p arg) | ||
| 1024 | ;; Directory as argument | ||
| 1025 | (dolist (src (condition-case nil | ||
| 1026 | (directory-files | ||
| 1027 | arg nil semantic-grammar-file-regexp) | ||
| 1028 | (error | ||
| 1029 | (error "Unable to read directory files")))) | ||
| 1030 | (or (semantic-grammar-batch-build-one-package | ||
| 1031 | (expand-file-name src arg)) | ||
| 1032 | (setq status 1))) | ||
| 1033 | ;; Specific file argument | ||
| 1034 | (or (semantic-grammar-batch-build-one-package arg) | ||
| 1035 | (setq status 1)))) | ||
| 1036 | (kill-emacs status) | ||
| 1037 | )) | ||
| 1038 | |||
| 1039 | ;;;; | ||
| 1040 | ;;;; Macros highlighting | ||
| 1041 | ;;;; | ||
| 1042 | |||
| 1043 | (defvar semantic--grammar-macros-regexp-1 nil) | ||
| 1044 | (make-variable-buffer-local 'semantic--grammar-macros-regexp-1) | ||
| 1045 | |||
| 1046 | (defun semantic--grammar-macros-regexp-1 () | ||
| 1047 | "Return font-lock keyword regexp for pre-installed macro names." | ||
| 1048 | (and semantic-grammar-macros | ||
| 1049 | (not semantic--grammar-macros-regexp-1) | ||
| 1050 | (condition-case nil | ||
| 1051 | (setq semantic--grammar-macros-regexp-1 | ||
| 1052 | (concat "(\\s-*" | ||
| 1053 | (regexp-opt | ||
| 1054 | (mapcar #'(lambda (e) (symbol-name (car e))) | ||
| 1055 | semantic-grammar-macros) | ||
| 1056 | t) | ||
| 1057 | "\\>")) | ||
| 1058 | (error nil))) | ||
| 1059 | semantic--grammar-macros-regexp-1) | ||
| 1060 | |||
| 1061 | (defconst semantic--grammar-macdecl-re | ||
| 1062 | "\\<%use-macros\\>[ \t\r\n]+\\(\\sw\\|\\s_\\)+[ \t\r\n]+{" | ||
| 1063 | "Regexp that matches a macro declaration statement.") | ||
| 1064 | |||
| 1065 | (defvar semantic--grammar-macros-regexp-2 nil) | ||
| 1066 | (make-variable-buffer-local 'semantic--grammar-macros-regexp-2) | ||
| 1067 | |||
| 1068 | (defun semantic--grammar-clear-macros-regexp-2 (&rest ignore) | ||
| 1069 | "Clear the cached regexp that match macros local in this grammar. | ||
| 1070 | IGNORE arguments. | ||
| 1071 | Added to `before-change-functions' hooks to be run before each text | ||
| 1072 | change." | ||
| 1073 | (setq semantic--grammar-macros-regexp-2 nil)) | ||
| 1074 | |||
| 1075 | (defun semantic--grammar-macros-regexp-2 () | ||
| 1076 | "Return the regexp that match macros local in this grammar." | ||
| 1077 | (unless semantic--grammar-macros-regexp-2 | ||
| 1078 | (let (macs) | ||
| 1079 | (save-excursion | ||
| 1080 | (goto-char (point-min)) | ||
| 1081 | (while (re-search-forward semantic--grammar-macdecl-re nil t) | ||
| 1082 | (condition-case nil | ||
| 1083 | (setq macs (nconc macs | ||
| 1084 | (split-string | ||
| 1085 | (buffer-substring-no-properties | ||
| 1086 | (point) | ||
| 1087 | (progn | ||
| 1088 | (backward-char) | ||
| 1089 | (forward-list 1) | ||
| 1090 | (down-list -1) | ||
| 1091 | (point)))))) | ||
| 1092 | (error nil))) | ||
| 1093 | (when macs | ||
| 1094 | (setq semantic--grammar-macros-regexp-2 | ||
| 1095 | (concat "(\\s-*" (regexp-opt macs t) "\\>")))))) | ||
| 1096 | semantic--grammar-macros-regexp-2) | ||
| 1097 | |||
| 1098 | (defun semantic--grammar-macros-matcher (end) | ||
| 1099 | "Search for a grammar macro name to highlight. | ||
| 1100 | END is the limit of the search." | ||
| 1101 | (let ((regexp (semantic--grammar-macros-regexp-1))) | ||
| 1102 | (or (and regexp (re-search-forward regexp end t)) | ||
| 1103 | (and (setq regexp (semantic--grammar-macros-regexp-2)) | ||
| 1104 | (re-search-forward regexp end t))))) | ||
| 1105 | |||
| 1106 | ;;;; | ||
| 1107 | ;;;; Define major mode | ||
| 1108 | ;;;; | ||
| 1109 | |||
| 1110 | (defvar semantic-grammar-syntax-table | ||
| 1111 | (let ((table (make-syntax-table (standard-syntax-table)))) | ||
| 1112 | (modify-syntax-entry ?\: "." table) ;; COLON | ||
| 1113 | (modify-syntax-entry ?\> "." table) ;; GT | ||
| 1114 | (modify-syntax-entry ?\< "." table) ;; LT | ||
| 1115 | (modify-syntax-entry ?\| "." table) ;; OR | ||
| 1116 | (modify-syntax-entry ?\; ". 12" table) ;; SEMI, Comment start ;; | ||
| 1117 | (modify-syntax-entry ?\n ">" table) ;; Comment end | ||
| 1118 | (modify-syntax-entry ?\" "\"" table) ;; String | ||
| 1119 | (modify-syntax-entry ?\% "w" table) ;; Word | ||
| 1120 | (modify-syntax-entry ?\- "_" table) ;; Symbol | ||
| 1121 | (modify-syntax-entry ?\. "_" table) ;; Symbol | ||
| 1122 | (modify-syntax-entry ?\\ "\\" table) ;; Quote | ||
| 1123 | (modify-syntax-entry ?\` "'" table) ;; Prefix ` (backquote) | ||
| 1124 | (modify-syntax-entry ?\' "'" table) ;; Prefix ' (quote) | ||
| 1125 | (modify-syntax-entry ?\, "'" table) ;; Prefix , (comma) | ||
| 1126 | (modify-syntax-entry ?\# "'" table) ;; Prefix # (sharp) | ||
| 1127 | table) | ||
| 1128 | "Syntax table used in a Semantic grammar buffers.") | ||
| 1129 | |||
| 1130 | (defvar semantic-grammar-mode-hook nil | ||
| 1131 | "Hook run when starting Semantic grammar mode.") | ||
| 1132 | |||
| 1133 | (defvar semantic-grammar-mode-keywords-1 | ||
| 1134 | `(("\\(\\<%%\\>\\|\\<%[{}]\\)" | ||
| 1135 | 0 font-lock-reference-face) | ||
| 1136 | ("\\(%\\)\\(\\(\\sw\\|\\s_\\)+\\)" | ||
| 1137 | (1 font-lock-reference-face) | ||
| 1138 | (2 font-lock-keyword-face)) | ||
| 1139 | ("\\<error\\>" | ||
| 1140 | 0 (unless (semantic-grammar-in-lisp-p) 'bold)) | ||
| 1141 | ("^\\(\\(\\sw\\|\\s_\\)+\\)[ \n\r\t]*:" | ||
| 1142 | 1 font-lock-function-name-face) | ||
| 1143 | (semantic--grammar-macros-matcher | ||
| 1144 | 1 ,(if (boundp 'font-lock-builtin-face) | ||
| 1145 | 'font-lock-builtin-face | ||
| 1146 | 'font-lock-preprocessor-face)) | ||
| 1147 | ("\\$\\(\\sw\\|\\s_\\)*" | ||
| 1148 | 0 font-lock-variable-name-face) | ||
| 1149 | ("<\\(\\(\\sw\\|\\s_\\)+\\)>" | ||
| 1150 | 1 font-lock-type-face) | ||
| 1151 | (,semantic-grammar-lex-c-char-re | ||
| 1152 | 0 ,(if (boundp 'font-lock-constant-face) | ||
| 1153 | 'font-lock-constant-face | ||
| 1154 | 'font-lock-string-face) t) | ||
| 1155 | ;; Must highlight :keyword here, because ':' is a punctuation in | ||
| 1156 | ;; grammar mode! | ||
| 1157 | ("[\r\n\t ]+:\\sw+\\>" | ||
| 1158 | 0 font-lock-builtin-face) | ||
| 1159 | ;; Append the Semantic keywords | ||
| 1160 | ,@semantic-fw-font-lock-keywords | ||
| 1161 | ) | ||
| 1162 | "Font Lock keywords used to highlight Semantic grammar buffers.") | ||
| 1163 | |||
| 1164 | (defvar semantic-grammar-mode-keywords-2 | ||
| 1165 | (append semantic-grammar-mode-keywords-1 | ||
| 1166 | lisp-font-lock-keywords-1) | ||
| 1167 | "Font Lock keywords used to highlight Semantic grammar buffers.") | ||
| 1168 | |||
| 1169 | (defvar semantic-grammar-mode-keywords-3 | ||
| 1170 | (append semantic-grammar-mode-keywords-1 | ||
| 1171 | lisp-font-lock-keywords-2) | ||
| 1172 | "Font Lock keywords used to highlight Semantic grammar buffers.") | ||
| 1173 | |||
| 1174 | (defvar semantic-grammar-mode-keywords | ||
| 1175 | semantic-grammar-mode-keywords-1 | ||
| 1176 | "Font Lock keywords used to highlight Semantic grammar buffers.") | ||
| 1177 | |||
| 1178 | (defvar semantic-grammar-map | ||
| 1179 | (let ((km (make-sparse-keymap))) | ||
| 1180 | |||
| 1181 | (define-key km "|" 'semantic-grammar-electric-punctuation) | ||
| 1182 | (define-key km ";" 'semantic-grammar-electric-punctuation) | ||
| 1183 | (define-key km "%" 'semantic-grammar-electric-punctuation) | ||
| 1184 | (define-key km "(" 'semantic-grammar-electric-punctuation) | ||
| 1185 | (define-key km ")" 'semantic-grammar-electric-punctuation) | ||
| 1186 | (define-key km ":" 'semantic-grammar-electric-punctuation) | ||
| 1187 | |||
| 1188 | (define-key km "\t" 'semantic-grammar-indent) | ||
| 1189 | (define-key km "\M-\t" 'semantic-grammar-complete) | ||
| 1190 | (define-key km "\C-c\C-c" 'semantic-grammar-create-package) | ||
| 1191 | (define-key km "\C-cm" 'semantic-grammar-find-macro-expander) | ||
| 1192 | (define-key km "\C-cik" 'semantic-grammar-insert-keyword) | ||
| 1193 | ;; (define-key km "\C-cc" 'semantic-grammar-generate-and-load) | ||
| 1194 | ;; (define-key km "\C-cr" 'semantic-grammar-generate-one-rule) | ||
| 1195 | |||
| 1196 | km) | ||
| 1197 | "Keymap used in `semantic-grammar-mode'.") | ||
| 1198 | |||
| 1199 | (defvar semantic-grammar-menu | ||
| 1200 | '("Grammar" | ||
| 1201 | ["Indent Line" semantic-grammar-indent] | ||
| 1202 | ["Complete Symbol" semantic-grammar-complete] | ||
| 1203 | ["Find Macro" semantic-grammar-find-macro-expander] | ||
| 1204 | "--" | ||
| 1205 | ["Insert %keyword" semantic-grammar-insert-keyword] | ||
| 1206 | "--" | ||
| 1207 | ["Update Lisp Package" semantic-grammar-create-package] | ||
| 1208 | ["Recreate Lisp Package" semantic-grammar-recreate-package] | ||
| 1209 | ) | ||
| 1210 | "Common semantic grammar menu.") | ||
| 1211 | |||
| 1212 | (defun semantic-grammar-setup-menu-emacs (symbol mode-menu) | ||
| 1213 | "Setup a GNU Emacs grammar menu in variable SYMBOL. | ||
| 1214 | MODE-MENU is an optional specific menu whose items are appended to the | ||
| 1215 | common grammar menu." | ||
| 1216 | (let ((items (make-symbol "items"))) | ||
| 1217 | `(unless (boundp ',symbol) | ||
| 1218 | (easy-menu-define ,symbol (current-local-map) | ||
| 1219 | "Grammar Menu" semantic-grammar-menu) | ||
| 1220 | (let ((,items (cdr ,mode-menu))) | ||
| 1221 | (when ,items | ||
| 1222 | (easy-menu-add-item ,symbol nil "--") | ||
| 1223 | (while ,items | ||
| 1224 | (easy-menu-add-item ,symbol nil (car ,items)) | ||
| 1225 | (setq ,items (cdr ,items)))))) | ||
| 1226 | )) | ||
| 1227 | |||
| 1228 | (defun semantic-grammar-setup-menu-xemacs (symbol mode-menu) | ||
| 1229 | "Setup an XEmacs grammar menu in variable SYMBOL. | ||
| 1230 | MODE-MENU is an optional specific menu whose items are appended to the | ||
| 1231 | common grammar menu." | ||
| 1232 | (let ((items (make-symbol "items")) | ||
| 1233 | (path (make-symbol "path"))) | ||
| 1234 | `(progn | ||
| 1235 | (unless (boundp ',symbol) | ||
| 1236 | (easy-menu-define ,symbol nil | ||
| 1237 | "Grammar Menu" (copy-sequence semantic-grammar-menu))) | ||
| 1238 | (easy-menu-add ,symbol) | ||
| 1239 | (let ((,items (cdr ,mode-menu)) | ||
| 1240 | (,path (list (car ,symbol)))) | ||
| 1241 | (when ,items | ||
| 1242 | (easy-menu-add-item nil ,path "--") | ||
| 1243 | (while ,items | ||
| 1244 | (easy-menu-add-item nil ,path (car ,items)) | ||
| 1245 | (setq ,items (cdr ,items)))))) | ||
| 1246 | )) | ||
| 1247 | |||
| 1248 | (defmacro semantic-grammar-setup-menu (&optional mode-menu) | ||
| 1249 | "Setup a mode local grammar menu. | ||
| 1250 | MODE-MENU is an optional specific menu whose items are appended to the | ||
| 1251 | common grammar menu." | ||
| 1252 | (let ((menu (intern (format "%s-menu" major-mode)))) | ||
| 1253 | (if (featurep 'xemacs) | ||
| 1254 | (semantic-grammar-setup-menu-xemacs menu mode-menu) | ||
| 1255 | (semantic-grammar-setup-menu-emacs menu mode-menu)))) | ||
| 1256 | |||
| 1257 | (defsubst semantic-grammar-in-lisp-p () | ||
| 1258 | "Return non-nil if point is in Lisp code." | ||
| 1259 | (or (>= (point) (semantic-grammar-epilogue-start)) | ||
| 1260 | (condition-case nil | ||
| 1261 | (save-excursion | ||
| 1262 | (up-list -1) | ||
| 1263 | t) | ||
| 1264 | (error nil)))) | ||
| 1265 | |||
| 1266 | (defun semantic-grammar-edits-new-change-hook-fcn (overlay) | ||
| 1267 | "Function set into `semantic-edits-new-change-hook'. | ||
| 1268 | Argument OVERLAY is the overlay created to mark the change. | ||
| 1269 | When OVERLAY marks a change in the scope of a nonterminal tag extend | ||
| 1270 | the change bounds to encompass the whole nonterminal tag." | ||
| 1271 | (let ((outer (car (semantic-find-tag-by-overlay-in-region | ||
| 1272 | (semantic-edits-os overlay) | ||
| 1273 | (semantic-edits-oe overlay))))) | ||
| 1274 | (if (semantic-tag-of-class-p outer 'nonterminal) | ||
| 1275 | (semantic-overlay-move overlay | ||
| 1276 | (semantic-tag-start outer) | ||
| 1277 | (semantic-tag-end outer))))) | ||
| 1278 | |||
| 1279 | (defun semantic-grammar-mode () | ||
| 1280 | "Initialize a buffer for editing Semantic grammars. | ||
| 1281 | |||
| 1282 | \\{semantic-grammar-map}" | ||
| 1283 | (interactive) | ||
| 1284 | (kill-all-local-variables) | ||
| 1285 | (setq major-mode 'semantic-grammar-mode | ||
| 1286 | mode-name "Semantic Grammar Framework") | ||
| 1287 | (set (make-local-variable 'parse-sexp-ignore-comments) t) | ||
| 1288 | (set (make-local-variable 'comment-start) ";;") | ||
| 1289 | ;; Look within the line for a ; following an even number of backslashes | ||
| 1290 | ;; after either a non-backslash or the line beginning. | ||
| 1291 | (set (make-local-variable 'comment-start-skip) | ||
| 1292 | "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *") | ||
| 1293 | (set-syntax-table semantic-grammar-syntax-table) | ||
| 1294 | (use-local-map semantic-grammar-map) | ||
| 1295 | (set (make-local-variable 'indent-line-function) | ||
| 1296 | 'semantic-grammar-indent) | ||
| 1297 | (set (make-local-variable 'fill-paragraph-function) | ||
| 1298 | 'lisp-fill-paragraph) | ||
| 1299 | (set (make-local-variable 'font-lock-multiline) | ||
| 1300 | 'undecided) | ||
| 1301 | (set (make-local-variable 'font-lock-defaults) | ||
| 1302 | '((semantic-grammar-mode-keywords | ||
| 1303 | semantic-grammar-mode-keywords-1 | ||
| 1304 | semantic-grammar-mode-keywords-2 | ||
| 1305 | semantic-grammar-mode-keywords-3) | ||
| 1306 | nil ;; perform string/comment fontification | ||
| 1307 | nil ;; keywords are case sensitive. | ||
| 1308 | ;; This puts _ & - as a word constituant, | ||
| 1309 | ;; simplifying our keywords significantly | ||
| 1310 | ((?_ . "w") (?- . "w")))) | ||
| 1311 | ;; Setup Semantic to parse grammar | ||
| 1312 | (semantic-grammar-wy--install-parser) | ||
| 1313 | (setq semantic-lex-comment-regex ";;" | ||
| 1314 | semantic-lex-analyzer 'semantic-grammar-lexer | ||
| 1315 | semantic-type-relation-separator-character '(":") | ||
| 1316 | semantic-symbol->name-assoc-list | ||
| 1317 | '( | ||
| 1318 | (code . "Setup Code") | ||
| 1319 | (keyword . "Keyword") | ||
| 1320 | (token . "Token") | ||
| 1321 | (nonterminal . "Nonterminal") | ||
| 1322 | (rule . "Rule") | ||
| 1323 | )) | ||
| 1324 | (set (make-local-variable 'semantic-format-face-alist) | ||
| 1325 | '( | ||
| 1326 | (code . default) | ||
| 1327 | (keyword . font-lock-keyword-face) | ||
| 1328 | (token . font-lock-type-face) | ||
| 1329 | (nonterminal . font-lock-function-name-face) | ||
| 1330 | (rule . default) | ||
| 1331 | )) | ||
| 1332 | (set (make-local-variable 'semantic-stickyfunc-sticky-classes) | ||
| 1333 | '(nonterminal)) | ||
| 1334 | ;; Before each change, clear the cached regexp used to highlight | ||
| 1335 | ;; macros local in this grammar. | ||
| 1336 | (semantic-make-local-hook 'before-change-functions) | ||
| 1337 | (add-hook 'before-change-functions | ||
| 1338 | 'semantic--grammar-clear-macros-regexp-2 nil t) | ||
| 1339 | ;; Handle safe re-parse of grammar rules. | ||
| 1340 | (semantic-make-local-hook 'semantic-edits-new-change-hooks) | ||
| 1341 | (add-hook 'semantic-edits-new-change-hooks | ||
| 1342 | 'semantic-grammar-edits-new-change-hook-fcn | ||
| 1343 | nil t) | ||
| 1344 | (semantic-run-mode-hooks 'semantic-grammar-mode-hook)) | ||
| 1345 | |||
| 1346 | ;;;; | ||
| 1347 | ;;;; Useful commands | ||
| 1348 | ;;;; | ||
| 1349 | |||
| 1350 | (defvar semantic-grammar-skip-quoted-syntax-table | ||
| 1351 | (let ((st (copy-syntax-table semantic-grammar-syntax-table))) | ||
| 1352 | (modify-syntax-entry ?\' "$" st) | ||
| 1353 | st) | ||
| 1354 | "Syntax table to skip a whole quoted expression in grammar code. | ||
| 1355 | Consider quote as a \"paired delimiter\", so `forward-sexp' will skip | ||
| 1356 | whole quoted expression.") | ||
| 1357 | |||
| 1358 | (defsubst semantic-grammar-backward-item () | ||
| 1359 | "Move point to beginning of the previous grammar item." | ||
| 1360 | (forward-comment (- (point-max))) | ||
| 1361 | (if (zerop (skip-syntax-backward ".")) | ||
| 1362 | (if (eq (char-before) ?\') | ||
| 1363 | (with-syntax-table | ||
| 1364 | ;; Can't be Lisp code here! Temporarily consider quote | ||
| 1365 | ;; as a "paired delimiter", so `forward-sexp' can skip | ||
| 1366 | ;; the whole quoted expression. | ||
| 1367 | semantic-grammar-skip-quoted-syntax-table | ||
| 1368 | (forward-sexp -1)) | ||
| 1369 | (forward-sexp -1)))) | ||
| 1370 | |||
| 1371 | (defun semantic-grammar-anchored-indentation () | ||
| 1372 | "Return indentation based on previous anchor character found." | ||
| 1373 | (let (indent) | ||
| 1374 | (save-excursion | ||
| 1375 | (while (not indent) | ||
| 1376 | (semantic-grammar-backward-item) | ||
| 1377 | (cond | ||
| 1378 | ((bobp) | ||
| 1379 | (setq indent 0)) | ||
| 1380 | ((looking-at ":\\(\\s-\\|$\\)") | ||
| 1381 | (setq indent (current-column)) | ||
| 1382 | (forward-char) | ||
| 1383 | (skip-syntax-forward "-") | ||
| 1384 | (if (eolp) (setq indent 2)) | ||
| 1385 | ) | ||
| 1386 | ((and (looking-at "[;%]") | ||
| 1387 | (not (looking-at "\\<%prec\\>"))) | ||
| 1388 | (setq indent 0) | ||
| 1389 | )))) | ||
| 1390 | indent)) | ||
| 1391 | |||
| 1392 | (defun semantic-grammar-do-grammar-indent () | ||
| 1393 | "Indent a line of grammar. | ||
| 1394 | When called the point is not in Lisp code." | ||
| 1395 | (let (indent n) | ||
| 1396 | (save-excursion | ||
| 1397 | (beginning-of-line) | ||
| 1398 | (skip-syntax-forward "-") | ||
| 1399 | (setq indent (current-column)) | ||
| 1400 | (cond | ||
| 1401 | ((or (bobp) | ||
| 1402 | (looking-at "\\(\\w\\|\\s_\\)+\\s-*:") | ||
| 1403 | (and (looking-at "%") | ||
| 1404 | (not (looking-at "%prec\\>")))) | ||
| 1405 | (setq n 0)) | ||
| 1406 | ((looking-at ":") | ||
| 1407 | (setq n 2)) | ||
| 1408 | ((and (looking-at ";;") | ||
| 1409 | (save-excursion (forward-comment (point-max)) | ||
| 1410 | (looking-at ":"))) | ||
| 1411 | (setq n 1)) | ||
| 1412 | (t | ||
| 1413 | (setq n (semantic-grammar-anchored-indentation)) | ||
| 1414 | (unless (zerop n) | ||
| 1415 | (cond | ||
| 1416 | ((looking-at ";;") | ||
| 1417 | (setq n (1- n))) | ||
| 1418 | ((looking-at "[|;]") | ||
| 1419 | ) | ||
| 1420 | (t | ||
| 1421 | (setq n (+ n 2))))))) | ||
| 1422 | (when (/= n indent) | ||
| 1423 | (beginning-of-line) | ||
| 1424 | (delete-horizontal-space) | ||
| 1425 | (indent-to n))))) | ||
| 1426 | |||
| 1427 | (defvar semantic-grammar-brackets-as-parens-syntax-table | ||
| 1428 | (let ((st (copy-syntax-table emacs-lisp-mode-syntax-table))) | ||
| 1429 | (modify-syntax-entry ?\{ "(} " st) | ||
| 1430 | (modify-syntax-entry ?\} "){ " st) | ||
| 1431 | st) | ||
| 1432 | "Syntax table that consider brackets as parenthesis. | ||
| 1433 | So `lisp-indent-line' will work inside bracket blocks.") | ||
| 1434 | |||
| 1435 | (defun semantic-grammar-do-lisp-indent () | ||
| 1436 | "Maybe run the Emacs Lisp indenter on a line of code. | ||
| 1437 | Return nil if not in a Lisp expression." | ||
| 1438 | (condition-case nil | ||
| 1439 | (save-excursion | ||
| 1440 | (beginning-of-line) | ||
| 1441 | (skip-chars-forward "\t ") | ||
| 1442 | (let ((first (point))) | ||
| 1443 | (or (>= first (semantic-grammar-epilogue-start)) | ||
| 1444 | (up-list -1)) | ||
| 1445 | (condition-case nil | ||
| 1446 | (while t | ||
| 1447 | (up-list -1)) | ||
| 1448 | (error nil)) | ||
| 1449 | (beginning-of-line) | ||
| 1450 | (save-restriction | ||
| 1451 | (narrow-to-region (point) first) | ||
| 1452 | (goto-char (point-max)) | ||
| 1453 | (with-syntax-table | ||
| 1454 | ;; Temporarily consider brackets as parenthesis so | ||
| 1455 | ;; `lisp-indent-line' can indent Lisp code inside | ||
| 1456 | ;; brackets. | ||
| 1457 | semantic-grammar-brackets-as-parens-syntax-table | ||
| 1458 | (lisp-indent-line)))) | ||
| 1459 | t) | ||
| 1460 | (error nil))) | ||
| 1461 | |||
| 1462 | (defun semantic-grammar-indent () | ||
| 1463 | "Indent the current line. | ||
| 1464 | Use the Lisp or grammar indenter depending on point location." | ||
| 1465 | (interactive) | ||
| 1466 | (let ((orig (point)) | ||
| 1467 | first) | ||
| 1468 | (or (semantic-grammar-do-lisp-indent) | ||
| 1469 | (semantic-grammar-do-grammar-indent)) | ||
| 1470 | (setq first (save-excursion | ||
| 1471 | (beginning-of-line) | ||
| 1472 | (skip-chars-forward "\t ") | ||
| 1473 | (point))) | ||
| 1474 | (if (or (< orig first) (/= orig (point))) | ||
| 1475 | (goto-char first)))) | ||
| 1476 | |||
| 1477 | (defun semantic-grammar-electric-punctuation () | ||
| 1478 | "Insert and reindent for the symbol just typed in." | ||
| 1479 | (interactive) | ||
| 1480 | (self-insert-command 1) | ||
| 1481 | (save-excursion | ||
| 1482 | (semantic-grammar-indent))) | ||
| 1483 | |||
| 1484 | (defun semantic-grammar-complete () | ||
| 1485 | "Attempt to complete the symbol under point. | ||
| 1486 | Completion is position sensitive. If the cursor is in a match section of | ||
| 1487 | a rule, then nonterminals symbols are scanned. If the cursor is in a Lisp | ||
| 1488 | expression then Lisp symbols are completed." | ||
| 1489 | (interactive) | ||
| 1490 | (if (semantic-grammar-in-lisp-p) | ||
| 1491 | ;; We are in lisp code. Do lisp completion. | ||
| 1492 | (lisp-complete-symbol) | ||
| 1493 | ;; We are not in lisp code. Do rule completion. | ||
| 1494 | (let* ((nonterms (semantic-find-tags-by-class 'nonterminal (current-buffer))) | ||
| 1495 | (sym (car (semantic-ctxt-current-symbol))) | ||
| 1496 | (ans (try-completion sym nonterms))) | ||
| 1497 | (cond ((eq ans t) | ||
| 1498 | ;; All done | ||
| 1499 | (message "Symbols is already complete")) | ||
| 1500 | ((and (stringp ans) (string= ans sym)) | ||
| 1501 | ;; Max matchable. Show completions. | ||
| 1502 | (with-output-to-temp-buffer "*Completions*" | ||
| 1503 | (display-completion-list (all-completions sym nonterms))) | ||
| 1504 | ) | ||
| 1505 | ((stringp ans) | ||
| 1506 | ;; Expand the completions | ||
| 1507 | (forward-sexp -1) | ||
| 1508 | (delete-region (point) (progn (forward-sexp 1) (point))) | ||
| 1509 | (insert ans)) | ||
| 1510 | (t (message "No Completions.")) | ||
| 1511 | )) | ||
| 1512 | )) | ||
| 1513 | |||
| 1514 | (defun semantic-grammar-insert-keyword (name) | ||
| 1515 | "Insert a new %keyword declaration with NAME. | ||
| 1516 | Assumes it is typed in with the correct casing." | ||
| 1517 | (interactive "sKeyword: ") | ||
| 1518 | (if (not (bolp)) (insert "\n")) | ||
| 1519 | (insert "%keyword " (upcase name) " \"" name "\" | ||
| 1520 | %put " (upcase name) " summary | ||
| 1521 | \"\"\n") | ||
| 1522 | (forward-char -2)) | ||
| 1523 | |||
| 1524 | ;;; Macro facilities | ||
| 1525 | ;; | ||
| 1526 | |||
| 1527 | (defsubst semantic--grammar-macro-function-tag (name) | ||
| 1528 | "Search for a function tag for the grammar macro with name NAME. | ||
| 1529 | Return the tag found or nil if not found." | ||
| 1530 | (car (semantic-find-tags-by-class | ||
| 1531 | 'function | ||
| 1532 | (or (semantic-find-tags-by-name name (current-buffer)) | ||
| 1533 | (and (featurep 'semanticdb) | ||
| 1534 | semanticdb-current-database | ||
| 1535 | (cdar (semanticdb-find-tags-by-name name nil t))))))) | ||
| 1536 | |||
| 1537 | (defsubst semantic--grammar-macro-lib-part (def) | ||
| 1538 | "Return the library part of the grammar macro defined by DEF." | ||
| 1539 | (let ((suf (format "-%s\\'" (regexp-quote (symbol-name (car def))))) | ||
| 1540 | (fun (symbol-name (cdr def)))) | ||
| 1541 | (substring fun 0 (string-match suf fun)))) | ||
| 1542 | |||
| 1543 | (defun semantic--grammar-macro-compl-elt (def &optional full) | ||
| 1544 | "Return a completion entry for the grammar macro defined by DEF. | ||
| 1545 | If optional argument FULL is non-nil qualify the macro name with the | ||
| 1546 | library found in DEF." | ||
| 1547 | (let ((mac (car def)) | ||
| 1548 | (lib (semantic--grammar-macro-lib-part def))) | ||
| 1549 | (cons (if full | ||
| 1550 | (format "%s/%s" mac lib) | ||
| 1551 | (symbol-name mac)) | ||
| 1552 | (list mac lib)))) | ||
| 1553 | |||
| 1554 | (defun semantic--grammar-macro-compl-dict () | ||
| 1555 | "Return a completion dictionnary of macro definitions." | ||
| 1556 | (let ((defs (semantic-grammar-macros)) | ||
| 1557 | def dups dict) | ||
| 1558 | (while defs | ||
| 1559 | (setq def (car defs) | ||
| 1560 | defs (cdr defs)) | ||
| 1561 | (if (or (assoc (car def) defs) (assoc (car def) dups)) | ||
| 1562 | (push def dups) | ||
| 1563 | (push (semantic--grammar-macro-compl-elt def) dict))) | ||
| 1564 | (while dups | ||
| 1565 | (setq def (car dups) | ||
| 1566 | dups (cdr dups)) | ||
| 1567 | (push (semantic--grammar-macro-compl-elt def t) dict)) | ||
| 1568 | dict)) | ||
| 1569 | |||
| 1570 | (defun semantic-grammar-find-macro-expander (macro-name library) | ||
| 1571 | "Visit the Emacs Lisp library where a grammar macro is implemented. | ||
| 1572 | MACRO-NAME is a symbol that identifies a grammar macro. | ||
| 1573 | LIBRARY is the name (sans extension) of the Emacs Lisp library where | ||
| 1574 | to start searching the macro implementation. Lookup in included | ||
| 1575 | libraries, if necessary. | ||
| 1576 | Find a function tag (in current tags table) whose name contains MACRO-NAME. | ||
| 1577 | Select the buffer containing the tag's definition, and move point there." | ||
| 1578 | (interactive | ||
| 1579 | (let* ((dic (semantic--grammar-macro-compl-dict)) | ||
| 1580 | (def (assoc (completing-read "Macro: " dic nil 1) dic))) | ||
| 1581 | (or (cdr def) '(nil nil)))) | ||
| 1582 | (when (and macro-name library) | ||
| 1583 | (let* ((lib (format "%s.el" library)) | ||
| 1584 | (buf (find-file-noselect (or (locate-library lib t) lib))) | ||
| 1585 | (tag (with-current-buffer buf | ||
| 1586 | (semantic--grammar-macro-function-tag | ||
| 1587 | (format "%s-%s" library macro-name))))) | ||
| 1588 | (if tag | ||
| 1589 | (progn | ||
| 1590 | (require 'semantic/decorate) | ||
| 1591 | (pop-to-buffer (semantic-tag-buffer tag)) | ||
| 1592 | (goto-char (semantic-tag-start tag)) | ||
| 1593 | (semantic-momentary-highlight-tag tag)) | ||
| 1594 | (pop-to-buffer buf) | ||
| 1595 | (message "No expander found in library %s for macro %s" | ||
| 1596 | library macro-name))))) | ||
| 1597 | |||
| 1598 | ;;; Additional help | ||
| 1599 | ;; | ||
| 1600 | |||
| 1601 | (defvar semantic-grammar-syntax-help | ||
| 1602 | `( | ||
| 1603 | ;; Lexical Symbols | ||
| 1604 | ("symbol" . "Syntax: A symbol of alpha numeric and symbol characters") | ||
| 1605 | ("number" . "Syntax: Numeric characters.") | ||
| 1606 | ("punctuation" . "Syntax: Punctuation character.") | ||
| 1607 | ("semantic-list" . "Syntax: A list delimited by any valid list characters") | ||
| 1608 | ("open-paren" . "Syntax: Open Parenthesis character") | ||
| 1609 | ("close-paren" . "Syntax: Close Parenthesis character") | ||
| 1610 | ("string" . "Syntax: String character delimited text") | ||
| 1611 | ("comment" . "Syntax: Comment character delimited text") | ||
| 1612 | ;; Special Macros | ||
| 1613 | ("EMPTY" . "Syntax: Match empty text") | ||
| 1614 | ("ASSOC" . "Lambda Key: (ASSOC key1 value1 key2 value2 ...)") | ||
| 1615 | ("EXPAND" . "Lambda Key: (EXPAND <list id> <rule>)") | ||
| 1616 | ("EXPANDFULL" . "Lambda Key: (EXPANDFULL <list id> <rule>)") | ||
| 1617 | ;; Tag Generator Macros | ||
| 1618 | ("TAG" . "Generic Tag Generation: (TAG <name> <tag-class> [ :key value ]*)") | ||
| 1619 | ("VARIABLE-TAG" . "(VARIABLE-TAG <name> <lang-type> <default-value> [ :key value ]*)") | ||
| 1620 | ("FUNCTION-TAG" . "(FUNCTION-TAG <name> <lang-type> <arg-list> [ :key value ]*)") | ||
| 1621 | ("TYPE-TAG" . "(TYPE-TAG <name> <lang-type> <part-list> <parents> [ :key value ]*)") | ||
| 1622 | ("INCLUDE-TAG" . "(INCLUDE-TAG <name> <system-flag> [ :key value ]*)") | ||
| 1623 | ("PACKAGE-TAG" . "(PACKAGE-TAG <name> <detail> [ :key value ]*)") | ||
| 1624 | ("CODE-TAG" . "(CODE-TAG <name> <detail> [ :key value ]*)") | ||
| 1625 | ("ALIAS-TAG" . "(ALIAS-TAG <name> <aliasclass> <definition> [:key value]*)") | ||
| 1626 | ;; Special value macros | ||
| 1627 | ("$1" . "Match Value: Value from match list in slot 1") | ||
| 1628 | ("$2" . "Match Value: Value from match list in slot 2") | ||
| 1629 | ("$3" . "Match Value: Value from match list in slot 3") | ||
| 1630 | ("$4" . "Match Value: Value from match list in slot 4") | ||
| 1631 | ("$5" . "Match Value: Value from match list in slot 5") | ||
| 1632 | ("$6" . "Match Value: Value from match list in slot 6") | ||
| 1633 | ("$7" . "Match Value: Value from match list in slot 7") | ||
| 1634 | ("$8" . "Match Value: Value from match list in slot 8") | ||
| 1635 | ("$9" . "Match Value: Value from match list in slot 9") | ||
| 1636 | ;; Same, but with annoying , in front. | ||
| 1637 | (",$1" . "Match Value: Value from match list in slot 1") | ||
| 1638 | (",$2" . "Match Value: Value from match list in slot 2") | ||
| 1639 | (",$3" . "Match Value: Value from match list in slot 3") | ||
| 1640 | (",$4" . "Match Value: Value from match list in slot 4") | ||
| 1641 | (",$5" . "Match Value: Value from match list in slot 5") | ||
| 1642 | (",$6" . "Match Value: Value from match list in slot 6") | ||
| 1643 | (",$7" . "Match Value: Value from match list in slot 7") | ||
| 1644 | (",$8" . "Match Value: Value from match list in slot 8") | ||
| 1645 | (",$9" . "Match Value: Value from match list in slot 9") | ||
| 1646 | ) | ||
| 1647 | "Association of syntax elements, and the corresponding help.") | ||
| 1648 | |||
| 1649 | (defun semantic-grammar-eldoc-get-macro-docstring (macro expander) | ||
| 1650 | "Return a one-line docstring for the given grammar MACRO. | ||
| 1651 | EXPANDER is the name of the function that expands MACRO." | ||
| 1652 | (require 'eldoc) | ||
| 1653 | (if (and (eq expander (aref eldoc-last-data 0)) | ||
| 1654 | (eq 'function (aref eldoc-last-data 2))) | ||
| 1655 | (aref eldoc-last-data 1) | ||
| 1656 | (let ((doc (help-split-fundoc (documentation expander t) expander))) | ||
| 1657 | (cond | ||
| 1658 | (doc | ||
| 1659 | (setq doc (car doc)) | ||
| 1660 | (string-match "\\`[^ )]* ?" doc) | ||
| 1661 | (setq doc (concat "(" (substring doc (match-end 0))))) | ||
| 1662 | (t | ||
| 1663 | (setq doc (eldoc-function-argstring expander)))) | ||
| 1664 | (when doc | ||
| 1665 | (setq doc | ||
| 1666 | (eldoc-docstring-format-sym-doc | ||
| 1667 | macro (format "==> %s %s" expander doc) 'default)) | ||
| 1668 | (eldoc-last-data-store expander doc 'function)) | ||
| 1669 | doc))) | ||
| 1670 | |||
| 1671 | (define-mode-local-override semantic-idle-summary-current-symbol-info | ||
| 1672 | semantic-grammar-mode () | ||
| 1673 | "Display additional eldoc information about grammar syntax elements. | ||
| 1674 | Syntax element is the current symbol at point. | ||
| 1675 | If it is associated a help string in `semantic-grammar-syntax-help', | ||
| 1676 | return that string. | ||
| 1677 | If it is a macro name, return a description of the associated expander | ||
| 1678 | function parameter list. | ||
| 1679 | If it is a function name, return a description of this function | ||
| 1680 | parameter list. | ||
| 1681 | It it is a variable name, return a brief (one-line) documentation | ||
| 1682 | string for the variable. | ||
| 1683 | If a default description of the current context can be obtained, | ||
| 1684 | return it. | ||
| 1685 | Otherwise return nil." | ||
| 1686 | (require 'eldoc) | ||
| 1687 | (let* ((elt (car (semantic-ctxt-current-symbol))) | ||
| 1688 | (val (and elt (cdr (assoc elt semantic-grammar-syntax-help))))) | ||
| 1689 | (when (and (not val) elt (semantic-grammar-in-lisp-p)) | ||
| 1690 | ;; Ensure to load macro definitions before doing `intern-soft'. | ||
| 1691 | (setq val (semantic-grammar-macros) | ||
| 1692 | elt (intern-soft elt) | ||
| 1693 | val (and elt (cdr (assq elt val)))) | ||
| 1694 | (cond | ||
| 1695 | ;; Grammar macro | ||
| 1696 | ((and val (fboundp val)) | ||
| 1697 | (setq val (semantic-grammar-eldoc-get-macro-docstring elt val))) | ||
| 1698 | ;; Function | ||
| 1699 | ((and elt (fboundp elt)) | ||
| 1700 | (setq val (eldoc-get-fnsym-args-string elt))) | ||
| 1701 | ;; Variable | ||
| 1702 | ((and elt (boundp elt)) | ||
| 1703 | (setq val (eldoc-get-var-docstring elt))) | ||
| 1704 | (t nil))) | ||
| 1705 | (or val (semantic-idle-summary-current-symbol-info-default)))) | ||
| 1706 | |||
| 1707 | (define-mode-local-override semantic-tag-boundary-p | ||
| 1708 | semantic-grammar-mode (tag) | ||
| 1709 | "Return non-nil for tags that should have a boundary drawn. | ||
| 1710 | Only tags of type 'nonterminal will be so marked." | ||
| 1711 | (let ((c (semantic-tag-class tag))) | ||
| 1712 | (eq c 'nonterminal))) | ||
| 1713 | |||
| 1714 | (define-mode-local-override semantic-ctxt-current-function | ||
| 1715 | semantic-grammar-mode (&optional point) | ||
| 1716 | "Determine the name of the current function at POINT." | ||
| 1717 | (save-excursion | ||
| 1718 | (and point (goto-char point)) | ||
| 1719 | (when (semantic-grammar-in-lisp-p) | ||
| 1720 | (with-mode-local emacs-lisp-mode | ||
| 1721 | (semantic-ctxt-current-function))))) | ||
| 1722 | |||
| 1723 | (define-mode-local-override semantic-ctxt-current-argument | ||
| 1724 | semantic-grammar-mode (&optional point) | ||
| 1725 | "Determine the argument index of the called function at POINT." | ||
| 1726 | (save-excursion | ||
| 1727 | (and point (goto-char point)) | ||
| 1728 | (when (semantic-grammar-in-lisp-p) | ||
| 1729 | (with-mode-local emacs-lisp-mode | ||
| 1730 | (semantic-ctxt-current-argument))))) | ||
| 1731 | |||
| 1732 | (define-mode-local-override semantic-ctxt-current-assignment | ||
| 1733 | semantic-grammar-mode (&optional point) | ||
| 1734 | "Determine the tag being assigned into at POINT." | ||
| 1735 | (save-excursion | ||
| 1736 | (and point (goto-char point)) | ||
| 1737 | (when (semantic-grammar-in-lisp-p) | ||
| 1738 | (with-mode-local emacs-lisp-mode | ||
| 1739 | (semantic-ctxt-current-assignment))))) | ||
| 1740 | |||
| 1741 | (define-mode-local-override semantic-ctxt-current-class-list | ||
| 1742 | semantic-grammar-mode (&optional point) | ||
| 1743 | "Determine the class of tags that can be used at POINT." | ||
| 1744 | (save-excursion | ||
| 1745 | (and point (goto-char point)) | ||
| 1746 | (if (semantic-grammar-in-lisp-p) | ||
| 1747 | (with-mode-local emacs-lisp-mode | ||
| 1748 | (semantic-ctxt-current-class-list)) | ||
| 1749 | '(nonterminal keyword)))) | ||
| 1750 | |||
| 1751 | (define-mode-local-override semantic-ctxt-current-mode | ||
| 1752 | semantic-grammar-mode (&optional point) | ||
| 1753 | "Return the major mode active at POINT. | ||
| 1754 | POINT defaults to the value of point in current buffer. | ||
| 1755 | Return `emacs-lisp-mode' is POINT is within Lisp code, otherwise | ||
| 1756 | return the current major mode." | ||
| 1757 | (save-excursion | ||
| 1758 | (and point (goto-char point)) | ||
| 1759 | (if (semantic-grammar-in-lisp-p) | ||
| 1760 | 'emacs-lisp-mode | ||
| 1761 | (semantic-ctxt-current-mode-default)))) | ||
| 1762 | |||
| 1763 | (define-mode-local-override semantic-format-tag-abbreviate | ||
| 1764 | semantic-grammar-mode (tag &optional parent color) | ||
| 1765 | "Return a string abbreviation of TAG. | ||
| 1766 | Optional PARENT is not used. | ||
| 1767 | Optional COLOR is used to flag if color is added to the text." | ||
| 1768 | (let ((class (semantic-tag-class tag)) | ||
| 1769 | (name (semantic-format-tag-name tag parent color))) | ||
| 1770 | (cond | ||
| 1771 | ((eq class 'nonterminal) | ||
| 1772 | (concat name ":")) | ||
| 1773 | ((eq class 'setting) | ||
| 1774 | "%settings%") | ||
| 1775 | ((memq class '(rule keyword)) | ||
| 1776 | name) | ||
| 1777 | (t | ||
| 1778 | (concat "%" (symbol-name class) " " name))))) | ||
| 1779 | |||
| 1780 | (define-mode-local-override semantic-format-tag-summarize | ||
| 1781 | semantic-grammar-mode (tag &optional parent color) | ||
| 1782 | "Return a string summarizing TAG. | ||
| 1783 | Optional PARENT is not used. | ||
| 1784 | Optional argument COLOR determines if color is added to the text." | ||
| 1785 | (let ((class (semantic-tag-class tag)) | ||
| 1786 | (name (semantic-format-tag-name tag parent color)) | ||
| 1787 | (label nil) | ||
| 1788 | (desc nil)) | ||
| 1789 | (cond | ||
| 1790 | ((eq class 'nonterminal) | ||
| 1791 | (setq label "Nonterminal: " | ||
| 1792 | desc (format | ||
| 1793 | " with %d match lists." | ||
| 1794 | (length (semantic-tag-components tag))))) | ||
| 1795 | ((eq class 'keyword) | ||
| 1796 | (setq label "Keyword: ") | ||
| 1797 | (let (summary) | ||
| 1798 | (semantic--find-tags-by-function | ||
| 1799 | #'(lambda (put) | ||
| 1800 | (unless summary | ||
| 1801 | (setq summary (cdr (assoc "summary" | ||
| 1802 | (semantic-tag-get-attribute | ||
| 1803 | put :value)))))) | ||
| 1804 | ;; Get `put' tag with TAG name. | ||
| 1805 | (semantic-find-tags-by-name-regexp | ||
| 1806 | (regexp-quote (semantic-tag-name tag)) | ||
| 1807 | (semantic-find-tags-by-class 'put (current-buffer)))) | ||
| 1808 | (setq desc (concat " = " | ||
| 1809 | (semantic-tag-get-attribute tag :value) | ||
| 1810 | (if summary | ||
| 1811 | (concat " - " (read summary)) | ||
| 1812 | ""))))) | ||
| 1813 | ((eq class 'token) | ||
| 1814 | (setq label "Token: ") | ||
| 1815 | (let ((val (semantic-tag-get-attribute tag :value)) | ||
| 1816 | (names (semantic-tag-get-attribute tag :rest)) | ||
| 1817 | (type (semantic-tag-type tag))) | ||
| 1818 | (if names | ||
| 1819 | (setq name (mapconcat 'identity (cons name names) " "))) | ||
| 1820 | (setq desc (concat | ||
| 1821 | (if type | ||
| 1822 | (format " <%s>" type) | ||
| 1823 | "") | ||
| 1824 | (if val | ||
| 1825 | (format "%s%S" val (if type " " "")) | ||
| 1826 | ""))))) | ||
| 1827 | ((eq class 'assoc) | ||
| 1828 | (setq label "Assoc: ") | ||
| 1829 | (let ((val (semantic-tag-get-attribute tag :value)) | ||
| 1830 | (type (semantic-tag-type tag))) | ||
| 1831 | (setq desc (concat | ||
| 1832 | (if type | ||
| 1833 | (format " <%s>" type) | ||
| 1834 | "") | ||
| 1835 | (if val | ||
| 1836 | (concat " " (mapconcat 'identity val " ")) | ||
| 1837 | ""))))) | ||
| 1838 | (t | ||
| 1839 | (setq desc (semantic-format-tag-abbreviate tag parent color)))) | ||
| 1840 | (if (and color label) | ||
| 1841 | (setq label (semantic--format-colorize-text label 'label))) | ||
| 1842 | (if (and color label desc) | ||
| 1843 | (setq desc (semantic--format-colorize-text desc 'comment))) | ||
| 1844 | (if label | ||
| 1845 | (concat label name desc) | ||
| 1846 | ;; Just a description is the abbreviated version | ||
| 1847 | desc))) | ||
| 1848 | |||
| 1849 | ;;; Semantic Analysis | ||
| 1850 | |||
| 1851 | (define-mode-local-override semantic-analyze-current-context | ||
| 1852 | semantic-grammar-mode (point) | ||
| 1853 | "Provide a semantic analysis object describing a context in a grammar." | ||
| 1854 | (require 'semantic/analyze) | ||
| 1855 | (if (semantic-grammar-in-lisp-p) | ||
| 1856 | (with-mode-local emacs-lisp-mode | ||
| 1857 | (semantic-analyze-current-context point)) | ||
| 1858 | |||
| 1859 | (let* ((context-return nil) | ||
| 1860 | (prefixandbounds (semantic-ctxt-current-symbol-and-bounds)) | ||
| 1861 | (prefix (car prefixandbounds)) | ||
| 1862 | (bounds (nth 2 prefixandbounds)) | ||
| 1863 | (prefixsym nil) | ||
| 1864 | (prefixclass (semantic-ctxt-current-class-list)) | ||
| 1865 | ) | ||
| 1866 | |||
| 1867 | ;; Do context for rules when in a match list. | ||
| 1868 | (setq prefixsym | ||
| 1869 | (semantic-find-first-tag-by-name | ||
| 1870 | (car prefix) | ||
| 1871 | (current-buffer))) | ||
| 1872 | |||
| 1873 | (setq context-return | ||
| 1874 | (semantic-analyze-context | ||
| 1875 | "context-for-semantic-grammar" | ||
| 1876 | :buffer (current-buffer) | ||
| 1877 | :scope nil | ||
| 1878 | :bounds bounds | ||
| 1879 | :prefix (if prefixsym | ||
| 1880 | (list prefixsym) | ||
| 1881 | prefix) | ||
| 1882 | :prefixtypes nil | ||
| 1883 | :prefixclass prefixclass | ||
| 1884 | )) | ||
| 1885 | |||
| 1886 | context-return))) | ||
| 1887 | |||
| 1888 | (define-mode-local-override semantic-analyze-possible-completions | ||
| 1889 | semantic-grammar-mode (context) | ||
| 1890 | "Return a list of possible completions based on CONTEXT." | ||
| 1891 | (require 'semantic/analyze/complete) | ||
| 1892 | (if (semantic-grammar-in-lisp-p) | ||
| 1893 | (with-mode-local emacs-lisp-mode | ||
| 1894 | (semantic-analyze-possible-completions context)) | ||
| 1895 | (save-excursion | ||
| 1896 | (set-buffer (oref context buffer)) | ||
| 1897 | (let* ((prefix (car (oref context :prefix))) | ||
| 1898 | (completetext (cond ((semantic-tag-p prefix) | ||
| 1899 | (semantic-tag-name prefix)) | ||
| 1900 | ((stringp prefix) | ||
| 1901 | prefix) | ||
| 1902 | ((stringp (car prefix)) | ||
| 1903 | (car prefix)))) | ||
| 1904 | (tags (semantic-find-tags-for-completion completetext | ||
| 1905 | (current-buffer)))) | ||
| 1906 | (semantic-analyze-tags-of-class-list | ||
| 1907 | tags (oref context prefixclass))) | ||
| 1908 | ))) | ||
| 1909 | |||
| 1910 | (provide 'semantic/grammar) | ||
| 1911 | |||
| 1912 | ;;; semantic/grammar.el ends here | ||