summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-23 12:47:31 +0100
committerFelix Perktold <Felix.Perktold@student.uibk.ac.at>2025-12-23 12:47:31 +0100
commit3a9a1921fe7a56cefe6650529a2572e9a8debc98 (patch)
tree8ac1eaa48a50fa0fd21b494a79528b937cdc04d4
parenteaf6f03f1a572798dca70e897895560110703324 (diff)
multiline support in REPL, tab completion for environment (no special forms yet)
-rw-r--r--main.c86
1 files changed, 77 insertions, 9 deletions
diff --git a/main.c b/main.c
index 5a7c893..3f851a8 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
env *global_env = NULL;
-
void eval_file(const char *filename) {
FILE *f = fopen(filename, "r");
if (!f) {
@@ -16,15 +15,63 @@ void eval_file(const char *filename) {
return;
}
+ int parens = 0;
char line[1024];
+ char buffer[4096] = "";
while (fgets(line, sizeof(line), f)) {
if (*line == '\n' || *line == ';') continue; // skip empty lines or comments
- yy_scan_string(line);
- yyparse();
+ for (char *c = line; *c != '\0'; c++) {
+ if (*c == '(') {
+ parens++;
+ } else if (*c == ')') {
+ parens--;
+ }
+ }
+ //append line to buffer
+ strcat(buffer, line);
+ strcat(buffer, "\n");
+ if (parens <= 0) {
+ //if parens are balanced: parse
+ yy_scan_string(buffer);
+ yyparse();
+ //reset buffer
+ buffer[0] = '\0';
+ }
}
fclose(f);
}
+char *env_token_gen(const char *text, int state) {
+ static int len;
+ static env *nth_env;
+ if (state == 0) {
+ nth_env = global_env->next;
+ len = strlen(text);
+ }
+
+ while (nth_env) {
+ const char *cur = nth_env->symbol;
+ nth_env = nth_env->next;
+
+ if (strncmp(cur, text, len) == 0) {
+ return strdup(cur);
+ }
+ }
+
+ return NULL;
+}
+
+/* Dispatch function: called by readline to get all matches */
+char **my_completion(const char *text, int start, int end) {
+ /* Prevent default filename completion */
+ rl_attempted_completion_over = 1;
+ return rl_completion_matches(text, env_token_gen);
+}
+
+void init_readline() {
+ rl_attempted_completion_function = my_completion;
+}
+
int main(int argc, char **argv) {
// init global env
global_env = env_create(NULL);
@@ -46,13 +93,34 @@ int main(int argc, char **argv) {
}
// START REPL
- char* line;
- while ((line = readline("λ> ")) != NULL) {
- if (*line) {
- add_history(line);
+ init_readline();
+
+ int parens = 0;
+ char *line;
+ char buffer[4096] = "";
+ char *prompt = "λ> ";
+ while ((line = readline(prompt)) != NULL) {
+ for (char *c = line; *c != '\0'; c++) {
+ if (*c == '(') {
+ parens++;
+ } else if (*c == ')') {
+ parens--;
+ }
+ }
+ //append line to buffer
+ strcat(buffer, line);
+ if (parens <= 0) {
+ //if parens are balanced parse
+ yy_scan_string(buffer);
+ yyparse();
+ add_history(buffer);
+ //reset buffer and prompt string
+ buffer[0] = '\0';
+ prompt = "λ> ";
+ } else {
+ strcat(buffer, "\n");
+ prompt = " ";
}
- yy_scan_string(line);
- yyparse();
free(line);
}
return 0;