Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/memoire/silk/SilkInputPort.java


1   
2   
3   package com.memoire.silk;
4   import com.memoire.silk.*;
5   
6   
7   import java.io.*;
8   
9   /** SilkInputPort is to SilkScheme as InputStream is to Java. 
10   * @author Peter Norvig, peter@norvig.com http://www.norvig.com  
11   * Copyright 1998 Peter Norvig, see http://www.norvig.com/license.html **/
12  
13  public class SilkInputPort extends SilkSchemeUtils {
14  
15    static  String EOF = "#!EOF";
16    boolean isPushedToken = false;
17    boolean isPushedChar = false;
18    Object  pushedToken = null;
19    int     pushedChar = -1;
20    Reader  in;
21    StringBuffer buff = new StringBuffer();
22  
23    /** Construct an SilkInputPort from an InputStream. **/
24    public SilkInputPort(InputStream in) { this.in = new InputStreamReader(in);}
25  
26    /** Construct an SilkInputPort from a Reader. **/
27    public SilkInputPort(Reader in) { this.in = in;}
28  
29    /** @GDX */
30    private int in_read() throws IOException
31    {
32      while(!in.ready())
33      {
34        if(exited_) return -1;
35        try { Thread.sleep(100); }
36        catch(InterruptedException ex) { }
37      }
38      return in.read();
39    }
40  
41    boolean exited_=false;
42  
43    /** Read and return a SilkScheme character or EOF. **/
44    public Object readChar() {
45      try {
46        if (isPushedChar) {
47    isPushedChar = false;
48    if (pushedChar == -1) return EOF; else return chr((char)pushedChar);
49        } else {
50    int ch = in_read();
51    if (ch == -1) return EOF; else return chr((char)ch);
52        }
53      } catch (IOException e) {
54        warn("On input, exception: " + e);
55        return EOF;
56      }
57    }
58  
59    /** Peek at and return the next SilkScheme character (or EOF).
60     * However, don't consume the character. **/
61    public Object peekChar() {
62      int p = peekCh();
63      if (p == -1) return EOF; else return chr((char)p);
64    }
65  
66    /** Push a character back to be re-used later. **/
67    int pushChar(int ch) {
68      isPushedChar = true;
69      return pushedChar = ch;
70    }
71  
72    /** Pop off the previously pushed character. **/
73    int popChar() {
74      isPushedChar = false;
75      return pushedChar;
76    }
77  
78    /** Peek at and return the next SilkScheme character as an int, -1 for EOF.
79     * However, don't consume the character. **/
80    public int peekCh() {
81      try { return isPushedChar ? pushedChar : pushChar(in_read()); }
82      catch (IOException e) {
83        warn("On input, exception: " + e);
84        return -1;
85      }
86    }
87  
88    /** Read and return a SilkScheme expression, or EOF. **/
89    public Object read() {
90      try {
91        Object token = nextToken(); 
92        if (token == "(")
93    return readTail(false);
94        else if (token == ")")
95    { warn("Extra ) ignored."); return read(); }
96        else if (token == ".")
97    { warn("Extra . ignored."); return read(); }
98        else if (token == "'")
99    return list("quote", read());
100       else if (token == "`")
101   return list("quasiquote", read());
102       else if (token == ",")
103   return list("unquote", read());
104       else if (token == ",@")
105   return list("unquote-splicing", read());
106       else 
107   return token;
108     } catch (IOException e) {
109       warn("On input, exception: " + e);
110       return EOF;
111     }
112   }
113 
114   /** Close the port.  Return TRUE if ok. **/
115   public Object close() {
116     try { this.in.close(); return TRUE; }
117     catch (IOException e) { return error("IOException: " + e); }
118   }
119 
120   /** Is the argument the EOF object? **/
121   public static boolean isEOF(Object x) { return x == EOF; }
122 
123   Object readTail(boolean dotOK) throws IOException {
124     Object token = nextToken(); 
125     if (token == EOF)
126       return error("EOF during read.");
127     else if (token == ")")
128       return null;
129     else if (token == ".") {
130       Object result = read();
131       token = nextToken(); 
132       if (token != ")") warn("Where's the ')'? Got " +
133            token + " after .");
134       return result;
135     } else {
136       isPushedToken = true;
137       pushedToken = token;
138       return cons(read(), readTail(true));
139     }
140   }
141 
142   Object nextToken() throws IOException {
143     int ch;
144 
145     // See if we should re-use a pushed char or token
146     if (isPushedToken) {
147       isPushedToken = false;
148       return pushedToken;
149     } else if (isPushedChar) {
150       ch = popChar();
151     } else {
152       ch = in_read();
153     }
154 
155     // Skip whitespace
156     while (Character.isWhitespace((char)ch)) ch = in_read();
157 
158     // See what kind of non-white character we got
159     switch(ch) {
160     case -1: return EOF;
161     case '(' : return "(";
162     case ')':  return ")";
163     case '\'': return "'";
164     case '`':  return "`";
165     case ',': 
166       ch = in_read();
167       if (ch == '@') return ",@";
168       else { pushChar(ch); return ","; }
169     case ';': 
170       // Comment: skip to end of line and then read next token
171       while(ch != -1 && ch != '\n' && ch != '\r') ch = in_read();
172       return nextToken();
173     case '"':
174       // Strings are represented as char[]
175       buff.setLength(0);
176       while ((ch = in_read()) != '"' && ch != -1) {
177   buff.append((char) ((ch == '\\') ? in_read() : ch));
178       }
179       if (ch == -1) warn("EOF inside of a string.");
180       return buff.toString().toCharArray(); 
181     case '#':
182       switch (ch = in_read()) {
183       case 't': case 'T': return TRUE;
184       case 'f': case 'F': return FALSE;
185       case '(':
186   pushChar('(');
187   return listToVector(read());
188       case '\\': 
189   ch = in_read();
190   if (ch == 's' || ch == 'S' || ch == 'n' || ch == 'N') {
191     pushChar(ch);
192     Object token = nextToken();
193     if (token == "space") return chr(' ');
194     else if (token == "newline") return chr('\n');
195     else {
196       isPushedToken = true;
197       pushedToken = token;
198       return chr((char)ch);
199     }
200   } else {
201     return chr((char)ch);
202   }
203       case 'e': case 'i': case 'd': return nextToken();
204       case 'b': case 'o': case 'x':
205   warn("#" + ((char)ch) + " not implemented, ignored."); 
206   return nextToken();
207       default: 
208   warn("#" + ((char)ch) + " not recognized, ignored."); 
209   return nextToken();
210       }
211     default: 
212       buff.setLength(0);
213       int c = ch;
214       do { 
215   buff.append((char)ch);
216   ch = in_read();
217       } while (!Character.isWhitespace((char)ch) && ch != -1 &&
218          ch != '(' && ch != ')' && ch != '\'' && ch != ';'
219          && ch != '"' && ch != ',' && ch != '`');
220       pushChar(ch);
221       // Try potential numbers, but catch any format errors.
222       if (c == '.' || c == '+' || c == '-' || (c >= '0' && c <= '9')) {
223   try { return new Double(buff.toString()); }
224   catch (NumberFormatException e) { ; }
225       }
226       return buff.toString().toLowerCase().intern();
227     }
228   }
229 }
230 
231