From 1a6c8a3cca5059576b7fa1d8366b4144f5219176 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 17 Oct 2013 20:48:50 +0900 Subject: [PATCH] support multi-line input in REPL --- include/picrin.h | 2 +- src/main.c | 30 +++++++++++++++++++++--------- src/parse.y | 30 ++++++++++++++++++++++++++---- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/include/picrin.h b/include/picrin.h index a83b1df9..06d08720 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -61,7 +61,7 @@ bool pic_eq_p(pic_state *, pic_value, pic_value); pic_value pic_intern_cstr(pic_state *, const char *); -pic_value pic_parse(pic_state *, const char *); +bool pic_parse(pic_state *, const char *, pic_value *); pic_value pic_eval(pic_state *, pic_value, struct pic_env *); pic_value pic_run(pic_state *, struct pic_proc *, pic_value); diff --git a/src/main.c b/src/main.c index 1e24ed3f..07f3edc3 100644 --- a/src/main.c +++ b/src/main.c @@ -31,17 +31,20 @@ test_object_creation(pic_state *pic) } } +#define CODE_MAX_LENGTH 1024 #define LINE_MAX_LENGTH 256 int main() { pic_state *pic; - char line[LINE_MAX_LENGTH], last_char, *read_line; + char code[CODE_MAX_LENGTH] = "", line[LINE_MAX_LENGTH]; + char last_char, *read_line, *prompt; int char_index; pic_value v; struct pic_proc *proc; int ai; + bool r; pic = pic_open(); @@ -52,9 +55,10 @@ main() ai = pic_gc_arena_preserve(pic); while (1) { + prompt = code[0] == '\0' ? "> " : "* "; #if PIC_ENABLE_READLINE - read_line = readline("> "); + read_line = readline(prompt); if (read_line == NULL) { line[0] = '\0'; } @@ -64,7 +68,7 @@ main() free(read_line); } #else - printf("> "); + printf(prompt); char_index = 0; while ((last_char = getchar()) != '\n') { @@ -77,8 +81,21 @@ main() line[char_index] = '\0'; #endif + if (strlen(code) + strlen(line) >= CODE_MAX_LENGTH) + goto overflow; + strcat(code, line); + /* read */ - v = pic_parse(pic, line); + r = pic_parse(pic, code, &v); + if (! r) { /* wait for more input */ + pic_gc_arena_restore(pic, ai); + continue; + } + code[0] = '\0'; + if (pic_undef_p(v)) { /* parse error */ + pic_gc_arena_restore(pic, ai); + continue; + } #if DEBUG printf("[read: "); @@ -86,11 +103,6 @@ main() printf("]\n"); #endif - if (pic_undef_p(v)) { - pic_gc_arena_restore(pic, ai); - continue; - } - /* eval */ proc = pic_codegen(pic, v, pic->global_env); v = pic_run(pic, proc, pic_nil_value()); diff --git a/src/parse.y b/src/parse.y index 1875d9d2..8c1176d7 100644 --- a/src/parse.y +++ b/src/parse.y @@ -9,6 +9,7 @@ struct parser_control { pic_state *pic; pic_value value; + bool incomp; }; %} @@ -31,12 +32,17 @@ struct parser_control { program : { - p->value = pic_undef_value(p->pic); + p->value = pic_undef_value(); } | datum { p->value = $1; } + | incomplete_datum + { + p->incomp = true; + p->value = pic_undef_value(); + } ; datum @@ -91,6 +97,18 @@ list_data } ; +incomplete_datum + : tLPAREN incomplete_data +; + +incomplete_data + : /* none */ + | datum tDOT + | datum incomplete_datum + | datum tDOT incomplete_datum + | datum incomplete_data +; + %% int @@ -99,12 +117,13 @@ yyerror(struct parser_control *p, const char *msg) puts(msg); } -pic_value -pic_parse(pic_state *pic, const char *str) +bool +pic_parse(pic_state *pic, const char *str, pic_value *v) { struct parser_control p; p.pic = pic; + p.incomp = false; yy_scan_string(str); yyparse(&p); @@ -114,5 +133,8 @@ pic_parse(pic_state *pic, const char *str) p.value = pic_undef_value(); } - return p.value; + if (! p.incomp) { + *v = p.value; + } + return ! p.incomp; }