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

145
ell.c
View File

@ -343,44 +343,112 @@ lexer_errorf (struct lexer *self, const char *fmt, ...) {
return e;
}
// --- 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_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_item_list (struct item *item) {
for (; item; item = item->next) {
print_item (item);
if (item->next)
putchar (' ');
}
}
// --- Parsing -----------------------------------------------------------------
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);
}
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");
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct parser {
struct lexer lexer; ///< Tokenizer
char *error; ///< Tokenizer error
@ -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;

View File

@ -38,11 +38,6 @@ main (int argc, char *argv[]) {
parser_init (&parser, buf.s, buf.len - 1);
const char *e = NULL;
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);
if (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->memory_failure = false;
} else {
print_tree (result, 0);
print_item_list (result);
putchar ('\n');
item_free_list (result);
}