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_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);

View File

@ -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());

View File

@ -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;
}