home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume11
/
templates
/
part04
/
tplparse.el
next >
Wrap
Lisp/Scheme
|
1987-10-04
|
36KB
|
1,194 lines
;;; tplparse.el -- Parsing routines for template package
;;; Copyright (C) 1987 Mark A. Ardis.
(require 'tplvars)
(require 'tplhelper)
(provide 'tplparse)
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; All global variables are in "tplvars"
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun looking-at-tpl ()
"t if text after point matches specified template."
(interactive)
; Local Variables
(let (name-list tpl-name)
; Body
(setq name-list (tpl-make-completion-list))
(setq tpl-name (completing-read "looking-at-tpl: Template name? "
name-list nil t nil))
(tpl-looking-at tpl-name)
) ; let
) ; defun looking-at-tpl
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun query-replace-tpl ()
"Replace some instances of a template with corresponding instances
of another."
(interactive)
; Local Variables
(let (name-list from to)
; Body
(setq name-list (tpl-make-completion-list))
(setq from (completing-read "query-replace-tpl: From? "
name-list nil t nil))
(setq to (completing-read (concat "query-replace-tpl: From " from " To? ")
name-list nil t nil))
(tpl-query-replace from to)
) ; let
) ; defun query-replace-tpl
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun replace-tpl ()
"Replace an instance of a template with a corresponding instance
of another template."
(interactive)
; Local Variables
(let (name-list from to)
; Body
(setq name-list (tpl-make-completion-list))
(setq from (completing-read "replace-tpl: From? "
name-list nil t nil))
(setq to (completing-read (concat "replace-tpl: From " from " To? ")
name-list nil t nil))
(while (tpl-search-forward from (point-max) t)
(exchange-point-and-mark)
(tpl-replace from to)
) ; while
) ; let
) ; defun replace-tpl
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun search-forward-tpl ()
"Search forward from point for a template."
(interactive)
; Local Variables
(let (name-list tpl-name)
; Body
(setq name-list (tpl-make-completion-list))
(setq tpl-name (completing-read "search-forward-tpl: Name of template? "
name-list nil t nil))
(tpl-search-forward tpl-name)
) ; let
) ; defun search-forward-tpl
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-delete-leading-whitespace (text-list)
"Remove leading whitespace tokens from TEXT-LIST and return remaining list."
; Local Variables
(let ()
; Body
(while (and text-list (equal tpl-whitespace-type
(tpl-token-name (car text-list))))
(setq text-list (cdr text-list))
) ; while
; return
text-list
) ; let
) ; defun tpl-delete-leading-whitespace
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-fix-match (tree old new)
"Adjust indentation in TREE from OLD to NEW."
; Local Variables
(let (result token-list token)
; Body
(if (not new)
(setq new old)
) ; if
(setq result nil)
(setq token-list (tpl-token-value tree))
(while token-list
(setq token (car token-list))
(setq token-list (cdr token-list))
;(debug nil "token" token)
(if (and (equal tpl-indentation-type (tpl-token-name token))
(/= tpl-comment-level (tpl-token-value token)))
(setq token (tpl-make-token (tpl-token-type token)
(tpl-token-name token)
(+ (- new old) (tpl-token-value token))))
) ; if
(setq result (append result (list token)))
) ; while token-list
; return
result
) ; let
) ; defun tpl-fix-match
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-get-match (placeholder tree indent)
"Find match for PLACEHOLDER in TREE. Adjust matched value with INDENT."
; Local Variables
(let (name match token token-type current-indent)
; Body
(setq name (tpl-token-name (tpl-parse-placeholder (tpl-token-value placeholder))))
(setq match nil)
(while (and tree (not match))
(setq token (car tree))
(setq tree (cdr tree))
(setq token-type (tpl-token-type token))
;(debug nil "token-type" token-type)
(if (equal tpl-terminal-type token-type)
(if (equal tpl-indentation-type (tpl-token-name token))
(setq current-indent (tpl-token-value token))
) ; if (equal tpl-indentation-type (tpl-token-name token))
; else
(if (equal name
(tpl-token-name
(tpl-parse-placeholder (tpl-token-name token))))
(setq match (tpl-fix-match token indent current-indent))
) ; if (equal name...)
) ; if (equal tpl-terminal-type token-type)
) ; while (and tree (not match))
; return
match
) ; let
) ; defun tpl-get-match
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-get-placeholder-end (placeholder tpl-name &optional occurrence)
"Prompt user for end of PLACEHOLDER in TPL-NAME.
Optional third argument OCCURRENCE specifies which
occurrence of placeholder to find."
; Local Variables
(let (template msg return stop size)
; Body
(if (not occurrence)
(setq occurrence 1)
) ; if
; Get value before changing buffer
(setq template (tpl-find-template tpl-name))
(save-window-excursion
(delete-other-windows)
(pop-to-buffer (get-buffer-create "*Template*"))
(erase-buffer)
(tpl-unscan template)
; Size the window
(setq stop (point-max))
(goto-char (point-min))
(setq size (1+ (count-lines (point) stop)))
(setq size (max size window-min-height))
(if (< size (window-height))
(shrink-window (- (window-height) size))
) ; if
; Find the placeholder
(search-forward placeholder (point-max) t occurrence)
(other-window 1)
(setq msg (concat "In \"" tpl-name "\" looking for end of \""
placeholder "\""))
(setq return (tpl-get-position (point) (point-max) msg))
) ; save-window-excursion
(bury-buffer "*Template*")
return
) ; let
) ; defun tpl-get-placeholder-end
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-get-position (start stop msg &optional start-pos narrow)
"Prompt user for a location between START and STOP with MSG.
Optional fourth argument START-POS may be used for initial
placement of point. Fifth argument NARROW, if non-nil,
narrows the region."
; Local Variables
(let (looking was-modifiable)
; Body
; Check for valid region
(if (< stop start)
(error "tpl-get-position: Invalid region specification.")
) ; if
; Save current status
(if (not start-pos)
(setq start-pos start)
) ; if
(save-restriction
(if narrow
(narrow-to-region start stop)
) ; if
(setq was-modifiable (not buffer-read-only))
(if was-modifiable
(toggle-read-only)
) ; if was-modifiable
(setq orig-buffer (current-buffer))
; Loop until acceptable answer
(setq looking t)
(while looking
(goto-char start-pos)
(message msg)
; Wait for user selection
(recursive-edit)
; Check validity
(if (or (not (equal orig-buffer (current-buffer)))
(< (point) start)
(> (point) stop))
(progn
(ding)
(message "Selected position out of bounds.")
(sit-for 2)
(pop-to-buffer orig-buffer)
(goto-char start-pos)
) ; progn
; else
(setq looking nil)
) ; if
) ; while looking
; Restore original status
(if was-modifiable
(toggle-read-only)
) ; if was-modifiable
(if narrow
(widen)
) ; if narrow
) ; save-restriction
(point) ; return
) ; let
) ; defun tpl-get-position
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-leading-text (template)
"Return literal text string at start of TEMPLATE (a name)."
; Local Variables
(let (body start stop result)
; Body
(setq body (tpl-find-template template))
(if (not body)
(error "Cannot find template.")
) ; if (not body)
(get-buffer-create "*Work*")
(save-window-excursion
(set-buffer "*Work*")
(erase-buffer)
(tpl-unscan body)
(goto-char (point-min))
(setq start (point))
(end-of-line nil)
(setq stop (point))
(goto-char start)
(if (re-search-forward tpl-begin-placeholder stop start)
(re-search-backward tpl-begin-placeholder)
) ; if
(setq result (buffer-substring start (point)))
) ; save-window-excursion
; return
result
) ; let
) ; defun tpl-leading-text
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-line-to-token (tree)
"Convert TREE from line-format to token-format."
; Local Variables
(let (line-list line token result type name)
; Body
(setq result nil)
(setq type (tpl-token-type tree))
(setq name (tpl-token-name tree))
(setq line-list (tpl-token-value tree))
(while line-list
(setq line (car line-list))
(setq line-list (cdr line-list))
(setq result
(append result
(list (tpl-make-token tpl-terminal-type
tpl-indentation-type
(tpl-line-indent line)))))
(setq result (append result (tpl-line-tokens line)))
(if line-list
(setq result (append result (list tpl-newline-token)))
) ; if line-list
) ; while line-list
(setq result (tpl-make-token type name result))
; return
result
) ; let
) ; defun tpl-line-to-token
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-looking-at (name)
"t if text after point matches template NAME"
; Local Variables
(let (result)
; Body
(setq result (tpl-match-template name))
(if result
t
nil
) ; if
) ; let
) ; defun tpl-looking-at
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-function-template (template)
"Match TEMPLATE and return t or nil."
; Local Variables
(let ()
; Body
(error "tpl-match-function-type: Cannot match function-type templates.")
) ; let
) ; defun tpl-match-function-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-lexical-template (template)
"Match TEMPLATE and return t or nil."
; Local Variables
(let ()
; Body
(looking-at (tpl-token-value template))
) ; let
) ; defun tpl-match-lexical-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-line (pattern text)
"Attempt to match the line described by PATTERN with TEXT. Return t or nil."
; Local Variables
(let (pattern-list text-list next-pattern result success)
; Body
(if (and text
(= (tpl-line-indent pattern) (tpl-line-indent text)))
(progn
(setq success t)
(setq pattern-list (tpl-line-tokens pattern))
(setq text-list (tpl-line-tokens text))
(while (and pattern-list success text-list)
(setq next-pattern (car pattern-list))
(setq pattern-list (cdr pattern-list))
(setq result (tpl-match-token next-pattern text-list))
(if result
(setq text-list (cdr result))
; else
(setq success nil)
) ; if result
) ; while pattern-list
) ; progn
; else
(setq success nil)
) ; if (= (tpl-line-indent pattern) (tpl-line-indent text))
; return
success
) ; let
) ; defun tpl-match-line
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-pattern (pattern-list scanner-patterns)
"Attempt to match each line in PATTERN-LIST with text after point.
Return a list of matches. Second argument SCANNER-PATTERNS
specifies what type of lexical patterns to use when scanning."
; Local Variables
(let (success tree this-pattern next-pattern this-match first-text next-text
start-region start-col
this-indent next-indent)
; Body
(setq success t)
(setq tree nil)
; Initialize scanner
(setq start-region (point))
(setq start-col (current-column))
(setq this-indent 0)
; Get first "next text line"
(back-to-indentation)
(setq next-text (tpl-scan-line start-col scanner-patterns))
(setq this-indent (tpl-line-indent next-text))
(if (not (eobp))
(forward-char)
) ; if
; For each line in pattern
(while (and pattern-list success)
;(debug nil "top of pattern loop")
; Get next pattern line
(setq this-pattern (car pattern-list))
(setq pattern-list (cdr pattern-list))
(if pattern-list
(setq next-pattern (car pattern-list))
; else
(setq next-pattern nil)
) ; if pattern-list
(setq this-match nil)
; Get first text line
(setq first-text next-text)
; Try to match lines
(if (tpl-match-line this-pattern first-text)
(progn
(setq this-match (list first-text))
(if next-pattern
(progn
(setq next-indent (tpl-line-indent next-pattern))
; Get next text line
(back-to-indentation)
(setq next-text (tpl-scan-line start-col scanner-patterns))
(setq this-indent (tpl-line-indent next-text))
(if (not (eobp))
(forward-char)
) ; if
; Append until next match
(while (and (not (eobp))
(or (> this-indent next-indent)
(equal (tpl-line-tokens next-text) nil)))
;(debug nil "appending in middle...")
(setq this-match (append this-match (list next-text)))
; Get next text line
(back-to-indentation)
(setq next-text (tpl-scan-line start-col scanner-patterns))
(setq this-indent (tpl-line-indent next-text))
(if (not (eobp))
(forward-char)
) ; if
) ; while
) ; progn
; else
; Append until no more indentation
(progn
(while (and (not (eobp))
(or (> this-indent 0)
(equal (tpl-line-tokens next-text) nil)))
;(debug nil "appending at end...")
(setq this-match (append this-match (list next-text)))
; Get next text line
(back-to-indentation)
(setq this-col (current-column))
(setq next-text (tpl-scan-line start-col scanner-patterns))
(setq this-indent (tpl-line-indent next-text))
(if (not (eobp))
(forward-char)
) ; if
) ; while
(if (> this-indent 0)
(setq this-match (append this-match (list next-text)))
(forward-line -1)
) ; if
) ; progn
) ; if next-pattern
(setq tree (append tree (list (list this-pattern this-match))))
) ; progn
; else
(setq success nil)
) ; if (tpl-match-line this-pattern first-text)
) ; while pattern-list
; Set point and mark
(if success
(progn
(setq success tree)
(set-mark start-region)
(if (eobp)
(end-of-line)
; else
(end-of-line 0)
) ; if
) ; progn
; else
(goto-char start-region)
) ; if success
; return
success
) ; let
) ; defun tpl-match-pattern
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-repetition-template (template)
"Match TEMPLATE and return t or nil."
; Local Variables
(let ()
; Body
(error
"tpl-match-repetition-template: Cannot match repetition-type template.")
) ; let
) ; defun tpl-match-repetition-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-selection-template (template)
"Match TEMPLATE and return tree or nil."
; Local Variables
(let (result selection-list selection)
; Body
(setq result nil)
(setq selection-list (tpl-token-value template))
(while (and selection-list (not result))
(setq selection (car selection-list))
(setq selection-list (cdr selection-list))
(setq selection (tpl-token-value (car (tpl-line-tokens selection))))
(setq result (tpl-match-template selection))
) ; while selection-list
; return
result
) ; let
) ; defun tpl-match-selection-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-sequence-template (template)
"Match TEMPLATE and return tree or nil."
; Local Variables
(let (pattern-list result)
; Body
(setq pattern-list (tpl-token-value template))
(setq result (tpl-match-pattern pattern-list lex-patterns))
(if result
(setq result (tpl-make-token
tpl-sequence-type (tpl-token-name template) result))
) ; if result
; return
result
) ; let
) ; defun tpl-match-sequence-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-string-template (template)
"Match TEMPLATE and return tree or nil."
; Local Variables
(let (pattern-list result)
; Body
(setq pattern-list (tpl-token-value template))
(setq result (tpl-match-pattern pattern-list string-patterns))
(if result
(setq result (tpl-make-token
tpl-sequence-type (tpl-token-name template) result))
) ; if result
; return
result
) ; let
) ; defun tpl-match-string-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-template (name)
"Match template NAME and return tree or nil."
; Local Variables
(let (template template-type result)
; Body
(setq template (tpl-find-template name))
(setq template-type (tpl-token-type template))
(cond
((equal template-type tpl-function-type)
(setq result (tpl-match-function-template template))
) ; (equal template-type tpl-function-type)
((equal template-type tpl-lexical-type)
(setq result (tpl-match-lexical-template template))
) ; (equal template-type tpl-lexical-type)
((equal template-type tpl-repetition-type)
(setq result (tpl-match-repetition-template template))
) ; (equal template-type tpl-repetition-type)
((equal template-type tpl-selection-type)
(setq result (tpl-match-selection-template template))
) ; (equal template-type tpl-selection-type)
((equal template-type tpl-sequence-type)
(setq result (tpl-match-sequence-template template))
) ; (equal template-type tpl-sequence-type)
((equal template-type tpl-string-type)
(setq result (tpl-match-string-template template))
) ; (equal template-type tpl-string-type)
) ; cond
; return
result
) ; let
) ; defun tpl-match-template
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-match-token (token text-list)
"Attempt to match TOKEN with tokens in TEXT-LIST. Return the
list (t remainder-of-TEXT-LIST) or nil."
; Local Variables
(let (type success)
; Body
(setq text-list (tpl-delete-leading-whitespace text-list))
(setq type (tpl-token-name token))
(cond
((or (equal type tpl-other-type)
(equal type tpl-punctuation-type)
(equal type tpl-string-type))
(progn
(if text-list
(progn
(setq success (equal (tpl-token-value token)
(tpl-token-value (car text-list))))
(setq text-list (cdr text-list))
) ; progn
; else
(setq success nil)
) ; if text-list
) ; progn
) ; (or (equal type tpl-other-type)...)
((equal type tpl-word-type)
(progn
(if text-list
(progn
(setq success (equal (upcase (tpl-token-value token))
(upcase (tpl-token-value (car text-list)))))
(setq text-list (cdr text-list))
) ; progn
; else
(setq success nil)
) ; if text-list
) ; progn
) ; (equal type tpl-word-type)
((equal type tpl-whitespace-type)
(progn
(if (and text-list
(equal tpl-whitespace-type (tpl-token-name (car text-list))))
(setq text-list (cdr text-list))
) ; if
(setq success t)
) ; progn
) ; (equal type tpl-whitespace-type)
((or (equal type tpl-placeholder-type)
(equal type tpl-optional-type))
(progn
(setq text-list nil)
(setq success t)
) ; progn
) ; (equal type tpl-placeholder-type)
) ; cond
(if success
(setq success (cons t text-list))
) ; if success
; return
success
) ; let
) ; defun tpl-match-token
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-function (template)
"Try to parse text at point as an instance of function-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let ()
; Body
(error "tpl-parse-function: Cannot parse function-type templates.")
) ; let
) ; defun tpl-parse-function
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-instance (tpl-name)
"Try to parse text at point as an instance of TPL-NAME.
Return a parse tree or nil."
; Local Variables
(let ()
; Body
(setq template (tpl-find-template tpl-name))
(setq template-type (tpl-token-type template))
(cond
((equal template-type tpl-function-type)
(setq result (tpl-parse-function template))
) ; (equal template-type tpl-function-type)
((equal template-type tpl-lexical-type)
(setq result (tpl-parse-lexical template))
) ; (equal template-type tpl-lexical-type)
((equal template-type tpl-repetition-type)
(setq result (tpl-parse-repetition template))
) ; (equal template-type tpl-repetition-type)
((equal template-type tpl-selection-type)
(setq result (tpl-parse-selection template))
) ; (equal template-type tpl-selection-type)
((equal template-type tpl-sequence-type)
(setq result (tpl-parse-sequence template))
) ; (equal template-type tpl-sequence-type)
((equal template-type tpl-string-type)
(setq result (tpl-parse-string template))
) ; (equal template-type tpl-string-type)
) ; cond
result ; return
) ; let
) ; defun tpl-parse-instance
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-lexical (template)
"Try to parse text at point as an instance of lexical-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let ()
; Body
(error "tpl-parse-lexical: Cannot parse lexical-type templates.")
) ; let
) ; defun tpl-parse-lexical
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-pattern (pattern tpl-name start-col scanner-patterns)
"Try to parse text at point as an instance of PATTERN within
template TPL-NAME. START-COL specifies the starting column of
the template. SCANNER-PATTERNS specifies which lexical patterns
to use when scanning. Return a token or nil."
; Local Variables
(let (type result start stop this-col indent-level)
; Body
(setq type (tpl-token-name pattern))
(cond
((equal type tpl-indentation-type)
(progn
(setq result pattern)
) ; progn
) ; (equal type tpl-indentation-type)
((equal type tpl-newline-type)
(progn
(setq result pattern)
) ; progn
) ; (equal type tpl-newline-type)
((equal type tpl-other-type)
(progn
(tpl-skip-over-whitespace)
(if (looking-at (tpl-token-value pattern))
(setq result (tpl-scan-token scanner-patterns))
(setq result nil)
) ; if
) ; progn
) ; (equal type tpl-other-type)
((equal type tpl-placeholder-type)
(progn
(tpl-skip-over-whitespace)
(setq start (point))
(setq stop (tpl-get-placeholder-end (tpl-token-value pattern)
tpl-name))
(setq result nil)
(goto-char start)
(while (< (point) stop)
(if (eolp)
; This code duplicates some of
; "tpl-scan-line"
(progn
(setq result
(append result (list tpl-newline-token)))
(forward-line 1)
(back-to-indentation)
(setq this-col (current-column))
(cond
((>= this-col comment-column)
(progn
(setq indent-level tpl-comment-level)
) ; progn
) ; comment
((<= this-col start-col)
(progn
(setq indent-level 0)
) ; progn
) ; too small
(t
(progn
(setq indent-level (- this-col start-col))
) ; progn
) ; t
) ; cond
(setq result
(append result (list (tpl-make-token
tpl-terminal-type
tpl-indentation-type
indent-level))))
) ; progn
; else
(progn
(setq result
(append result (list (tpl-scan-token scanner-patterns))))
) ; progn
) ; if
) ; while
(setq result (tpl-make-token tpl-placeholder-type
(tpl-token-value pattern)
result))
) ; progn
) ; (equal type tpl-placeholder-type)
((equal type tpl-punctuation-type)
(progn
(tpl-skip-over-whitespace)
(if (looking-at (tpl-token-value pattern))
(setq result (tpl-scan-token scanner-patterns))
(setq result nil)
) ; if
) ; progn
) ; (equal type tpl-punctuation-type)
((equal type tpl-string-type)
(progn
(tpl-skip-over-whitespace)
(if (looking-at (tpl-token-value pattern))
(setq result (tpl-scan-token scanner-patterns))
(setq result nil)
) ; if
) ; progn
) ; (equal type tpl-string-type)
((equal type tpl-whitespace-type)
(progn
(setq result pattern)
) ; progn
) ; (equal type tpl-whitespace-type)
((equal type tpl-word-type)
(progn
(tpl-skip-over-whitespace)
(if (looking-at (tpl-token-value pattern))
(setq result (tpl-scan-token scanner-patterns))
(setq result nil)
) ; if
) ; progn
) ; (equal type tpl-word-type)
) ; cond
result ; return
) ; let
) ; defun tpl-parse-pattern
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-placeholder (string)
"Parse STRING as a placeholder and return token."
; Local Variables
(let (token)
; Body
(get-buffer-create "*Work*")
(save-window-excursion
(set-buffer "*Work*")
(erase-buffer)
(insert string)
(beginning-of-line)
(setq token (tpl-scan-placeholder))
) ; save-window-excursion
; return
token
) ; let
) ; defun tpl-parse-placeholder
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-repetition (template)
"Try to parse text at point as an instance of repetition-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let ()
; Body
(error "tpl-parse-repetition: Cannot parse repetition-type templates.")
) ; let
) ; defun tpl-parse-repetition
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-selection (template)
"Try to parse text at point as an instance of selection-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let ()
; Body
(error "tpl-parse-selection: Cannot parse selection-type templates.")
) ; let
) ; defun tpl-parse-selection
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-sequence (template)
"Try to parse text at point as an instance of sequence-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let (tpl-name pattern-list pattern result success match start-col)
; Body
(setq tpl-name (tpl-token-name template))
(setq pattern-list (tpl-token-value (tpl-line-to-token template)))
(setq start-col (current-column))
(setq result nil)
(setq success t)
(while (and success pattern-list)
(setq pattern (car pattern-list))
(setq pattern-list (cdr pattern-list))
(setq match (tpl-parse-pattern pattern tpl-name start-col lex-patterns))
(if match
(setq result (append result (list match)))
; else
(setq success nil)
) ; if match
) ; while
(if success
result ; return
; else
nil ; return
) ; if success
) ; let
) ; defun tpl-parse-sequence
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-parse-string (template)
"Try to parse text at point as an instance of string-type TEMPLATE.
Return a parse tree or nil."
; Local Variables
(let (tpl-name pattern-list pattern result success match start-col)
; Body
(setq tpl-name (tpl-token-name template))
(setq pattern-list (tpl-token-value (tpl-line-to-token template)))
(setq start-col (current-column))
(setq result nil)
(setq success t)
(while (and success pattern-list)
(setq pattern (car pattern-list))
(setq pattern-list (cdr pattern-list))
(setq match (tpl-parse-pattern
pattern tpl-name start-col string-patterns))
(if match
(setq result (append result (list match)))
; else
(setq success nil)
) ; if match
) ; while
(if success
result ; return
; else
nil ; return
) ; if success
) ; let
) ; defun tpl-parse-string
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-query-replace (from to)
"Replace some instances after point matching FROM template with
corresponding instances of TO. As each match is found, the user
must type a character saying what to do with it. For directions,
type \\[help-command] at that time."
; Local Variables
(let ()
; Body
(perform-replace-tpl from to t nil nil
'tpl-search-forward
'exchange-point-and-mark 'tpl-replace)
) ; let
) ; defun tpl-query-replace
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-replace (from to)
"Replace the instance of template FROM with a corresponding instance
of template TO."
; Local Variables
(let (token-tree new start)
; Body
(setq start (point))
(message (concat "replace-tpl: Trying to match \"" from "\"..."))
(setq token-tree (tpl-parse-instance from))
;(debug nil "token-tree" token-tree)
(message (concat "replace-tpl: Trying to construct \"" to "\"..."))
(setq new (tpl-token-to-line (tpl-replace-placeholders to token-tree)))
;(debug nil "new tree" new)
(delete-region start (point))
(setq start (point))
(tpl-unscan new)
(set-mark start)
(message "replace-tpl: Done.")
) ; let
) ; defun tpl-replace
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-replace-placeholders (name tree)
"Replace placeholders in template NAME using values from TREE."
; Local Variables
(let (result template token-list token token-type current-indent match)
; Body
(setq result nil)
(setq template (tpl-find-template name))
(if (not (or
(equal tpl-sequence-type (tpl-token-type template))
(equal tpl-string-type (tpl-token-type template))))
(error (concat "tpl-replace-placeholders: "
"Target template must be SEQUENCE or STRING type"))
) ; if
(setq token-list (tpl-token-value (tpl-line-to-token template)))
(while token-list
(setq token (car token-list))
(setq token-list (cdr token-list))
(setq token-type (tpl-token-name token))
;(debug nil "token-type" token-type)
(if (or (equal tpl-placeholder-type token-type)
(equal tpl-optional-type token-type))
(progn
(setq match (tpl-get-match token tree current-indent))
(if match
(setq result (append result match))
; else
(setq result (append result (list token)))
) ; if match
) ; progn
; else
(progn
(if (equal tpl-indentation-type token-type)
(setq current-indent (tpl-token-value token))
) ; if (equal tpl-indentation-type token-type)
(setq result (append result (list token)))
) ; progn
) ; if (equal tpl-placeholder-type token-type)
) ; while token-list
(setq result (tpl-make-token t t result))
; return
result
) ; let
) ; defun tpl-replace-placeholders
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-search-forward (template &optional bound forgiving count)
"Search forward from point for TEMPLATE (a name).
An optional second argument bounds the search; it is a buffer
position. The match found must not extend beyond that position.
Optional third argument, if t, means if fail just return nil
(no error). If not nil and not t, move to limit of search and
return nil. Optional fourth argument is repeat count."
; Local Variables
(let (leading found occur gaveup start trial)
; Body
(setq start (point))
(if (not bound)
(setq bound (point-max))
)
(if (not count)
(setq count 1)
)
(setq occur 0)
(setq leading (tpl-leading-text template))
(if leading
(progn
(setq found nil)
(setq gaveup nil)
(while (and (not found) (not gaveup))
(if (search-forward leading bound t)
(progn
(search-backward leading)
(setq trial (point))
(setq found (tpl-looking-at template))
(if (and found
(<= (point) bound))
(progn
(setq occur (1+ occur))
(if (< occur count)
(setq found nil)
)
) ; progn
; else
(if found
(setq gaveup t) ; Out of bounds---no more
; else
(progn ; Failed this time---try again
(goto-char trial)
(forward-line 1)
) ; progn
) ; if found
) ; if (and found...)
) ; progn
; else
(setq gaveup t)
) ; if (search-forward...)
) ; while
) ; progn
; else
(error "Cannot search for templates that start with a placeholder.")
) ; if leading
(if (or gaveup (not found))
(if (not forgiving)
(progn
(goto-char bound)
(error "Could not find template.")
) ; progn
; else
(if (eq forgiving t)
(progn
(goto-char start)
) ; progn
; else
(progn
(goto-char bound)
) ; progn
) ; if (eq forgiving t)
) ; if (not forgiving)
) ; if (not found)
(if gaveup
(setq found nil)
) ; if gaveup
; return
found
) ; let
) ; defun tpl-search-forward
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-skip-over-whitespace ()
"Advance point past newlines and whitespace."
; Local Variables
(let (moving)
; Body
(setq moving t)
(while (and moving (not (eobp)))
(setq moving nil)
(if (eolp)
(progn
(setq moving t)
(forward-line 1)
) ; progn
) ; if
(if (looking-at tpl-pattern-whitespace)
(progn
(setq moving t)
(re-search-forward tpl-pattern-whitespace)
) ; progn
) ; if
) ; while
) ; let
) ; defun tpl-skip-over-whitespace
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(defun tpl-token-to-line (tree)
"Convert TREE from token-format to line-format."
; Local Variables
(let (result line token-list token type name token-type save-indent)
; Body
(setq result nil)
(setq line nil)
(setq type (tpl-token-type tree))
(setq name (tpl-token-name tree))
(setq token-list (tpl-token-value tree))
(while token-list
(setq token (car token-list))
(setq token-list (cdr token-list))
(setq token-type (tpl-token-name token))
(cond
((equal token-type tpl-indentation-type)
(progn
(setq save-indent (tpl-token-value token))
) ; progn
) ; tpl-indentation-type
((equal token-type tpl-newline-type)
(progn
(setq result (append result (list (tpl-make-line save-indent line))))
(setq line nil)
) ; progn
) ; tpl-newline-type
(t
(progn
(setq line (append line (list token)))
) ; progn
) ; t
) ; cond
) ; while token-list
(setq result (append result (list (tpl-make-line save-indent line))))
(setq result (tpl-make-token type name result))
; return
result
) ; let
) ; defun tpl-token-to-line
;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;; end of tplparse.el