diff --git a/frontend/cmd/repl.c b/frontend/cmd/repl.c index 54c17e4..7d789aa 100644 --- a/frontend/cmd/repl.c +++ b/frontend/cmd/repl.c @@ -5,13 +5,18 @@ #include #include #include +#include #include -int repl(const b_command *cmd, const b_arglist *args, const b_array *_) +enum { + OPT_LEX_ONLY = 0x1000u, +}; + +static int repl_lex_only() { struct line_ed *ed = line_ed_create(); line_ed_set_flags(ed, LINE_ED_REMOVE_CONTINUATIONS); - + struct ivy_lexer *lex; enum ivy_status status = ivy_lexer_create(&lex); @@ -36,20 +41,6 @@ int repl(const b_command *cmd, const b_arglist *args, const b_array *_) } print_lex_token(tok); -#if 0 - long v = line_ed_readline(ed, buf, sizeof buf); - if (v == -1) { - break; - } - - if (v == 0) { - continue; - } - - buf[strcspn(buf, "\n")] = 0; - - printf("input: '%s'\n", buf); -#endif } ivy_lexer_destroy(lex); @@ -57,6 +48,83 @@ int repl(const b_command *cmd, const b_arglist *args, const b_array *_) return 0; } +static void skip_line(struct ivy_lexer *lex) +{ + while (ivy_lexer_tokens_available(lex)) { + struct ivy_token *tok = ivy_lexer_read(lex); + bool line_end = (tok->t_type == IVY_TOK_LINEFEED); + + ivy_token_destroy(tok); + + if (line_end) { + break; + } + } +} + +static int repl_full() +{ + struct line_ed *ed = line_ed_create(); + line_ed_set_flags(ed, LINE_ED_REMOVE_CONTINUATIONS); + + struct ivy_lexer *lex; + enum ivy_status status = ivy_lexer_create(&lex); + + if (status != IVY_OK) { + line_ed_destroy(ed); + return -1; + } + + ivy_lexer_set_source(lex, &ed->l_line_source); + + struct ivy_parser *parser; + status = ivy_parser_create(&parser); + + if (status != IVY_OK) { + ivy_lexer_destroy(lex); + line_ed_destroy(ed); + return -1; + } + + while (true) { + struct ivy_token *tok = ivy_lexer_read(lex); + status = ivy_lexer_get_status(lex); + if (status == IVY_ERR_EOF) { + break; + } + + if (status != IVY_OK) { + b_err("lex error (%s)", + ivy_status_to_string(ivy_lexer_get_status(lex))); + continue; + } + + status = ivy_parser_push_token(parser, tok); + + if (status != IVY_OK) { + b_err("parse error (%s)", + ivy_status_to_string(status)); + ivy_token_destroy(tok); + skip_line(lex); + continue; + } + } + + ivy_parser_destroy(parser); + ivy_lexer_destroy(lex); + line_ed_destroy(ed); + return 0; +} + +int repl(const b_command *cmd, const b_arglist *args, const b_array *_) +{ + if (b_arglist_get_count(args, OPT_LEX_ONLY, B_COMMAND_INVALID_ID) > 0) { + return repl_lex_only(); + } + + return repl_full(); +} + B_COMMAND(CMD_REPL, CMD_ROOT) { B_COMMAND_NAME("shell"); @@ -64,4 +132,10 @@ B_COMMAND(CMD_REPL, CMD_ROOT) B_COMMAND_DESC("start an interactive Ivy shell."); B_COMMAND_HELP_OPTION(); B_COMMAND_FUNCTION(repl); + + B_COMMAND_OPTION(OPT_LEX_ONLY) { + B_OPTION_LONG_NAME("lex-only"); + B_OPTION_SHORT_NAME('L'); + B_OPTION_DESC("print the lexical tokens generated by the user input."); + } }