diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-25 18:57:01 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-25 18:57:01 +0200 |
commit | 5ae69c1cfcc05f3dce30a60fcfe38ce6de7a799d (patch) | |
tree | 8c363842c352acb5c606f3f1587cd9b0eebfe633 /ell.c | |
parent | 76df28e492de6b6b11e0777576834a2308fba6c3 (diff) | |
download | ell-5ae69c1cfcc05f3dce30a60fcfe38ce6de7a799d.tar.gz ell-5ae69c1cfcc05f3dce30a60fcfe38ce6de7a799d.tar.xz ell-5ae69c1cfcc05f3dce30a60fcfe38ce6de7a799d.zip |
Finish implementation of printing
Now readds all syntax sugar and quotes strings properly.
Removed automatic line breaking and indenting since it is complicated.
Removed #ifndef since it stopped making any sense.
Diffstat (limited to 'ell.c')
-rw-r--r-- | ell.c | 131 |
1 files changed, 99 insertions, 32 deletions
@@ -343,43 +343,111 @@ lexer_errorf (struct lexer *self, const char *fmt, ...) { return e; } -// --- Parsing ----------------------------------------------------------------- +// --- Printing ---------------------------------------------------------------- + +static void print_item_list (struct item *item); + +static bool +print_string_needs_quoting (struct item *s) { + for (size_t i = 0; i < s->len; i++) { + unsigned char c = s->value[i]; + if (lexer_is_whitespace (c) || lexer_tokens[c] + || c == LEXER_ESCAPE || c < 32) + return true; + } + return s->len == 0; +} + +static bool +print_string (struct item *s) { + if (s->type != ITEM_STRING) + return false; + if (!print_string_needs_quoting (s)) { + printf ("%s", s->value); + return true; + } + + putchar (LEXER_STRING_QUOTE); + for (size_t i = 0; i < s->len; i++) { + unsigned char c = s->value[i]; + if (c < 32) + printf ("\\x%02x", c); + else if (c == LEXER_ESCAPE || c == LEXER_STRING_QUOTE) + printf ("\\%c", c); + else + putchar (c); + } + putchar (LEXER_STRING_QUOTE); + return true; +} + +static bool +print_block (struct item *list) { + if (!list->head || strcmp (list->head->value, "quote") + || !list->head->next || list->head->next->next + || list->head->next->type != ITEM_LIST) + return false; + + list = list->head->next->head; + for (struct item *line = list; line; line = line->next) + if (line->type != ITEM_LIST) + return false; + + putchar ('{'); + for (struct item *line = list; line; line = line->next) { + putchar (' '); + print_item_list (line->head); + putchar (line->next ? ';' : ' '); + } + putchar ('}'); + return true; +} + +static bool +print_set (struct item *list) { + if (!list->head || strcmp (list->head->value, "set") + || !list->head->next || list->head->next->next) + return false; + + putchar ('@'); + print_item_list (list->head->next); + return true; +} + +static bool +print_list (struct item *list) { + if (!list->head || strcmp (list->head->value, "list")) + return false; + + putchar ('['); + print_item_list (list->head->next); + putchar (']'); + return true; +} static void -print_string (const char *s) { - putc ('\'', stdout); - for (; *s; s++) - if (*s == '\n') printf ("\\n"); - else if (*s == '\\') putc ('\\', stdout); - else putc (*s, stdout); - putc ('\'', stdout); +print_item (struct item *item) { + if (print_string (item) + || print_block (item) + || print_set (item) + || print_list (item)) + return; + + putchar ('('); + print_item_list (item->head); + putchar (')'); } static void -print_tree (struct item *tree, int level) { - // TODO: also re-add syntax sugar - for (struct item *iter = tree; iter; iter = iter->next) { - if (iter != tree) - printf ("%*s", level, ""); - if (iter->type == ITEM_STRING) { - print_string (iter->value); - } else if (iter->head - && iter->head->type == ITEM_STRING - && !strcmp (iter->head->value, "list")) { - printf ("["); - print_tree (iter->head->next, level + 1); - printf ("]"); - } else { - printf ("("); - print_tree (iter->head, level + 1); - printf (")"); - } - if (iter->next) - printf ("\n"); +print_item_list (struct item *item) { + for (; item; item = item->next) { + print_item (item); + if (item->next) + putchar (' '); } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// --- Parsing ----------------------------------------------------------------- struct parser { struct lexer lexer; ///< Tokenizer @@ -965,9 +1033,8 @@ defn (fn_print) { (void) result; for (; args; args = args->next) { if (args->type != ITEM_STRING) - // TODO: print lists as their parsable representation - return set_error (ctx, "cannot print lists"); - if (fwrite (args->value, 1, args->len, stdout) != args->len) + print_item (args); + else if (fwrite (args->value, 1, args->len, stdout) != args->len) return set_error (ctx, "write failed: %s", strerror (errno)); } return true; |