This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A useful syntax for regexps and other things



Currently, the use of the backslash escape syntax and the escape
syntax for regular expressions and sometimes other things clash
horribly - to write a regular expression that matches a literal
backslash, you must write "\\\\". To match literal \*, you must write
"\\\\\\*". It only gets worse from there. I propose the following
reader extension as a solution:

(read-hash-extend #\q 
		  (lambda (c port)
		    (let ((delimiter (read-char port)))
		      (let loop ((str "")
				 (ch (read-char port)))
			(cond
			 ((eof-object? ch) 
			  (error "end of file in #q-quoted string"))
			 ((char=? ch delimiter) 
			  (if (char=? delimiter (peek-char port))
			      (begin
				(read-char port)
				(loop 
				 (string-append str (list->string (list ch)))
				 (read-char port)))
			      str))
			 (else (loop 
				(string-append str (list->string (list ch)))
				(read-char port))))))))

When #q is encountered, the next character becomes the delimiter that
begins and ends a literal string with no backslash escapes
expanded. To get the delimiter into the string, simply double it. This
is vaguely based on perl's q operator, but is not exactly the same;
perl's q operator will ignore backslashes unless they are doubled or
precede the delimiter and therefore do not make regexps sufficiently
easier to read for our purposes. Here are some examples of the #q
syntax in action:

guile> #q/some funny \\ weird string\/
"some funny \\\\ weird string\\"
guile> #q%any delimiter %% will do %
"any delimiter % will do "
guile> #q@This is a weird \* \\.* x? regexp@
"This is a weird \\* \\\\.* x? regexp"