00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <assert.h>
00024 #include <ctype.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027
00028 #include "construo_error.hxx"
00029 #include <lispreader.hxx>
00030
00031 #define TOKEN_ERROR -1
00032 #define TOKEN_EOF 0
00033 #define TOKEN_OPEN_PAREN 1
00034 #define TOKEN_CLOSE_PAREN 2
00035 #define TOKEN_SYMBOL 3
00036 #define TOKEN_STRING 4
00037 #define TOKEN_INTEGER 5
00038 #define TOKEN_REAL 6
00039 #define TOKEN_PATTERN_OPEN_PAREN 7
00040 #define TOKEN_DOT 8
00041 #define TOKEN_TRUE 9
00042 #define TOKEN_FALSE 10
00043
00044
00045 #define MAX_TOKEN_LENGTH 1024
00046
00047 static char token_string[MAX_TOKEN_LENGTH + 1] = "";
00048 static int token_length = 0;
00049
00050 static lisp_object_t end_marker = { LISP_TYPE_EOF };
00051 static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR };
00052 static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR };
00053 static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR };
00054
00055 static void
00056 _token_clear (void)
00057 {
00058 token_string[0] = '\0';
00059 token_length = 0;
00060 }
00061
00062 static void
00063 _token_append (char c)
00064 {
00065 assert(token_length < MAX_TOKEN_LENGTH);
00066
00067 token_string[token_length++] = c;
00068 token_string[token_length] = '\0';
00069 }
00070
00071 static int
00072 _next_char (lisp_stream_t *stream)
00073 {
00074 switch (stream->type)
00075 {
00076 case LISP_STREAM_FILE :
00077 return getc(stream->v.file);
00078
00079 case LISP_STREAM_STRING :
00080 {
00081 char c = stream->v.string.buf[stream->v.string.pos];
00082
00083 if (c == 0)
00084 return EOF;
00085
00086 ++stream->v.string.pos;
00087
00088 return c;
00089 }
00090
00091 case LISP_STREAM_ANY:
00092 return stream->v.any.next_char(stream->v.any.data);
00093 }
00094 assert(0);
00095 return EOF;
00096 }
00097
00098 static void
00099 _unget_char (char c, lisp_stream_t *stream)
00100 {
00101 switch (stream->type)
00102 {
00103 case LISP_STREAM_FILE :
00104 ungetc(c, stream->v.file);
00105 break;
00106
00107 case LISP_STREAM_STRING :
00108 --stream->v.string.pos;
00109 break;
00110
00111 case LISP_STREAM_ANY:
00112 stream->v.any.unget_char(c, stream->v.any.data);
00113 break;
00114
00115 default :
00116 assert(0);
00117 }
00118 }
00119
00120 static int
00121 _scan (lisp_stream_t *stream)
00122 {
00123 static char *delims = "\"();";
00124
00125 int c;
00126
00127 _token_clear();
00128
00129 do
00130 {
00131 c = _next_char(stream);
00132 if (c == EOF)
00133 return TOKEN_EOF;
00134 else if (c == ';')
00135 while (1)
00136 {
00137 c = _next_char(stream);
00138 if (c == EOF)
00139 return TOKEN_EOF;
00140 else if (c == '\n')
00141 break;
00142 }
00143 } while (isspace(c));
00144
00145 switch (c)
00146 {
00147 case '(' :
00148 return TOKEN_OPEN_PAREN;
00149
00150 case ')' :
00151 return TOKEN_CLOSE_PAREN;
00152
00153 case '"' :
00154 while (1)
00155 {
00156 c = _next_char(stream);
00157 if (c == EOF)
00158 return TOKEN_ERROR;
00159 if (c == '"')
00160 break;
00161 if (c == '\\')
00162 {
00163 c = _next_char(stream);
00164
00165 switch (c)
00166 {
00167 case EOF :
00168 return TOKEN_ERROR;
00169
00170 case 'n' :
00171 c = '\n';
00172 break;
00173
00174 case 't' :
00175 c = '\t';
00176 break;
00177 }
00178 }
00179
00180 _token_append(c);
00181 }
00182 return TOKEN_STRING;
00183
00184 case '#' :
00185 c = _next_char(stream);
00186 if (c == EOF)
00187 return TOKEN_ERROR;
00188
00189 switch (c)
00190 {
00191 case 't' :
00192 return TOKEN_TRUE;
00193
00194 case 'f' :
00195 return TOKEN_FALSE;
00196
00197 case '?' :
00198 c = _next_char(stream);
00199 if (c == EOF)
00200 return TOKEN_ERROR;
00201
00202 if (c == '(')
00203 return TOKEN_PATTERN_OPEN_PAREN;
00204 else
00205 return TOKEN_ERROR;
00206 }
00207 return TOKEN_ERROR;
00208
00209 default :
00210 if (isdigit(c) || c == '-')
00211 {
00212 int have_nondigits = 0;
00213 int have_digits = 0;
00214 int have_floating_point = 0;
00215
00216 do
00217 {
00218 if (isdigit(c))
00219 have_digits = 1;
00220 else if (c == '.')
00221 have_floating_point++;
00222 _token_append(c);
00223
00224 c = _next_char(stream);
00225
00226 if (c != EOF && !isdigit(c) && !isspace(c) && c != '.' && !strchr(delims, c))
00227 have_nondigits = 1;
00228 } while (c != EOF && !isspace(c) && !strchr(delims, c));
00229
00230 if (c != EOF)
00231 _unget_char(c, stream);
00232
00233 if (have_nondigits || !have_digits || have_floating_point > 1)
00234 return TOKEN_SYMBOL;
00235 else if (have_floating_point == 1)
00236 return TOKEN_REAL;
00237 else
00238 return TOKEN_INTEGER;
00239 }
00240 else
00241 {
00242 if (c == '.')
00243 {
00244 c = _next_char(stream);
00245 if (c != EOF && !isspace(c) && !strchr(delims, c))
00246 _token_append('.');
00247 else
00248 {
00249 _unget_char(c, stream);
00250 return TOKEN_DOT;
00251 }
00252 }
00253 do
00254 {
00255 _token_append(c);
00256 c = _next_char(stream);
00257 } while (c != EOF && !isspace(c) && !strchr(delims, c));
00258 if (c != EOF)
00259 _unget_char(c, stream);
00260
00261 return TOKEN_SYMBOL;
00262 }
00263 }
00264
00265 assert(0);
00266 return TOKEN_ERROR;
00267 }
00268
00269 static lisp_object_t*
00270 lisp_object_alloc (int type)
00271 {
00272 lisp_object_t *obj = (lisp_object_t*)malloc(sizeof(lisp_object_t));
00273
00274 obj->type = type;
00275
00276 return obj;
00277 }
00278
00279 lisp_stream_t*
00280 lisp_stream_init_file (lisp_stream_t *stream, FILE *file)
00281 {
00282 stream->type = LISP_STREAM_FILE;
00283 stream->v.file = file;
00284
00285 return stream;
00286 }
00287
00288 lisp_stream_t*
00289 lisp_stream_init_string (lisp_stream_t *stream, char *buf)
00290 {
00291 stream->type = LISP_STREAM_STRING;
00292 stream->v.string.buf = buf;
00293 stream->v.string.pos = 0;
00294
00295 return stream;
00296 }
00297
00298 lisp_stream_t*
00299 lisp_stream_init_any (lisp_stream_t *stream, void *data,
00300 int (*next_char) (void *data),
00301 void (*unget_char) (char c, void *data))
00302 {
00303 assert(next_char != 0 && unget_char != 0);
00304
00305 stream->type = LISP_STREAM_ANY;
00306 stream->v.any.data = data;
00307 stream->v.any.next_char= next_char;
00308 stream->v.any.unget_char = unget_char;
00309
00310 return stream;
00311 }
00312
00313 lisp_object_t*
00314 lisp_make_integer (int value)
00315 {
00316 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_INTEGER);
00317
00318 obj->v.integer = value;
00319
00320 return obj;
00321 }
00322
00323 lisp_object_t*
00324 lisp_make_real (float value)
00325 {
00326 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_REAL);
00327
00328 obj->v.real = value;
00329
00330 return obj;
00331 }
00332
00333 lisp_object_t*
00334 lisp_make_symbol (const char *value)
00335 {
00336 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_SYMBOL);
00337
00338 obj->v.string = strdup(value);
00339
00340 return obj;
00341 }
00342
00343 lisp_object_t*
00344 lisp_make_string (const char *value)
00345 {
00346 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_STRING);
00347
00348 obj->v.string = strdup(value);
00349
00350 return obj;
00351 }
00352
00353 lisp_object_t*
00354 lisp_make_cons (lisp_object_t *car, lisp_object_t *cdr)
00355 {
00356 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_CONS);
00357
00358 obj->v.cons.car = car;
00359 obj->v.cons.cdr = cdr;
00360
00361 return obj;
00362 }
00363
00364 lisp_object_t*
00365 lisp_make_boolean (int value)
00366 {
00367 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_BOOLEAN);
00368
00369 obj->v.integer = value ? 1 : 0;
00370
00371 return obj;
00372 }
00373
00374 static lisp_object_t*
00375 lisp_make_pattern_cons (lisp_object_t *car, lisp_object_t *cdr)
00376 {
00377 lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_CONS);
00378
00379 obj->v.cons.car = car;
00380 obj->v.cons.cdr = cdr;
00381
00382 return obj;
00383 }
00384
00385 lisp_object_t*
00386 lisp_read (lisp_stream_t *in)
00387 {
00388 int token = _scan(in);
00389 lisp_object_t *obj = lisp_nil();
00390
00391 if (token == TOKEN_EOF)
00392 return &end_marker;
00393
00394 switch (token)
00395 {
00396 case TOKEN_ERROR :
00397 return &error_object;
00398
00399 case TOKEN_EOF :
00400 return &end_marker;
00401
00402 case TOKEN_OPEN_PAREN :
00403 case TOKEN_PATTERN_OPEN_PAREN :
00404 {
00405 lisp_object_t *last = lisp_nil(), *car;
00406
00407 do
00408 {
00409 car = lisp_read(in);
00410 if (car == &error_object || car == &end_marker)
00411 {
00412 lisp_free(obj);
00413 return &error_object;
00414 }
00415 else if (car == &dot_marker)
00416 {
00417 if (lisp_nil_p(last))
00418 {
00419 lisp_free(obj);
00420 return &error_object;
00421 }
00422
00423 car = lisp_read(in);
00424 if (car == &error_object || car == &end_marker)
00425 {
00426 lisp_free(obj);
00427 return car;
00428 }
00429 else
00430 {
00431 last->v.cons.cdr = car;
00432
00433 if (_scan(in) != TOKEN_CLOSE_PAREN)
00434 {
00435 lisp_free(obj);
00436 return &error_object;
00437 }
00438
00439 car = &close_paren_marker;
00440 }
00441 }
00442 else if (car != &close_paren_marker)
00443 {
00444 if (lisp_nil_p(last))
00445 obj = last = (token == TOKEN_OPEN_PAREN ? lisp_make_cons(car, lisp_nil()) : lisp_make_pattern_cons(car, lisp_nil()));
00446 else
00447 last = last->v.cons.cdr = lisp_make_cons(car, lisp_nil());
00448 }
00449 } while (car != &close_paren_marker);
00450 }
00451 return obj;
00452
00453 case TOKEN_CLOSE_PAREN :
00454 return &close_paren_marker;
00455
00456 case TOKEN_SYMBOL :
00457 return lisp_make_symbol(token_string);
00458
00459 case TOKEN_STRING :
00460 return lisp_make_string(token_string);
00461
00462 case TOKEN_INTEGER :
00463 return lisp_make_integer(atoi(token_string));
00464
00465 case TOKEN_REAL :
00466 return lisp_make_real((float)atof(token_string));
00467
00468 case TOKEN_DOT :
00469 return &dot_marker;
00470
00471 case TOKEN_TRUE :
00472 return lisp_make_boolean(1);
00473
00474 case TOKEN_FALSE :
00475 return lisp_make_boolean(0);
00476 }
00477
00478 assert(0);
00479 return &error_object;
00480 }
00481
00482 void
00483 lisp_free (lisp_object_t *obj)
00484 {
00485 if (obj == 0)
00486 return;
00487
00488 switch (obj->type)
00489 {
00490 case LISP_TYPE_INTERNAL :
00491 case LISP_TYPE_PARSE_ERROR :
00492 case LISP_TYPE_EOF :
00493 return;
00494
00495 case LISP_TYPE_SYMBOL :
00496 case LISP_TYPE_STRING :
00497 free(obj->v.string);
00498 break;
00499
00500 case LISP_TYPE_CONS :
00501 case LISP_TYPE_PATTERN_CONS :
00502 lisp_free(obj->v.cons.car);
00503 lisp_free(obj->v.cons.cdr);
00504 break;
00505
00506 case LISP_TYPE_PATTERN_VAR :
00507 lisp_free(obj->v.pattern.sub);
00508 break;
00509 }
00510
00511 free(obj);
00512 }
00513
00514 lisp_object_t*
00515 lisp_read_from_string (const char *buf)
00516 {
00517 lisp_stream_t stream;
00518
00519 lisp_stream_init_string(&stream, (char*)buf);
00520 return lisp_read(&stream);
00521 }
00522
00523 int
00524 lisp_type (lisp_object_t *obj)
00525 {
00526 if (obj == 0)
00527 return LISP_TYPE_NIL;
00528 return obj->type;
00529 }
00530
00531 int
00532 lisp_integer (lisp_object_t *obj)
00533 {
00534 assert(obj->type == LISP_TYPE_INTEGER);
00535
00536 return obj->v.integer;
00537 }
00538
00539 char*
00540 lisp_symbol (lisp_object_t *obj)
00541 {
00542 assert(obj->type == LISP_TYPE_SYMBOL);
00543
00544 return obj->v.string;
00545 }
00546
00547 char*
00548 lisp_string (lisp_object_t *obj)
00549 {
00550 if (obj->type != LISP_TYPE_STRING)
00551 ConstruoError::raise("lispreader Error: obj->type != LISP_TYPE_STRING");
00552
00553 return obj->v.string;
00554 }
00555
00556 int
00557 lisp_boolean (lisp_object_t *obj)
00558 {
00559 assert(obj->type == LISP_TYPE_BOOLEAN);
00560
00561 return obj->v.integer;
00562 }
00563
00564 float
00565 lisp_real (lisp_object_t *obj)
00566 {
00567 assert(obj->type == LISP_TYPE_REAL || obj->type == LISP_TYPE_INTEGER);
00568
00569 if (obj->type == LISP_TYPE_INTEGER)
00570 return obj->v.integer;
00571 return obj->v.real;
00572 }
00573
00574 lisp_object_t*
00575 lisp_car (lisp_object_t *obj)
00576 {
00577 if (!(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS))
00578 ConstruoError::raise("lispreader Error: !(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS)");
00579
00580 return obj->v.cons.car;
00581 }
00582
00583 lisp_object_t*
00584 lisp_cdr (lisp_object_t *obj)
00585 {
00586 assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
00587
00588 return obj->v.cons.cdr;
00589 }
00590
00591 lisp_object_t*
00592 lisp_cxr (lisp_object_t *obj, const char *x)
00593 {
00594 int i;
00595
00596 for (i = strlen(x) - 1; i >= 0; --i)
00597 if (x[i] == 'a')
00598 obj = lisp_car(obj);
00599 else if (x[i] == 'd')
00600 obj = lisp_cdr(obj);
00601 else
00602 assert(0);
00603
00604 return obj;
00605 }
00606
00607 int
00608 lisp_list_length (lisp_object_t *obj)
00609 {
00610 int length = 0;
00611
00612 while (obj != 0)
00613 {
00614 assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
00615
00616 ++length;
00617 obj = obj->v.cons.cdr;
00618 }
00619
00620 return length;
00621 }
00622
00623 lisp_object_t*
00624 lisp_list_nth_cdr (lisp_object_t *obj, int index)
00625 {
00626 while (index > 0)
00627 {
00628 assert(obj != 0);
00629 assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS);
00630
00631 --index;
00632 obj = obj->v.cons.cdr;
00633 }
00634
00635 return obj;
00636 }
00637
00638 lisp_object_t*
00639 lisp_list_nth (lisp_object_t *obj, int index)
00640 {
00641 obj = lisp_list_nth_cdr(obj, index);
00642
00643 assert(obj != 0);
00644
00645 return obj->v.cons.car;
00646 }
00647
00648 void
00649 lisp_dump (lisp_object_t *obj, FILE *out)
00650 {
00651 if (obj == 0)
00652 {
00653 fprintf(out, "()");
00654 return;
00655 }
00656
00657 switch (lisp_type(obj))
00658 {
00659 case LISP_TYPE_EOF :
00660 fputs("#<eof>", out);
00661 break;
00662
00663 case LISP_TYPE_PARSE_ERROR :
00664 fputs("#<error>", out);
00665 break;
00666
00667 case LISP_TYPE_INTEGER :
00668 fprintf(out, "%d", lisp_integer(obj));
00669 break;
00670
00671 case LISP_TYPE_REAL :
00672 fprintf(out, "%f", lisp_real(obj));
00673 break;
00674
00675 case LISP_TYPE_SYMBOL :
00676 fputs(lisp_symbol(obj), out);
00677 break;
00678
00679 case LISP_TYPE_STRING :
00680 {
00681 char *p;
00682
00683 fputc('"', out);
00684 for (p = lisp_string(obj); *p != 0; ++p)
00685 {
00686 if (*p == '"' || *p == '\\')
00687 fputc('\\', out);
00688 fputc(*p, out);
00689 }
00690 fputc('"', out);
00691 }
00692 break;
00693
00694 case LISP_TYPE_CONS :
00695 case LISP_TYPE_PATTERN_CONS :
00696 fputs(lisp_type(obj) == LISP_TYPE_CONS ? "(" : "#?(", out);
00697 while (obj != 0)
00698 {
00699 lisp_dump(lisp_car(obj), out);
00700 obj = lisp_cdr(obj);
00701 if (obj != 0)
00702 {
00703 if (lisp_type(obj) != LISP_TYPE_CONS
00704 && lisp_type(obj) != LISP_TYPE_PATTERN_CONS)
00705 {
00706 fputs(" . ", out);
00707 lisp_dump(obj, out);
00708 break;
00709 }
00710 else
00711 fputc(' ', out);
00712 }
00713 }
00714 fputc(')', out);
00715 break;
00716
00717 case LISP_TYPE_BOOLEAN :
00718 if (lisp_boolean(obj))
00719 fputs("#t", out);
00720 else
00721 fputs("#f", out);
00722 break;
00723
00724 default :
00725 assert(0);
00726 }
00727 }