Skip to content
Browse files

The parser can read strings now.

rs_write() can print out strings with escape sequences. Once rs_read()
can handle reading in hex and octal escape sequences (and hex character
literals), I think I'll tag v0.3.
  • Loading branch information...
1 parent 8a0a051 commit b27bbcfae9b775979041dc318b819d2a95137864 @ingramj committed Aug 17, 2011
Showing with 113 additions and 8 deletions.
  1. +3 −1 README
  2. +56 −2 read.c
  3. +0 −4 rescheme.c
  4. +54 −1 write.c
View
4 README
@@ -13,7 +13,7 @@ Compilation and Usage
"CC = gcc", or whatever is appropriate. There are no external dependencies.
So far, ReScheme is just a pretty-printer, and doesn't evaluate expressions.
-Integers, characters, booleans, null, and symbols have been implemented.
+Integers, characters, booleans, null, symbols, and strings have been added.
$ make
$ ./rescheme
@@ -37,6 +37,8 @@ Integers, characters, booleans, null, and symbols have been implemented.
<=>
> ReScheme
rescheme
+ > "Hello, World!"
+ "Hello, World!"
> <Ctrl-D>
$
View
58 read.c
@@ -21,7 +21,7 @@
*/
enum state { ST_START, ST_DECIMAL, ST_HASH, ST_BINARY, ST_OCTAL, ST_HEX,
ST_CHARACTER, ST_CHAR_N, ST_CHAR_S, ST_CHAR_T, ST_SYMBOL,
- ST_END };
+ ST_STRING, ST_ESCAPE, ST_END };
/* More can happen inside a state than just choosing the next state. The input
character can be pushed back so that the next state (or the next call to the
@@ -161,6 +161,9 @@ rs_object rs_read(FILE *in)
BUF_PUSH(&buf, tolower(c));
cur_state = ST_SYMBOL;
break;
+ case '"':
+ cur_state = ST_STRING;
+ break;
default:
rs_fatal("invalid expression");
}
@@ -373,8 +376,59 @@ rs_object rs_read(FILE *in)
cur_state = ST_END;
break;
default:
- rs_fatal("'%c' cannot appear in an identifier", c);
+ if (isgraph(c)) {
+ rs_fatal("'%c' cannot appear in an identifier", c);
+ } else {
+ rs_fatal("'\\x%02x' cannot appear in an identifier", c);
+ }
+ }
+ break;
+
+ case ST_STRING:
+ switch (c) {
+ case '"':
+ obj = rs_string_create(rs_buf_str(&buf));
+ cur_state = ST_END;
+ break;
+ case '\\':
+ cur_state = ST_ESCAPE;
+ break;
+ default:
+ BUF_PUSH(&buf, c);
+ }
+ break;
+
+ case ST_ESCAPE:
+ switch (c) {
+ case 'n':
+ BUF_PUSH(&buf, '\n');
+ break;
+ case 't':
+ BUF_PUSH(&buf, '\t');
+ break;
+ case '"':
+ BUF_PUSH(&buf, '"');
+ break;
+ case '\\':
+ BUF_PUSH(&buf, '\\');
+ break;
+ case 'r':
+ BUF_PUSH(&buf, '\r');
+ break;
+ case 'b':
+ BUF_PUSH(&buf, '\b');
+ break;
+ case 'a':
+ BUF_PUSH(&buf, '\a');
+ break;
+ default:
+ if (isgraph(c)) {
+ rs_fatal("unknown string escape sequence: \\%c", c);
+ } else {
+ rs_fatal("unknown string escape sequence: \\x%02x", c);
+ }
}
+ cur_state = ST_STRING;
break;
default:
View
4 rescheme.c
@@ -7,10 +7,6 @@ int main(void)
rs_gc_init();
rs_object obj;
-
- obj = rs_string_create("Hello, World!\n");
- rs_write(stdout, obj);
-
for (;;) {
printf("> ");
obj = rs_read(stdin);
View
55 write.c
@@ -1,6 +1,10 @@
#include "rescheme.h"
#include <assert.h>
+#include <ctype.h>
+
+
+static int rs_write_string(FILE *out, rs_string *str);
int rs_write(FILE *out, rs_object obj)
@@ -28,9 +32,58 @@ int rs_write(FILE *out, rs_object obj)
} else if (rs_symbol_p(obj)) {
result = fprintf(out, "%s", rs_symbol_cstr(rs_obj_to_symbol(obj)));
} else if (rs_string_p(obj)) {
- result = fprintf(out, "%s", rs_string_cstr(rs_obj_to_string(obj)));
+ result = rs_write_string(out, rs_obj_to_string(obj));
} else {
rs_fatal("illegal object type");
}
return result;
}
+
+
+static int rs_write_string(FILE *out, rs_string *str)
+{
+ assert(rs_string_cstr(str) != NULL);
+
+ const char *cstr = rs_string_cstr(str);
+ int count = 0;
+ fputc('"', out);
+ while (*cstr != '\0') {
+ switch (*cstr) {
+ case '\n':
+ count += fprintf(out, "\\n");
+ break;
+ case '\t':
+ count += fprintf(out, "\\t");
+ break;
+ case '\"':
+ count += fprintf(out, "\\\"");
+ break;
+ case '\\':
+ count += fprintf(out, "\\\\");
+ break;
+ case '\r':
+ count += fprintf(out, "\\r");
+ break;
+ case '\b':
+ count += fprintf(out, "\\b");
+ break;
+ case '\a':
+ count += fprintf(out, "\\a");
+ break;
+ case ' ':
+ fputc(' ', out);
+ count++;
+ break;
+ default:
+ if (isgraph(*cstr)) {
+ fputc(*cstr, out);
+ count++;
+ } else {
+ count += fprintf(out, "\\x%02x", *cstr);
+ }
+ }
+ cstr++;
+ }
+ fputc('"', out);
+ return 2 + count;
+}

0 comments on commit b27bbcf

Please sign in to comment.
Something went wrong with that request. Please try again.