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.
This commit is contained in:
Přemysl Eric Janouch 2017-05-25 18:57:01 +02:00
parent 76df28e492
commit 5ae69c1cfc
Signed by: p
GPG Key ID: B715679E3A361BE6
3 changed files with 101 additions and 39 deletions

133
ell.c
View File

@ -343,43 +343,111 @@ lexer_errorf (struct lexer *self, const char *fmt, ...) {
return e; return e;
} }
// --- Parsing ----------------------------------------------------------------- // --- Printing ----------------------------------------------------------------
static void static void print_item_list (struct item *item);
print_string (const char *s) {
putc ('\'', stdout); static bool
for (; *s; s++) print_string_needs_quoting (struct item *s) {
if (*s == '\n') printf ("\\n"); for (size_t i = 0; i < s->len; i++) {
else if (*s == '\\') putc ('\\', stdout); unsigned char c = s->value[i];
else putc (*s, stdout); if (lexer_is_whitespace (c) || lexer_tokens[c]
putc ('\'', stdout); || 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 static void
print_tree (struct item *tree, int level) { print_item (struct item *item) {
// TODO: also re-add syntax sugar if (print_string (item)
for (struct item *iter = tree; iter; iter = iter->next) { || print_block (item)
if (iter != tree) || print_set (item)
printf ("%*s", level, ""); || print_list (item))
if (iter->type == ITEM_STRING) { return;
print_string (iter->value);
} else if (iter->head putchar ('(');
&& iter->head->type == ITEM_STRING print_item_list (item->head);
&& !strcmp (iter->head->value, "list")) { putchar (')');
printf ("["); }
print_tree (iter->head->next, level + 1);
printf ("]"); static void
} else { print_item_list (struct item *item) {
printf ("("); for (; item; item = item->next) {
print_tree (iter->head, level + 1); print_item (item);
printf (")"); if (item->next)
} putchar (' ');
if (iter->next)
printf ("\n");
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // --- Parsing -----------------------------------------------------------------
struct parser { struct parser {
struct lexer lexer; ///< Tokenizer struct lexer lexer; ///< Tokenizer
@ -965,9 +1033,8 @@ defn (fn_print) {
(void) result; (void) result;
for (; args; args = args->next) { for (; args; args = args->next) {
if (args->type != ITEM_STRING) if (args->type != ITEM_STRING)
// TODO: print lists as their parsable representation print_item (args);
return set_error (ctx, "cannot print lists"); else if (fwrite (args->value, 1, args->len, stdout) != args->len)
if (fwrite (args->value, 1, args->len, stdout) != args->len)
return set_error (ctx, "write failed: %s", strerror (errno)); return set_error (ctx, "write failed: %s", strerror (errno));
} }
return true; return true;

View File

@ -38,11 +38,6 @@ main (int argc, char *argv[]) {
parser_init (&parser, buf.s, buf.len - 1); parser_init (&parser, buf.s, buf.len - 1);
const char *e = NULL; const char *e = NULL;
struct item *program = parser_run (&parser, &e); struct item *program = parser_run (&parser, &e);
#ifndef NDEBUG
printf ("\x1b[1m%s\x1b[0m\n", buf.s);
print_tree (program, 0);
printf ("\n\n");
#endif
free (buf.s); free (buf.s);
if (e) { if (e) {
printf ("%s: %s\n", "parse error", e); printf ("%s: %s\n", "parse error", e);

2
repl.c
View File

@ -36,7 +36,7 @@ run (struct context *ctx, struct item *program) {
ctx->error = NULL; ctx->error = NULL;
ctx->memory_failure = false; ctx->memory_failure = false;
} else { } else {
print_tree (result, 0); print_item_list (result);
putchar ('\n'); putchar ('\n');
item_free_list (result); item_free_list (result);
} }