From e47650852b8aa4da6d0b0cea3b5421955795cc64 Mon Sep 17 00:00:00 2001 From: Blendoit Date: Sat, 1 Aug 2020 15:24:03 -0700 Subject: Definitely /not/ including elpa/, that would be chaos. --- elpa/gnuplot-20200322.53/gnuplot-context.el | 2216 --------------------------- 1 file changed, 2216 deletions(-) delete mode 100644 elpa/gnuplot-20200322.53/gnuplot-context.el (limited to 'elpa/gnuplot-20200322.53/gnuplot-context.el') diff --git a/elpa/gnuplot-20200322.53/gnuplot-context.el b/elpa/gnuplot-20200322.53/gnuplot-context.el deleted file mode 100644 index 7b067b7..0000000 --- a/elpa/gnuplot-20200322.53/gnuplot-context.el +++ /dev/null @@ -1,2216 +0,0 @@ -;;; gnuplot-context.el -- context-sensitive help and completion for gnuplot - -;; Copyright (C) 2012-2013 Jon Oddie - -;; Author: Jon Oddie -;; URL: https://github.com/emacsorphanage/gnuplot - -;; This file is not part of GNU Emacs. - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; -;; This file enhances gnuplot-mode with context-sensitive completion, -;; ElDoc support, and info page lookup for gnuplot script and shell -;; buffers. -;; -;; Usage -;; ===== -;; -;; Make sure to byte-compile this file, or things will be noticeably -;; slow. -;; -;; Summary of key bindings: -;; C-c C-d read info page for construction at point -;; C-u C-c C-d prompt for info page to read -;; C-c M-h, C-c C-/ pop up multi-line ElDoc string for construction -;; at point -;; -;; Gnuplot's context sensitive mode is best controlled using Customize -;; (M-x customize-group gnuplot): simply enable the -;; `gnuplot-context-sensitive-mode' setting. On recent Emacs (>= 23), -;; you may also want to turn on `gnuplot-tab-completion' so that the -;; TAB key does auto-completion on lines which are already -;; indented. (This just sets the Emacs variable `tab-always-indent' to -;; `complete' in Gnuplot buffers). -;; -;; If you need to turn context sensitivity on or off from Lisp code -;; for some reason, call the function -;; `gnuplot-context-sensitive-mode', which behaves like a minor mode. -;; -;; With `eldoc-mode' support, gnuplot-mode will show one-line syntax -;; hints automatically in the echo area. Whether eldoc-mode is active -;; or not, you can always pop up a longer description of syntax using -;; `gnuplot-help-function' (C-c C-/ or C-c M-h). ElDoc support also -;; requires an additional file of help strings, `gnuplot-eldoc.el', -;; which should be included in recent Gnuplot releases. If it didn't -;; come with your Gnuplot installation, you'll need to grab a recent -;; source distribution of Gnuplot from http://gnuplot.info, and use -;; the `doc2texi.el' program in the docs/ directory to create it. So -;; long as the file is on your Emacs load path somewhere it will be -;; loaded automatically when needed. -;; -;; You can customize gnuplot-mode to turn on eldoc mode automatically -;; using variable `gnuplot-eldoc-mode'. Simply calling `eldoc-mode' -;; will also work. -;; -;; Internal details -;; ================ -;; -;; Gnuplot's command language has a fair amount of syntactic -;; complexity, and the only way I could think of to support these -;; features was to do a complete parse of the command line. So that's -;; what this package does. Instead of building a parse tree, it -;; matches up until the token at point, and then either makes a list -;; of possible completions, or sets the variables `gnuplot-eldoc' and -;; `gnuplot-info-at-point' based on where it is in the grammar at that -;; point. -;; -;; The parsing/matching process happens in two phases: tokenizing -;; (`gnuplot-tokenize') and matching (`gnuplot-match-pattern'). In -;; order to be able to construct a full list of possible completions -;; via backtracking, the matching algorithm simulates a simple stack -;; machine with continuations. At byte-compile time, the PEG-like -;; grammar in S-expression notation (`gnuplot-grammar') is compiled -;; down into a vector of "machine code" for the parsing machine (see -;; `gnuplot-compile-pattern', `gnuplot-compile-grammar' and -;; `gnuplot-compiled-grammar'). This is complicated, but it seems to -;; work well enough, and it saves on the Emacs call stack. -;; -;; Compiling the grammar does require increasing `max-lisp-eval-depth' -;; modestly. This shouldn't cause any problems on modern machines, and -;; it only needs to be done once, at byte-compilation time. -;; -;; The parsing machine and compiler are partially based on the -;; description in Medeiros and Ierusalimschy 2008, "A Parsing Machine -;; for PEGs" (http://dl.acm.org/citation.cfm?doid=1408681.1408683). -;; -;; The pattern-matching language -;; ============================= -;; -;; The gnuplot-mode grammar (see `gnuplot-compiled-grammar') is a list -;; of rules (RULE PATTERN), with each pattern written in S-expression -;; notation as follows: -;; -;; any -;; Match any token -;; -;; name, number, string, separator -;; Match a token of the given type. "Separator" is semicolon, the -;; statement separator. -;; -;; Any other symbol -;; Match another named rule in the grammar. May be recursive. -;; -;; "STRING" -;; Match literally: a token with exactly the text "STRING". -;; -;; (kw KEYWORD ALIASES ...) -;; Match abbreviated Gnuplot keywords. KEYWORD can be a string or -;; a cons (PREFIX . SUFFIX). In the latter case, this pattern -;; will match PREFIX plus any number of characters from the -;; beginning of SUFFIX. Any literal string from ALIASES will -;; also match. The token-id of the matching token is mutated to -;; the canonical value of KEYWORD. -;; Example: -;; (kw ("linew" ."idth") "lw") matches "linew", "linewi", -;; ... "linewidth" as well as "lw". Any of these tokens will -;; appear as "linewidth" in subsequent processing. (This is -;; important for the "info-keyword" form, see below). -;; -;; The other pattern forms combine simpler patterns, much like regular -;; expressions or PEGs (parsing expression grammars): -;; -;; (sequence { (:eldoc "eldoc string") } -;; { (:info "info page") } -;; { (:no-info) } -;; PATTERN PATTERN... ) -;; Match all the PATTERNs in sequence or fail. Sequences can also -;; have optional ElDoc strings and info pages associated with -;; them; the innermost ElDoc or info page around point is the one -;; shown to the user. Alternatively, either property may be a -;; symbol, which should be a function to be called to get the -;; real value. Finally, if no ElDoc string is specified but the -;; variable `gnuplot-eldoc-hash' contains a value for the name of -;; the info page at point, that value is used as the ElDoc string -;; instead. -;; -;; For better readability, sequence forms can also be written as -;; a vector, omitting the `sequence': [PATTERN PATTERN ...] -;; -;; (either PATTERN PATTERN...) -;; Match the first PATTERN to succeed, or fail if none -;; matches. Like regexp `|'. -;; -;; (many PATTERN) -;; Match PATTERN zero or more times, greedily; like regexp -;; `*'. Unlike a regular expression matcher, the parsing machine -;; will not backtrack and try to match fewer times if a later -;; part of the pattern fails. This applies equally to the other -;; non-deterministic forms "either" and "maybe". -;; -;; (maybe PATTERN) -;; Match PATTERN zero or one times, like regexp `?'. -;; -;; (capture NAME PATTERN) -;; Match PATTERN, capturing the tokens in a capture group named -;; NAME. Capture groups are stored in `gnuplot-captures' -;; and can be retrieved using `gnuplot-capture-group'. This is -;; used to store the plotting style, which we need in order to -;; give the correct ElDoc string for "using" clauses, and for -;; info keywords (see below) -;; -;; (info-keyword PATTERN) -;; Match PATTERN, and use whatever the value of the first token -;; it matches is to look up info pages for this pattern. Most -;; Gnuplot info pages have the same name as the keyword they -;; document, so by using this we only have to put :info -;; properties on the few that don't, such as "set". -;; -;; For convenience, "many", "maybe", "capture" and "info-keyword" -;; wrap the rest of their arguments in an implicit "sequence" form, -;; so we can write (maybe "," expression) instead of -;; (maybe (sequence "," expression)) -;; -;; (delimited-list PATTERN SEPARATOR) -;; Match a list of PATTERNs separated by SEPARATOR. Sugar for: -;; (sequence PATTERN (many (sequence SEPARATOR PATTERN))) -;; -;; (assert LISP-FORM) -;; Evaluate LISP-FORM and fail if it returns NIL. We need this in -;; the patterns for "plot" and "splot" to check whether the -;; command at point should be parsed in parametric mode or -;; not. See `gnuplot-guess-parametric-p'. -;; -;; -;; Bugs, TODOs, etc. -;; ======================= -;; -;; It would be useful to complete on user-defined functions and -;; variables as well as built-ins. -;; -;; Completion probably will not work in continuation lines entered -;; into the gnuplot interaction buffer. -;; -;; It would be better to pop up longer syntax descriptions in a -;; temporary window, rather than making the echo area grow to fit -;; many lines. -;; -;; In ElDoc mode, we parse the whole line every time the user stops -;; typing. This is wasteful; should cache things in text properties -;; instead. -;; -;; The pattern matching engine uses backtracking, which can take -;; exponential time. So far it seems "fast enough" in actual use. -;; -;; The patterns don't really distinguish between "plot" and "splot" -;; for things like plot styles, binary arguments, etc. -;; -;; Some other the patterns are probably not quite right, especially for -;; things like abbreviated keywords, and features that I don't use -;; myself like "fit". Hopefully anyone bothered by this will submit -;; patches ;-) -;; -;; It would be possible to provide more helpful ElDoc strings for -;; sub-parts of complicated options like "cntrparam". This is a time -;; and maintenance issue rather than a technical one. - -;;; Code: - - -;; Library dependencies -(eval-when-compile - (require 'cl) - - ;; Prevent compiler warnings about undefined functions - (require 'gnuplot)) - -;; We need ElDoc support -(require 'eldoc) - -;; Compatibility for Emacs version < 23 -(eval-when-compile - (when (not (fboundp 'string-match-p)) - (defmacro string-match-p (&rest args) - `(save-match-data (string-match ,@args))))) - - -;;;; The tokenizer. - -(defstruct gnuplot-token - start ; Buffer start position - end ; Buffer end position - id ; Text - type) ; a symbol: name, number, string, operator, separator - -(defvar gnuplot-operator-regexp - (eval-when-compile - (regexp-opt - '("(" ")" "(" ")" "{" "," "}" "[" ":" "]" "!" "**" "-" "+" "~" "!" "*" "/" - "%" "+" "-" "." "<" "<=" ">" ">=" "==" "!=" "eq" "ne" "&" "^" "|" "&&" "||" - "?" ":" "=" "$"))) - "Regexp to match Gnuplot operators for tokenizing.") - -(eval-when-compile - (defmacro gnuplot-tokenize-by-regexps (&rest rules) - `(cond ,@(mapcar - (lambda (rule) - (let ((regexp (car rule)) - (token-type (cadr rule))) - `((looking-at ,regexp) - (let ((str (match-string-no-properties 0))) - (forward-char (length str)) - (make-gnuplot-token :id str - :type ',token-type - :start (match-beginning 0) - :end (match-end 0)))))) - rules)))) - -(defun gnuplot-tokenize (&optional completing-p) - "Tokenize the Gnuplot command at point. -Return a list of `gnuplot-token' objects. - -If COMPLETING-P is non-nil, omits the token at point if it is a -name; otherwise continues tokenizing up to the token at point. FIXME." - (let ((tokens '()) - (stop-point (min (point) - (gnuplot-point-at-end-of-command)))) - (save-excursion - (if (save-excursion ; HACK FIXME - (gnuplot-beginning-of-continuation) - (looking-at "\\s-*if\\s-*(")) - (gnuplot-beginning-of-continuation) - (gnuplot-beginning-of-command)) - (while - ;; Skip whitespace and continuation lines - (progn - (skip-syntax-forward "-" stop-point) - (while (looking-at "\\\\\n") - (forward-line) - (skip-syntax-forward "-" stop-point)) - ;; Don't tokenize anything starting after point - (and (not (looking-at "#")) - (< (point) stop-point))) - (let* ((from (point)) - (token - (cond - ((gnuplot-tokenize-by-regexps - ("[A-Za-z_][A-Za-z0-9_]*" name) - ("[0-9]+\\(\\.[0-9]*\\)?\\([eE][+-]?[0-9]+\\)?\\|\\.[0-9]+\\([eE][+-]?[0-9]+\\)?" number) - (gnuplot-operator-regexp operator) - (";" separator))) - - ((looking-at "['\"]") - (let* ((bounds (bounds-of-thing-at-point 'sexp)) - (to (or (cdr bounds) stop-point))) - (goto-char to) - (make-gnuplot-token - :id (buffer-substring-no-properties from to) - :type 'string - :start from :end to))) - - (t (error - "Gnuplot-tokenize: bad token beginning %s" - (buffer-substring-no-properties (point) stop-point)))))) - - (push token tokens)))) - - ;; If we are looking for completions, AND if the last token - ;; read is a name, AND if point is within the bounds of the - ;; last token, then discard it. The matching function - ;; generates a list of all possible tokens that could appear - ;; in that position for completion. - (if (and completing-p - tokens - (eq (gnuplot-token-type (car tokens)) 'name) - (<= (point) (gnuplot-token-end (car tokens)))) - (pop tokens)) - - (nreverse tokens))) - - - -;;;; The pattern and grammar compiler -;; -;; These functions compile the source S-expression grammar into a -;; vector of instructions for the parsing machine, -;; `gnuplot-match-pattern'. Its state consists of a program counter -;; (PC), a position in the list of tokens, a call stack, and a second -;; stack of backtracking entries (continuations). Its "machine -;; instructions" are the following: -;; -;; (any) -;; Match any token (fails only at end of command). -;; -;; (literal LITERAL NO-COMPLETE) -;; Match token with `gnuplot-token-id' LITERAL or fail. If we -;; have reached the token before point, include LITERAL in the -;; completion list unless NO-COMPLETE is non-`nil'. -;; -;; (token-type TYPE) -;; Match a token with `gnuplot-token-type' TYPE, or fail. -;; -;; (keyword REGEXP NAME) -;; Match any token whose `gnuplot-token-id' matches REGEXP. Use -;; NAME for the completion list. -;; -;; (jump OFFSET FIXED) -;; Jump to (set PC to) OFFSET if FIXED is non-nil, otherwise to -;; PC + OFFSET -;; -;; (call OFFSET FIXED) -;; Like "jump", but push a return address onto the stack for -;; (return). (The compiler adds the name of the rule being called -;; as a fourth element on the end of the list, but this is just a -;; comment for debugging purposes). -;; -;; (return) -;; Return to the PC address on top of the stack, or finish -;; matching if stack is empty. (Usually this doesn't happen, -;; because the machine stops as soon as it gets to the token at -;; point). -;; -;; (choice OFFSET) -;; Push a backtracking entry for location PC + OFFSET onto the -;; backtracking stack. Backtracking entries save the contents of -;; the call stack, position in the token list, the values of -;; capture groups, and the record of loop progress (see below). -;; -;; (check-progress) -;; Break out of infinite loops, like (many (many ...)). Checks -;; an alist of conses (pc . tokens) for the position in the token -;; stream the last time this instruction was reached, and breaks -;; out of the loop if stuck in the same place; otherwise pushes a -;; new entry onto the list. -;; -;; (fail) -;; Pop the most recent backtracking entry and continue from -;; there, or fail the whole match if out of backtrack -;; points. Failing to match returns the remainder of the token -;; list, although we don't currently use this for anything. -;; -;; (commit OFFSET) -;; Discard one backtracking point and jump to PC + OFFSET. This -;; is used to make the (either) form non-deterministic. -;; -;; (push TYPE VALUE) -;; Push an entry for an eldoc or info string (specified by TYPE) -;; onto the stack. -;; -;; (pop TYPE) -;; Pop something off the stack; checks that it has the expected -;; TYPE, for safety. -;; -;; (save-start NAME) -;; Open a capture group named NAME. Pushes an entry onto -;; `gnuplot-captures' with current position in token list as the -;; start of the group. -;; -;; (save-end NAME) -;; Close the capture group named NAME. Finds the topmost entry in -;; `gnuplot-captures' with this name and sets its endpoint to the -;; current position in token list. Error if no group with that -;; name is found. -;; -;; (label NAME) -;; This should never be reached and will cause an error. The -;; compiler inserts it at the beginning of compiled rules only -;; for debugging purposes. -;; - - -(eval-and-compile - ;; Compile a single pattern into a list of instructions. Leaves - ;; calls to other rules as symbolic instructions (call SYMBOL) and - ;; jumps, commits etc. as relative offsets; these are resolved into - ;; absolute locations by `gnuplot-compile-grammar', below. - (defun gnuplot-compile-pattern (pat) - (cond - ;; Strings match a single token literally - ((stringp pat) - ;; Don't add non-words to completion lists - (let ((wordp (string-match-p "^\\sw\\(\\sw\\|\\s_\\)*$" pat))) - `((literal ,pat ,(not wordp))))) - - ;; Symbols match token types or calls to other patterns - ((symbolp pat) - (case pat - ((any) `((any))) - ((name number string separator) `((token-type ,pat))) - (t `((call ,pat))))) - - ;; Syntactic sugar: write sequences (sequence ...) as vectors [...] - ((vectorp pat) - (gnuplot-compile-pattern - (append '(sequence) pat '()))) - - ;; Other forms combine simpler patterns - (t - (let ((type (car pat))) - (case type - ;; (sequence...): concatenate patterns, with optional eldoc - ;; and info strings - ((sequence) - (destructuring-bind - (subpats eldoc info) - (gnuplot-filter-arg-list (cdr pat)) - (let ((eldoc-push '()) (eldoc-pop '()) - (info-push '()) (info-pop '()) - (compiled - (mapcar 'gnuplot-compile-pattern subpats))) - (if eldoc - (setq eldoc-push `((push eldoc ,eldoc)) - eldoc-pop `((pop eldoc)))) - (if info - (if (eq info :no-info) - (setq info-push '((push no-scan t)) - info-pop '((pop no-scan))) - (setq info-push `((push info ,info)) - info-pop `((pop info))))) - (apply 'append - `(,info-push - ,eldoc-push - ,@compiled - ,eldoc-pop - ,info-pop))))) - - ;; (either...): choose between patterns - ((either) - (cond - ((= (length pat) 2) ; trivial case - (gnuplot-compile-pattern (cadr pat))) - - ((> (length pat) 3) ; could be more efficient... - (gnuplot-compile-pattern (gnuplot-either-helper pat))) - - (t ; two patterns - (let* ((pat1 (cadr pat)) - (pat2 (caddr pat)) - (pat1-c (gnuplot-compile-pattern pat1)) - (pat2-c (gnuplot-compile-pattern pat2)) - (pat1-l (length pat1-c)) - (pat2-l (length pat2-c))) - `((choice ,(+ pat1-l 2)) - ,@pat1-c - (commit ,(+ pat2-l 1)) - ,@pat2-c))))) - - ;; Repetition (*) - ((many) - (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1)) - (pat1-l (length pat1-c))) - `((choice ,(+ pat1-l 3)) - (check-progress) ; bail out of infinite loops - ,@pat1-c - (commit ,(- (+ pat1-l 2)))))) - - ;; Repetition (+) - ((many1) - (let* ((pat1 (cdr pat))) - (gnuplot-compile-pattern - `(sequence ,@pat1 (many ,@pat1))))) - - - ;; Optional (?) - ((maybe) - (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1)) - (pat1-l (length pat1-c))) - `((choice ,(+ pat1-l 1)) - ,@pat1-c))) - - ;; Syntactic sugar for delimited lists - ((delimited-list) - (let* ((item (cadr pat)) - (sep (caddr pat))) - (gnuplot-compile-pattern - `(sequence ,item (many (sequence ,sep ,item)))))) - - ;; keywords - ((kw) - (destructuring-bind (regex name) - (gnuplot-keyword-helper (cdr pat)) - `((keyword ,regex ,name)))) - - ;; Capturing groups - ((capture) - (let* ((name (cadr pat)) - (pat1 (cons 'sequence (cddr pat))) - (pat1-c (gnuplot-compile-pattern pat1))) - `((save-start ,name) - ,@pat1-c - (save-end ,name)))) - - ;; Use the first token as an info keyword - ((info-keyword) - (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1))) - `((push info first-token) - ,@pat1-c - (pop info)))) - - ;; Assertions - ((assert) - (let* ((form (cadr pat))) - `((assert ,form)))) - - (t - (error "Gnuplot-compile-pattern: bad pattern form %s" pat))))))) - - ;; Helper function for destructuring (sequence ...) forms in patterns - ;; Takes the cdr of the sequence form, returns a list (PATTERNS ELDOC - ;; INFO). - (defun gnuplot-filter-arg-list (args) - (let ((accum '()) - (eldoc nil) (info nil)) - (dolist (item args) - (let ((type (car-safe item))) - (case type - ((:eldoc) (setq eldoc (cadr item))) - ((:no-info) (setq info :no-info)) ; inhibit stack scanning - ((:info) (setq info (cadr item))) - (t (push item accum))))) - (list (reverse accum) eldoc info))) - - ;; Helper function for compiling (kw...) patterns - ;; Takes the cdr of the kw form, returns a list (REGEXP KEYWORD) - (defun gnuplot-keyword-helper (args) - (let ((keyword (car args)) (aliases (cdr args))) - (when (consp keyword) - (let ((pre (car keyword)) (suf (cdr keyword))) - (setq keyword (concat pre suf)) - (while (progn - (push pre aliases) - (not (zerop (length suf)))) - (setq pre (concat pre (substring suf 0 1)) - suf (substring suf 1))))) - (let ((regex - (concat "^" - (regexp-opt (cons keyword aliases)) - "$"))) - (list regex keyword)))) - - ;; Helper function for compiling (either ...) patterns. Rewrites - ;; alternates (either A B C) into (either A (either B (either C D))) - (defun gnuplot-either-helper (pat) - (if (= (length pat) 3) - pat - `(either ,(cadr pat) - ,(gnuplot-either-helper - (cons 'either (cddr pat)))))) - - ;; Compile the grammar (a list of rule-pattern pairs (RULE PATTERN)) - ;; into a single vector of matching-machine instructions. Compiles - ;; each pattern individually, then "links" them into one vector, - ;; converting symbolic (call ...) instructions into numeric offsets - (defun gnuplot-compile-grammar (grammar start-symbol) - (let ((compiled-pats '()) ; Alist of (name . instructions) - ;; Reserve space for a jump to the start symbol - (code-length 1)) - - ;; Compile each rule and find the total number of instructions - (dolist (item grammar) - (let* ((name (car item)) - (pat (cadr item)) - (code (gnuplot-compile-pattern pat))) - (push (cons name code) compiled-pats) - ;; Reserve space for a label at the beginning and (return) at - ;; the end - (setq code-length (+ code-length 2 (length code))))) - - ;; Copy instructions into a single vector - (let ((object-code (make-vector code-length nil)) - (name->offset (make-hash-table)) - (i 1)) - (setf (aref object-code 0) `(jump ,start-symbol)) - (dolist (chunk compiled-pats) - (let ((name (car chunk)) - (code (cdr chunk))) - (setf (aref object-code i) `(label ,name)) - (incf i) - (puthash name i name->offset) - (while code - (setf (aref object-code i) (car code) - code (cdr code) - i (1+ i))) - (setf (aref object-code i) '(return) - i (1+ i)))) - - ;; Resolve symbolic and relative jumps - (let ((pattern-name nil)) - (dotimes (i (length object-code)) - (let ((inst (aref object-code i))) - (case (car inst) - ((label) - (setq pattern-name (cadr inst))) - - ((jump call choice commit) - (cond - ((symbolp (cadr inst)) - (let* ((name (cadr inst)) - (location (gethash name name->offset))) - (if (not location) - (error - (concat "gnuplot-compile-grammar: " - "No rule found for symbol `%s' in pattern `%s'") - name pattern-name)) - (setcdr inst `(,location ,name)))) - - ((numberp (cadr inst)) - (let* ((offset (cadr inst)) - (location (+ offset i))) - (setcdr inst `(,location)))) - - (t - (error "Gnuplot-compile-grammar: bad instruction %s" inst)))))))) - object-code)))) - -;;; The grammar. -(defvar gnuplot-compiled-grammar - (eval-when-compile - (let ((max-lisp-eval-depth 600)) - (gnuplot-compile-grammar - '((expression - [infix-expression (maybe "?" expression ":" expression)]) - - (prefix-operator - (either "!" "~" "-" "+")) - - (infix-operator - (either "**" "*" "/" "%" "+" "-" "." "<" "<=" ">" ">=" "==" "!=" "eq" "ne" - "&" "^" "|" "&&" "||")) - - (infix-expression - [(many prefix-operator) - primary-expression - (many infix-operator expression)]) - - (primary-expression - [(either number string parenthesized-expression - column-ref complex-number function-call name) - (many "!") - (maybe "**" infix-expression) - (maybe substring-range)]) - - (function-call - (either - (info-keyword - [(either "abs" "acos" "acosh" "arg" "asin" "asinh" "atan" "atan2" "atanh" - "besj0" "besj1" "besy0" "besy1" "ceil" "column" "columnhead" - "cos" "cosh" "defined" "erf" "erfc" "exists" "exp" "floor" - "gamma" "gprintf" "ibeta" "igamma" "imag" "int" "inverf" - "invnorm" "lambertw" "lgamma" "log" "log10" "norm" "real" - "sgn" "sin" "sinh" "sprintf" "sqrt" "strftime" "stringcolumn" - "strlen" "strptime" "strstrt" "substr" "tan" "tanh" "timecolumn" - "tm_hour" "tm_mday" "tm_min" "tm_mon" "tm_sec" "tm_wday" - "tm_yday" "tm_year" "valid" "value" "word" "words" "rand") - parenthesized-expression]) - [(:info "elliptic_integrals") - (either "EllipticK" "EllipticE" "EllipticPi") - parenthesized-expression] - [name - parenthesized-expression])) - - (parenthesized-expression - ["(" comma-list ")"]) - - (complex-number - ["{" (maybe "-") number "," (maybe "-") number "}"]) - - (column-ref - ["$" number]) - - (substring-range-component - (maybe (either "*" expression))) - - (substring-range - ["[" (delimited-list substring-range-component ":" 2 2) "]"]) - -;;; Assignments - (lhs - [name (maybe "(" (delimited-list name "," 1) ")")]) - - (assignment - [lhs "=" (either assignment expression)]) - -;;; Lists of expressions - (comma-list - (delimited-list (either assignment expression) ",")) - - (colon-list - (delimited-list expression ":")) - - (tuple - ["(" (delimited-list expression "," 2 3) ")"]) - -;;; Commands - (command - (info-keyword - (either plot-command splot-command replot-command fit-command print-command - set-command cd-command call-command simple-command - eval-command load-command lower-raise-command pause-command - save-command system-command test-command undefine-command - update-command assignment if-command new-if-command do-command))) - - (command-list - (delimited-list command separator)) - - (block ["{" command-list (maybe separator) "}"]) - -;;; old-style one-line if(..) command - (if-command - (info-keyword - "if" parenthesized-expression command-list - (maybe separator "else" command-list))) - -;;; new-style block-structured if - (new-if-command - (info-keyword - "if" parenthesized-expression block - (maybe "else" block))) - -;;; block-structured "do" - (do-command - (info-keyword "do" iteration-spec block)) - -;;; PLOT, SPLOT commands - (plot-command - [(kw ("pl" . "ot")) - - (either - ;; Parametric ranges - [(assert (gnuplot-guess-parametric-p)) - (maybe t-axis-range) (maybe x-axis-range) (maybe y-axis-range)] - - ;; Non-parametric ranges - [(maybe x-axis-range) (maybe y-axis-range)]) - - plot-body]) - - (splot-command - [ ;; This capturing group lets `gnuplot-find-using-eldoc' know - ;; that this is an splot command - (capture :splot-command (kw ("spl" . "ot"))) - - (either - ;; Parametric ranges - [(assert (gnuplot-guess-parametric-p)) - (maybe u-axis-range) (maybe v-axis-range) - (maybe x-axis-range) (maybe y-axis-range) (maybe z-axis-range)] - - ;; Non-parametric ranges - [(maybe x-axis-range) (maybe y-axis-range) (maybe z-axis-range)]) - - plot-body]) - - (replot-command [(kw "replot") plot-body]) - - ;; Axis ranges - (axis-range-component - (maybe (either "*" expression))) - - (axis-range-body - (delimited-list axis-range-component ":" 2 3)) - - (axis-range - [(:info "ranges") - "[" (maybe (maybe name "=") axis-range-body) "]"]) - - (x-axis-range [(:eldoc "X RANGE: [{=}:]") axis-range]) - (y-axis-range [(:eldoc "Y RANGE: [{=}:]") axis-range]) - (z-axis-range [(:eldoc "Z RANGE: [{=}:]") axis-range]) - (t-axis-range [(:eldoc "T RANGE: [{=}:]") axis-range]) - (u-axis-range [(:eldoc "U RANGE: [{=}:]") axis-range]) - (v-axis-range [(:eldoc "V RANGE: [{=}:]") axis-range]) - - ;; Body of a plot/splot command. Should really be different for - ;; parametric vs non-parametric, but that's too hard. - (plot-body - (delimited-list - [(maybe iteration-spec) plot-expression plot-modifiers] - ",")) - - ;; Iteration: for [... ] - (iteration-spec - [(:info "iteration") - (many1 - "for" "[" name - (either ["=" (delimited-list expression ":")] - ["in" expression]) - "]")]) - - ;; Expressions to plot can be preceded by any number of - ;; assignments, with or without commas - (plot-expression - [(many [(:no-info) assignment (maybe ",")]) - expression]) - -;;; Plot/splot modifiers - ;; These should probably be more different for plot and splot ... - (plot-modifiers (many (either plot-modifier datafile-modifier))) - - (plot-modifier - (info-keyword - (either - ;; simple one-word modifiers - (kw "nohidden3d") (kw "nocontours") (kw "nosurface") - - ;; word followed by expression - [(either - (kw ("lines" . "tyle") "ls") - (kw ("linet" . "ype") "lt") - (kw ("linew" . "idth") "lw") - (kw ("pointt" . "ype") "pt") - (kw ("points" . "ize") "ps") - (kw ("pointi" . "nterval") "pi")) - expression] - - ;; others defined below - title-modifier notitle-modifier axes-modifier with-modifier - linecolor-modifier fillstyle-modifier))) - - (title-modifier - [(kw ("t" . "itle")) expression]) - - (notitle-modifier - [(:info "title") - (kw ("not" . "itle")) - (maybe string)]) - - (axes-modifier - [(kw ("ax" . "es")) (either "x1y1" "x1y2" "x2y1" "x2y2")]) - - (linecolor-modifier - [(kw ("linec" . "olor") "lc") color-spec]) - - (fillstyle-modifier - [(kw "fillstyle" "fs") - ;; fill-style also used by "set style fill" - fill-style]) - - (fill-style - [(either - "empty" - [(maybe "transparent") - (either "pattern" "solid") - (maybe (either fill-style-border-clause expression))]) - (maybe fill-style-border-clause)]) - - (fill-style-border-clause - (either "noborder" [(kw ("bo" . "rder")) expression])) - - (color-spec - [(:info "colorspec") - (either - (kw ("var" . "iable")) - - [(kw ("pal" . "ette")) - (either "z" - [(either "frac" "cb") expression])] - - [(kw ("rgb" . "color")) - (either (kw ("var" . "iable")) string)])]) - - (with-modifier - [(:info "plotting_styles") - (kw ("w" . "ith")) - - ;; plotting-style also used for "set style data" - (capture :with-style plotting-style)]) - - (plotting-style - (info-keyword - (either - ;; Simple styles that take no arguments - (kw ("l" . "ines")) (kw ("i" . "mpulses")) (kw ("p" . "oints")) - (kw ("linesp" . "oints") "lp") (kw ("d" . "ots")) (kw ("yerrorl" . "ines")) - (kw ("errorl" . "ines")) (kw ("xerrorl" . "ines")) (kw ("xyerrorl" . "ines")) - (kw ("ye" . "rrorbars")) (kw ("e" . "rrorbars")) (kw ("xe" . "rrorbars")) - (kw ("xye" . "rrorbars")) (kw "boxes") (kw ("hist" . "ograms")) - (kw ("boxer" . "rorbars")) (kw ("boxx" . "yerrorbars")) (kw ("st" . "eps")) - (kw ("fs" . "teps")) (kw ("his" . "teps")) (kw ("fin" . "ancebars")) - (kw ("can" . "dlesticks")) (kw ("pm" . "3d")) - (kw ("cir" . "cles")) - - ;; Image styles all use the same info page - [(:info "image") - (either (kw ("ima" . "ge")) - (kw ("rgbima" . "ge")) - (kw ("rgba" . "lpha")))] - - ;; More complicated styles defined below - labels-style-clause - filledcurves-style-clause - vectors-style-clause))) - - (labels-style-clause - [(kw "labels") - (maybe textcolor-spec)]) - - (filledcurves-style-clause - [(kw ("filledc" . "urves")) - (maybe - (either - "closed" - - ["xy" "=" expression "," expression] - - [(maybe (either "above" "below")) - (maybe [(either "x1" "x2" "y1" "y2") - (maybe "=" expression)])]))]) - - (vectors-style-clause - [(kw ("vec" . "tors")) - (many - (either - "nohead" "head" "heads" "filled" "empty" "nofilled" "front" "back" - [(kw "arrowstyle" "as") expression] - ["size" (delimited-list expression ",")] - linestyle-spec))]) - -;;; Various style specifiers, used in different places - (linestyle-spec - (many1 - (either - [(kw ("lines" . "tyle") "ls") expression] - [(kw ("linet" . "ype") "lt") expression] - [(kw ("linew" . "idth") "lw") expression]))) - - (textcolor-spec - [(kw "textcolor" "tc") - (either "default" - ["lt" expression] - color-spec)]) - - (pointsize-spec [(kw "pointsize" "ps") expression]) - -;;; Datafile modifiers - (datafile-modifier - (info-keyword - (either binary-modifier - [(maybe "nonuniform") (kw ("mat" . "rix"))] - index-modifier every-modifier - thru-modifier using-modifier - smooth-modifier - "volatile" "noautoscale"))) - - (index-modifier - [(kw ("i" . "ndex")) - (either string (delimited-list expression ":" 0 2))]) - - (every-modifier - [(kw ("ev" . "ery")) (delimited-list (maybe expression) ":")]) - - (thru-modifier - [(kw "thru") expression]) - - (using-modifier - [(:eldoc gnuplot-find-using-eldoc) - (kw ("u" . "sing")) - (either - string - [colon-list (maybe string)])]) - - (smooth-modifier - [(kw ("s" . "mooth")) - (either (kw ("a" . "csplines")) (kw ("b" . "ezier")) (kw ("c" . "splines")) - (kw ("s" . "bezier")) (kw ("u" . "nique")) (kw ("f" . "requency")) - (kw ("cum" . "ulative")) (kw ("k" . "density")))]) - -;;; Binary datafile modifiers - (binary-modifier - ["binary" (many binary-keyword)]) - - (binary-keyword - (either - ;; All of these binary keywords are described on the same - ;; info page - [(:info "keywords") - (either - "transpose" "flipx" "flipy" "flipz" - ["flip" "=" (either "x" "y" "z")] - ["scan" "=" name] - [(either "dx" "dy" "dz") "=" number] - [(either "origin" "center" "perpendicular") "=" - (delimited-list tuple ":")] - [(kw ("rot" . "ate") "rotation") "=" - (sequence expression (maybe (kw ("d" . "eg")) (kw ("p" . "i"))))])] - - ;; remaining binary keywords have their own info pages - (info-keyword - (either - [(either "array" "record") - "=" - (delimited-list expression ":")] - - [(either "skip") - "=" - (delimited-list expression ":")] - - [(either "format" "endian" "filetype") - "=" - expression])))) - -;;; "fit" command - (fit-command - [(:info "fit") - (kw "fit") - (many axis-range) - expression - string - (many plot-modifier) - (kw "via") - (either string (delimited-list name ","))]) - -;;; print command - (print-command - [(kw ("pr" . "int")) (delimited-list expression ",")]) - -;;; set commands - (set-command - [(:eldoc "set ...") - (:info "set-show") - (either (kw "set") (kw "unset") (kw "show")) - (maybe iteration-spec) - (info-keyword - (either set-angles-clause set-arrow-clause - set-autoscale-clause set-bars-clause - set-border-clause set-boxwidth-clause - set-clabel-clause set-clip-clause - set-cntrparam-clause set-colorbox-clause - set-contour-clause set-datafile-clause - set-decimalsign-clause set-dgrid3d-clause - set-dummy-clause set-encoding-clause - set-fit-clause set-fontpath-clause - set-format-clause set-grid-clause - set-hidden3d-clause set-historysize-clause - set-isosamples-clause set-key-clause - set-label-clause set-loadpath-clause - set-locale-clause set-logscale-clause - set-mapping-clause set-margin-clause - set-multiplot-clause set-mxtics-clause - set-object-clause set-offsets-clause - set-origin-clause set-output-clause - set-parametric-clause set-pm3d-clause - set-palette-clause set-pointsize-clause - set-polar-clause set-print-clause - set-samples-clause set-size-clause - set-style-clause - set-surface-clause set-table-clause - set-terminal-clause set-termoption-clause - set-tics-clause set-tics-clause-2 - set-xtics-clause - set-timestamp-clause set-timefmt-clause - set-title-clause set-view-clause - set-data-clause set-dtics-clause - set-xlabel-clause - set-mtics-clause set-range-clause - set-xyplane-clause set-zero-clause - set-zeroaxis-clause))]) - -;;; positions and coordinate systems for set options - (position-system - (either "first" "second" "graph" "screen" "character")) - - (dimension [(maybe position-system) expression]) - - (position - [dimension "," dimension (maybe "," dimension)]) - - (to (either "to" "rto")) - -;;; all the different "set ... " options - (set-angles-clause - ["angles" (either "degrees" "radians")]) - - (set-arrow-clause - ["arrow" (maybe number) - (many - (either ["from" position] [to position] - [(kw "arrowstyle" "as") expression] - "nohead" "head" "backhead" "heads" - ["size" dimension "," expression (maybe "," expression)] - "filled" "empty" "nofilled" "front" "back" - linecolor-modifier linestyle-spec))]) - - (set-autoscale-clause - ["autoscale" - (either "fix" - "keepfix" - "x" "y" "z" "cb" "x2" "y2" "xy" - "xmin" "ymin" "zmin" "cbmin" "x2min" "y2min" - "xmax" "ymax" "zmax" "cbmax" "x2max" "y2max" - "xfix" "yfix" "zfix" "cbfix" "x2fix" "y2fix" - "xfixmax" "yfixmax" "zfixmax" "cbfixmax" "x2fixmax" "y2fixmax" - "xfixmin" "yfixmin" "zfixmin" "cbfixmin" "x2fixmin" "y2fixmin")]) - - (set-bars-clause - ["bars" - (either expression "small" "large" "fullwidth") - (either "front" "back")]) - - (set-border-clause - ["border" - (maybe number) - (maybe (either "front" "back")) - (maybe (kw "linewidth" "lw") expression) - (maybe - (either (kw "linestyle" "ls") (kw "linetype" "lt")) - expression)]) - - (set-boxwidth-clause - ["boxwidth" - (maybe expression) - (maybe (either (kw ("abs" . "olute")) "relative"))]) - - (set-clabel-clause - ["clabel" (maybe string)]) - - (set-clip-clause - ["clip" (maybe (either "points" "one" "two"))]) - - (set-cntrparam-clause - [(kw "cntrparam") - (either - "linear" "cubicspline" "bspline" - - [(either "points" "order") number] - - [(kw "levels") - (either - number - (sequence (kw "auto") (maybe number)) - (sequence - (kw "discrete") comma-list) - (sequence - (kw "incremental") (delimited-list expression "," 2 3)))])]) - - (set-colorbox-clause - [(:info "color_box") - (kw ("colorb" . "ox")) - (many - (either - (kw ("vert" . "ical")) (kw ("horiz" . "ontal")) - "default" "user" - ["origin" expression "," expression] - ["size" expression "," expression] - "front" "back" - "noborder" "bdefault" - ["border" expression]))]) - - (set-contour-clause - ["contour" (either "base" "surface" "both")]) - - (set-datafile-clause - ["datafile" - (either [(:info "set_datafile_fortran") - "fortran"] - [(:info "set_datafile_nofpe_trap") - "nofpe_trap"] - [(:info "set_datafile_missing") - "missing" (maybe string)] - [(:info "set_datafile_separator") - "separator" (either "whitespace" string)] - [(:info "set_datafile_commentschars") - "commentschars" (maybe string)] - [(:info "set_datafile_binary") - "binary" (many binary-keyword)])]) - - (set-decimalsign-clause - ["decimalsign" - (either string ["locale" (maybe string)])]) - - (set-dgrid3d-clause - ["dgrid3d" - (maybe expression) ; fixme - (maybe "," expression) - (either - "splines" - ["qnorm" expression] - [(either "gauss" "cauchy" "exp" "box" "hann") - (maybe expression) - (maybe "," expression)])]) - - (set-dummy-clause - ["dummy" - name (maybe "," name)]) - - (set-encoding-clause - ["encoding" - (either "default" "iso_8859_1" "iso_8859_15" "iso_8859_2" "iso_8859_9" - "koi8r" "koi8u" "cp437" "cp850" "cp852" "cp1250" "cp1251" "cp1254" - "utf8" "locale")]) - - (set-fit-clause - [(:info "fit_") - "fit" - (either - ["logfile" string] - "errorvariables" "noerrorvariables")]) - - (set-fontpath-clause - ["fontpath" (many string)]) - - (set-format-clause - [(:info "format_") - "format" - (maybe (either "x" "y" "xy" "x2" "y2" "z" "cb")) - string]) - - (set-grid-clause - ["grid" - (either "nomxtics" "mxtics" "noxtics" "xtics" "nomytics" "mytics" - "noytics" "ytics" "nomztics" "mztics" "noztics" "ztics" - "nomx2tics" "mx2tics" "nox2tics" "x2tics" "nomy2tics" - "my2tics" "noy2tics" "y2tics" "nomcbtics" "mcbtics" - "nocbtics" "cbtics" "layerdefault" "front" "back" - [linestyle-spec (maybe "," linestyle-spec)])]) - - (set-hidden3d-clause - [(kw ("hidden" . "3d")) - (many - (either - "defaults" "front" "back" - ["offset" expression] "nooffset" - ["trianglepattern" - (either "0" "1" "2" "3" "4" "5" "6" "7")] - ["undefined" (either "1" "2" "3")] - ["noundefined"] - "altdiagonal" "noaltdiagonal" - "bentover" "nobentover"))]) - - (set-historysize-clause - ["historysize" number]) - - (set-isosamples-clause - [(kw ("isosam" . "ples")) number (maybe "," number)]) - - (set-key-clause - ["key" - (many - (either "on" "off" "default" - [(either "inside" "outside") - (either "lmargin" "rmargin" "tmargin" "bmargin")] - ["at" expression "," expression] - "left" "right" "center" "top" "bottom" "vertical" - "horizontal" "Left" "Right" "reverse" "noreverse" "invert" - "noinvert" "above" "over" "below" "under" - ["samplen" number] - ["spacing" number] - ["width" number] - [(either "autotitle" "noautotitle") (maybe "columnheader")] - ["title" expression] "enhanced" "noenhanced" ["font" string] - textcolor-spec - [(either "box" "nobox") linestyle-spec] - ["maxcols" (either expression "auto")] - ["maxrows" (either expression "auto")]))]) - - (set-label-clause - ["label" - (maybe expression) - (either label-clause-component expression) - (many label-clause-component)]) - - (label-clause-component - (either - ["at" position] - "left" "center" "right" - (either "norotate" ["rotate" "by" expression]) - ["font" string] - "noenhanced" - "front" "back" - textcolor-spec - "nopoint" ["point" (many (either pointsize-spec linestyle-spec))] - ["offset" position])) - - (set-loadpath-clause - ["loadpath" (many string)]) - - (set-locale-clause - ["locale" (maybe string)]) - - (set-logscale-clause - ["logscale" - (either "x" "y" "xy" "x2" "y2" "z" "cb" name)]) - - (set-mapping-clause - ["mapping" (either "cartesian" "spherical" "cylindrical")]) - - (set-margin-clause - [(either "bmargin" "lmargin" "rmargin" "tmargin") - (maybe "at" "screen") expression]) - - ;; TODO: set-mouse-clause - - (set-multiplot-clause - ["multiplot" - (maybe - ["layout" number "," number - (maybe (either "rowsfirst" "columnsfirst")) - (maybe (either "downwards" "upwards")) - (maybe "title" string) - (maybe "scale" number (maybe "," number)) - (maybe "offset" number (maybe "," number))])]) - - (set-mxtics-clause - [(:info "mxtics") - (either "mxtics" "mytics" "mztics" "mx2tics" "my2tics" "mcbtics") - (either "default" number)]) - - ;; "set object", objects, dimensions, positions - (set-object-clause - ["object" - (maybe number) - (info-keyword - (either rectangle-object ellipse-object circle-object polygon-object)) - (maybe (either "front" "back" "behind")) - (maybe (kw "fillcolor" "fc") color-spec) - (maybe "fs" expression) - (maybe "default") - (maybe (kw "linewidth" "lw") expression)]) - - (rectangle-object - [(kw ("rect" . "angle")) - (maybe - (either - ["from" position (either "to" "rto") position] - ["center" position "size" dimension "," dimension] - ["at" position "size" dimension "," dimension]))]) - - (ellipse-object - ["ellipse" - (either "at" "center") position - "size" dimension "," dimension - (maybe "angle" number)]) - - (circle-object - ["circle" - (either "at" "center") position - "size" dimension - (maybe "arc" "[" number ":" number "]")]) - - (polygon-object - ["polygon" - "from" position (many (either "to" "rto") position)]) - - ;; "set offsets" - (set-offsets-clause - ["offsets" - (delimited-list [(maybe "graph") expression] "," 4 4)]) - - (set-origin-clause - ["origin" expression "," expression]) - - (set-output-clause - ["output" (maybe string)]) - - (set-parametric-clause - [(:info "parametric_") - (kw ("param" . "etric"))]) - - (set-pm3d-clause - ["pm3d" - (many - (either - ["at" name] - ["interpolate" number "," number] - (either "scansautomatic" "scansforward" "scansbackward" "depthorder") - ["flush" (either "begin" "center" "end")] - (either "ftriangles" "noftriangles") - (either "clip1in" "clip4in") - ["corners2color" - (either "mean" "geomean" "median" "min" "max" "c1" "c2" "c3" "c4")] - ["hidden3d" number] - "nohidden3d" - "implicit" "explicit" "map"))]) - - (set-palette-clause - ["palette" - (many - (either - "gray" "color" - ["gamma" number] - ["rgbformulae" number "," number "," number] - "defined" ; not complete - ["functions" expression "," expression "," expression] - ["file" string (many datafile-modifier)] - "RGB" "HSV" "CMY" "YIQ" "XYZ" - "positive" "negative" - "nops_allcF" "ps_allcF" - ["maxcolors" number]))]) - - (set-pointsize-clause pointsize-spec) - - (set-polar-clause "polar") - - (set-print-clause - [(:info "print_") - "print" - (maybe string)]) - - (set-samples-clause - ["samples" expression (maybe "," expression)]) - - (set-size-clause - ["size" - (either - "square" "nosquare" - ["ratio" expression] - "noratio" - [expression "," expression])]) - - (set-style-clause - ["style" - (either style-arrow-clause style-data-clause style-fill-clause - style-function-clause style-increment-clause - style-line-clause style-circle-clause style-rectangle-clause)]) - - ;; begin subclauses of "set style ..." - (style-arrow-clause - [(:info "set_style_arrow") - "arrow" - number - (either - "default" - (many - (either "nohead" "head" "heads" - "filled" "empty" "nofilled" - "front" "back" - ["size" dimension "," number (maybe "," number)] - linestyle-spec)))]) - - (style-data-clause - [(:info "set_style_data") - "data" plotting-style]) - - (style-fill-clause - [(:info "set_style_fill") - "fill" fill-style]) - - (style-function-clause - [(:info "set_style_function") - "function" plotting-style]) - - (style-increment-clause - [(:info "set_style_increment") - "increment" - (either (kw ("d" . "efault")) (kw ("u" . "serstyles")))]) - - (style-line-clause - [(:info "set_style_line") - "line" - expression - (either - "default" - (many - (either - "palette" - [(kw ("linet" . "ype") "lt") - (either expression color-spec)] - [(kw ("linec" . "olor") "lc") color-spec] - [(either (kw ("linew" . "idth") "lw") - (kw ("pointt" . "ype") "pt") - (kw ("points" . "ize") "ps") - (kw ("pointi" . "nterval") "pi")) - expression])))]) - - (style-circle-clause - [(:info "set_style_circle") - "circle" "radius" dimension]) - - (style-rectangle-clause - [(:info "set_style_rectangle") - "rectangle" - (many - (either - "front" "back" - [(kw ("linew" . "idth") "lw") expression] - [(kw "fillcolor" "fc") color-spec] - ["fs" expression]))]) - ;; end of "set style ..." clauses - - (set-surface-clause "surface") - - (set-table-clause ["table" (maybe string)]) - - (set-terminal-clause ; not sure how to do this... - ["terminal" (maybe (either "push" "pop"))]) - - (set-termoption-clause - ["termoption" - (either - "enhanced" "noenhanced" - ["font" string] - "solid" "dashed" - [(kw "linewidth" "lw") expression])]) - - (set-tics-clause - ["tics" - (many - (either - "axis" "border" "mirror" "nomirror" "in" "out" - ["scale" (either "default" [expression (maybe "," expression)])] - [(either "rotate" "norotate") (maybe "by" expression)] - ["offset" expression] "nooffset" - ["format" string] - ["font" string] - textcolor-spec))]) - - (set-tics-clause-2 - ["tics" (either "front" "back")]) - - (set-xtics-clause - [(:info "xtics") - (either "xtics" "ytics" "ztics" "x2tics" "y2tics" "cbtics") - (many - (either - "axis" "border" "mirror" "nomirror" "in" "out" - ["scale" (either "default" [expression (maybe "," expression)])] - [(either "rotate" "norotate") (maybe "by" expression)] - ["offset" position] "nooffset" - "add" "autofreq" - ["(" (delimited-list [(maybe string) expression (maybe number)] ",") ")"] - ["format" string] - ["font" string] - "rangelimited" - textcolor-spec - (delimited-list expression ",")))]) - - (set-timestamp-clause - ["timestamp" - (maybe string) - (maybe (either "top" "bottom")) - (maybe (either "rotate" "norotate")) - (maybe "offset" position) - (maybe "font" string)]) - - (set-timefmt-clause - ["timefmt" string]) - - (set-title-clause - [(:info "title_") - "title" - (maybe expression) - (many - (either - ["offset" position] - ["font" string] - textcolor-spec - "enhanced" "noenhanced"))]) - - (set-view-clause - ["view" - (either - "map" - [(either "equal" "noequal") (maybe (either "xy" "xyz"))] - (delimited-list (maybe expression) ","))]) - - (set-data-clause - [(:info "xdata") - (either "xdata" "ydata" "zdata" "x2data" "y2data" "cbdata") - (maybe (either "time" "geographic"))]) - - (set-dtics-clause - [(:info "xdtics") - (either "xdtics" "ydtics" "zdtics" "x2dtics" "y2dtics" "cbdtics")]) - - (set-xlabel-clause - [(:info "xlabel") - (either (kw ("xlab" . "el")) (kw ("ylab" . "el")) - (kw ("zlab" . "el")) (kw ("x2lab" . "el")) - (kw ("y2lab" . "el")) (kw ("cblab" . "el"))) - (maybe expression) - (many - (either - ["offset" position] - ["font" string] - textcolor-spec - "enhanced" "noenhanced"))]) - - (set-mtics-clause - [(:info "xmtics") - (either "xmtics" "ymtics" "zmtics" "x2mtics" "y2mtics" "cbmtics")]) - - (set-range-clause - [(:info "xrange") - (either (kw ("xr" . "ange")) (kw ("yr" . "ange")) - (kw ("x2r" . "ange")) (kw ("y2r" . "ange")) - (kw ("zr" . "ange")) (kw ("tr" . "ange")) - (kw ("ur" . "ange")) (kw ("vr" . "ange")) - (kw ("rr" . "ange")) (kw ("cbr" . "ange"))) - (either - "restore" - ["[" (maybe - [(maybe axis-range-component) ":" - (maybe axis-range-component)]) - "]" - (many (either "reverse" "noreverse" "writeback" "nowriteback"))])]) - - (set-xyplane-clause - ["xyplane" (either "at" "relative") expression]) - - (set-zero-clause - ["zero" expression]) - - (set-zeroaxis-clause - [(:info "zeroaxis") - (either "zeroaxis" "xzeroaxis" "x2zeroaxis" "yzeroaxis" "y2zeroaxis" - "zzeroaxis") - (maybe linestyle-spec)]) - - -;;; Other commands - (cd-command - ["cd" string]) - - (call-command - ["call" string (many expression)]) - - (simple-command - (either "clear" "exit" "quit" "pwd" "refresh" "reread" "reset" - "shell")) - - (eval-command - ["eval" expression]) - - (load-command - ["load" string]) - - (lower-raise-command [(either "lower" "raise") number]) - - (pause-command - ["pause" - (either - expression - ["mouse" (maybe endcondition (maybe "," endcondition))]) - string]) - - (endcondition (either "keypress" "button1" "button2" "button3" "close" "any")) - - (save-command - ["save" - (either "functions" "variables" "terminal" "set") - string]) - - (system-command - ["system" string]) - - (test-command - ["test" - (either - "terminal" - ["palette" - (maybe - (either "rgb" "rbg" "grb" "gbr" "brg" "bgr"))])]) - - (undefine-command - ["undefine" (many name)]) - - (update-command - ["update" string (maybe string)])) - - ;; This is the start symbol - 'command)))) - - -;; The following macros are used for debugging; load -;; gnuplot-debug-context.el and then re-load this file to enable -;; them. For normal use, they compile to no-ops. -(eval-when-compile - (when (not (featurep 'gnuplot-debug-context)) - (defmacro with-gnuplot-trace-buffer (&rest args) "No-op." '(progn nil)) - (defmacro gnuplot-trace (&rest args) "No-op." '(progn nil)) - (defmacro gnuplot-debug (&rest args) "No-op." '(progn nil)))) - - - -;;;; Variables to be set via pattern matching -(defvar gnuplot-completions nil - "List of possible gnuplot-mode completions at point. -This is filled in by `gnuplot-match-pattern' when it reaches the -token before point.") - -(defvar gnuplot-info-at-point nil - "Relevant page of the Gnuplot info manual for the construction at point. - -Set by `gnuplot-match-pattern' using information from -`gnuplot-compiled-grammar'. `gnuplot-match-pattern' pushes ElDoc -and info strings onto the stack as it runs, and scans the stack -for the topmost entry when it reaches the token at point.") - -(defvar gnuplot-eldoc nil - "ElDoc documentation string for the Gnuplot construction at point. - -Set by `gnuplot-match-pattern'. See also `gnuplot-info-at-point'.") - -(defvar gnuplot-captures nil - "Alist of named capture groups for gnuplot-mode completion code. - -Each entry is of the form (NAME BEGIN END), where NAME is the -name specified in the (capture NAME PATTERN) form in the -`gnuplot-compiled-grammar' source, BEGIN is the tail of the token -list beginning the capture group, and END is the tail of the -token list just after the end of the capture group.") - - -;;;; The pattern matching machine -(defun gnuplot-match-pattern (instructions tokens completing-p - &optional start-symbol) - "Parse TOKENS, setting completions, info and ElDoc information. - -This function parses TOKENS by simulating a stack machine with -unlimited backtracking. If COMPLETING-P is non-nil, it stops -before the token at point and collects a list of the next tokens -that it would accept in `gnuplot-completions'. If COMPLETING-P is -nil, it parses up to the token at point and sets `gnuplot-eldoc' -and `gnuplot-info-at-point' based on the contents of the stack -there." - (catch 'return - (let ((pc 0) ; Program counter - ;; Stack of return addresses (return PC), eldoc strings - ;; (eldoc STRING) and info pages (info STRING) - (stack '()) - ;; Stack of backtracking records: - ;; ((STACK TOKENS RESUME-PC CAPTURES PROGRESS) ...) - (backtrack '()) - ;; Match failure flag, set to `t' to cause backtracking - (fail nil) - ;; Flag set by JUMP and CALL instructions to stop PC advance - (jump nil) - ;; Record of progress made within (many ...) loops, an alist - ;; of conses (pc . tokens) - (progress '())) - - (with-gnuplot-trace-buffer (erase-buffer)) - - (when start-symbol ; HACK FIXME - (let ((look-for `(label ,start-symbol))) - (while (not (equal (aref instructions pc) look-for)) - (incf pc)) - (incf pc))) - - (setq gnuplot-completions nil - gnuplot-eldoc nil - gnuplot-info-at-point nil - gnuplot-captures nil) - - (flet ((advance - () - (pop tokens) - (if (and (null tokens) (not completing-p)) - (gnuplot-scan-stack stack tokens))) - (fail () (setq fail t))) - - ;; Main loop - (while t - (let* ((inst (aref instructions pc)) - (opcode (car inst)) - (token (car tokens)) - (end-of-tokens (null tokens))) - (gnuplot-trace "%s\t%s\t%s\n" pc inst (and token (gnuplot-token-id token))) - - (case opcode - ;; (literal LITERAL NO-COMPLETE) - ((literal) - (let ((expect (cadr inst)) - (no-complete (caddr inst))) - (cond (end-of-tokens - (unless no-complete - (gnuplot-trace "\tpushing \"%s\" to completions\n" expect) - (push expect gnuplot-completions)) - (fail)) - - ((not (equal (gnuplot-token-id token) expect)) - (fail)) - - ;; otherwise succeed - (t (advance))))) - - ;; (token-type TYPE) - ((token-type) - (let ((expect (cadr inst))) - (if (or end-of-tokens - (not (eq (gnuplot-token-type token) expect))) - (fail) - (advance)))) - - ;; (keyword REGEXP NAME): match any token whose ID - ;; regexp-matches REGEXP, use NAME for completions - ((keyword) - (let ((regexp (cadr inst)) - (name (caddr inst))) - (cond (end-of-tokens - (gnuplot-trace "\tpushing \"%s\" to completions\n" name) - (push name gnuplot-completions) - (fail)) - - ((not (string-match-p regexp (gnuplot-token-id token))) - (fail)) - - ;; otherwise succeed - (t - (setf (gnuplot-token-id token) name) - (advance))))) - - ;; (any): match any token - ((any) - (if end-of-tokens - (fail) - (advance))) - - ;; (jump LOCATION): jump to instruction at LOCATION - ((jump) - (let ((location (cadr inst))) - (setq jump location))) - - ;; (call LOCATION): push the next instruction as a - ;; return location and jump - ((call) - (let ((location (cadr inst))) - (push `(return ,(+ pc 1)) stack) - (setq jump location))) - - ;; (return): return to address at topmost RETURN record on - ;; stack, or stop matching and return if stack is empty - ((return) - (while (and stack - (not (eq (caar stack) 'return))) - (pop stack)) - (if (not stack) - ;; Successful match - (throw 'return (list tokens)) - ;; Otherwise, return to caller - (let* ((r (pop stack)) - (r-pc (cadr r))) - (setq jump r-pc)))) - - ;; (choice LOCATION): push LOCATION onto the stack of - ;; backtracking points and continue at next instruction - ((choice) - (let ((location (cadr inst))) - (push `(,stack ,tokens ,location ,gnuplot-captures - ,progress) - backtrack))) - - ;; (commit LOCATION): discard most recent backtrack point - ;; and jump to LOCATION - ((commit) - (let ((location (cadr inst))) - (if (not backtrack) - (error "No more backtrack points in commit")) - (pop backtrack) - (setq jump location))) - - ;; (fail): force this match to fail, going back to most - ;; recent backtrack point - ((fail) - (fail)) - - ;; (assert): run Lisp code and fail if it returns NIL - ((assert) - (let ((form (cadr inst))) - (if (not (eval form)) (fail)))) - - ;; (push TYPE VALUE): push an info page or eldoc string - ;; onto the stack - ((push) - (let* ((type (cadr inst)) - (value (caddr inst))) - (push `(,type ,value ,tokens) stack))) - - ;; (pop TYPE): pop something off the stack - ((pop) - (let ((type (cadr inst))) - (if (not (and stack - (eq (caar stack) type))) - (error "Expected a %s on the stack but found %s" type stack)) - (pop stack))) - - ;; (save-start NAME): save current token pointer as - ;; beginning of capture group NAME - ((save-start) - (let ((name (cadr inst))) - (push `(,name ,tokens nil) gnuplot-captures))) - - ;; (save-end NAME): save current token pointer as end of - ;; capture group NAME - ((save-end) - (let* ((name (cadr inst)) - (record (assoc name gnuplot-captures))) - (if (not record) - (error "Gnuplot-match-tokens: no open capture group named %s" name) - (setf (caddr record) tokens) - (gnuplot-debug (gnuplot-dump-captures))))) - - ;; (check-progress): make sure not stuck in an infinite loop - ((check-progress) - (let ((prev-progress (cdr (assoc pc progress)))) - (if (and prev-progress (eq prev-progress tokens)) - (fail) - (push (cons pc tokens) progress)))) - - (t - (error "Bad instruction: %s" inst))) - - ;; Increment PC or jump - (setq pc (or jump (1+ pc)) - jump nil) - - ;; Backtrack on failure - (when fail - (if (not backtrack) ; Out of backtracking stack: failed match - (throw 'return nil) - (gnuplot-trace "\t*fail*\t%s\n" (length backtrack)) - (gnuplot-debug (gnuplot-dump-backtrack backtrack)) - ;; If we got as far as token-at-point before failing, - ;; scan the stack for eldoc and info strings - (when (and end-of-tokens (not completing-p)) - (gnuplot-scan-stack stack tokens)) - - (destructuring-bind - (bt-stack bt-tokens bt-pc bt-captures bt-progress) - (pop backtrack) - (setq stack bt-stack - tokens bt-tokens - pc bt-pc - gnuplot-captures bt-captures - progress bt-progress - fail nil) - (gnuplot-debug (gnuplot-dump-progress progress))))))))))) - -(defun gnuplot-scan-stack (stack tokens) - "Scan STACK for the most recently pushed eldoc and info strings." - (gnuplot-trace "\t* scanning stack *\n") - (gnuplot-debug (gnuplot-backtrace)) - (gnuplot-debug (gnuplot-dump-captures)) - - (catch 'no-scan - (while (and stack - (not (and gnuplot-info-at-point gnuplot-eldoc))) - (let* ((item (car stack)) - (type (car item)) - (position (caddr item))) ; must progress by at least one token - (if (and (memq type '(info eldoc no-scan)) - (not (eq position tokens))) - (case type - ((no-scan) - (throw 'no-scan nil)) - - ((info) - (when (not gnuplot-info-at-point) - (let ((info (cadr item))) - (setq gnuplot-info-at-point - (cond - ((eq info 'first-token) - (gnuplot-token-id (car position))) - ((functionp info) (funcall info)) - (t info))) - (when gnuplot-info-at-point - (gnuplot-trace "\tset info to \"%s\"\n" gnuplot-info-at-point) - (when (and (not gnuplot-eldoc) gnuplot-eldoc-hash) - (let ((eldoc - (car (gethash gnuplot-info-at-point gnuplot-eldoc-hash)))) - (when eldoc - (setq gnuplot-eldoc eldoc) - (gnuplot-trace "\tand set eldoc to \"%s\"\n" eldoc)))))))) - - ((eldoc) - (when (not gnuplot-eldoc) - (let ((eldoc (cadr item))) - (setq gnuplot-eldoc - (if (functionp eldoc) (funcall eldoc) eldoc)) - (gnuplot-trace "\tset eldoc to \"%s\"\n" gnuplot-eldoc))))))) - (pop stack)))) - -(defun gnuplot-capture-group (name) - "Return capture group NAME from the most recent parse, as a list of tokens." - (let ((record (assoc name gnuplot-captures))) - (if (not record) nil - (let ((begin (cadr record)) - (end (caddr record)) - (accum '())) - (while (and begin (not (eq begin end))) - (push (pop begin) accum)) - (nreverse accum))))) - -(defun gnuplot-capture-group->string (name) - (let ((tokens (gnuplot-capture-group name))) - (and tokens - (mapconcat 'gnuplot-token-id tokens " ")))) - - -;;; Interface to the matching machine -(defun gnuplot-parse-at-point (completing-p) - (let ((tokens (gnuplot-tokenize completing-p))) - (gnuplot-match-pattern gnuplot-compiled-grammar tokens completing-p))) - -;; Completions -(defun gnuplot-completions () - (gnuplot-parse-at-point t) - (if (featurep 'xemacs) ; Need an alist - (mapcar (lambda (s) (cons s nil)) gnuplot-completions) - gnuplot-completions)) - -(defun gnuplot-context-completion-at-point () - "Return completions of keyword preceding point, using context." - (let* ((end (point)) - (beg - (save-excursion - (skip-syntax-backward "w_" (gnuplot-point-at-beginning-of-command)) - (point))) - (word nil) - (completions (gnuplot-completions))) - - (setq word (buffer-substring beg end) - completions (all-completions word completions)) - - (if completions - (list beg end completions) - (if (not (equal "" word)) - (message "No gnuplot keywords complete '%s'" word) - (message "No completions at point")) - nil))) - -;; Eldoc help -(defun gnuplot-eldoc-function () - "Return the ElDoc string for the Gnuplot construction at point." - (gnuplot-parse-at-point nil) - gnuplot-eldoc) - -(defun gnuplot-help-function () - "Pop up the extended documentation for the construction at point." - (interactive) - (gnuplot-parse-at-point nil) - (if (and gnuplot-info-at-point gnuplot-eldoc-hash) - (let ((eldoc - (cadr (gethash gnuplot-info-at-point gnuplot-eldoc-hash)))) - (if eldoc (message eldoc))))) - -;; Info lookup -(defun gnuplot-info-at-point (&optional query) - "Open the relevant gnuplot info page for the construction at point." - (interactive "P") - (setq gnuplot-info-at-point nil) - (unless query - (gnuplot-parse-at-point nil)) - (if (or query (not gnuplot-info-at-point)) - (let ((info - (info-lookup-interactive-arguments 'symbol))) - (setq gnuplot-info-at-point (car info)))) - (when gnuplot-info-at-point - (gnuplot--find-info-node gnuplot-info-at-point))) - -(defun gnuplot--find-info-node (node) - (save-window-excursion - (if (>= emacs-major-version 23) - (info (format "(gnuplot)%s" node)) - (info) - (Info-find-node "gnuplot" node))) - (gnuplot--adjust-info-display)) - - -;;; Some context-sensitive hacks - -;; ElDoc strings for "using" specs, which depend on other information -;; from the parsed command - -(defvar gnuplot-using-eldoc - '(("boxerrorbars" . "x:y:ydelta{:xdelta} | x:y:ylow:yhigh{:xdelta}") - ("boxes" . "x:y{:x_width}") - ("boxxyerrorbars" . "x:y:xdelta:ydelta | x:y:xlow:xhigh:ylow:yhigh") - ("candlesticks" . "x:box_min:whisker_min:whisker_high:box_high | date:open:low:high:close") - ("circles" . "x:y:radius") - ("dots" . "x{:y{:z}}") - ("filledcurves" . "x:y | x:y1:y2") - ("financebars" . "date:open:low:high:close") - ("fsteps" . "y | x:y") - ("histeps" . "y | x:y") - ("histograms" . "y:yerr | y:ymin:ymax") - ("image" . "x:y:value") - ("rgbimage" . "x:y:r:g:b") - ("rgbalpha" . "x:y:r:g:b:a") - ("impulses" . "x{:y{:z}}") - ("labels" . "x:y:string") - ("lines" . "y | x:y") - ("steps" . "y | x:y") - ("vectors" . "x:y:xdelta:ydelta") - ("xerrorbars" . "x:y:xdelta | x:y:xlow:xhigh") - ("xyerrorbars" . "x:y:xdelta:ydelta | x:y:xlow:xhigh:ylow:yhigh") - ("yerrorbars" . "x:y:ydelta | x:y:ylow:yhigh") - ("yerrorlines" . "x:y:ydelta | x:y:ylow:yhigh") - ("xerrorlines" "x:y:xdelta | x:y:xlow:xhigh") - ("xyerrorlines" . "x:y:xdelta:ydelta | x:y:xlow:xhigh:ylow:yhigh")) - "Alist of ElDoc strings for Gnuplot \"using\" clauses in \"plot\" commands.") - -(defvar gnuplot-using-3d-eldoc - (append - '(("fsteps" . "z | x:y:z") - ("histeps" . "z | x:y:z") - ("histograms" . "y:yerr | y:ymin:ymax") - ("image" . "x:y:z:value") - ("rgbimage" . "x:y:z:r:g:b") - ("rgbalpha" . "x:y:z:r:g:b:a") - ("labels" . "x:y:z:string") - ("lines" . "z | x:y:z") - ("steps" . "z | x:y:z") - ("vectors" . "x:y:z:xdelta:ydelta:zdelta")) - gnuplot-using-eldoc) - "Alist of ElDoc strings for Gnuplot \"using\" clauses in \"splot\" commands.") - -(defun gnuplot-find-using-eldoc () - "Return ElDoc string for a Gnuplot \"using\" clause, based on plotting style. - -This will fail if the \"using\" clause comes before the \"with\" -clause." - (let ((with-style (gnuplot-capture-group :with-style)) - (3d-p (gnuplot-capture-group :splot-command)) - (column-description nil)) - (if with-style - (let ((with-style-string (gnuplot-token-id (car with-style)))) - (setq column-description - (or (and 3d-p - (cdr (assoc with-style-string gnuplot-using-3d-eldoc))) - (cdr (assoc with-style-string gnuplot-using-eldoc)) - "")))) - (format "using %s {'format'}" column-description))) - -;;; Needed for correctly parsing plot commands -(defun gnuplot-guess-parametric-p (&optional start) - "Guess whether the command beginning at START is in parametric mode. - -Searches backward in current buffer for an \"(un)set parametric\" -command." - (save-excursion - (and start (goto-char start)) - (catch 'result - (while - (search-backward-regexp "reset\\|set\\s-+parametric" (point-min) t) - (gnuplot-beginning-of-command) - (cond ((looking-at "reset\\|unset\\s-+parametric") (throw 'result nil)) - ((looking-at "set\\s-+parametric") (throw 'result t)))) - nil))) - - - -;;; All done! -(provide 'gnuplot-context) - -;; Local Variables: -;; indent-tabs-mode: nil -;; End: - -;;; gnuplot-context.el ends here -- cgit v1.2.3