summaryrefslogtreecommitdiff
path: root/src/jvm/clojure
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-06-15 22:04:43 +0000
committerRich Hickey <richhickey@gmail.com>2006-06-15 22:04:43 +0000
commit3d54fc288b133949a5f49a078641ca07e7ccf3d0 (patch)
treef1eca839a2d880ed42281075ecdd9a0e2f48cef4 /src/jvm/clojure
parenta6945186568b8265f775e448778255d16daba8db (diff)
reader in sync both platforms, symbols, vars, hostnames, numbers, strings, chars, lists, comments
Diffstat (limited to 'src/jvm/clojure')
-rw-r--r--src/jvm/clojure/lang/LispReader.java128
-rw-r--r--src/jvm/clojure/lang/RT.java43
2 files changed, 147 insertions, 24 deletions
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index a36775c0..ce0d2980 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -10,10 +10,10 @@
package clojure.lang;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
+import java.util.ArrayList;
import java.math.BigInteger;
public class LispReader {
@@ -33,8 +33,11 @@ static Pattern classNamePat = Pattern.compile("([a-zA-Z_][\\w\\.]*)\\.");
static{
macros['"'] = new StringReader();
macros[';'] = new CommentReader();
+macros['('] = new ListReader();
+macros[')'] = new UnmatchedDelimiterReader();
+macros['\\'] = new CharacterReader();
}
-static public Object read(LineNumberingPushbackReader r, boolean eofIsError, Object eofValue, boolean isRecursive)
+static public Object read(PushbackReader r, boolean eofIsError, Object eofValue, boolean isRecursive)
throws Exception {
for (; ;)
@@ -54,7 +57,7 @@ static public Object read(LineNumberingPushbackReader r, boolean eofIsError, Obj
IFn macroFn = getMacro(ch);
if (macroFn != null)
{
- Object ret = macroFn.invoke(r, ch);
+ Object ret = macroFn.invoke(r, (char)ch);
if(RT.suppressRead())
return null;
//no op macros return the reader
@@ -63,16 +66,16 @@ static public Object read(LineNumberingPushbackReader r, boolean eofIsError, Obj
return ret;
}
- String token = readToken(r,ch);
+ String token = readToken(r,(char)ch);
if(RT.suppressRead())
return null;
return interpretToken(token);
}
}
-static private String readToken(LineNumberingPushbackReader r, int initch) throws Exception {
+static private String readToken(PushbackReader r, char initch) throws Exception {
StringBuilder sb = new StringBuilder();
- sb.append((char)initch);
+ sb.append(initch);
for(;;)
{
@@ -166,22 +169,6 @@ static private boolean isMacro(int ch) {
}
-public static void main(String[] args){
- LineNumberingPushbackReader r = new LineNumberingPushbackReader(new InputStreamReader(System.in));
- Object ret = null;
- try{
- for(;;){
- ret = LispReader.read(r, true, null, false);
- System.out.println(ret.getClass().getName());
- System.out.println(ret.toString());
- }
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
-}
-
static class StringReader extends AFn{
public Object invoke(Object reader, Object doublequote) throws Exception {
StringBuilder sb = new StringBuilder();
@@ -219,8 +206,8 @@ static class StringReader extends AFn{
}
return sb.toString();
}
-}
+}
static class CommentReader extends AFn{
public Object invoke(Object reader, Object semicolon) throws Exception {
Reader r = (Reader) reader;
@@ -231,6 +218,99 @@ static class CommentReader extends AFn{
} while (ch != -1 && ch != '\n' && ch != '\r');
return r;
}
+
+}
+static class CharacterReader extends AFn{
+ public Object invoke(Object reader, Object backslash) throws Exception {
+ PushbackReader r = (PushbackReader) reader;
+ int ch = r.read();
+ if(ch == -1)
+ throw new Exception("EOF while reading character");
+ String token = readToken(r,(char)ch);
+ if(token.length() == 1)
+ return token.charAt(0);
+ else if(token.equals("newline"))
+ return '\n';
+ else if(token.equals("space"))
+ return ' ';
+ else if(token.equals("tab"))
+ return '\t';
+ throw new Exception("Unsupported character: \\" + token);
+ }
+
+}
+static class ListReader extends AFn{
+ public Object invoke(Object reader, Object leftparen) throws Exception {
+ PushbackReader r = (PushbackReader) reader;
+ return readDelimitedList(')', r, true);
+ }
+
+}
+static class UnmatchedDelimiterReader extends AFn{
+ public Object invoke(Object reader, Object rightdelim) throws Exception {
+ throw new Exception("Unmatched delimiter: " + rightdelim);
+ }
+
}
+public static ISeq readDelimitedList(char delim, PushbackReader r, boolean isRecursive) throws Exception {
+ ArrayList a = new ArrayList();
+
+ for (; ;)
+ {
+ int ch = r.read();
+
+ while (Character.isWhitespace(ch))
+ ch = r.read();
+
+ if (ch == -1)
+ throw new Exception("EOF while reading");
+
+ if(ch == delim)
+ break;
+
+ IFn macroFn = getMacro(ch);
+ if (macroFn != null)
+ {
+ Object mret = macroFn.invoke(r, (char)ch);
+ //no op macros return the reader
+ if (mret != r)
+ a.add(mret);
+ }
+ else
+ {
+ r.unread(ch);
+
+ Object o = read(r, true, null, isRecursive);
+ if (o != r)
+ a.add(o);
+ }
+ }
+
+ ISeq ret = null;
+ for(int i=a.size()-1;i>=0;--i)
+ ret = RT.cons(a.get(i), ret);
+ return ret;
+}
+
+public static void main(String[] args){
+ LineNumberingPushbackReader r = new LineNumberingPushbackReader(new InputStreamReader(System.in));
+ OutputStreamWriter w = new OutputStreamWriter(System.out);
+ Object ret = null;
+ try{
+ for(;;)
+ {
+ ret = LispReader.read(r, true, null, false);
+ RT.print(ret, w);
+ w.write('\n');
+ w.flush();
+ }
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+}
+
+
}
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index aea8e677..645da926 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -15,6 +15,8 @@ package clojure.lang;
import java.util.Iterator;
import java.io.Reader;
import java.io.PushbackReader;
+import java.io.Writer;
+import java.io.IOException;
public class RT{
@@ -316,6 +318,47 @@ static public boolean suppressRead(){
return false;
}
+static public void print(Object x, Writer w) throws Exception {
+ //todo - make extensible
+ if(x == null)
+ w.write("null");
+ else if(x instanceof ISeq)
+ {
+ w.write('(');
+ for(ISeq s = (ISeq)x;s != null;s = s.rest())
+ {
+ print(s.first(), w);
+ if(s.rest()!=null)
+ w.write(' ');
+ }
+ w.write(')');
+ }
+ else if(x instanceof String)
+ {
+ w.write('"');
+ w.write(x.toString());
+ w.write('"');
+ }
+ else if(x instanceof Character)
+ {
+ w.write('\\');
+ char c = ((Character)x).charValue();
+ switch(c){
+ case '\n':
+ w.write("newline");
+ break;
+ case '\t':
+ w.write("tab");
+ break;
+ case ' ':
+ w.write("space");
+ break;
+ default:
+ w.write(c);
+ }
+ }
+ else w.write(x.toString());
+}
///////////////////////////////// values //////////////////////////
static public Object setValues(Object... vals)