support multi-line input in REPL

This commit is contained in:
Yuichi Nishiwaki 2013-10-17 20:48:50 +09:00
parent 458ac6b9ab
commit 1a6c8a3cca
3 changed files with 48 additions and 14 deletions

View File

@ -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_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_eval(pic_state *, pic_value, struct pic_env *);
pic_value pic_run(pic_state *, struct pic_proc *, pic_value); pic_value pic_run(pic_state *, struct pic_proc *, pic_value);

View File

@ -31,17 +31,20 @@ test_object_creation(pic_state *pic)
} }
} }
#define CODE_MAX_LENGTH 1024
#define LINE_MAX_LENGTH 256 #define LINE_MAX_LENGTH 256
int int
main() main()
{ {
pic_state *pic; 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; int char_index;
pic_value v; pic_value v;
struct pic_proc *proc; struct pic_proc *proc;
int ai; int ai;
bool r;
pic = pic_open(); pic = pic_open();
@ -52,9 +55,10 @@ main()
ai = pic_gc_arena_preserve(pic); ai = pic_gc_arena_preserve(pic);
while (1) { while (1) {
prompt = code[0] == '\0' ? "> " : "* ";
#if PIC_ENABLE_READLINE #if PIC_ENABLE_READLINE
read_line = readline("> "); read_line = readline(prompt);
if (read_line == NULL) { if (read_line == NULL) {
line[0] = '\0'; line[0] = '\0';
} }
@ -64,7 +68,7 @@ main()
free(read_line); free(read_line);
} }
#else #else
printf("> "); printf(prompt);
char_index = 0; char_index = 0;
while ((last_char = getchar()) != '\n') { while ((last_char = getchar()) != '\n') {
@ -77,8 +81,21 @@ main()
line[char_index] = '\0'; line[char_index] = '\0';
#endif #endif
if (strlen(code) + strlen(line) >= CODE_MAX_LENGTH)
goto overflow;
strcat(code, line);
/* read */ /* 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 #if DEBUG
printf("[read: "); printf("[read: ");
@ -86,11 +103,6 @@ main()
printf("]\n"); printf("]\n");
#endif #endif
if (pic_undef_p(v)) {
pic_gc_arena_restore(pic, ai);
continue;
}
/* eval */ /* eval */
proc = pic_codegen(pic, v, pic->global_env); proc = pic_codegen(pic, v, pic->global_env);
v = pic_run(pic, proc, pic_nil_value()); v = pic_run(pic, proc, pic_nil_value());

View File

@ -9,6 +9,7 @@
struct parser_control { struct parser_control {
pic_state *pic; pic_state *pic;
pic_value value; pic_value value;
bool incomp;
}; };
%} %}
@ -31,12 +32,17 @@ struct parser_control {
program program
: :
{ {
p->value = pic_undef_value(p->pic); p->value = pic_undef_value();
} }
| datum | datum
{ {
p->value = $1; p->value = $1;
} }
| incomplete_datum
{
p->incomp = true;
p->value = pic_undef_value();
}
; ;
datum 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 int
@ -99,12 +117,13 @@ yyerror(struct parser_control *p, const char *msg)
puts(msg); puts(msg);
} }
pic_value bool
pic_parse(pic_state *pic, const char *str) pic_parse(pic_state *pic, const char *str, pic_value *v)
{ {
struct parser_control p; struct parser_control p;
p.pic = pic; p.pic = pic;
p.incomp = false;
yy_scan_string(str); yy_scan_string(str);
yyparse(&p); yyparse(&p);
@ -114,5 +133,8 @@ pic_parse(pic_state *pic, const char *str)
p.value = pic_undef_value(); p.value = pic_undef_value();
} }
return p.value; if (! p.incomp) {
*v = p.value;
}
return ! p.incomp;
} }