guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: SRFI-88-style keywords


From: Ludovic Courtès
Subject: Re: SRFI-88-style keywords
Date: Tue, 15 Apr 2008 20:08:41 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

Hi,

"Julian Graham" <address@hidden> writes:

> What if we added another reader option, say, (keywords 'postfix),
> which would recognize SRFI-88-style keywords?

I think now is a good time so I just committed the attached patch.

Now, we should do something about `cond-expand' and `require-extension'.
For the former, we should probably look at the current value of
`(read-options)', but that requires changing the implementation of
`cond-expand'.  For the latter, we can provide a dummy module that
modifies `read-options' and re-export the needed procedures.

Thoughts?

Thanks,
Ludovic.

>From 75946eddfc4b086f59766ea1e207480261be0315 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Ludovic=20Court=C3=A8s?= <address@hidden>
Date: Tue, 15 Apr 2008 19:52:43 +0200
Subject: [PATCH] Add support for SRFI-88-like postfix keyword read syntax.

---
 NEWS                         |    4 ++++
 doc/ref/ChangeLog            |    7 +++++++
 doc/ref/api-data.texi        |   22 ++++++++++++++++++++--
 doc/ref/api-options.texi     |    6 +++---
 libguile/ChangeLog           |    7 +++++++
 libguile/read.c              |   26 ++++++++++++++++++++------
 test-suite/ChangeLog         |    5 +++++
 test-suite/tests/reader.test |   16 +++++++++++++++-
 8 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/NEWS b/NEWS
index 6d889d3..02b90e6 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,10 @@ The new repository can be accessed using
 "git-clone git://git.sv.gnu.org/guile.git", or can be browsed on-line at
 http://git.sv.gnu.org/gitweb/?p=guile.git .  See `README' for details.
 
+* New features (see the manual for details)
+
+** New `postfix' read option, for SRFI-88 keyword syntax
+
 * Bugs fixed
 
 ** `scm_add_slot ()' no longer segfaults (fixes bug #22369)
diff --git a/doc/ref/ChangeLog b/doc/ref/ChangeLog
index b41db5c..371cac3 100644
--- a/doc/ref/ChangeLog
+++ b/doc/ref/ChangeLog
@@ -1,3 +1,10 @@
+2008-04-15  Ludovic Courtès  <address@hidden>
+
+       * api-data.texi (Keywords): Mention postfix syntax.
+       (Keyword Read Syntax): Document `postfix' read option.
+       * api-options.texi (Reader options): Update examples.
+       (Examples of option use): Likewise.
+
 2008-03-19  Neil Jerram  <address@hidden>
 
        * api-debug.texi (Debugging Examples): New (from CVS HEAD).
diff --git a/doc/ref/api-data.texi b/doc/ref/api-data.texi
index f4549f6..31c1c6b 100755
--- a/doc/ref/api-data.texi
+++ b/doc/ref/api-data.texi
@@ -4894,7 +4894,7 @@ makes them easy to type.
 
 Guile's keyword support conforms to R5RS, and adds a (switchable) read
 syntax extension to permit keywords to begin with @code{:} as well as
address@hidden:}.
address@hidden:}, or to end with @code{:}.
 
 @menu
 * Why Use Keywords?::           Motivation for keyword usage.
@@ -5039,9 +5039,17 @@ If the @code{keyword} read option is set to 
@code{'prefix}, Guile also
 recognizes the alternative read syntax @code{:NAME}.  Otherwise, tokens
 of the form @code{:NAME} are read as symbols, as required by R5RS.
 
address@hidden SRFI-88 keyword syntax
+
+If the @code{keyword} read option is set to @code{'postfix}, Guile
+recognizes the @uref{http://srfi.schemers.org/srfi-88/srfi-88.html,
+SRFI-88 read syntax} @code{NAME:}.  Otherwise, tokens of this form are
+read as symbols.
+
 To enable and disable the alternative non-R5RS keyword syntax, you use
 the @code{read-set!} procedure documented in @ref{User level options
-interfaces} and @ref{Reader options}.
+interfaces} and @ref{Reader options}.  Note that the @code{prefix} and
address@hidden syntax are mutually exclusive.
 
 @smalllisp
 (read-set! keywords 'prefix)
@@ -5054,6 +5062,16 @@ interfaces} and @ref{Reader options}.
 @result{}
 #:type
 
+(read-set! keywords 'postfix)
+
+type:
address@hidden
+#:type
+
+:type
address@hidden
+:type
+
 (read-set! keywords #f)
 
 #:type
diff --git a/doc/ref/api-options.texi b/doc/ref/api-options.texi
index ed1c42d..0805108 100644
--- a/doc/ref/api-options.texi
+++ b/doc/ref/api-options.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Guile Reference Manual.
address@hidden Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 
2006
address@hidden Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 
2006, 2008
 @c   Free Software Foundation, Inc.
 @c See the file guile.texi for copying conditions.
 
@@ -491,7 +491,7 @@ Here is the list of reader options generated by typing
 values.
 
 @smalllisp
-keywords         #f      Style of keyword recognition: #f or 'prefix
+keywords         #f      Style of keyword recognition: #f, 'prefix or 'postfix
 case-insensitive no      Convert symbols to lower case.
 positions        yes     Record positions of source code expressions.
 copy             no      Copy source code expressions.
@@ -715,7 +715,7 @@ ABORT: (misc-error)
 
 Type "(backtrace)" to get more information.
 guile> (read-options 'help)
-keywords       #f      Style of keyword recognition: #f or 'prefix
+keywords       #f      Style of keyword recognition: #f, 'prefix or 'postfix
 case-insensitive       no      Convert symbols to lower case.
 positions      yes     Record positions of source code expressions.
 copy           no      Copy source code expressions.
diff --git a/libguile/ChangeLog b/libguile/ChangeLog
index 93453f4..5692927 100644
--- a/libguile/ChangeLog
+++ b/libguile/ChangeLog
@@ -1,3 +1,10 @@
+2008-04-15  Ludovic Courtès  <address@hidden>
+           Julian Graham  <address@hidden>
+
+       * read.c (scm_keyword_postfix): New.
+       (scm_read_opts): Update docstring for `keywords'.
+       (scm_read_mixed_case_symbol): Add support for postfix keywords.
+
 2008-04-13  Ludovic Courtès  <address@hidden>
 
        * inline.h (SCM_C_USE_EXTERN_INLINE): New macro.  Use it to make
diff --git a/libguile/read.c b/libguile/read.c
index 8290f19..8bc1dff 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -54,6 +54,7 @@
 
 SCM_GLOBAL_SYMBOL (scm_sym_dot, ".");
 SCM_SYMBOL (scm_keyword_prefix, "prefix");
+SCM_SYMBOL (scm_keyword_postfix, "postfix");
 
 scm_t_option scm_read_opts[] = {
   { SCM_OPTION_BOOLEAN, "copy", 0,
@@ -63,7 +64,7 @@ scm_t_option scm_read_opts[] = {
   { SCM_OPTION_BOOLEAN, "case-insensitive", 0,
     "Convert symbols to lower case."},
   { SCM_OPTION_SCM, "keywords", SCM_UNPACK (SCM_BOOL_F),
-    "Style of keyword recognition: #f or 'prefix."}
+    "Style of keyword recognition: #f, 'prefix or 'postfix."},
 #if SCM_ENABLE_ELISP
   ,
   { SCM_OPTION_BOOLEAN, "elisp-vectors", 0,
@@ -561,15 +562,19 @@ static SCM
 scm_read_mixed_case_symbol (int chr, SCM port)
 {
   SCM result, str = SCM_EOL;
-  int overflow = 0;
+  int overflow = 0, ends_with_colon = 0;
   char buffer[READER_BUFFER_SIZE];
   size_t read = 0;
+  int postfix = scm_is_eq (SCM_PACK (SCM_KEYWORD_STYLE), scm_keyword_postfix);
 
   scm_ungetc (chr, port);
   do
     {
       overflow = read_token (port, buffer, sizeof (buffer), &read);
 
+      if (read > 0)
+       ends_with_colon = (buffer[read - 1] == ':');
+
       if ((overflow) || (scm_is_pair (str)))
        str = scm_cons (scm_from_locale_stringn (buffer, read), str);
     }
@@ -579,12 +584,21 @@ scm_read_mixed_case_symbol (int chr, SCM port)
     {
       str = scm_string_concatenate (scm_reverse_x (str, SCM_EOL));
       result = scm_string_to_symbol (str);
+
+      /* Per SRFI-88, `:' alone is an identifier, not a keyword.  */
+      if (postfix && ends_with_colon && (scm_c_string_length (result) > 1))
+       result = scm_symbol_to_keyword (result);
     }
   else
-    /* For symbols smaller than `sizeof (buffer)', we don't need to recur to
-       Scheme strings.  Therefore, we only create one Scheme object (a
-       symbol) per symbol read.  */
-    result = scm_from_locale_symboln (buffer, read);
+    {
+      /* For symbols smaller than `sizeof (buffer)', we don't need to recur
+        to Scheme strings.  Therefore, we only create one Scheme object (a
+        symbol) per symbol read.  */
+      if (postfix && ends_with_colon && (read > 1))
+       result = scm_from_locale_keywordn (buffer, read - 1);
+      else
+       result = scm_from_locale_symboln (buffer, read);
+    }
 
   return result;
 }
diff --git a/test-suite/ChangeLog b/test-suite/ChangeLog
index 518e53f..210c802 100644
--- a/test-suite/ChangeLog
+++ b/test-suite/ChangeLog
@@ -1,3 +1,8 @@
+2008-04-15  Ludovic Courtès  <address@hidden>
+
+       * tests/reader.test (read-options)[prefix non-keywords, postfix
+       keywords, `:' is not a postfix keyword (per SRFI-88)]: New tests.
+
 2008-04-13  Ludovic Courtès  <address@hidden>
 
        * tests/goops.test (defining classes)[interaction with
diff --git a/test-suite/tests/reader.test b/test-suite/tests/reader.test
index d6047a2..0b13cf1 100644
--- a/test-suite/tests/reader.test
+++ b/test-suite/tests/reader.test
@@ -1,6 +1,6 @@
 ;;;; reader.test --- Exercise the reader.               -*- Scheme -*-
 ;;;;
-;;;; Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
+;;;; Copyright (C) 1999, 2001, 2002, 2003, 2007, 2008 Free Software 
Foundation, Inc.
 ;;;; Jim Blandy <address@hidden>
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
@@ -149,6 +149,20 @@
          (with-read-options '(keywords prefix case-insensitive)
            (lambda ()
              (read-string ":KeyWord")))))
+  (pass-if "prefix non-keywords"
+    (symbol? (with-read-options '(keywords prefix)
+               (lambda ()
+                 (read-string "srfi88-keyword:")))))
+  (pass-if "postfix keywords"
+    (eq? #:keyword
+         (with-read-options '(keywords postfix)
+           (lambda ()
+             (read-string "keyword:")))))
+  (pass-if "`:' is not a postfix keyword (per SRFI-88)"
+    (eq? ':
+         (with-read-options '(keywords postfix)
+           (lambda ()
+             (read-string ":")))))
   (pass-if "no positions"
     (let ((sexp (with-read-options '()
                   (lambda ()
-- 
1.5.5


reply via email to

[Prev in Thread] Current Thread [Next in Thread]