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:
parent
76df28e492
commit
5ae69c1cfc
145
ell.c
145
ell.c
|
@ -343,44 +343,112 @@ lexer_errorf (struct lexer *self, const char *fmt, ...) {
|
||||||
return e;
|
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 -----------------------------------------------------------------
|
// --- 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 parser {
|
||||||
struct lexer lexer; ///< Tokenizer
|
struct lexer lexer; ///< Tokenizer
|
||||||
char *error; ///< Tokenizer error
|
char *error; ///< Tokenizer error
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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
2
repl.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue