source: trunk/abcl/src/org/armedbear/lisp/LispReader.java @ 12458

Last change on this file since 12458 was 12431, checked in by Mark Evenson, 15 years ago

Replace FastStringBuffer? with java.lang.StringBuilder?.

Phil Hudson suggested in Feburary 2009 that "[FastStringBuffer?] should
be removed with all references to it replaced with
java.lang.StringBuilder? once enough confidence in this change has been
gained." After almost a year of using FastStringBuffer? as a delagate
for StringBuilder?, that confidence has indeed been gained.

One subtlety for use of StringBuilder?: there is no

StringBuilder?(char)

constructor, so use

StringBuilder?(String.valueOf(c))

to construct a new StringBuilder? containing a single char. Otherwise
that char will get promoted to an int, and you will invoke

StringBuilder?(int capacity)

which will "swallow" the first character that you thought you were adding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.0 KB
Line 
1/*
2 * LispReader.java
3 *
4 * Copyright (C) 2004-2007 Peter Graves
5 * $Id: LispReader.java 12431 2010-02-08 08:05:15Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38public final class LispReader
39{
40    // ### read-comment
41    public static final ReaderMacroFunction READ_COMMENT =
42        new ReaderMacroFunction("read-comment", PACKAGE_SYS, false,
43                                "stream character")
44    {
45        @Override
46        public LispObject execute(Stream stream, char ignored)
47
48        {
49          try 
50            {
51              while (true) {
52                int n = stream._readChar();
53                if (n < 0)
54                  return null;
55                if (n == '\n')
56                  return null;
57              }
58            }
59          catch (java.io.IOException e)
60            {
61              return null;
62            }
63        }
64    };
65
66    // ### read-string
67    public static final ReaderMacroFunction READ_STRING =
68        new ReaderMacroFunction("read-string", PACKAGE_SYS, false,
69                                "stream character")
70    {
71        @Override
72        public LispObject execute(Stream stream, char terminator)
73
74        {
75            final LispThread thread = LispThread.currentThread();
76            final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread);
77            StringBuilder sb = new StringBuilder();
78            try 
79              {
80                while (true) {
81                  int n = stream._readChar();
82                  if (n < 0) {
83                    error(new EndOfFile(stream));
84                    // Not reached.
85                    return null;
86                  }
87                  char c = (char) n; // ### BUG: Codepoint conversion
88                  if (rt.getSyntaxType(c) == Readtable.SYNTAX_TYPE_SINGLE_ESCAPE) {
89                    // Single escape.
90                    n = stream._readChar();
91                    if (n < 0) {
92                      error(new EndOfFile(stream));
93                      // Not reached.
94                      return null;
95                    }
96                    sb.append((char)n); // ### BUG: Codepoint conversion
97                    continue;
98                  }
99                  if (Utilities.isPlatformWindows) {
100                    if (c == '\r') {
101                      n = stream._readChar();
102                      if (n < 0) {
103                        error(new EndOfFile(stream));
104                        // Not reached.
105                        return null;
106                      }
107                      if (n == '\n') {
108                        sb.append('\n');
109                      } else {
110                        // '\r' was not followed by '\n'.
111                        stream._unreadChar(n);
112                        sb.append('\r');
113                      }
114                      continue;
115                    }
116                  }
117                  if (c == terminator)
118                    break;
119                  // Default.
120                  sb.append(c);
121                }
122              }
123            catch (java.io.IOException e)
124              {
125                //error(new EndOfFile(stream));
126    return new SimpleString(sb);
127              }
128            return new SimpleString(sb);
129        }
130    };
131
132    // ### read-list
133    public static final ReaderMacroFunction READ_LIST =
134        new ReaderMacroFunction("read-list", PACKAGE_SYS, false,
135                                "stream character")
136    {
137        @Override
138        public LispObject execute(Stream stream, char ignored)
139
140        {
141            return stream.readList(false, false);
142        }
143    };
144
145    // ### read-right-paren
146    public static final ReaderMacroFunction READ_RIGHT_PAREN =
147        new ReaderMacroFunction("read-right-paren", PACKAGE_SYS, false,
148                                "stream character")
149    {
150        @Override
151        public LispObject execute(Stream stream, char ignored)
152
153        {
154            return error(new ReaderError("Unmatched right parenthesis.", stream));
155        }
156    };
157
158    // ### read-quote
159    public static final ReaderMacroFunction READ_QUOTE =
160        new ReaderMacroFunction("read-quote", PACKAGE_SYS, false,
161                                "stream character")
162    {
163        @Override
164        public LispObject execute(Stream stream, char ignored)
165
166        {
167            return new Cons(Symbol.QUOTE,
168                            new Cons(stream.read(true, NIL, true,
169                                                 LispThread.currentThread())));
170        }
171    };
172
173    // ### read-dispatch-char
174    public static final ReaderMacroFunction READ_DISPATCH_CHAR =
175        new ReaderMacroFunction("read-dispatch-char", PACKAGE_SYS, false,
176                                "stream character")
177    {
178        @Override
179        public LispObject execute(Stream stream, char c)
180
181        {
182            return stream.readDispatchChar(c, false);
183        }
184    };
185
186    // ### sharp-left-paren
187    public static final DispatchMacroFunction SHARP_LEFT_PAREN =
188        new DispatchMacroFunction("sharp-left-paren", PACKAGE_SYS, false,
189                                  "stream sub-char numarg")
190    {
191        @Override
192        public LispObject execute(Stream stream, char c, int n)
193
194        {
195            final LispThread thread = LispThread.currentThread();
196            LispObject list = stream.readList(true, false);
197            if (_BACKQUOTE_COUNT_.symbolValue(thread).zerop()) {
198                if (n >= 0) {
199                    LispObject[] array = new LispObject[n];
200                    for (int i = 0; i < n; i++) {
201                        array[i] = list.car();
202                        if (list.cdr() != NIL)
203                            list = list.cdr();
204                    }
205                    return new SimpleVector(array);
206                } else
207                    return new SimpleVector(list);
208            }
209            return new Cons(_BQ_VECTOR_FLAG_.symbolValue(thread), list);
210        }
211    };
212
213    // ### sharp-star
214    public static final DispatchMacroFunction SHARP_STAR =
215        new DispatchMacroFunction("sharp-star", PACKAGE_SYS, false,
216                                  "stream sub-char numarg")
217    {
218        @Override
219        public LispObject execute(Stream stream, char ignored, int n)
220
221        {
222            final LispThread thread = LispThread.currentThread();
223            final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread);
224            final boolean suppress = Symbol.READ_SUPPRESS.symbolValue(thread) != NIL;
225            StringBuilder sb = new StringBuilder();
226            try 
227              {
228                while (true) {
229                  int ch = stream._readChar();
230                  if (ch < 0)
231                    break;
232                  char c = (char) ch; // ### BUG: Codepoint conversion
233                  if (c == '0' || c == '1')
234                    sb.append(c);
235                  else {
236                    int syntaxType = rt.getSyntaxType(c);
237                    if (syntaxType == Readtable.SYNTAX_TYPE_WHITESPACE ||
238                        syntaxType == Readtable.SYNTAX_TYPE_TERMINATING_MACRO) {
239                      stream._unreadChar(c);
240                      break;
241                    } else if (!suppress) {
242                      String name = LispCharacter.charToName(c);
243                      if (name == null)
244                        name = "#\\" + c;
245                      error(new ReaderError("Illegal element for bit-vector: " + name,
246                                            stream));
247                    }
248                  }
249                }
250              }
251            catch (java.io.IOException e)
252              {
253                error(new ReaderError("IO error-vector: ",
254                                      stream));
255              }
256            if (suppress)
257                return NIL;
258            if (n >= 0) {
259                // n was supplied.
260                final int length = sb.length();
261                if (length == 0) {
262                    if (n > 0)
263                        return error(new ReaderError("No element specified for bit vector of length " +
264                                                      n + '.',
265                                                      stream));
266                }
267                if (n > length) {
268                    final char c = sb.charAt(length - 1);
269                    for (int i = length; i < n; i++)
270                        sb.append(c);
271                } else if (n < length) {
272                    return error(new ReaderError("Bit vector is longer than specified length: #" +
273                                                  n + '*' + sb.toString(),
274                                                  stream));
275                }
276            }
277            return new SimpleBitVector(sb.toString());
278        }
279    };
280
281    // ### sharp-dot
282    public static final DispatchMacroFunction SHARP_DOT =
283        new DispatchMacroFunction("sharp-dot", PACKAGE_SYS, false,
284                                  "stream sub-char numarg")
285    {
286        @Override
287        public LispObject execute(Stream stream, char c, int n)
288
289        {
290            final LispThread thread = LispThread.currentThread();
291            if (Symbol.READ_EVAL.symbolValue(thread) == NIL)
292                return error(new ReaderError("Can't read #. when *READ-EVAL* is NIL.",
293                                              stream));
294            else
295                return eval(stream.read(true, NIL, true, thread),
296                            new Environment(), thread);
297        }
298    };
299
300    // ### sharp-colon
301    public static final DispatchMacroFunction SHARP_COLON =
302        new DispatchMacroFunction("sharp-colon", PACKAGE_SYS, false,
303                                  "stream sub-char numarg")
304    {
305        @Override
306        public LispObject execute(Stream stream, char c, int n)
307
308        {
309            return stream.readSymbol();
310        }
311    };
312
313    // ### sharp-a
314    public static final DispatchMacroFunction SHARP_A =
315        new DispatchMacroFunction("sharp-a", PACKAGE_SYS, false,
316                                  "stream sub-char numarg")
317    {
318        @Override
319        public LispObject execute(Stream stream, char c, int n)
320
321        {
322            return stream.readArray(n);
323        }
324    };
325
326    // ### sharp-b
327    public static final DispatchMacroFunction SHARP_B =
328        new DispatchMacroFunction("sharp-b", PACKAGE_SYS, false,
329                                  "stream sub-char numarg")
330    {
331        @Override
332        public LispObject execute(Stream stream, char c, int n)
333
334        {
335            return stream.readRadix(2);
336        }
337    };
338
339    // ### sharp-c
340    public static final DispatchMacroFunction SHARP_C =
341        new DispatchMacroFunction("sharp-c", PACKAGE_SYS, false,
342                                  "stream sub-char numarg")
343    {
344        @Override
345        public LispObject execute(Stream stream, char c, int n)
346
347        {
348            return stream.readComplex();
349        }
350    };
351
352    // ### sharp-o
353    public static final DispatchMacroFunction SHARP_O =
354        new DispatchMacroFunction("sharp-o", PACKAGE_SYS, false,
355                                  "stream sub-char numarg")
356    {
357        @Override
358        public LispObject execute(Stream stream, char c, int n)
359
360        {
361            return stream.readRadix(8);
362        }
363    };
364
365    // ### sharp-p
366    public static final DispatchMacroFunction SHARP_P =
367        new DispatchMacroFunction("sharp-p", PACKAGE_SYS, false,
368                                  "stream sub-char numarg")
369    {
370        @Override
371        public LispObject execute(Stream stream, char c, int n)
372
373        {
374            return stream.readPathname();
375        }
376    };
377
378    // ### sharp-r
379    public static final DispatchMacroFunction SHARP_R =
380        new DispatchMacroFunction("sharp-r", PACKAGE_SYS, false,
381                                  "stream sub-char numarg")
382    {
383        @Override
384        public LispObject execute(Stream stream, char c, int n)
385
386        {
387            return stream.readRadix(n);
388        }
389    };
390
391    // ### sharp-s
392    public static final DispatchMacroFunction SHARP_S =
393        new DispatchMacroFunction("sharp-s", PACKAGE_SYS, false,
394                                  "stream sub-char numarg")
395    {
396        @Override
397        public LispObject execute(Stream stream, char c, int n)
398
399        {
400            return stream.readStructure();
401        }
402    };
403
404    // ### sharp-x
405    public static final DispatchMacroFunction SHARP_X =
406        new DispatchMacroFunction("sharp-x", PACKAGE_SYS, false,
407                                  "stream sub-char numarg")
408    {
409        @Override
410        public LispObject execute(Stream stream, char c, int n)
411
412        {
413            return stream.readRadix(16);
414        }
415    };
416
417    // ### sharp-quote
418    public static final DispatchMacroFunction SHARP_QUOTE =
419        new DispatchMacroFunction("sharp-quote", PACKAGE_SYS, false,
420                                  "stream sub-char numarg")
421    {
422        @Override
423        public LispObject execute(Stream stream, char c, int n)
424
425        {
426            return new Cons(Symbol.FUNCTION,
427                            new Cons(stream.read(true, NIL, true,
428                                                 LispThread.currentThread())));
429        }
430    };
431
432    // ### sharp-backslash
433    public static final DispatchMacroFunction SHARP_BACKSLASH =
434        new DispatchMacroFunction("sharp-backslash", PACKAGE_SYS, false,
435                                  "stream sub-char numarg")
436    {
437        @Override
438        public LispObject execute(Stream stream, char c, int n)
439
440        {
441            final LispThread thread = LispThread.currentThread();
442            final Readtable rt = (Readtable) Symbol.CURRENT_READTABLE.symbolValue(thread);
443            return stream.readCharacterLiteral(rt, thread);
444        }
445    };
446
447    // ### sharp-vertical-bar
448    public static final DispatchMacroFunction SHARP_VERTICAL_BAR =
449        new DispatchMacroFunction("sharp-vertical-bar", PACKAGE_SYS, false,
450                                  "stream sub-char numarg")
451    {
452        @Override
453        public LispObject execute(Stream stream, char c, int n)
454
455        {
456            stream.skipBalancedComment();
457            return null;
458        }
459    };
460
461    // ### sharp-illegal
462    public static final DispatchMacroFunction SHARP_ILLEGAL =
463        new DispatchMacroFunction("sharp-illegal", PACKAGE_SYS, false,
464                                  "stream sub-char numarg")
465    {
466        @Override
467        public LispObject execute(Stream stream, char c, int n)
468
469        {
470            StringBuilder sb = new StringBuilder("Illegal # macro character: #\\");
471            String s = LispCharacter.charToName(c);
472            if (s != null)
473                sb.append(s);
474            else
475                sb.append(c);
476            return error(new ReaderError(sb.toString(), stream));
477        }
478    };
479}
Note: See TracBrowser for help on using the repository browser.