diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-04-08 15:01:54 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-04-08 15:01:54 +0000 |
commit | 0da93ff9864827b21f9f2050e3826cda52b1fab0 (patch) | |
tree | 40c2ce0da4d4700a7bb1b35f4e7a9be4837b63f3 /src | |
parent | 06ca71ac1978472c9cf740298b517af13b1b45e8 (diff) |
added Unicode escape patch from Toralf Wittner
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 78 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 18 |
2 files changed, 95 insertions, 1 deletions
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 6fda4c9e..ed73d75f 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -198,6 +198,42 @@ static private Object readNumber(PushbackReader r, char initch) throws Exception return n;
}
+static private int readUnicodeChar(String token, int offset, int length, int base) throws Exception {
+ if (token.length() != offset + length)
+ throw new IllegalArgumentException("Invalid unicode character: \\" + token);
+ int uc = 0;
+ for (int i = offset; i < offset + length; ++i)
+ {
+ int d = Character.digit(token.charAt(i), base);
+ if (d == -1)
+ throw new IllegalArgumentException("Invalid digit: " + (char) d);
+ uc = uc * base + d;
+ }
+ return (char) uc;
+}
+
+static private int readUnicodeChar(PushbackReader r, int initch, int base, int length, boolean exact) throws Exception {
+ int uc = Character.digit(initch, base);
+ if(uc == -1)
+ throw new IllegalArgumentException("Invalid digit: " + initch);
+ int i = 1;
+ for(; i < length; ++i)
+ {
+ int ch = r.read();
+ if(ch == -1 || isWhitespace(ch) || isMacro(ch))
+ {
+ unread(r, ch);
+ break;
+ }
+ int d = Character.digit(ch, base);
+ if(d == -1)
+ throw new IllegalArgumentException("Invalid digit: " + (char) ch);
+ uc = uc * base + d;
+ }
+ if(i != length && exact)
+ throw new IllegalArgumentException("Invalid character length: " + i + ", should be: " + length);
+ return uc;
+}
static private Object interpretToken(String s) throws Exception{
if(s.equals("nil"))
@@ -311,8 +347,32 @@ static class StringReader extends AFn{ break;
case '"':
break;
+ case 'b':
+ ch = '\b';
+ break;
+ case 'f':
+ ch = '\f';
+ break;
+ case 'u':
+ {
+ ch = r.read();
+ if (Character.isDigit(ch))
+ ch = readUnicodeChar((PushbackReader) r, ch, 16, 4, true);
+ else
+ throw new Exception("Invalid unicode escape: \\" + (char) ch);
+ break;
+ }
default:
- throw new Exception("Unsupported escape character: \\" + (char) ch);
+ {
+ if (Character.isDigit(ch))
+ {
+ ch = readUnicodeChar((PushbackReader) r, ch, 8, 3, false);
+ if (ch > 0377)
+ throw new Exception("Octal escape sequence must be in range [0, 377].");
+ }
+ else
+ throw new Exception("Unsupported escape character: \\" + (char) ch);
+ }
}
}
sb.append((char) ch);
@@ -653,6 +713,22 @@ static class CharacterReader extends AFn{ return ' ';
else if(token.equals("tab"))
return '\t';
+ else if(token.equals("backspace"))
+ return '\b';
+ else if(token.equals("formfeed"))
+ return '\f';
+ else if (token.startsWith("u"))
+ return (char) readUnicodeChar(token, 1, 4, 16);
+ else if (token.startsWith("o"))
+ {
+ int len = token.length() - 1;
+ if (len > 3)
+ throw new Exception("Invalid octal escape sequence length: " + len);
+ int uc = readUnicodeChar(token, 1, len, 8);
+ if (uc > 0377)
+ throw new Exception("Octal escape sequence must be in range [0, 377].");
+ return (char) uc;
+ }
throw new Exception("Unsupported character: \\" + token);
}
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 02858459..4d3b60dd 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -902,6 +902,12 @@ static public void print(Object x, Writer w) throws Exception{ case '\\': w.write("\\\\"); break; + case '\f': + w.write("\\f"); + break; + case '\b': + w.write("\\b"); + break; default: w.write(c); } @@ -981,6 +987,12 @@ static public void print(Object x, Writer w) throws Exception{ case ' ': w.write("space"); break; + case '\b': + w.write("backspace"); + break; + case '\f': + w.write("formfeed"); + break; default: w.write(c); } @@ -1034,6 +1046,12 @@ static public void formatStandard(Writer w, Object obj) throws IOException{ case ' ': w.write("space"); break; + case '\b': + w.write("backspace"); + break; + case '\f': + w.write("formfeed"); + break; default: w.write(c); } |