1 ;;; calc-aent.el --- algebraic entry functions for Calc
3 ;; Copyright (C) 1990-1993, 2001-2015 Free Software Foundation, Inc.
5 ;; Author: Dave Gillespie <daveg@synaptics.com>
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 ;; This file is autoloaded from calc.el.
31 (defvar calc-quick-calc-history nil
32 "The history list for quick-calc.")
35 (defun calc-do-quick-calc (&optional insert)
38 (if (eq major-mode 'calc-mode)
39 (calc-algebraic-entry t)
43 (let* ((calc-command-flags nil)
44 (calc-dollar-values calc-quick-prev-results)
46 (enable-recursive-minibuffers t)
47 (calc-language (if (memq calc-language '(nil big))
49 (entry (calc-do-alg-entry "" "Quick calc: " t 'calc-quick-calc-history))
50 (alg-exp (mapcar 'math-evaluate-expr entry)))
51 (when (and (= (length alg-exp) 1)
52 (eq (car-safe (car alg-exp)) 'calcFunc-assign)
53 (= (length (car alg-exp)) 3)
54 (eq (car-safe (nth 1 (car alg-exp))) 'var))
55 (set (nth 2 (nth 1 (car alg-exp))) (nth 2 (car alg-exp)))
56 (calc-refresh-evaltos (nth 2 (nth 1 (car alg-exp))))
57 (setq alg-exp (list (nth 2 (car alg-exp)))))
58 (setq calc-quick-prev-results alg-exp
59 buf (mapconcat (function (lambda (x)
60 (math-format-value x 1000)))
64 (if (and (= (length alg-exp) 1)
65 (eq (car-safe (car alg-exp)) nil)
67 (= calc-number-radix 10))
68 (setq buf (concat buf " ("
69 (let ((calc-number-radix 16))
70 (math-format-value (car alg-exp) 1000))
72 (let ((calc-number-radix 8))
73 (math-format-value (car alg-exp) 1000))
75 (let ((calc-number-radix 2))
76 (math-format-value (car alg-exp) 1000))
77 (if (and (integerp (car alg-exp))
79 (< (car alg-exp) 127))
80 (format ", \"%c\"" (car alg-exp))
83 (if (and (< (length buf) (frame-width)) (= (length entry) 1)
85 (let ((long (concat (math-format-value (car entry) 1000)
87 (if (<= (length long) (- (frame-width) 8))
90 (message "Result: %s" buf)))
92 (eq last-command-char ?\n)) ;10))
94 (kill-new shortbuf)))))
97 (defun calc-do-calc-eval (str separator args)
103 ((and (consp str) (not (symbolp (car str))))
104 (let ((calc-language nil)
105 (math-expr-opers (math-standard-ops))
106 (calc-internal-prec 12)
108 (calc-symbolic-mode nil)
109 (calc-matrix-mode nil)
110 (calc-angle-mode 'deg)
111 (calc-number-radix 10)
112 (calc-twos-complement-mode nil)
113 (calc-leading-zeros nil)
114 (calc-group-digits nil)
115 (calc-point-char ".")
116 (calc-frac-format '(":" nil))
117 (calc-prefer-frac nil)
118 (calc-hms-format "%s@ %s' %s\"")
119 (calc-date-format '((H ":" mm C SS pp " ")
120 Www " " Mmm " " D ", " YYYY))
121 (calc-float-format '(float 0))
122 (calc-full-float-format '(float 0))
123 (calc-complex-format nil)
124 (calc-matrix-just nil)
125 (calc-full-vectors t)
126 (calc-break-vectors nil)
127 (calc-vector-commas ",")
128 (calc-vector-brackets "[]")
129 (calc-matrix-brackets '(R O))
130 (calc-complex-mode 'cplx)
131 (calc-infinite-mode nil)
132 (calc-display-strings nil)
133 (calc-simplify-mode nil)
134 (calc-display-working-message 'lots)
137 (set (car strp) (nth 1 strp))
138 (setq strp (cdr (cdr strp))))
139 (calc-do-calc-eval (car str) separator args)))
140 ((eq separator 'eval)
142 ((eq separator 'macro)
144 (let* ((calc-buffer (current-buffer))
145 (calc-window (get-buffer-window calc-buffer))
146 (save-window (selected-window)))
150 (select-window calc-window)
151 (calc-execute-kbd-macro str nil (car args)))
152 (and (window-point save-window)
153 (select-window save-window)))
154 (save-window-excursion
155 (select-window (get-largest-window))
156 (switch-to-buffer calc-buffer)
157 (calc-execute-kbd-macro str nil (car args)))))
160 (or (not (integerp str))
162 (calc-pop (min str (calc-stack-size))))
167 (<= str (calc-stack-size))
168 (math-format-value (calc-top-n str (car args)) 1000)))
169 ((eq separator 'rawtop)
172 (<= str (calc-stack-size))
173 (calc-top-n str (car args))))
175 (let* ((calc-command-flags nil)
177 (calc-language (if (memq calc-language '(nil big))
178 'flat calc-language))
179 (calc-dollar-values (mapcar
184 (setq x (math-read-exprs x))
194 (res (if (stringp str)
195 (math-read-exprs str)
198 (if (eq (car res) 'error)
199 (calc-eval-error (cdr res))
200 (setq res (mapcar 'calc-normalize res))
201 (and (memq 'clear-message calc-command-flags)
203 (cond ((eq separator 'pred)
205 (if (= (length res) 1)
206 (math-is-true (car res))
207 (calc-eval-error '(0 "Single value expected"))))
209 (if (= (length res) 1)
211 (calc-eval-error '(0 "Single value expected"))))
212 ((eq separator 'list)
214 ((memq separator '(num rawnum))
215 (if (= (length res) 1)
216 (if (math-constp (car res))
217 (if (eq separator 'num)
218 (math-format-value (car res) 1000)
223 (calc-explain-why (car calc-next-why))
224 "Number expected"))))
225 (calc-eval-error '(0 "Single value expected"))))
226 ((eq separator 'push)
230 (setq buf (concat buf
231 (and buf (or separator ", "))
232 (math-format-value (car res) 1000))
236 (defvar calc-eval-error nil
237 "Determines how calc handles errors.
238 If nil, return a list containing the character position of error.
239 STRING means return error message as string rather than list.
240 The value t means abort and give an error message.")
242 (defun calc-eval-error (msg)
244 (if (eq calc-eval-error 'string)
246 (error "%s" (nth 1 msg)))
250 ;;;; Reading an expression in algebraic form.
253 (defun calc-auto-algebraic-entry (&optional prefix)
255 (calc-algebraic-entry prefix t))
258 (defun calc-algebraic-entry (&optional prefix auto)
261 (let ((calc-language (if prefix nil calc-language))
262 (math-expr-opers (if prefix (math-standard-ops) (math-expr-ops))))
263 (calc-alg-entry (and auto (char-to-string last-command-char))))))
265 (defvar calc-alg-entry-history nil
266 "History for algebraic entry.")
268 (defvar calc-plain-entry nil)
271 (defun calc-alg-entry (&optional initial prompt)
272 (let* ((calc-dollar-values (mapcar #'calc-get-stack-element
273 (nthcdr calc-stack-top calc-stack)))
276 (alg-exp (calc-do-alg-entry initial prompt t 'calc-alg-entry-history)))
277 (if (stringp alg-exp)
280 (calc-alg-edit alg-exp))
281 (let* ((calc-simplify-mode (if (eq last-command-char ?\C-j)
284 (nvals (mapcar 'calc-normalize alg-exp)))
286 (calc-record (if (featurep 'calc-ext) (car alg-exp) (car nvals))
288 (calc-pop-push-record-list calc-dollar-used
289 (and (not (equal (car alg-exp)
294 (setq alg-exp (cdr alg-exp)
296 calc-dollar-used 0)))
297 (calc-handle-whys))))
299 (defvar calc-alg-ent-map
300 (let ((map (make-sparse-keymap)))
301 (set-keymap-parent map minibuffer-local-map)
302 (define-key map "'" 'calcAlg-previous)
303 (define-key map "`" 'calcAlg-edit)
304 (define-key map "\C-m" 'calcAlg-enter)
305 (define-key map "\C-j" 'calcAlg-enter)
307 "The keymap used for algebraic entry.")
309 (defvar calc-alg-exp)
312 (defun calc-do-alg-entry (&optional initial prompt no-normalize history)
313 (let* (;; (calc-buffer (current-buffer)) -- appears unused --SY.
314 ;; (blink-matching-check-function 'calcAlg-blink-matching-check)
315 (calc-alg-exp 'error))
316 (if (eq calc-algebraic-mode 'total)
318 (define-key calc-alg-ent-map "\e+" 'calcAlg-plus-minus)
319 (define-key calc-alg-ent-map "\em" 'calcAlg-mod)
320 (define-key calc-alg-ent-map "\e=" 'calcAlg-equals)
321 (define-key calc-alg-ent-map "\e\r" 'calcAlg-equals)
322 (define-key calc-alg-ent-map "\ep" 'previous-history-element)
323 (define-key calc-alg-ent-map "\en" 'next-history-element)
324 (define-key calc-alg-ent-map "\e%" 'self-insert-command))
325 (setq calc-aborted-prefix nil)
326 (let ((buf (read-from-minibuffer (or prompt "Algebraic: ")
328 calc-alg-ent-map nil history)))
329 (when (eq calc-alg-exp 'error)
330 (when (eq (car-safe (setq calc-alg-exp (math-read-exprs buf))) 'error)
331 (setq calc-alg-exp nil)))
332 (setq calc-aborted-prefix "alg'")
334 (and calc-alg-exp (setq calc-alg-exp (mapcar 'calc-normalize calc-alg-exp))))
337 (defun calcAlg-plus-minus ()
339 (if (calc-minibuffer-contains ".* \\'")
343 (defun calcAlg-mod ()
345 (if (not (calc-minibuffer-contains ".* \\'"))
347 (if (calc-minibuffer-contains ".* mod +\\'")
348 (if calc-previous-modulo
349 (insert (math-format-flat-expr calc-previous-modulo 0))
353 (defun calcAlg-previous ()
355 (if (calc-minibuffer-contains "\\'")
356 (previous-history-element 1)
359 (defun calcAlg-equals ()
363 (if (consp calc-alg-exp)
364 (progn (setq prefix-arg (length calc-alg-exp))
365 (calc-unread-command ?=)))))
367 (defun calcAlg-escape ()
369 (calc-unread-command)
372 (use-local-map calc-mode-map))
375 (defun calcAlg-edit ()
377 (if (or (not calc-plain-entry)
378 (calc-minibuffer-contains
379 "\\`\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*\\'"))
381 (setq calc-alg-exp (minibuffer-contents))
386 (defun calcAlg-enter ()
388 (let* ((str (minibuffer-contents))
389 (exp (and (> (length str) 0)
390 (with-current-buffer calc-buffer
391 (math-read-exprs str)))))
392 (if (eq (car-safe exp) 'error)
394 (goto-char (minibuffer-prompt-end))
395 (forward-char (nth 1 exp))
397 (calc-temp-minibuffer-message
398 (concat " [" (or (nth 2 exp) "Error") "]"))
399 (calc-clear-unread-commands))
400 (setq calc-alg-exp (if (calc-minibuffer-contains "\\` *\\[ *\\'")
406 (defun calc-alg-digit-entry ()
408 (calc-digit-start-entry)))
410 ;; The variable calc-digit-value is initially declared in calc.el,
411 ;; but can be set by calcDigit-algebraic and calcDigit-edit.
412 (defvar calc-digit-value)
415 (defun calcDigit-algebraic ()
417 (if (calc-minibuffer-contains ".*[@oh] *[^'m ]+[^'m]*\\'")
419 (setq calc-digit-value (minibuffer-contents))
423 (defun calcDigit-edit ()
425 (calc-unread-command)
426 (setq calc-digit-value (minibuffer-contents))
430 ;;; Algebraic expression parsing. [Public]
433 (defun math-read-preprocess-string (str)
435 ;;; Don't use this in SXEmacs yet.
436 ; "Replace some substrings of STR by Calc equivalents."
438 ; (replace-regexp-in-string (concat "[" math-read-superscripts "]+")
441 ;; The next few variables are local to math-read-exprs (and math-read-expr
442 ;; in calc-ext.el), but are set in functions they call.
444 (defvar math-exp-pos)
445 (defvar math-exp-str)
446 (defvar math-exp-old-pos)
447 (defvar math-exp-token)
448 (defvar math-exp-keep-spaces)
449 (defvar math-expr-data)
452 (defun math-read-exprs (math-exp-str)
453 (let ((math-exp-pos 0)
455 (math-exp-keep-spaces nil)
456 math-exp-token math-expr-data)
457 ; (setq math-exp-str (math-read-preprocess-string math-exp-str))
458 (if (memq calc-language calc-lang-allow-percentsigns)
459 (setq math-exp-str (math-remove-percentsigns math-exp-str)))
460 (if calc-language-input-filter
461 (setq math-exp-str (funcall calc-language-input-filter math-exp-str)))
462 (while (setq math-exp-token
463 (string-match "\\.\\.\\([^.]\\|.[^.]\\)" math-exp-str))
465 (concat (substring math-exp-str 0 math-exp-token) "\\dots"
466 (substring math-exp-str (+ math-exp-token 2)))))
467 (math-build-parse-table)
469 (let ((val (catch 'syntax (math-read-expr-list))))
471 (list 'error math-exp-old-pos val)
472 (if (equal math-exp-token 'end)
474 (list 'error math-exp-old-pos "Syntax error"))))))
477 (defun math-read-expr-list ()
478 (let* ((math-exp-keep-spaces nil)
479 (val (list (math-read-expr-level 0)))
481 (while (equal math-expr-data ",")
483 (let ((rest (list (math-read-expr-level 0))))
488 (defvar calc-user-parse-table nil)
489 (defvar calc-last-main-parse-table nil)
490 (defvar calc-last-user-lang-parse-table nil)
491 (defvar calc-last-lang-parse-table nil)
492 (defvar calc-user-tokens nil)
493 (defvar calc-user-token-chars nil)
495 (defvar math-toks nil
496 "Tokens to pass between math-build-parse-table and math-find-user-tokens.")
499 (defun math-build-parse-table ()
500 (let ((mtab (cdr (assq nil calc-user-parse-tables)))
501 (ltab (cdr (assq calc-language calc-user-parse-tables)))
502 (lltab (get calc-language 'math-parse-table)))
503 (or (and (eq mtab calc-last-main-parse-table)
504 (eq ltab calc-last-user-lang-parse-table)
505 (eq lltab calc-last-lang-parse-table))
506 (let ((p (append mtab ltab lltab))
508 (setq calc-user-parse-table p)
509 (setq calc-user-token-chars nil)
511 (math-find-user-tokens (car (car p)))
513 (setq calc-user-tokens (mapconcat 'identity
514 (sort (mapcar 'car math-toks)
515 (function (lambda (x y)
519 calc-last-main-parse-table mtab
520 calc-last-user-lang-parse-table ltab
521 calc-last-lang-parse-table lltab)))))
524 (defun math-find-user-tokens (p)
526 (cond ((and (stringp (car p))
527 (or (> (length (car p)) 1) (equal (car p) "$")
528 (equal (car p) "\""))
529 ;;; Don't yet use the symbols in SXEmacs
530 ;;; (string-match "[^a-zA-Zα-ωΑ-Ω0-9]" (car p)))
531 (string-match "[^a-zA-Z0-9]" (car p)))
532 (let ((s (regexp-quote (car p))))
533 ;;; (if (string-match "\\`[a-zA-Zα-ωΑ-Ω0-9]" s)
534 (if (string-match "\\`[a-zA-Z0-9]" s)
535 (setq s (concat "\\<" s)))
536 ;;; (if (string-match "[a-zA-Zα-ωΑ-Ω0-9]\\'" s)
537 (if (string-match "[a-zA-Z0-9]\\'" s)
538 (setq s (concat s "\\>")))
539 (or (assoc s math-toks)
541 (setq math-toks (cons (list s) math-toks))
542 (or (memq (aref (car p) 0) calc-user-token-chars)
543 (setq calc-user-token-chars
544 (cons (aref (car p) 0)
545 calc-user-token-chars)))))))
547 (math-find-user-tokens (nth 1 (car p)))
548 (or (eq (car (car p)) '\?)
549 (math-find-user-tokens (nth 2 (car p))))))
553 (defun math-read-token ()
554 (if (>= math-exp-pos (length math-exp-str))
555 (setq math-exp-old-pos math-exp-pos
557 math-expr-data "\000")
559 (ch (aref math-exp-str math-exp-pos)))
560 (setq math-exp-old-pos math-exp-pos)
561 (cond ((memq ch '(? ?\n ?\t))
562 (setq math-exp-pos (1+ math-exp-pos))
563 (if math-exp-keep-spaces
564 (setq math-exp-token 'space
567 ((and (memq ch calc-user-token-chars)
568 (let ((case-fold-search nil))
570 calc-user-tokens math-exp-str math-exp-pos)
572 (setq math-exp-token 'punc
573 math-expr-data (math-match-substring math-exp-str 0)
574 math-exp-pos (match-end 0)))
575 ((or (and (>= ch ?a) (<= ch ?z))
576 (and (>= ch ?A) (<= ch ?Z))
577 ;;; Don't yet use the symbols in SXEmacs
578 ;;; (and (>= ch ?α) (<= ch ?ω))
579 ;;; (and (>= ch ?Α) (<= ch ?Ω)))
583 ((and (memq calc-language calc-lang-allow-underscores)
584 (memq calc-language calc-lang-allow-percentsigns))
585 ;;; Don't yet use the symbols in SXEmacs
586 ;;; "[a-zA-Zα-ωΑ-Ω0-9_'#]*")
588 ((memq calc-language calc-lang-allow-underscores)
589 ;;; "[a-zA-Zα-ωΑ-Ω0-9_#]*")
590 ;;; (t "[a-zA-Zα-ωΑ-Ω0-9'#]*"))
592 (t "[a-zA-Z0-9'#]*"))
593 math-exp-str math-exp-pos)
594 (setq math-exp-token 'symbol
595 math-exp-pos (match-end 0)
596 math-expr-data (math-restore-dashes
597 (math-match-substring math-exp-str 0)))
598 (if (setq adfn (get calc-language 'math-lang-adjust-words))
600 ((or (and (>= ch ?0) (<= ch ?9))
602 (eq (string-match "\\.[0-9]" math-exp-str math-exp-pos)
605 (eq (string-match "_\\.?[0-9]" math-exp-str math-exp-pos)
607 (or (eq math-exp-pos 0)
608 (and (not (memq calc-language
609 calc-lang-allow-underscores))
610 (eq (string-match "[^])}\"a-zA-Z0-9'$]_"
611 ; (eq (string-match "[^])}\"a-zA-Zα-ωΑ-Ω0-9'$]_"
612 math-exp-str (1- math-exp-pos))
613 (1- math-exp-pos))))))
614 (or (and (memq calc-language calc-lang-c-type-hex)
615 (string-match "0[xX][0-9a-fA-F]+" math-exp-str math-exp-pos))
616 ;;; Don't yet use the symbols in SXEmacs
617 ;;; (string-match "_?\\([0-9]+.?0*@ *\\)?\\([0-9]+.?0*' *\\)?\\(0*\\([2-9]\\|1[0-4]\\)\\(#[#]?\\|\\^\\^\\)[0-9a-dA-D.]+[eE][-+_]?[0-9]+\\|0*\\([2-9]\\|[0-2][0-9]\\|3[0-6]\\)\\(#[#]?\\|\\^\\^\\)[0-9a-zA-Zα-ωΑ-Ω:.]+\\|[0-9]+:[0-9:]+\\|[0-9.]+\\([eE][-+_]?[0-9]+\\)?\"?\\)?"
618 (string-match "_?\\([0-9]+.?0*@ *\\)?\\([0-9]+.?0*' *\\)?\\(0*\\([2-9]\\|1[0-4]\\)\\(#\\|\\^\\^\\)[0-9a-dA-D.]+[eE][-+_]?[0-9]+\\|0*\\([2-9]\\|[0-2][0-9]\\|3[0-6]\\)\\(#\\|\\^\\^\\)[0-9a-zA-Z:.]+\\|[0-9]+:[0-9:]+\\|[0-9.]+\\([eE][-+_]?[0-9]+\\)?\"?\\)?"
619 math-exp-str math-exp-pos))
620 (setq math-exp-token 'number
621 math-expr-data (math-match-substring math-exp-str 0)
622 math-exp-pos (match-end 0)))
624 (assq ch (get calc-language 'math-lang-read-symbol)))
628 (if (eq (string-match "\\$\\([1-9][0-9]*\\)" math-exp-str math-exp-pos)
630 (setq math-expr-data (- (string-to-number (math-match-substring
632 (string-match "\\$+" math-exp-str math-exp-pos)
633 (setq math-expr-data (- (match-end 0) (match-beginning 0))))
634 (setq math-exp-token 'dollar
635 math-exp-pos (match-end 0)))
637 (if (eq (string-match "#\\([1-9][0-9]*\\)" math-exp-str math-exp-pos)
639 (setq math-expr-data (string-to-number
640 (math-match-substring math-exp-str 1))
641 math-exp-pos (match-end 0))
642 (setq math-expr-data 1
643 math-exp-pos (1+ math-exp-pos)))
644 (setq math-exp-token 'hash))
645 ((eq (string-match "~=\\|<=\\|>=\\|<>\\|/=\\|\\+/-\\|\\\\dots\\|\\\\ldots\\|\\*\\*\\|<<\\|>>\\|==\\|!=\\|&&&\\||||\\|!!!\\|&&\\|||\\|!!\\|:=\\|::\\|=>"
646 math-exp-str math-exp-pos)
648 (setq math-exp-token 'punc
649 math-expr-data (math-match-substring math-exp-str 0)
650 math-exp-pos (match-end 0)))
652 (string-match "\\(\"\\([^\"\\]\\|\\\\.\\)*\\)\\(\"\\|\\'\\)"
653 math-exp-str math-exp-pos))
654 (setq math-exp-token 'string
655 math-expr-data (math-match-substring math-exp-str 1)
656 math-exp-pos (match-end 0)))
657 ((and (setq adfn (get calc-language 'math-lang-read))
659 (eval (nth 1 adfn))))
660 ((eq (string-match "%%.*$" math-exp-str math-exp-pos) math-exp-pos)
661 (setq math-exp-pos (match-end 0))
664 (if (setq adfn (assq ch (get calc-language 'math-punc-table)))
665 (setq ch (cdr adfn)))
666 (setq math-exp-token 'punc
667 math-expr-data (char-to-string ch)
668 math-exp-pos (1+ math-exp-pos)))))))
670 (defconst math-alg-inequalities
671 '(calcFunc-lt calcFunc-gt calcFunc-leq calcFunc-geq
672 calcFunc-eq calcFunc-neq))
674 (defun math-read-expr-level (exp-prec &optional exp-term)
675 (let* ((math-expr-opers (math-expr-ops))
676 (x (math-read-factor))
679 (while (and (or (and calc-user-parse-table
680 (setq op (calc-check-user-syntax x exp-prec))
682 op '("2x" ident 999999 -1)))
683 (and (setq op (assoc math-expr-data math-expr-opers))
685 (or (and (setq op2 (assoc
687 (cdr (memq op math-expr-opers))))
688 (eq (= (nth 3 op) -1)
690 (eq (= (nth 3 op2) -1)
691 (not (math-factor-after)))
694 (and (or (eq (nth 2 op) -1)
695 (memq math-exp-token '(symbol number dollar hash))
696 (equal math-expr-data "(")
697 (and (equal math-expr-data "[")
700 'math-function-open) "["))
701 (not (and math-exp-keep-spaces
702 (eq (car-safe x) 'vec)))))
703 (or (not (setq op (assoc math-expr-data math-expr-opers)))
705 (or (not calc-user-parse-table)
706 (not (eq math-exp-token 'symbol))
707 (let ((p calc-user-parse-table))
710 (car (car (car p)))))
712 (nth 1 (car (car p)))
716 (setq op (assoc "2x" math-expr-opers))))
717 (not (and exp-term (equal math-expr-data exp-term)))
718 (>= (nth 2 op) exp-prec))
719 (if (not (equal (car op) "2x"))
721 (and (memq (nth 1 op) '(sdev mod))
723 (setq x (cond ((consp (nth 1 op))
724 (funcall (car (nth 1 op)) x op))
726 (if (eq (nth 1 op) 'ident)
728 (if (eq (nth 1 op) 'closing)
729 (if (eq (nth 2 op) exp-prec)
733 (throw 'syntax "Mismatched delimiters"))
734 (list (nth 1 op) x))))
736 (memq (nth 1 op) math-alg-inequalities)
737 (memq (car-safe x) math-alg-inequalities))
739 (math-composite-inequalities x op))
742 (math-read-expr-level (nth 3 op) exp-term))))
746 ;; calc-arg-values is defined in calc-ext.el, but is used here.
747 (defvar calc-arg-values)
750 (defun calc-check-user-syntax (&optional x prec)
751 (let ((p calc-user-parse-table)
756 (setq rule (car (car p)))
758 (and (integerp (car rule))
760 (equal math-expr-data
761 (car (setq rule (cdr rule)))))
762 (equal math-expr-data (car rule)))))
763 (let ((save-exp-pos math-exp-pos)
764 (save-exp-old-pos math-exp-old-pos)
765 (save-exp-token math-exp-token)
766 (save-exp-data math-expr-data))
768 (setq matches (calc-match-user-syntax rule))))
775 (setq matches (cons x matches)))
776 (setq match (cdr (car p)))
777 (while (and (eq (car-safe match)
779 (= (length match) 3))
780 (setq conds (append (math-flatten-lands
783 match (nth 1 match)))
784 (while (and conds match)
786 (cond ((eq (car-safe (car conds))
788 (setq temp (car conds))
789 (or (= (length temp) 3)
790 (and (= (length temp) 2)
791 (eq (car-safe (nth 1 temp))
793 (= (length (nth 1 temp)) 3)
794 (setq temp (nth 1 temp)))
802 args (cons (nth 1 temp)
804 ((and (eq (car-safe (car conds))
806 (= (length (car conds)) 3))
807 (setq temp (calcFunc-vmatches
811 (nth 2 (car conds))))
814 (while (setq temp (cdr temp))
815 (setq matches (cons (nth 2 (car temp))
817 args (cons (nth 1 (car temp))
820 (or (math-is-true (math-simplify
825 (setq conds (cdr conds)))
827 (not (setq match (math-multi-subst
828 match args matches)))
829 (setq math-exp-old-pos save-exp-old-pos
830 math-exp-token save-exp-token
831 math-expr-data save-exp-data
832 math-exp-pos save-exp-pos)))))))
837 (defun calc-match-user-syntax (p &optional term)
839 (save-exp-pos math-exp-pos)
840 (save-exp-old-pos math-exp-old-pos)
841 (save-exp-token math-exp-token)
842 (save-exp-data math-expr-data)
845 (cond ((stringp (car p))
846 (and (equal math-expr-data (car p))
851 (and (setq m (catch 'syntax
852 (math-read-expr-level
855 (if (consp (nth 1 p))
856 (car (nth 1 (nth 1 p)))
860 (setq matches (nconc matches (list m)))))
861 ((eq (car (car p)) '\?)
862 (setq m (calc-match-user-syntax (nth 1 (car p))))
867 (cons 'vec (and (listp m) m))))))
868 (or (listp m) (not (nth 2 (car p)))
869 (not (eq (aref (car (nth 2 (car p))) 0) ?\$))
870 (eq math-exp-token 'end)))
872 (setq m (calc-match-user-syntax (nth 1 (car p))
873 (car (nth 2 (car p)))))
875 (let ((vec (cons 'vec m))
878 (setq opos math-exp-pos
879 mm (calc-match-user-syntax
882 (car (nth 2 (car p))))))
883 (> math-exp-pos opos))
884 (setq vec (nconc vec mm)))
885 (setq matches (nconc matches (list vec))))
886 (and (eq (car (car p)) '*)
887 (setq matches (nconc matches (list '(vec)))))))))
890 (setq math-exp-pos save-exp-pos
891 math-exp-old-pos save-exp-old-pos
892 math-exp-token save-exp-token
893 math-expr-data save-exp-data
898 (defun math-remove-dashes (x)
899 (if (string-match "\\`\\(.*\\)-\\(.*\\)\\'" x)
901 (concat (math-match-substring x 1) "#" (math-match-substring x 2)))
904 (defun math-remove-percentsigns (x)
905 (if (string-match "\\`\\(.*\\)%\\(.*\\)\\'" x)
906 (math-remove-percentsigns
907 (concat (math-match-substring x 1) "o'o" (math-match-substring x 2)))
910 (defun math-restore-dashes (x)
911 (if (string-match "\\`\\(.*\\)[#_]\\(.*\\)\\'" x)
913 (concat (math-match-substring x 1) "-" (math-match-substring x 2)))
916 (defun math-restore-placeholders (x)
917 "Replace placeholders by the proper characters in the symbol x.
918 This includes `#' for `_' and `'' for `%'.
919 If the current Calc language does not use placeholders, return nil."
920 (if (or (memq calc-language calc-lang-allow-underscores)
921 (memq calc-language calc-lang-allow-percentsigns))
922 (let ((sx (symbol-name x)))
923 (when (memq calc-language calc-lang-allow-percentsigns)
925 (setq sx (math-to-percentsigns sx)))
926 (if (memq calc-language calc-lang-allow-underscores)
927 (setq sx (math-string-restore-underscores sx)))
930 (defun math-string-restore-underscores (x)
931 "Replace pound signs by underscores in the string x."
932 (if (string-match "\\`\\(.*\\)#\\(.*\\)\\'" x)
933 (math-string-restore-underscores
934 (concat (math-match-substring x 1) "_" (math-match-substring x 2)))
938 (defun math-read-if (cond op)
939 (let ((then (math-read-expr-level 0)))
940 (or (equal math-expr-data ":")
941 (throw 'syntax "Expected `:'"))
943 (list 'calcFunc-if cond then (math-read-expr-level (nth 3 op)))))
945 (defun math-factor-after ()
946 (let ((math-exp-pos math-exp-pos)
947 math-exp-old-pos math-exp-token math-expr-data)
949 (or (memq math-exp-token '(number symbol dollar hash string))
950 (and (assoc math-expr-data '(("-") ("+") ("!") ("|") ("/")))
951 (assoc (concat "u" math-expr-data) math-expr-opers))
952 (eq (nth 2 (assoc math-expr-data math-expr-opers)) -1)
953 (assoc math-expr-data '(("(") ("[") ("{"))))))
955 (defun math-read-factor ()
956 (let ((math-expr-opers (math-expr-ops))
958 (cond ((eq math-exp-token 'number)
959 (let ((num (math-read-number math-expr-data)))
962 (setq math-exp-old-pos math-exp-pos)
963 (throw 'syntax "Bad format")))
965 (if (and math-read-expr-quotes
969 ((and calc-user-parse-table
970 (setq op (calc-check-user-syntax)))
972 ((or (equal math-expr-data "-")
973 (equal math-expr-data "+")
974 (equal math-expr-data "!")
975 (equal math-expr-data "|")
976 (equal math-expr-data "/"))
977 (setq math-expr-data (concat "u" math-expr-data))
979 ((and (setq op (assoc math-expr-data math-expr-opers))
981 (if (consp (nth 1 op))
982 (funcall (car (nth 1 op)) op)
984 (let ((val (math-read-expr-level (nth 3 op))))
985 (cond ((eq (nth 1 op) 'ident)
987 ((and (Math-numberp val)
988 (equal (car op) "u-"))
990 (t (list (nth 1 op) val))))))
991 ((eq math-exp-token 'symbol)
992 (let ((sym (intern math-expr-data)))
994 (if (equal math-expr-data calc-function-open)
995 (let ((f (assq sym math-expr-function-mapping)))
998 (funcall (car (cdr f)) f sym)
999 (let ((args (if (or (equal math-expr-data calc-function-close)
1000 (eq math-exp-token 'end))
1002 (math-read-expr-list))))
1003 (if (not (or (equal math-expr-data calc-function-close)
1004 (eq math-exp-token 'end)))
1005 (throw 'syntax "Expected `)'"))
1007 (if (and (memq calc-language
1008 calc-lang-parens-are-subscripts)
1011 (let ((calc-matrix-mode 'scalar))
1016 (symbol-name sym)))))))
1017 (math-parse-fortran-subscr sym args)
1020 (and (= (aref (symbol-name sym) 0) ?\\)
1021 (< (prefix-numeric-value calc-language-option)
1023 (setq sym (intern (substring (symbol-name sym)
1025 (or (string-match "-" (symbol-name sym))
1028 (symbol-name sym))))))
1030 (if math-read-expr-quotes
1032 (let ((val (list 'var
1033 (intern (math-remove-dashes
1035 (if (string-match "-" (symbol-name sym))
1037 (intern (concat "var-"
1038 (symbol-name sym)))))))
1040 (assq (nth 1 val) math-expr-variable-mapping)
1041 (assq (math-restore-placeholders (nth 1 val))
1042 math-expr-variable-mapping))))
1043 (and v (setq val (if (consp (cdr v))
1044 (funcall (car (cdr v)) v val)
1047 (substring (symbol-name (cdr v))
1050 (while (and (memq calc-language
1051 calc-lang-brackets-are-subscripts)
1052 (equal math-expr-data "["))
1054 (let ((el (math-read-expr-list)))
1056 (setq val (append (list 'calcFunc-subscr val)
1058 (setq el (cdr el))))
1059 (if (equal math-expr-data "]")
1061 (throw 'syntax "Expected `]'")))
1063 ((eq math-exp-token 'dollar)
1064 (let ((abs (if (> math-expr-data 0) math-expr-data (- math-expr-data))))
1065 (if (>= (length calc-dollar-values) abs)
1066 (let ((num math-expr-data))
1068 (setq calc-dollar-used (max calc-dollar-used num))
1069 (math-check-complete (nth (1- abs) calc-dollar-values)))
1070 (throw 'syntax (if calc-dollar-values
1072 "$'s not allowed in this context")))))
1073 ((eq math-exp-token 'hash)
1074 (or calc-hashes-used
1075 (throw 'syntax "#'s not allowed in this context"))
1077 (if (<= math-expr-data (length calc-arg-values))
1078 (let ((num math-expr-data))
1080 (setq calc-hashes-used (max calc-hashes-used num))
1081 (nth (1- num) calc-arg-values))
1082 (throw 'syntax "Too many # arguments")))
1083 ((equal math-expr-data "(")
1084 (let* ((exp (let ((math-exp-keep-spaces nil))
1086 (if (or (equal math-expr-data "\\dots")
1087 (equal math-expr-data "\\ldots"))
1088 '(neg (var inf var-inf))
1089 (math-read-expr-level 0)))))
1090 (let ((math-exp-keep-spaces nil))
1092 ((equal math-expr-data ",")
1095 (let ((exp2 (math-read-expr-level 0)))
1097 (if (and exp2 (Math-realp exp) (Math-realp exp2))
1098 (math-normalize (list 'cplx exp exp2))
1099 (list '+ exp (list '* exp2 '(var i var-i))))))))
1100 ((equal math-expr-data ";")
1103 (let ((exp2 (math-read-expr-level 0)))
1104 (setq exp (if (and exp2 (Math-realp exp)
1106 (math-normalize (list 'polar exp exp2))
1111 (math-to-radians-2 exp2)
1112 '(var i var-i)))))))))
1113 ((or (equal math-expr-data "\\dots")
1114 (equal math-expr-data "\\ldots"))
1117 (let ((exp2 (if (or (equal math-expr-data ")")
1118 (equal math-expr-data "]")
1119 (eq math-exp-token 'end))
1121 (math-read-expr-level 0))))
1124 (if (equal math-expr-data ")") 0 1)
1127 (if (not (or (equal math-expr-data ")")
1128 (and (equal math-expr-data "]") (eq (car-safe exp) 'intv))
1129 (eq math-exp-token 'end)))
1130 (throw 'syntax "Expected `)'"))
1133 ((eq math-exp-token 'string)
1136 ((equal math-expr-data "[")
1138 (math-read-brackets t "]"))
1139 ((equal math-expr-data "{")
1141 (math-read-brackets nil "}"))
1142 ((equal math-expr-data "<")
1144 (math-read-angle-brackets))
1145 (t (throw 'syntax "Expected a number")))))
1147 (provide 'calc-aent)
1152 ;;; calc-aent.el ends here