15dfecf96Smrg; 25dfecf96Smrg;; Copyright (c) 2002 by The XFree86 Project, Inc. 35dfecf96Smrg;; 45dfecf96Smrg;; Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg;; copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg;; to deal in the Software without restriction, including without limitation 75dfecf96Smrg;; the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg;; and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg;; Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg;; 115dfecf96Smrg;; The above copyright notice and this permission notice shall be included in 125dfecf96Smrg;; all copies or substantial portions of the Software. 135dfecf96Smrg;; 145dfecf96Smrg;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg;; THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg;; OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg;; SOFTWARE. 215dfecf96Smrg;; 225dfecf96Smrg;; Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg;; not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg;; dealings in this Software without prior written authorization from the 255dfecf96Smrg;; XFree86 Project. 265dfecf96Smrg;; 275dfecf96Smrg;; Author: Paulo César Pereira de Andrade 285dfecf96Smrg;; 295dfecf96Smrg;; 305dfecf96Smrg;; $XFree86: xc/programs/xedit/lisp/modules/indent.lsp,v 1.6 2003/01/16 03:50:46 paulo Exp $ 315dfecf96Smrg;; 325dfecf96Smrg 335dfecf96Smrg(provide "indent") 345dfecf96Smrg(require "xedit") 355dfecf96Smrg(in-package "XEDIT") 365dfecf96Smrg 375dfecf96Smrg(defconstant indent-spaces '(#\Tab #\Space)) 385dfecf96Smrg 395dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 405dfecf96Smrg;; The final indentation function. 415dfecf96Smrg;; Parameters: 425dfecf96Smrg;; indent 435dfecf96Smrg;; Number of spaces to insert 445dfecf96Smrg;; offset 455dfecf96Smrg;; Offset to where indentation should be added 465dfecf96Smrg;; no-tabs 475dfecf96Smrg;; If set, tabs aren't inserted 485dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 495dfecf96Smrg(defun indent-text (indent offset &optional no-tabs 505dfecf96Smrg &aux start line length index current tabs spaces string 515dfecf96Smrg barrier base result (point (point)) 525dfecf96Smrg ) 535dfecf96Smrg 545dfecf96Smrg ;; Initialize 555dfecf96Smrg (setq 565dfecf96Smrg start (scan offset :eol :left) 575dfecf96Smrg line (read-text start (- offset start)) 585dfecf96Smrg length (length line) 595dfecf96Smrg index (1- length) 605dfecf96Smrg current 0 615dfecf96Smrg base 0 625dfecf96Smrg ) 635dfecf96Smrg 645dfecf96Smrg (and (minusp indent) (setq indent 0)) 655dfecf96Smrg 665dfecf96Smrg ;; Skip any spaces after offset, "paranoia check" 675dfecf96Smrg (while (member (char-after offset) indent-spaces) 685dfecf96Smrg (incf offset) 695dfecf96Smrg ) 705dfecf96Smrg 715dfecf96Smrg ;; Check if there are only spaces before `offset' and the line `start' 725dfecf96Smrg (while (and (>= index 0) (member (char line index) indent-spaces)) 735dfecf96Smrg (decf index) 745dfecf96Smrg ) 755dfecf96Smrg 765dfecf96Smrg ;; `index' will be zero if there are only spaces in the `line' 775dfecf96Smrg (setq barrier (+ start (incf index))) 785dfecf96Smrg 795dfecf96Smrg ;; Calculate `base' unmodifiable indentation, if any 805dfecf96Smrg (dotimes (i index) 815dfecf96Smrg (if (char= (char line i) #\Tab) 825dfecf96Smrg (incf base (- 8 (rem base 8))) 835dfecf96Smrg (incf base) 845dfecf96Smrg ) 855dfecf96Smrg ) 865dfecf96Smrg 875dfecf96Smrg ;; If any non blank character would need to be deleted 885dfecf96Smrg (and (> base indent) (return-from indent-text nil)) 895dfecf96Smrg 905dfecf96Smrg ;; Calculate `current' indentation 915dfecf96Smrg (setq current base) 925dfecf96Smrg (while (< index length) 935dfecf96Smrg (if (char= (char line index) #\Tab) 945dfecf96Smrg (incf current (- 8 (rem current 8))) 955dfecf96Smrg (incf current) 965dfecf96Smrg ) 975dfecf96Smrg (incf index) 985dfecf96Smrg ) 995dfecf96Smrg 1005dfecf96Smrg ;; Maybe could also "optimize" the indentation even if it is already 1015dfecf96Smrg ;; correct, removing spaces "inside" tabs. 1025dfecf96Smrg (when (/= indent current) 1035dfecf96Smrg (if no-tabs 1045dfecf96Smrg (setq 1055dfecf96Smrg length (- indent base) 1065dfecf96Smrg result (+ barrier length) 1075dfecf96Smrg string (make-string length :initial-element #\Space) 1085dfecf96Smrg ) 1095dfecf96Smrg (progn 1105dfecf96Smrg (multiple-value-setq (tabs spaces) (floor (- indent base) 8)) 1115dfecf96Smrg (setq 1125dfecf96Smrg length (+ tabs spaces) 1135dfecf96Smrg result (+ barrier length) 1145dfecf96Smrg string (make-string length :initial-element #\Tab) 1155dfecf96Smrg ) 1165dfecf96Smrg (fill string #\Space :start tabs) 1175dfecf96Smrg ) 1185dfecf96Smrg ) 1195dfecf96Smrg 1205dfecf96Smrg (replace-text barrier offset string) 1215dfecf96Smrg (and (>= offset point) (>= point barrier) (goto-char result)) 1225dfecf96Smrg ) 1235dfecf96Smrg) 1245dfecf96Smrg(compile 'indent-text) 1255dfecf96Smrg 1265dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1275dfecf96Smrg;; Helper function, returns indentation of a given offset 1285dfecf96Smrg;; If `align' is set, stop once a non blank character is seen, that 1295dfecf96Smrg;; is, use `offset' only as a line identifier 1305dfecf96Smrg;; If `resolve' is set, it means that the offset is just a hint, it 1315dfecf96Smrg;; maybe anywhere in the line 1325dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1335dfecf96Smrg(defun offset-indentation (offset &key resolve align 1345dfecf96Smrg &aux 1355dfecf96Smrg char 1365dfecf96Smrg line 1375dfecf96Smrg (start (scan offset :eol :left)) 1385dfecf96Smrg (indent 0)) 1395dfecf96Smrg (if resolve 1405dfecf96Smrg (loop 1415dfecf96Smrg (if (characterp (setq char (char-after start))) 1425dfecf96Smrg (if (char= char #\Tab) 1435dfecf96Smrg (incf indent (- 8 (rem indent 8))) 1445dfecf96Smrg ;; Not a tab, check if is a space 1455dfecf96Smrg (if (char= char #\Space) 1465dfecf96Smrg (incf indent) 1475dfecf96Smrg ;; Not a tab neither a space 1485dfecf96Smrg (return indent) 1495dfecf96Smrg ) 1505dfecf96Smrg ) 1515dfecf96Smrg ;; EOF found 1525dfecf96Smrg (return indent) 1535dfecf96Smrg ) 1545dfecf96Smrg ;; Increment offset to check next character 1555dfecf96Smrg (incf start) 1565dfecf96Smrg ) 1575dfecf96Smrg (progn 1585dfecf96Smrg (setq line (read-text start (- offset start))) 1595dfecf96Smrg (dotimes (i (length line) indent) 1605dfecf96Smrg (if (char= (setq char (char line i)) #\Tab) 1615dfecf96Smrg (incf indent (- 8 (rem indent 8))) 1625dfecf96Smrg (progn 1635dfecf96Smrg (or align (member char indent-spaces) 1645dfecf96Smrg (return indent) 1655dfecf96Smrg ) 1665dfecf96Smrg (incf indent) 1675dfecf96Smrg ) 1685dfecf96Smrg ) 1695dfecf96Smrg ) 1705dfecf96Smrg ) 1715dfecf96Smrg ) 1725dfecf96Smrg) 1735dfecf96Smrg(compile 'offset-indentation) 1745dfecf96Smrg 1755dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1765dfecf96Smrg;; A default/fallback indentation function, just copy indentation 1775dfecf96Smrg;; of previous line. 1785dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1795dfecf96Smrg(defun default-indent (syntax syntable) 1805dfecf96Smrg (let 1815dfecf96Smrg ( 1825dfecf96Smrg (offset (scan (point) :eol :left)) 1835dfecf96Smrg start 1845dfecf96Smrg left 1855dfecf96Smrg right 1865dfecf96Smrg ) 1875dfecf96Smrg 1885dfecf96Smrg syntable ;; XXX hack to not generate warning about unused 1895dfecf96Smrg ;; variable, should be temporary (until unused 1905dfecf96Smrg ;; variables can be declared as such) 1915dfecf96Smrg 1925dfecf96Smrg (if 1935dfecf96Smrg (or 1945dfecf96Smrg ;; if indentation is disabled 1955dfecf96Smrg (and 1965dfecf96Smrg (hash-table-p (syntax-options syntax)) 1975dfecf96Smrg (gethash :disable-indent (syntax-options syntax)) 1985dfecf96Smrg ) 1995dfecf96Smrg ;; or if not at the start of a new line 2005dfecf96Smrg (> (scan offset :eol :right) offset) 2015dfecf96Smrg ) 2025dfecf96Smrg (return-from default-indent) 2035dfecf96Smrg ) 2045dfecf96Smrg 2055dfecf96Smrg (setq left offset) 2065dfecf96Smrg (loop 2075dfecf96Smrg (setq 2085dfecf96Smrg start left 2095dfecf96Smrg left (scan start :eol :left :count 2) 2105dfecf96Smrg right (scan left :eol :right) 2115dfecf96Smrg ) 2125dfecf96Smrg ;; if start of file reached 2135dfecf96Smrg (and (>= left start) (return)) 2145dfecf96Smrg (when 2155dfecf96Smrg (setq 2165dfecf96Smrg start 2175dfecf96Smrg (position-if-not 2185dfecf96Smrg #'(lambda (char) (member char indent-spaces)) 2195dfecf96Smrg (read-text left (- right left)) 2205dfecf96Smrg ) 2215dfecf96Smrg ) 2225dfecf96Smrg 2235dfecf96Smrg ;; indent the current line 2245dfecf96Smrg (indent-text (offset-indentation (+ left start) :align t) offset) 2255dfecf96Smrg (return) 2265dfecf96Smrg ) 2275dfecf96Smrg ) 2285dfecf96Smrg ) 2295dfecf96Smrg) 2305dfecf96Smrg(compile 'default-indent) 2315dfecf96Smrg 2325dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2335dfecf96Smrg;; Helper function 2345dfecf96Smrg;; Clear line before cursor if it is empty 2355dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2365dfecf96Smrg(defun indent-clear-empty-line (&aux left offset right line index) 2375dfecf96Smrg (setq 2385dfecf96Smrg offset (scan (point) :eol :left) 2395dfecf96Smrg left (scan offset :eol :left :count 2) 2405dfecf96Smrg right (scan left :eol :right) 2415dfecf96Smrg ) 2425dfecf96Smrg 2435dfecf96Smrg ;; If not at the first line in the file and line is not already empty 2445dfecf96Smrg (when (and (/= offset left) (/= left right)) 2455dfecf96Smrg (setq 2465dfecf96Smrg line (read-text left (- right left)) 2475dfecf96Smrg index (1- (length line)) 2485dfecf96Smrg ) 2495dfecf96Smrg (while (and (>= index 0) (member (char line index) indent-spaces)) 2505dfecf96Smrg (decf index) 2515dfecf96Smrg ) 2525dfecf96Smrg ;; If line was only spaces 2535dfecf96Smrg (and (minusp index) (replace-text left right "")) 2545dfecf96Smrg ) 2555dfecf96Smrg) 2565dfecf96Smrg 2575dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2585dfecf96Smrg;; Macro to be called whenever an indentation rule decides that 2595dfecf96Smrg;; the parser is done. 2605dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2615dfecf96Smrg(defmacro indent-macro-terminate (&optional result) 2625dfecf96Smrg `(return-from ind-terminate-block ,result) 2635dfecf96Smrg) 2645dfecf96Smrg 2655dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2665dfecf96Smrg;; Like indent-terminate, but "rejects" the input for the current line 2675dfecf96Smrg;; and terminates the loop. 2685dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2695dfecf96Smrg(defmacro indent-macro-reject (&optional result) 2705dfecf96Smrg `(progn 2715dfecf96Smrg (setq ind-state ind-prev-state) 2725dfecf96Smrg (return-from ind-terminate-block ,result) 2735dfecf96Smrg ) 2745dfecf96Smrg) 2755dfecf96Smrg 2765dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2775dfecf96Smrg;; Like indent-reject, but "rejects" anything before the current token 2785dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2795dfecf96Smrg(defmacro indent-macro-reject-left (&optional result) 2805dfecf96Smrg `(progn 2815dfecf96Smrg (setq ind-state ind-matches) 2825dfecf96Smrg (return-from ind-terminate-block ,result) 2835dfecf96Smrg ) 2845dfecf96Smrg) 2855dfecf96Smrg 2865dfecf96Smrg 2875dfecf96Smrg(defstruct indtoken 2885dfecf96Smrg regex ;; a string, character or regex 2895dfecf96Smrg token ;; the resulting token, nil or a keyword 2905dfecf96Smrg begin ;; begin a new table 2915dfecf96Smrg switch ;; switch to another table 2925dfecf96Smrg ;; begin and switch fields are used like the ones for the syntax highlight 2935dfecf96Smrg ;; syntoken structure. 2945dfecf96Smrg label ;; filed at compile time 2955dfecf96Smrg code ;; code to execute when it matches 2965dfecf96Smrg) 2975dfecf96Smrg 2985dfecf96Smrg(defstruct indtable 2995dfecf96Smrg label ;; a keyword, name of the table 3005dfecf96Smrg tokens ;; list of indtoken structures 3015dfecf96Smrg tables ;; list of indtable structures 3025dfecf96Smrg augments ;; augment list 3035dfecf96Smrg) 3045dfecf96Smrg 3055dfecf96Smrg(defstruct indaugment 3065dfecf96Smrg labels ;; list of keywords labeling tables 3075dfecf96Smrg) 3085dfecf96Smrg 3095dfecf96Smrg(defstruct indinit 3105dfecf96Smrg variables ;; list of variables and optional initialization 3115dfecf96Smrg ;; Format of variables must be suitable to LET*, example of call: 3125dfecf96Smrg ;; (indinit 3135dfecf96Smrg ;; var1 ;; initialized to NIL 3145dfecf96Smrg ;; (var2 (afun)) ;; initialized to the value returned by AFUN 3155dfecf96Smrg ;; ) 3165dfecf96Smrg) 3175dfecf96Smrg 3185dfecf96Smrg(defstruct indreduce 3195dfecf96Smrg token ;; reduced token 3205dfecf96Smrg rules ;; list of rules 3215dfecf96Smrg label ;; unique label associated with rule, this 3225dfecf96Smrg ;; field is automatically filled in the 3235dfecf96Smrg ;; compilation process. this field exists 3245dfecf96Smrg ;; to allow several indreduce definitions 3255dfecf96Smrg ;; that result in the same token 3265dfecf96Smrg check ;; FORM evaluated, if T apply reduce rule 3275dfecf96Smrg code ;; PROGN to be called when a rule matches 3285dfecf96Smrg) 3295dfecf96Smrg 3305dfecf96Smrg;; NOTE, unlike "reduce" rules, "resolve" rules cannot be duplicated 3315dfecf96Smrg(defstruct indresolve 3325dfecf96Smrg match ;; the matched token (or a list of tokens) 3335dfecf96Smrg code ;; PROGN to apply for this token 3345dfecf96Smrg) 3355dfecf96Smrg 3365dfecf96Smrg(defstruct indent 3375dfecf96Smrg reduces ;; list of indreduce structures 3385dfecf96Smrg tables ;; list of indtable structures 3395dfecf96Smrg inits ;; initialization list 3405dfecf96Smrg resolves ;; list of indresolve structures 3415dfecf96Smrg token-code ;; code to execute when a token matches 3425dfecf96Smrg check-code ;; code to execute before applying a reduce rule 3435dfecf96Smrg reduce-code ;; code to execute after reduce rule 3445dfecf96Smrg resolve-code ;; code to execute when matching a token 3455dfecf96Smrg) 3465dfecf96Smrg 3475dfecf96Smrg(defmacro defindent (variable label &rest lists) 3485dfecf96Smrg `(if (boundp ',variable) 3495dfecf96Smrg ,variable 3505dfecf96Smrg (progn 3515dfecf96Smrg (proclaim '(special ,variable)) 3525dfecf96Smrg (setq ,variable (compile-indent-table ,label ,@lists)) 3535dfecf96Smrg ) 3545dfecf96Smrg ) 3555dfecf96Smrg) 3565dfecf96Smrg 3575dfecf96Smrg 3585dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3595dfecf96Smrg;; Create an indent token. 3605dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3615dfecf96Smrg(defmacro indtoken (pattern token 3625dfecf96Smrg &key icase nospec begin switch code (nosub t)) 3635dfecf96Smrg (setq pattern (re-comp (eval pattern) :icase icase :nospec nospec :nosub nosub)) 3645dfecf96Smrg (when (consp (re-exec pattern "" :notbol t :noteol t)) 3655dfecf96Smrg (error "INDTOKEN: regex ~A matches empty string" pattern) 3665dfecf96Smrg ) 3675dfecf96Smrg 3685dfecf96Smrg ;; result of macro, return token structure 3695dfecf96Smrg (make-indtoken 3705dfecf96Smrg :regex pattern 3715dfecf96Smrg :token token 3725dfecf96Smrg :begin begin 3735dfecf96Smrg :switch switch 3745dfecf96Smrg :code code 3755dfecf96Smrg ) 3765dfecf96Smrg) 3775dfecf96Smrg 3785dfecf96Smrg 3795dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3805dfecf96Smrg;; Create an indentation table. Basically a list of indentation tokens. 3815dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3825dfecf96Smrg(defun indtable (label &rest definitions) 3835dfecf96Smrg ;; check for simple errors 3845dfecf96Smrg (unless (keywordp label) 3855dfecf96Smrg (error "INDTABLE: ~A is not a keyword" label) 3865dfecf96Smrg ) 3875dfecf96Smrg (dolist (item definitions) 3885dfecf96Smrg (unless 3895dfecf96Smrg (or 3905dfecf96Smrg (atom item) 3915dfecf96Smrg (indtoken-p item) 3925dfecf96Smrg (indtable-p item) 3935dfecf96Smrg (indaugment-p item) 3945dfecf96Smrg ) 3955dfecf96Smrg (error "INDTABLE: invalid indent table argument ~A" item) 3965dfecf96Smrg ) 3975dfecf96Smrg ) 3985dfecf96Smrg 3995dfecf96Smrg ;; return indent table structure 4005dfecf96Smrg (make-indtable 4015dfecf96Smrg :label label 4025dfecf96Smrg :tokens (remove-if-not #'indtoken-p definitions) 4035dfecf96Smrg :tables (remove-if-not #'indtable-p definitions) 4045dfecf96Smrg :augments (remove-if-not #'indaugment-p definitions) 4055dfecf96Smrg ) 4065dfecf96Smrg) 4075dfecf96Smrg 4085dfecf96Smrg 4095dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4105dfecf96Smrg;; Add identifier to list of augment tables. 4115dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4125dfecf96Smrg(defun indaugment (&rest keywords) 4135dfecf96Smrg (dolist (keyword keywords) 4145dfecf96Smrg (unless (keywordp keyword) 4155dfecf96Smrg (error "INDAUGMENT: bad indent table label ~A" keyword) 4165dfecf96Smrg ) 4175dfecf96Smrg ) 4185dfecf96Smrg 4195dfecf96Smrg ;; return augment list structure 4205dfecf96Smrg (make-indaugment :labels keywords) 4215dfecf96Smrg) 4225dfecf96Smrg 4235dfecf96Smrg 4245dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4255dfecf96Smrg;; Add variables to initialization list 4265dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4275dfecf96Smrg(defmacro indinit (&rest variables) 4285dfecf96Smrg (make-indinit :variables variables) 4295dfecf96Smrg) 4305dfecf96Smrg 4315dfecf96Smrg 4325dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4335dfecf96Smrg;; Create a "reduction rule" 4345dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4355dfecf96Smrg(defmacro indreduce (token check rules &rest code &aux nullp consp) 4365dfecf96Smrg ;; check for simple errors 4375dfecf96Smrg (unless (or (keywordp token) (null token)) 4385dfecf96Smrg (error "INDREDUCE: ~A is not a keyword" token) 4395dfecf96Smrg ) 4405dfecf96Smrg (dolist (rule rules) 4415dfecf96Smrg (or (listp rule) (error "INDREDUCE: invalid indent rule ~A" rule)) 4425dfecf96Smrg ;; XXX This test is not enough, maybe should add some sort of 4435dfecf96Smrg ;; runtime check to avoid circularity. 4445dfecf96Smrg (and (eq token (car rule)) (null (cdr rule)) 4455dfecf96Smrg (error "INDREDUCE: ~A reduces to ~A" token) 4465dfecf96Smrg ) 4475dfecf96Smrg (dolist (item rule) 4485dfecf96Smrg (and (or nullp consp) (not (keywordp item)) 4495dfecf96Smrg (error "INDREDUCE: a keyword must special pattern") 4505dfecf96Smrg ) 4515dfecf96Smrg (if (consp item) 4525dfecf96Smrg (progn 4535dfecf96Smrg (unless 4545dfecf96Smrg (or 4555dfecf96Smrg (and 4565dfecf96Smrg (eq (car item) 'not) 4575dfecf96Smrg (keywordp (cadr item)) 4585dfecf96Smrg (null (cddr item)) 4595dfecf96Smrg ) 4605dfecf96Smrg (and 4615dfecf96Smrg (eq (car item) 'or) 4625dfecf96Smrg (null (member-if-not #'keywordp (cdr item))) 4635dfecf96Smrg ) 4645dfecf96Smrg ) 4655dfecf96Smrg (error "INDREDUCE: syntax error parsing ~A" item) 4665dfecf96Smrg ) 4675dfecf96Smrg (setq consp t) 4685dfecf96Smrg ) 4695dfecf96Smrg (progn 4705dfecf96Smrg (setq nullp (null item) consp nil) 4715dfecf96Smrg (unless (or (keywordp item) nullp (eq item t)) 4725dfecf96Smrg (error "INDREDUCE: ~A is not a keyword" item) 4735dfecf96Smrg ) 4745dfecf96Smrg ) 4755dfecf96Smrg ) 4765dfecf96Smrg ) 4775dfecf96Smrg; (and consp 4785dfecf96Smrg; (error "INDREDUCE: pattern must be followed by keyword") 4795dfecf96Smrg; ) 4805dfecf96Smrg ) 4815dfecf96Smrg 4825dfecf96Smrg ;; result of macro, return indent reduce structure 4835dfecf96Smrg (make-indreduce 4845dfecf96Smrg :token token 4855dfecf96Smrg :check check 4865dfecf96Smrg :rules (remove-if #'null rules) 4875dfecf96Smrg :code code 4885dfecf96Smrg ) 4895dfecf96Smrg) 4905dfecf96Smrg 4915dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4925dfecf96Smrg;; Create a "resolve rule" 4935dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4945dfecf96Smrg(defmacro indresolve (match &rest code) 4955dfecf96Smrg ;; check for simple errors 4965dfecf96Smrg (if (consp match) 4975dfecf96Smrg (dolist (token match) 4985dfecf96Smrg (or (keywordp token) (error "INDRESOLVE: ~A is not a keyword" token)) 4995dfecf96Smrg ) 5005dfecf96Smrg (or (keywordp match) (error "INDRESOLVE: ~A is not a keyword" match)) 5015dfecf96Smrg ) 5025dfecf96Smrg 5035dfecf96Smrg ;; result of macro, return indent resolve structure 5045dfecf96Smrg (make-indresolve 5055dfecf96Smrg :match match 5065dfecf96Smrg :code code 5075dfecf96Smrg ) 5085dfecf96Smrg) 5095dfecf96Smrg 5105dfecf96Smrg 5115dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5125dfecf96Smrg;; Helper function for compile-indent-table. Returns a list of all 5135dfecf96Smrg;; tables and tokens for a given table, including tokens and tables 5145dfecf96Smrg;; of children. 5155dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5165dfecf96Smrg(defun list-indtable-elements (table &aux result sub-result) 5175dfecf96Smrg (setq result (cons (indtable-tokens table) (indtable-tables table))) 5185dfecf96Smrg (dolist (child (indtable-tables table)) 5195dfecf96Smrg (setq sub-result (list-indtable-elements child)) 5205dfecf96Smrg (rplaca result (append (car result) (car sub-result))) 5215dfecf96Smrg (rplacd result (append (cdr result) (cdr sub-result))) 5225dfecf96Smrg ) 5235dfecf96Smrg ;; Return pair of all nested tokens and tables 5245dfecf96Smrg result 5255dfecf96Smrg) 5265dfecf96Smrg 5275dfecf96Smrg 5285dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5295dfecf96Smrg;; First pass adding augumented tokens to a table, done in two passes 5305dfecf96Smrg;; to respect inheritance order. 5315dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5325dfecf96Smrg(defun compile-indent-augment-list (table table-list &aux labels augment tokens) 5335dfecf96Smrg 5345dfecf96Smrg ;; Create a list of all augment tables. 5355dfecf96Smrg (dolist (augment (indtable-augments table)) 5365dfecf96Smrg (setq labels (append labels (indaugment-labels augment))) 5375dfecf96Smrg ) 5385dfecf96Smrg 5395dfecf96Smrg ;; Remove duplicates and references to "itself", without warnings? 5405dfecf96Smrg (setq 5415dfecf96Smrg labels 5425dfecf96Smrg (remove (indtable-label table) (remove-duplicates labels :from-end t)) 5435dfecf96Smrg ) 5445dfecf96Smrg 5455dfecf96Smrg ;; Check if the specified indent tables exists! 5465dfecf96Smrg (dolist (label labels) 5475dfecf96Smrg (unless 5485dfecf96Smrg (setq augment (car (member label table-list :key #'indtable-label))) 5495dfecf96Smrg (error "COMPILE-INDENT-AUGMENT-LIST: Cannot augment ~A in ~A" 5505dfecf96Smrg label 5515dfecf96Smrg (indtable-label table) 5525dfecf96Smrg ) 5535dfecf96Smrg ) 5545dfecf96Smrg 5555dfecf96Smrg ;; Increase list of tokens. 5565dfecf96Smrg (setq tokens (append tokens (indtable-tokens augment))) 5575dfecf96Smrg ) 5585dfecf96Smrg 5595dfecf96Smrg ;; Store the tokens in the augment list. They will be added 5605dfecf96Smrg ;; to the indent table in the second pass. 5615dfecf96Smrg (setf (indtable-augments table) tokens) 5625dfecf96Smrg 5635dfecf96Smrg ;; Recurse on every child table. 5645dfecf96Smrg (dolist (child (indtable-tables table)) 5655dfecf96Smrg (compile-indent-augment-list child table-list) 5665dfecf96Smrg ) 5675dfecf96Smrg) 5685dfecf96Smrg 5695dfecf96Smrg 5705dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5715dfecf96Smrg;; Last pass adding augmented tokens to a table. 5725dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5735dfecf96Smrg(defun link-indent-augment-list (table) 5745dfecf96Smrg (setf 5755dfecf96Smrg (indtable-tokens table) 5765dfecf96Smrg (remove-duplicates 5775dfecf96Smrg (nconc (indtable-tokens table) (indtable-augments table)) 5785dfecf96Smrg :key #'indtoken-regex 5795dfecf96Smrg :test #'equal 5805dfecf96Smrg :from-end t 5815dfecf96Smrg ) 5825dfecf96Smrg 5835dfecf96Smrg ;; Don't need to keep this list anymore. 5845dfecf96Smrg (indtable-augments table) 5855dfecf96Smrg () 5865dfecf96Smrg ) 5875dfecf96Smrg 5885dfecf96Smrg (dolist (child (indtable-tables table)) 5895dfecf96Smrg (link-indent-augment-list child) 5905dfecf96Smrg ) 5915dfecf96Smrg) 5925dfecf96Smrg 5935dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5945dfecf96Smrg;; Compile the indent reduction rules 5955dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5965dfecf96Smrg(defun compile-indent-reduces (reduces 5975dfecf96Smrg &aux need label check rules reduce 5985dfecf96Smrg check-code reduce-code) 5995dfecf96Smrg (dolist (item reduces) 6005dfecf96Smrg (setq 6015dfecf96Smrg label (indreduce-label item) 6025dfecf96Smrg check (indreduce-check item) 6035dfecf96Smrg rules (indreduce-rules item) 6045dfecf96Smrg reduce (indreduce-code item) 6055dfecf96Smrg need (and 6065dfecf96Smrg rules 6075dfecf96Smrg (not label) 6085dfecf96Smrg (or 6095dfecf96Smrg reduce 6105dfecf96Smrg (null check) 6115dfecf96Smrg (not (constantp check)) 6125dfecf96Smrg ) 6135dfecf96Smrg ) 6145dfecf96Smrg ) 6155dfecf96Smrg (when need 6165dfecf96Smrg (and (null label) (setq label (intern (string (gensym)) 'keyword))) 6175dfecf96Smrg 6185dfecf96Smrg (setf (indreduce-label item) label) 6195dfecf96Smrg 6205dfecf96Smrg (and 6215dfecf96Smrg (or (null check) 6225dfecf96Smrg (not (constantp check)) 6235dfecf96Smrg ) 6245dfecf96Smrg (setq 6255dfecf96Smrg check (list (list 'eq '*ind-label* label) check) 6265dfecf96Smrg check-code (nconc check-code (list check)) 6275dfecf96Smrg ) 6285dfecf96Smrg ) 6295dfecf96Smrg 6305dfecf96Smrg (and reduce 6315dfecf96Smrg (setq 6325dfecf96Smrg reduce (cons (list 'eq '*ind-label* label) reduce) 6335dfecf96Smrg reduce-code (nconc reduce-code (list reduce)) 6345dfecf96Smrg ) 6355dfecf96Smrg ) 6365dfecf96Smrg ) 6375dfecf96Smrg ) 6385dfecf96Smrg 6395dfecf96Smrg ;; XXX Instead of using COND, could/should use CASE 6405dfecf96Smrg ;; TODO Implement a smart CASE in the bytecode compiler, if 6415dfecf96Smrg ;; possible, should generate a hashtable, or a table 6425dfecf96Smrg ;; of indexes (for example when all elements in the cases 6435dfecf96Smrg ;; are characters) and then jump directly to the code. 6445dfecf96Smrg (if check-code 6455dfecf96Smrg (setq check-code (cons 'cond (nconc check-code '((t t))))) 6465dfecf96Smrg (setq check-code t) 6475dfecf96Smrg ) 6485dfecf96Smrg (and reduce-code (setq reduce-code (cons 'cond reduce-code))) 6495dfecf96Smrg 6505dfecf96Smrg (values check-code reduce-code) 6515dfecf96Smrg) 6525dfecf96Smrg 6535dfecf96Smrg 6545dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6555dfecf96Smrg;; Compile the indent resolve code 6565dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6575dfecf96Smrg(defun compile-indent-resolves (resolves &aux match resolve resolve-code) 6585dfecf96Smrg (and 6595dfecf96Smrg (/= 6605dfecf96Smrg (length resolves) 6615dfecf96Smrg (length (remove-duplicates resolves :key #'indresolve-match)) 6625dfecf96Smrg ) 6635dfecf96Smrg ;; XXX Could do a more complete job and tell what is wrong... 6645dfecf96Smrg (error "COMPILE-INDENT-RESOLVES: duplicated labels") 6655dfecf96Smrg ) 6665dfecf96Smrg 6675dfecf96Smrg (dolist (item resolves) 6685dfecf96Smrg (when (setq resolve (indresolve-code item)) 6695dfecf96Smrg (setq 6705dfecf96Smrg match 6715dfecf96Smrg (indresolve-match item) 6725dfecf96Smrg 6735dfecf96Smrg resolve 6745dfecf96Smrg (cons 6755dfecf96Smrg (if (listp match) 6765dfecf96Smrg (list 'member '*ind-token* `',match :test `#'eq) 6775dfecf96Smrg (list 'eq '*ind-token* match) 6785dfecf96Smrg ) 6795dfecf96Smrg resolve 6805dfecf96Smrg ) 6815dfecf96Smrg 6825dfecf96Smrg resolve-code 6835dfecf96Smrg (nconc resolve-code (list resolve)) 6845dfecf96Smrg ) 6855dfecf96Smrg ) 6865dfecf96Smrg ) 6875dfecf96Smrg 6885dfecf96Smrg (and resolve-code (cons 'cond resolve-code)) 6895dfecf96Smrg) 6905dfecf96Smrg 6915dfecf96Smrg 6925dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6935dfecf96Smrg;; Create an indentation table 6945dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6955dfecf96Smrg(defun compile-indent-table (name &rest lists 6965dfecf96Smrg &aux main elements switches begins tables symbols 6975dfecf96Smrg label code token-code check-code reduce-code 6985dfecf96Smrg (inits (remove-if-not #'indinit-p lists)) 6995dfecf96Smrg (reduces (remove-if-not #'indreduce-p lists)) 7005dfecf96Smrg (resolves (remove-if-not #'indresolve-p lists)) 7015dfecf96Smrg ) 7025dfecf96Smrg (setq 7035dfecf96Smrg lists (delete-if 7045dfecf96Smrg #'(lambda (object) 7055dfecf96Smrg (or 7065dfecf96Smrg (indinit-p object) 7075dfecf96Smrg (indreduce-p object) 7085dfecf96Smrg (indresolve-p object) 7095dfecf96Smrg ) 7105dfecf96Smrg ) 7115dfecf96Smrg lists) 7125dfecf96Smrg main (apply #'indtable name lists) 7135dfecf96Smrg elements (list-indtable-elements main) 7145dfecf96Smrg switches (remove-if #'null (car elements) :key #'indtoken-switch) 7155dfecf96Smrg begins (remove-if #'null (car elements) :key #'indtoken-begin) 7165dfecf96Smrg tables (cons main (cdr elements)) 7175dfecf96Smrg ) 7185dfecf96Smrg 7195dfecf96Smrg ;; Check for typos in the keywords, or for not defined indent tables. 7205dfecf96Smrg (dolist (item (mapcar #'indtoken-switch switches)) 7215dfecf96Smrg (unless 7225dfecf96Smrg (or (and (integerp item) (minusp item)) 7235dfecf96Smrg (member item tables :key #'indtable-label) 7245dfecf96Smrg ) 7255dfecf96Smrg (error "COMPILE-INDENT-TABLE: SWITCH ~A cannot be matched" item) 7265dfecf96Smrg ) 7275dfecf96Smrg ) 7285dfecf96Smrg (dolist (item (mapcar #'indtoken-begin begins)) 7295dfecf96Smrg (unless (member item tables :key #'indtable-label) 7305dfecf96Smrg (error "COMPILE-INDENT-TABLE: BEGIN ~A cannot be matched" item) 7315dfecf96Smrg ) 7325dfecf96Smrg ) 7335dfecf96Smrg 7345dfecf96Smrg ;; Build augment list. 7355dfecf96Smrg (compile-indent-augment-list main tables) 7365dfecf96Smrg (link-indent-augment-list main) 7375dfecf96Smrg 7385dfecf96Smrg ;; Change switch and begin fields to point to the indent table 7395dfecf96Smrg (dolist (item switches) 7405dfecf96Smrg (if (keywordp (indtoken-switch item)) 7415dfecf96Smrg (setf 7425dfecf96Smrg (indtoken-switch item) 7435dfecf96Smrg (car (member (indtoken-switch item) tables :key #'indtable-label)) 7445dfecf96Smrg ) 7455dfecf96Smrg ) 7465dfecf96Smrg ) 7475dfecf96Smrg (dolist (item begins) 7485dfecf96Smrg (setf 7495dfecf96Smrg (indtoken-begin item) 7505dfecf96Smrg (car (member (indtoken-begin item) tables :key #'indtable-label)) 7515dfecf96Smrg ) 7525dfecf96Smrg ) 7535dfecf96Smrg 7545dfecf96Smrg ;; Build initialization list 7555dfecf96Smrg (dolist (init inits) 7565dfecf96Smrg (setq symbols (nconc symbols (indinit-variables init))) 7575dfecf96Smrg ) 7585dfecf96Smrg 7595dfecf96Smrg ;; Build token code 7605dfecf96Smrg (dolist (item (car elements)) 7615dfecf96Smrg (when (setq code (indtoken-code item)) 7625dfecf96Smrg (setf 7635dfecf96Smrg label 7645dfecf96Smrg (intern (string (gensym)) 'keyword) 7655dfecf96Smrg 7665dfecf96Smrg (indtoken-label item) 7675dfecf96Smrg label 7685dfecf96Smrg 7695dfecf96Smrg code 7705dfecf96Smrg (list (list 'eq '*ind-label* label) code) 7715dfecf96Smrg 7725dfecf96Smrg token-code 7735dfecf96Smrg (nconc token-code (list code)) 7745dfecf96Smrg ) 7755dfecf96Smrg ) 7765dfecf96Smrg ) 7775dfecf96Smrg 7785dfecf96Smrg (multiple-value-setq 7795dfecf96Smrg (check-code reduce-code) 7805dfecf96Smrg (compile-indent-reduces reduces) 7815dfecf96Smrg ) 7825dfecf96Smrg 7835dfecf96Smrg (make-indent 7845dfecf96Smrg :tables tables 7855dfecf96Smrg :inits symbols 7865dfecf96Smrg :reduces reduces 7875dfecf96Smrg :resolves resolves 7885dfecf96Smrg :token-code (and token-code (cons 'cond token-code)) 7895dfecf96Smrg :check-code check-code 7905dfecf96Smrg :reduce-code reduce-code 7915dfecf96Smrg :resolve-code (compile-indent-resolves resolves) 7925dfecf96Smrg ) 7935dfecf96Smrg) 7945dfecf96Smrg 7955dfecf96Smrg 7965dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7975dfecf96Smrg;; Search rule-pattern in match-pattern 7985dfecf96Smrg;; Returns offset of match, and it's length, if any 7995dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8005dfecf96Smrg(defun indent-search-rule (rule-pattern match-pattern 8015dfecf96Smrg &aux start rule rulep matchp test offset length) 8025dfecf96Smrg (if (member-if-not #'keywordp rule-pattern) 8035dfecf96Smrg ;; rule has wildcards 8045dfecf96Smrg (progn 8055dfecf96Smrg (setq 8065dfecf96Smrg rulep rule-pattern 8075dfecf96Smrg matchp match-pattern 8085dfecf96Smrg start match-pattern 8095dfecf96Smrg ) 8105dfecf96Smrg (loop 8115dfecf96Smrg (setq rule (car rulep)) 8125dfecf96Smrg (cond 8135dfecf96Smrg ;; Special pattern 8145dfecf96Smrg ((consp rule) 8155dfecf96Smrg (if (eq (car rule) 'not) 8165dfecf96Smrg (progn 8175dfecf96Smrg (setq 8185dfecf96Smrg test (cadr rule) 8195dfecf96Smrg rulep (cdr rulep) 8205dfecf96Smrg rule (car rulep) 8215dfecf96Smrg ) 8225dfecf96Smrg (while 8235dfecf96Smrg (and 8245dfecf96Smrg ;; something to match 8255dfecf96Smrg matchp 8265dfecf96Smrg ;; NOT match is true 8275dfecf96Smrg (not (eq (car matchp) test)) 8285dfecf96Smrg ;; next match is not true 8295dfecf96Smrg (not (eq (car matchp) rule)) 8305dfecf96Smrg ) 8315dfecf96Smrg (setq matchp (cdr matchp)) 8325dfecf96Smrg ) 8335dfecf96Smrg (if (eq (car matchp) rule) 8345dfecf96Smrg ;; rule matched 8355dfecf96Smrg (setq 8365dfecf96Smrg matchp (cdr matchp) 8375dfecf96Smrg rulep (cdr rulep) 8385dfecf96Smrg ) 8395dfecf96Smrg ;; failed 8405dfecf96Smrg (setq 8415dfecf96Smrg rulep rule-pattern 8425dfecf96Smrg matchp (cdr start) 8435dfecf96Smrg start matchp 8445dfecf96Smrg ) 8455dfecf96Smrg ) 8465dfecf96Smrg ) 8475dfecf96Smrg ;; (eq (car rule) 'or) 8485dfecf96Smrg (progn 8495dfecf96Smrg (if (member (car matchp) (cdr rule) :test #'eq) 8505dfecf96Smrg (setq rulep (cdr rulep) matchp (cdr matchp)) 8515dfecf96Smrg ;; failed 8525dfecf96Smrg (progn 8535dfecf96Smrg ;; end of match found! 8545dfecf96Smrg (and (null matchp) (return)) 8555dfecf96Smrg ;; reset search 8565dfecf96Smrg (setq 8575dfecf96Smrg rulep rule-pattern 8585dfecf96Smrg matchp (cdr start) 8595dfecf96Smrg start matchp 8605dfecf96Smrg ) 8615dfecf96Smrg ) 8625dfecf96Smrg ) 8635dfecf96Smrg ) 8645dfecf96Smrg ) 8655dfecf96Smrg ) 8665dfecf96Smrg 8675dfecf96Smrg ;; Skip until end of match-pattern or rule is found 8685dfecf96Smrg ((null rule) 8695dfecf96Smrg (setq rulep (cdr rulep)) 8705dfecf96Smrg ;; If matches everything 8715dfecf96Smrg (if (null rulep) 8725dfecf96Smrg (progn (setq matchp nil) (return)) 8735dfecf96Smrg ;; If next token cannot be matched 8745dfecf96Smrg (unless 8755dfecf96Smrg (setq 8765dfecf96Smrg matchp 8775dfecf96Smrg (member (car rulep) matchp :test #'eq) 8785dfecf96Smrg ) 8795dfecf96Smrg (setq rulep rule-pattern) 8805dfecf96Smrg (return) 8815dfecf96Smrg ) 8825dfecf96Smrg ) 8835dfecf96Smrg (setq rulep (cdr rulep) matchp (cdr matchp)) 8845dfecf96Smrg ) 8855dfecf96Smrg 8865dfecf96Smrg ;; Matched 8875dfecf96Smrg ((eq rule t) 8885dfecf96Smrg ;; If there isn't a rule to skip 8895dfecf96Smrg (and (null matchp) (return)) 8905dfecf96Smrg (setq rulep (cdr rulep) matchp (cdr matchp)) 8915dfecf96Smrg ) 8925dfecf96Smrg 8935dfecf96Smrg ;; Matched 8945dfecf96Smrg ((eq rule (car matchp)) 8955dfecf96Smrg (setq rulep (cdr rulep) matchp (cdr matchp)) 8965dfecf96Smrg ) 8975dfecf96Smrg 8985dfecf96Smrg ;; No match 8995dfecf96Smrg (t 9005dfecf96Smrg ;; end of match found! 9015dfecf96Smrg (and (null matchp) (return)) 9025dfecf96Smrg ;; reset search 9035dfecf96Smrg (setq 9045dfecf96Smrg rulep rule-pattern 9055dfecf96Smrg matchp (cdr start) 9065dfecf96Smrg start matchp 9075dfecf96Smrg ) 9085dfecf96Smrg ) 9095dfecf96Smrg ) 9105dfecf96Smrg 9115dfecf96Smrg ;; if everything matched 9125dfecf96Smrg (or rulep (return)) 9135dfecf96Smrg ) 9145dfecf96Smrg 9155dfecf96Smrg ;; All rules matched 9165dfecf96Smrg (unless rulep 9175dfecf96Smrg ;; Calculate offset and length of match 9185dfecf96Smrg (setq offset 0 length 0) 9195dfecf96Smrg (until (eq match-pattern start) 9205dfecf96Smrg (setq 9215dfecf96Smrg offset (1+ offset) 9225dfecf96Smrg match-pattern (cdr match-pattern) 9235dfecf96Smrg ) 9245dfecf96Smrg ) 9255dfecf96Smrg (until (eq match-pattern matchp) 9265dfecf96Smrg (setq 9275dfecf96Smrg length (1+ length) 9285dfecf96Smrg match-pattern (cdr match-pattern) 9295dfecf96Smrg ) 9305dfecf96Smrg ) 9315dfecf96Smrg ) 9325dfecf96Smrg ) 9335dfecf96Smrg ;; no wildcards 9345dfecf96Smrg (and (setq offset (search rule-pattern match-pattern :test #'eq)) 9355dfecf96Smrg (setq length (length rule-pattern)) 9365dfecf96Smrg ) 9375dfecf96Smrg ) 9385dfecf96Smrg 9395dfecf96Smrg (values offset length) 9405dfecf96Smrg) 9415dfecf96Smrg(compile 'indent-search-rule) 9425dfecf96Smrg 9435dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9445dfecf96Smrg;; Indentation parser 9455dfecf96Smrg;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9465dfecf96Smrg(defmacro indent-macro (ind-definition ind-offset &optional ind-no-tabs) 9475dfecf96Smrg `(prog* 9485dfecf96Smrg ( 9495dfecf96Smrg ;; Current indentation table 9505dfecf96Smrg (ind-table (car (indent-tables ,ind-definition))) 9515dfecf96Smrg 9525dfecf96Smrg ;; The parser rules 9535dfecf96Smrg (ind-reduces (indent-reduces ,ind-definition)) 9545dfecf96Smrg 9555dfecf96Smrg ;; Token list for the table 9565dfecf96Smrg (ind-tokens (indtable-tokens ind-table)) 9575dfecf96Smrg 9585dfecf96Smrg ;; Stack of nested tables/states 9595dfecf96Smrg ind-stack 9605dfecf96Smrg 9615dfecf96Smrg ;; indentation to be used 9625dfecf96Smrg (*indent* 0) 9635dfecf96Smrg 9645dfecf96Smrg ;; offset to apply indentation 9655dfecf96Smrg *offset* 9665dfecf96Smrg 9675dfecf96Smrg ;; Number of lines read 9685dfecf96Smrg (*ind-lines* 1) 9695dfecf96Smrg 9705dfecf96Smrg ;; Matched token 9715dfecf96Smrg *ind-token* 9725dfecf96Smrg 9735dfecf96Smrg ;; list of tokens after current match, should not be changed 9745dfecf96Smrg *ind-token-list* 9755dfecf96Smrg 9765dfecf96Smrg ;; label associated with rule 9775dfecf96Smrg *ind-label* 9785dfecf96Smrg 9795dfecf96Smrg ;; offset of match 9805dfecf96Smrg *ind-offset* 9815dfecf96Smrg 9825dfecf96Smrg ;; length of match 9835dfecf96Smrg *ind-length* 9845dfecf96Smrg 9855dfecf96Smrg ;; insert position 9865dfecf96Smrg (*ind-point* (point)) 9875dfecf96Smrg 9885dfecf96Smrg (ind-from (scan ,ind-offset :eol :left)) 9895dfecf96Smrg (ind-to ,ind-offset) 9905dfecf96Smrg (ind-line (read-text ind-from (- ind-to ind-from))) 9915dfecf96Smrg 9925dfecf96Smrg ;; start of current line 9935dfecf96Smrg (*ind-start* ind-from) 9945dfecf96Smrg 9955dfecf96Smrg ;; State information 9965dfecf96Smrg ind-state 9975dfecf96Smrg 9985dfecf96Smrg ;; For use with (indent-macro-reject) 9995dfecf96Smrg ind-prev-state 10005dfecf96Smrg 10015dfecf96Smrg ;; Matches for the current line 10025dfecf96Smrg ind-matches 10035dfecf96Smrg 10045dfecf96Smrg ;; Matched tokens not yet used 10055dfecf96Smrg ind-cache 10065dfecf96Smrg 10075dfecf96Smrg ;; Pattern being tested 10085dfecf96Smrg ind-token 10095dfecf96Smrg 10105dfecf96Smrg ;; Used when searching for a regex 10115dfecf96Smrg ind-match 10125dfecf96Smrg 10135dfecf96Smrg ;; Table to change 10145dfecf96Smrg ind-change 10155dfecf96Smrg 10165dfecf96Smrg ;; Length of ind-line 10175dfecf96Smrg (ind-length (length ind-line)) 10185dfecf96Smrg 10195dfecf96Smrg ;; Don't parse after this offset 10205dfecf96Smrg (ind-end ind-length) 10215dfecf96Smrg 10225dfecf96Smrg ;; Temporary variables used during loops 10235dfecf96Smrg ind-left 10245dfecf96Smrg ind-right 10255dfecf96Smrg ind-tleft 10265dfecf96Smrg ind-tright 10275dfecf96Smrg 10285dfecf96Smrg ;; Set when start of file is found 10295dfecf96Smrg ind-startp 10305dfecf96Smrg 10315dfecf96Smrg ;; Flag for regex search 10325dfecf96Smrg (ind-noteol (< ind-to (scan ind-from :eol :right))) 10335dfecf96Smrg 10345dfecf96Smrg ;; Initialization variables expanded here 10355dfecf96Smrg ,@(indent-inits (eval ind-definition)) 10365dfecf96Smrg ) 10375dfecf96Smrg 10385dfecf96Smrg ;; Initial input already read 10395dfecf96Smrg (go :ind-loop) 10405dfecf96Smrg 1041f14f4646Smrg ;; Just to avoid a warning about unused variable, as this 1042f14f4646Smrg ;; variable is somewhat redundant as code should already 1043f14f4646Smrg ;; know before entering indent parser, but useful inside 1044f14f4646Smrg ;; indent macros. 1045f14f4646Smrg *ind-point* 1046f14f4646Smrg 10475dfecf96Smrg;------------------------------------------------------------------------ 10485dfecf96Smrg; Read a text line 10495dfecf96Smrg:ind-read 10505dfecf96Smrg (setq 10515dfecf96Smrg ind-to ind-from 10525dfecf96Smrg ind-from (scan ind-from :eol :left :count 2) 10535dfecf96Smrg ) 10545dfecf96Smrg ;; If start of file reached 10555dfecf96Smrg (and (= ind-to ind-from) (setq ind-startp t) (go :ind-process)) 10565dfecf96Smrg 10575dfecf96Smrg (setq 10585dfecf96Smrg *ind-lines* (1+ *ind-lines*) 10595dfecf96Smrg ind-to (scan ind-from :eol :right) 10605dfecf96Smrg ind-line (read-text ind-from (- ind-to ind-from)) 10615dfecf96Smrg ind-length (length ind-line) 10625dfecf96Smrg ind-end ind-length 10635dfecf96Smrg ind-noteol nil 10645dfecf96Smrg ind-cache nil 10655dfecf96Smrg ind-prev-state ind-state 10665dfecf96Smrg ) 10675dfecf96Smrg 10685dfecf96Smrg;------------------------------------------------------------------------ 10695dfecf96Smrg; Loop parsing backwards 10705dfecf96Smrg:ind-loop 10715dfecf96Smrg (setq ind-matches nil) 10725dfecf96Smrg (dolist (token ind-tokens) 10735dfecf96Smrg ;; Prepare to loop 10745dfecf96Smrg (setq 10755dfecf96Smrg ind-token (indtoken-regex token) 10765dfecf96Smrg ind-left 0 10775dfecf96Smrg ) 10785dfecf96Smrg ;; While the pattern matches 10795dfecf96Smrg (loop 10805dfecf96Smrg (setq ind-right ind-left) 10815dfecf96Smrg (if 10825dfecf96Smrg (consp 10835dfecf96Smrg (setq 10845dfecf96Smrg ind-match 10855dfecf96Smrg (re-exec 10865dfecf96Smrg ind-token 10875dfecf96Smrg ind-line 10885dfecf96Smrg :start ind-left 10895dfecf96Smrg :end ind-end 10905dfecf96Smrg :notbol (> ind-left 0) 10915dfecf96Smrg :noteol ind-noteol 10925dfecf96Smrg ) 10935dfecf96Smrg ) 10945dfecf96Smrg ) 10955dfecf96Smrg 10965dfecf96Smrg ;; Remember about match 10975dfecf96Smrg (setq 10985dfecf96Smrg ind-match (car ind-match) 10995dfecf96Smrg ind-left (cdr ind-match) 11005dfecf96Smrg ind-matches (cons (cons token ind-match) ind-matches) 11015dfecf96Smrg ) 11025dfecf96Smrg 11035dfecf96Smrg ;; No match 11045dfecf96Smrg (return) 11055dfecf96Smrg ) 11065dfecf96Smrg ;; matched an empty string 11075dfecf96Smrg (and (= ind-left ind-right) (incf ind-left)) 11085dfecf96Smrg 11095dfecf96Smrg ;; matched a single eol or bol 11105dfecf96Smrg (and (>= ind-left ind-end) (return)) 11115dfecf96Smrg ) 11125dfecf96Smrg ) 11135dfecf96Smrg 11145dfecf96Smrg ;; Add new matches to cache 11155dfecf96Smrg (when ind-matches 11165dfecf96Smrg (setq 11175dfecf96Smrg ind-cache 11185dfecf96Smrg (stable-sort 11195dfecf96Smrg (nconc (nreverse ind-matches) ind-cache) #'< :key #'cadr 11205dfecf96Smrg ) 11215dfecf96Smrg ) 11225dfecf96Smrg ) 11235dfecf96Smrg 11245dfecf96Smrg ;; If nothing in the cache 11255dfecf96Smrg (or ind-cache (go :ind-process)) 11265dfecf96Smrg 11275dfecf96Smrg (setq 11285dfecf96Smrg ind-left (cadar ind-cache) 11295dfecf96Smrg ind-right (cddar ind-cache) 11305dfecf96Smrg ind-matches (cdr ind-cache) 11315dfecf96Smrg ) 11325dfecf96Smrg 11335dfecf96Smrg ;; If only one element in the cache 11345dfecf96Smrg (or ind-matches (go :ind-parse)) 11355dfecf96Smrg 11365dfecf96Smrg (setq 11375dfecf96Smrg ind-tleft (cadar ind-matches) 11385dfecf96Smrg ind-tright (cddar ind-matches) 11395dfecf96Smrg ) 11405dfecf96Smrg 11415dfecf96Smrg ;; Remove overlaps 11425dfecf96Smrg (loop 11435dfecf96Smrg (if (or (>= ind-tleft ind-right) (<= ind-tright ind-left)) 11445dfecf96Smrg ;; No overlap 11455dfecf96Smrg (progn 11465dfecf96Smrg (setq 11475dfecf96Smrg ind-left ind-tleft 11485dfecf96Smrg ind-right ind-tright 11495dfecf96Smrg ind-matches (cdr ind-matches) 11505dfecf96Smrg ) 11515dfecf96Smrg ;; If everything checked 11525dfecf96Smrg (or ind-matches (return)) 11535dfecf96Smrg ) 11545dfecf96Smrg ;; Overlap found 11555dfecf96Smrg (progn 11565dfecf96Smrg (if (consp (cdr ind-matches)) 11575dfecf96Smrg ;; There are yet items to be checked 11585dfecf96Smrg (progn 11595dfecf96Smrg (rplaca ind-matches (cadr ind-matches)) 11605dfecf96Smrg (rplacd ind-matches (cddr ind-matches)) 11615dfecf96Smrg ) 11625dfecf96Smrg ;; Last item 11635dfecf96Smrg (progn 11645dfecf96Smrg (rplacd (last ind-cache 2) nil) 11655dfecf96Smrg (return) 11665dfecf96Smrg ) 11675dfecf96Smrg ) 11685dfecf96Smrg ) 11695dfecf96Smrg ) 11705dfecf96Smrg 11715dfecf96Smrg ;; Prepare for next check 11725dfecf96Smrg (setq 11735dfecf96Smrg ind-tleft (cadar ind-matches) 11745dfecf96Smrg ind-tright (cddar ind-matches) 11755dfecf96Smrg ) 11765dfecf96Smrg ) 11775dfecf96Smrg 11785dfecf96Smrg;------------------------------------------------------------------------ 11795dfecf96Smrg; Process the matched tokens 11805dfecf96Smrg:ind-parse 11815dfecf96Smrg (setq ind-cache (nreverse ind-cache)) 11825dfecf96Smrg 11835dfecf96Smrg:ind-parse-loop 11845dfecf96Smrg (or (setq ind-match (car ind-cache)) (go :ind-process)) 11855dfecf96Smrg 11865dfecf96Smrg (setq 11875dfecf96Smrg ind-cache (cdr ind-cache) 11885dfecf96Smrg ind-token (car ind-match) 11895dfecf96Smrg ) 11905dfecf96Smrg 11915dfecf96Smrg (or (member ind-token ind-tokens :test #'eq) 11925dfecf96Smrg (go :ind-parse-loop) 11935dfecf96Smrg ) 11945dfecf96Smrg 11955dfecf96Smrg ;; If a state should be added 11965dfecf96Smrg (when (setq ind-change (indtoken-token ind-token)) 11975dfecf96Smrg (setq 11985dfecf96Smrg ind-left (cadr ind-match) 11995dfecf96Smrg ind-right (cddr ind-match) 12005dfecf96Smrg 12015dfecf96Smrg *ind-offset* 12025dfecf96Smrg (+ ind-from ind-left) 12035dfecf96Smrg 12045dfecf96Smrg *ind-length* 12055dfecf96Smrg (- ind-right ind-left) 12065dfecf96Smrg 12075dfecf96Smrg ind-state 12085dfecf96Smrg (cons 12095dfecf96Smrg (cons ind-change (cons *ind-offset* *ind-length*)) 12105dfecf96Smrg ind-state 12115dfecf96Smrg ) 12125dfecf96Smrg 12135dfecf96Smrg *ind-label* 12145dfecf96Smrg (indtoken-label ind-token) 12155dfecf96Smrg ) 12165dfecf96Smrg 12175dfecf96Smrg ;; Expand token code 12185dfecf96Smrg ,(indent-token-code (eval ind-definition)) 12195dfecf96Smrg ) 12205dfecf96Smrg 12215dfecf96Smrg ;; Check if needs to switch to another table 12225dfecf96Smrg (when (setq ind-change (indtoken-switch ind-token)) 12235dfecf96Smrg ;; Need to switch to a previous table 12245dfecf96Smrg (if (integerp ind-change) 12255dfecf96Smrg ;; Relative switch 12265dfecf96Smrg (while (and ind-stack (minusp ind-change)) 12275dfecf96Smrg (setq 12285dfecf96Smrg ind-table (pop ind-stack) 12295dfecf96Smrg ind-change (1+ ind-change) 12305dfecf96Smrg ) 12315dfecf96Smrg ) 12325dfecf96Smrg ;; Search table in the stack 12335dfecf96Smrg (until 12345dfecf96Smrg (or 12355dfecf96Smrg (null ind-stack) 12365dfecf96Smrg (eq 12375dfecf96Smrg (setq ind-table (pop ind-stack)) 12385dfecf96Smrg ind-change 12395dfecf96Smrg ) 12405dfecf96Smrg ) 12415dfecf96Smrg ) 12425dfecf96Smrg ) 12435dfecf96Smrg 12445dfecf96Smrg ;; If no match or stack became empty 12455dfecf96Smrg (and (null ind-table) 12465dfecf96Smrg (setq 12475dfecf96Smrg ind-table 12485dfecf96Smrg (car (indent-tables ,ind-definition)) 12495dfecf96Smrg ) 12505dfecf96Smrg ) 12515dfecf96Smrg ) 12525dfecf96Smrg 12535dfecf96Smrg ;; Check if needs to start a new table 12545dfecf96Smrg ;; XXX use ind-tleft to reduce number of local variables 12555dfecf96Smrg (when (setq ind-tleft (indtoken-begin ind-token)) 12565dfecf96Smrg (setq 12575dfecf96Smrg ind-change ind-tleft 12585dfecf96Smrg ind-stack (cons ind-table ind-stack) 12595dfecf96Smrg ind-table ind-change 12605dfecf96Smrg ) 12615dfecf96Smrg ) 12625dfecf96Smrg 12635dfecf96Smrg ;; If current "indent pattern table" changed 12645dfecf96Smrg (when ind-change 12655dfecf96Smrg (setq 12665dfecf96Smrg ind-tokens (indtable-tokens ind-table) 12675dfecf96Smrg ind-cache (nreverse ind-cache) 12685dfecf96Smrg ind-end (cadr ind-match) 12695dfecf96Smrg ind-noteol (> ind-length ind-end) 12705dfecf96Smrg ) 12715dfecf96Smrg (go :ind-loop) 12725dfecf96Smrg ) 12735dfecf96Smrg 12745dfecf96Smrg (and ind-cache (go :ind-parse-loop)) 12755dfecf96Smrg 12765dfecf96Smrg;------------------------------------------------------------------------ 12775dfecf96Smrg; Everything checked, process result 12785dfecf96Smrg:ind-process 12795dfecf96Smrg 12805dfecf96Smrg ;; If stack is not empty, don't apply rules 12815dfecf96Smrg (and ind-stack (not ind-startp) (go :ind-read)) 12825dfecf96Smrg 12835dfecf96Smrg (block ind-terminate-block 12845dfecf96Smrg (setq ind-cache nil ind-tleft 0 ind-change (mapcar #'car ind-state)) 12855dfecf96Smrg (dolist (entry ind-reduces) 12865dfecf96Smrg (setq 12875dfecf96Smrg *ind-token* (indreduce-token entry) 12885dfecf96Smrg *ind-label* (indreduce-label entry) 12895dfecf96Smrg ) 12905dfecf96Smrg (dolist (rule (indreduce-rules entry)) 12915dfecf96Smrg (loop 12925dfecf96Smrg ;; Check if reduction can be applied 12935dfecf96Smrg (or 12945dfecf96Smrg (multiple-value-setq 12955dfecf96Smrg (ind-match ind-length) 12965dfecf96Smrg (indent-search-rule rule ind-change) 12975dfecf96Smrg ) 12985dfecf96Smrg (return) 12995dfecf96Smrg ) 13005dfecf96Smrg 13015dfecf96Smrg (setq 13025dfecf96Smrg ;; First element matched 13035dfecf96Smrg ind-matches (nthcdr ind-match ind-state) 13045dfecf96Smrg 13055dfecf96Smrg ;; Offset of match 13065dfecf96Smrg *ind-offset* (cadar ind-matches) 13075dfecf96Smrg 13085dfecf96Smrg *ind-token-list* (nthcdr ind-match ind-change) 13095dfecf96Smrg 13105dfecf96Smrg ;; Length of match, note that *ind-length* 13115dfecf96Smrg ;; Will be transformed to zero bellow if 13125dfecf96Smrg ;; the rule is deleting entries. 13135dfecf96Smrg *ind-length* 13145dfecf96Smrg (if (> ind-length 1) 13155dfecf96Smrg (progn 13165dfecf96Smrg (setq 13175dfecf96Smrg ;; XXX using ind-tright, to reduce 13185dfecf96Smrg ;; number of local variables... 13195dfecf96Smrg ind-tright 13205dfecf96Smrg (nth (1- ind-length) ind-matches) 13215dfecf96Smrg 13225dfecf96Smrg ind-right 13235dfecf96Smrg (+ (cadr ind-tright) 13245dfecf96Smrg (cddr ind-tright) 13255dfecf96Smrg ) 13265dfecf96Smrg ) 13275dfecf96Smrg (- ind-right *ind-offset*) 13285dfecf96Smrg ) 13295dfecf96Smrg (cddar ind-matches) 13305dfecf96Smrg ) 13315dfecf96Smrg ) 13325dfecf96Smrg 13335dfecf96Smrg ;; XXX using ind-tleft as a counter, to reduce 13345dfecf96Smrg ;; number of used variables... 13355dfecf96Smrg (and (>= (incf ind-tleft) 1000) 13365dfecf96Smrg ;; Should never apply so many reduce rules on 13375dfecf96Smrg ;; every iteration, if needs to, something is 13385dfecf96Smrg ;; wrong in the indentation definition... 13395dfecf96Smrg (error "~D INDREDUCE iterations, ~ 13405dfecf96Smrg now checking (~A ~A)" 13415dfecf96Smrg ind-tleft *ind-token* rule 13425dfecf96Smrg ) 13435dfecf96Smrg ) 13445dfecf96Smrg 13455dfecf96Smrg ;; Check if should apply the reduction 13465dfecf96Smrg (or 13475dfecf96Smrg ;; Expand check code 13485dfecf96Smrg ,(indent-check-code (eval ind-definition)) 13495dfecf96Smrg (return) 13505dfecf96Smrg ) 13515dfecf96Smrg 13525dfecf96Smrg (if (null *ind-token*) 13535dfecf96Smrg ;; Remove match 13545dfecf96Smrg (progn 13555dfecf96Smrg (setq *ind-length* 0) 13565dfecf96Smrg (if (= ind-match 0) 13575dfecf96Smrg ;; Matched the first entry 13585dfecf96Smrg (setq 13595dfecf96Smrg ind-state 13605dfecf96Smrg (nthcdr ind-length ind-matches) 13615dfecf96Smrg ) 13625dfecf96Smrg (progn 13635dfecf96Smrg (setq 13645dfecf96Smrg ind-matches 13655dfecf96Smrg (nthcdr (1- ind-match) ind-state) 13665dfecf96Smrg ) 13675dfecf96Smrg (rplacd 13685dfecf96Smrg ind-matches 13695dfecf96Smrg (nthcdr (1+ ind-length) ind-matches) 13705dfecf96Smrg ) 13715dfecf96Smrg ) 13725dfecf96Smrg ) 13735dfecf96Smrg ) 13745dfecf96Smrg 13755dfecf96Smrg ;; Substitute/simplify 13765dfecf96Smrg (progn 13775dfecf96Smrg (rplaca (car ind-matches) *ind-token*) 13785dfecf96Smrg (when (> ind-length 1) 13795dfecf96Smrg (rplacd (cdar ind-matches) *ind-length*) 13805dfecf96Smrg (rplacd 13815dfecf96Smrg ind-matches 13825dfecf96Smrg (nthcdr ind-length ind-matches) 13835dfecf96Smrg ) 13845dfecf96Smrg ) 13855dfecf96Smrg ) 13865dfecf96Smrg ) 13875dfecf96Smrg (setq 13885dfecf96Smrg ind-cache t 13895dfecf96Smrg ind-change (mapcar #'car ind-state) 13905dfecf96Smrg ) 13915dfecf96Smrg 13925dfecf96Smrg ;; Expand reduce code 13935dfecf96Smrg ,(indent-reduce-code (eval ind-definition)) 13945dfecf96Smrg ) 13955dfecf96Smrg ) 13965dfecf96Smrg ) 13975dfecf96Smrg 13985dfecf96Smrg ;; ind-cache will be T if at least one change was done 13995dfecf96Smrg (and ind-cache (go :ind-process)) 14005dfecf96Smrg 14015dfecf96Smrg ;; Start of file reached 14025dfecf96Smrg (or ind-startp (go :ind-read)) 14035dfecf96Smrg 14045dfecf96Smrg ) ;; end of ind-terminate-block 14055dfecf96Smrg 14065dfecf96Smrg 14075dfecf96Smrg (block ind-terminate-block 14085dfecf96Smrg (setq *ind-token-list* (mapcar #'car ind-state)) 14095dfecf96Smrg (dolist (item ind-state) 14105dfecf96Smrg (setq 14115dfecf96Smrg *ind-token* (car item) 14125dfecf96Smrg *ind-offset* (cadr item) 14135dfecf96Smrg *ind-length* (cddr item) 14145dfecf96Smrg ) 14155dfecf96Smrg ;; Expand resolve code 14165dfecf96Smrg ,(indent-resolve-code (eval ind-definition)) 14175dfecf96Smrg (setq *ind-token-list* (cdr *ind-token-list*)) 14185dfecf96Smrg ) 14195dfecf96Smrg ) 14205dfecf96Smrg 14215dfecf96Smrg (and (integerp *indent*) 14225dfecf96Smrg (integerp *offset*) 14235dfecf96Smrg (indent-text *indent* *offset* ,ind-no-tabs) 14245dfecf96Smrg ) 14255dfecf96Smrg ) 14265dfecf96Smrg) 1427