123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- // Copyright (c) 2001 Per M.A. Bothner
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.kawa.lispexpr;
- import gnu.kawa.io.InPort;
- import gnu.text.*;
- import gnu.mapping.Values;
- public final class ReaderParens extends ReadTableEntry
- {
- char open;
- char close;
- int kind;
- Object command;
- public int getKind()
- {
- return kind;
- }
- private static ReaderParens instance;
- public static ReaderParens getInstance(char open, char close)
- {
- return getInstance(open, close, ReadTable.TERMINATING_MACRO);
- }
- public static ReaderParens getInstance(char open, char close, int kind)
- {
- if (open == '(' && close == ')' && kind == ReadTable.TERMINATING_MACRO)
- {
- if (instance == null)
- instance = new ReaderParens(open, close, kind, null);
- return instance;
- }
- else
- {
- return new ReaderParens(open, close, kind, null);
- }
- }
- public static ReaderParens getInstance(char open, char close, int kind, Object command)
- {
- if (command == null)
- return getInstance(open, close, kind);
- else
- return new ReaderParens(open, close, kind, command);
- }
- public ReaderParens(char open, char close, int kind, Object command)
- {
- this.open = open;
- this.close = close;
- this.kind = kind;
- this.command = command;
- }
- /** Read a list (possibly improper) of zero or more Scheme forms.
- * Assumes '(' has been read.
- */
- public Object read (Lexer in, int ch, int count, int sharingIndex)
- throws java.io.IOException, SyntaxException
- {
- Object p = null;
- if (command != null)
- {
- InPort port = in.getPort();
- int startLine = port.getLineNumber();
- int startColumn = port.getColumnNumber();
- // startColumn is the 0-based position *after* reading ch.
- // We want the position *before* reading ch.
- // (makePair converts from 0-based to 1-based.)
- p = ((LispReader) in).makePair(command, startLine, startColumn-1);
- ((LispReader) in).bindSharedObject(sharingIndex, p);
- sharingIndex = -1;
- }
- return readList((LispReader) in, p, ch, count, close, sharingIndex);
- }
- public static Object readList (LispReader lexer, Object last,
- int ch, int count, int close, int sharingIndex)
- throws java.io.IOException, SyntaxException
- {
- InPort port = lexer.getPort();
- char saveReadState = lexer.pushNesting(close == ']' ? '[' : '(');
- int startLine = port.getLineNumber();
- int startColumn = port.getColumnNumber();
- try
- {
- Object list = last == null ? lexer.makeNil() : last;
- boolean sawDot = false;
- boolean sawDotCdr = false;
- ReadTable readTable = ReadTable.getCurrent();
- for (;;)
- {
- int line = port.getLineNumber();
- int column = port.getColumnNumber();
- ch = port.read();
- if (ch == close)
- break;
- if (ch < 0) {
- if (lexer.isTentative()) {
- Object value = gnu.lists.Pair.incompleteListMarker;
- if (last == null)
- list = value;
- else
- lexer.setCdr(last, value);
- return list;
- }
- lexer.eofError("unexpected EOF in list starting here",
- startLine + 1, startColumn);
- }
- ReadTableEntry entry;
- if (ch == '.')
- {
- ch = port.peek();
- entry = readTable.lookup(ch);
- int kind = entry.getKind();
- if (kind == ReadTable.WHITESPACE
- || kind == ReadTable.TERMINATING_MACRO
- || kind == ReadTable.ILLEGAL)
- {
- port.skip();
- column++;
- if (ch == close)
- {
- lexer.error("unexpected '"
- + ((char) close) + "' after '.'");
- break;
- }
- if (ch < 0)
- lexer.eofError("unexpected EOF in list starting here",
- startLine + 1, startColumn);
- if (sawDot)
- {
- lexer.error("multiple '.' in list");
- sawDotCdr = false;
- list = lexer.makeNil();
- last = null;
- }
- sawDot = true;
- }
- else
- {
- // Treat '.' as start of token.
- ch = '.';
- entry = ReadTableEntry.getConstituentInstance();
- }
- }
- else
- entry = readTable.lookup(ch);
- if (entry.getKind() == ReadTable.WHITESPACE)
- continue;
- Object first = null;
- if (! sawDot && last == null)
- {
- first = lexer.makePair(null, line, column);
- lexer.bindSharedObject(sharingIndex, first);
- }
- Object value = lexer.readValues(ch, entry, readTable, -1);
- if (value == Values.empty)
- continue;
- value = lexer.handlePostfix(value, readTable, line, column);
- // ( a1 ... an . cdr) creates an n-element list ended by
- // cdr. If n==0, a reasonable (and common) extension is to
- // interpret this as a 0-element list ended by cdr - i.e.
- // just cdr by itself.
- if (sawDotCdr)
- {
- lexer.error("multiple values after '.'");
- last = null;
- list = lexer.makeNil();
- sawDotCdr = false;
- continue;
- }
- else if (sawDot)
- {
- sawDotCdr = true;
- }
- else
- {
- int endline = port.getLineNumber();
- int endcolumn = port.getColumnNumber();
- if (last == null)
- {
- lexer.setCar(first, value, endline+1, endcolumn+1);
- value = first;
- sharingIndex = -1;
- }
- else
- value = lexer.makePair(value, line, column,
- endline, endcolumn);
- }
- if (last == null)
- list = value;
- else
- lexer.setCdr(last, value);
- last = value;
- }
- if (sawDot && ! sawDotCdr)
- lexer.error("missing value after '.'");
- return lexer.bindSharedObject(sharingIndex, list);
- }
- finally
- {
- lexer.popNesting(saveReadState);
- }
-
- }
- }
|