; Tcl parser — thin layer over tcl-tokenize ; Adds tcl-parse entry point and word utility fns ; Entry point: parse Tcl source to a list of commands. ; Returns same structure as tcl-tokenize. (define tcl-parse (fn (src) (tcl-tokenize src))) ; True if word has no substitutions — value can be read statically. ; braced words are always simple. compound words are simple when all ; parts are plain text with no var/cmd parts. (define tcl-word-simple? (fn (word) (cond ((= (get word :type) "braced") true) ((= (get word :type) "compound") (let ((parts (get word :parts))) (every? (fn (p) (= (get p :type) "text")) parts))) (else false)))) ; Concatenate text parts of a simple word into a single string. ; For braced words returns :value directly. ; For compound words with only text parts, joins them. ; Returns nil for words with substitutions. (define tcl-word-literal (fn (word) (cond ((= (get word :type) "braced") (get word :value)) ((= (get word :type) "compound") (if (tcl-word-simple? word) (join "" (map (fn (p) (get p :value)) (get word :parts))) nil)) (else nil)))) ; Number of words in a parsed command. (define tcl-cmd-len (fn (cmd) (len (get cmd :words)))) ; Nth word literal from a command (index 0 = command name). ; Returns nil if word has substitutions. (define tcl-nth-literal (fn (cmd n) (tcl-word-literal (nth (get cmd :words) n))))