From 94521a2cf4dfe82bc67a2998013cf6bed7c86869 Mon Sep 17 00:00:00 2001 From: Taylan Kammer Date: Tue, 6 Jan 2026 01:17:18 +0100 Subject: Update reader note and spec/syntax.md. --- notes/250219-reader.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'notes/250219-reader.md') diff --git a/notes/250219-reader.md b/notes/250219-reader.md index de71b4e..503d402 100644 --- a/notes/250219-reader.md +++ b/notes/250219-reader.md @@ -7,6 +7,10 @@ article:* [Symbols are strings are symbols](250210-symbols.html) +*This whole article is me rambling, and the actual implementation of +the parser that I settled on is slightly different from all the ideas +that are wildly explored here. See late addition at the bottom.* + OK but hear me out... What if there were different reader modes, for code and (pure) data? @@ -463,10 +467,57 @@ from the apostrophe if needed.) Also, all those would work without a rune as well, to allow a file to change the meaning of some of the default syntax sugar if desired: - "foo" -> (#string . foo) + "foo" -> (#string . foo) [foo bar] -> (#square foo bar) {foo bar} -> (#braces foo bar) Or something like that. I'm making this all up as I go. + +## Actual implementation + +_2026 January_ + +Just to summarize what I actually ended up implementing in the end: + +- There is only one parser, not separate data and code parsers. + +- It simply desugars `"foo bar"` into `(#QUOTE . |foo bar|)`, i.e., + these expressions are equivalent, and indistinguishable once they + have been parsed into data. (The syntax `|foo bar|` represents a + string literal in its purest form.) Another equivalent expression + would be `'|foo bar|` that also parses into `(#QUOTE . |foo bar|)`. + All three parse into the exact same data in memory. + +- If you want to use Zisp expressions for something like config files + and want to type `"foo bar"` instead of `|foo bar|` but don't want + to deal with `(#QUOTE . |foo bar|)` then just run a decoder on the + data before using it. You'll need to run a decoder on it anyway if + you want to support vectors, mappings, and other such data types in + your config file that don't have a *direct* data representation. + +- The decoder is not implemented yet, but it will be configurable and + may have default configurations for "code" and "data" where the data + configuration would presumably just strip `(#QUOTE . foo)` down to + `foo` just to make `"foo"` and `|foo|` totally equivalent in data + contexts like config files. In the code configuration, it would + decode `(#QUOTE . foo)` into a macro call expression object which, + when evaluated, results in `foo`. + +- If you wanted to have a config file with code snippets in it, and + don't want e.g. `(code (string-append "foo" x))` to be decoded into + `(code (string-append foo x))` thus changing the meaning of the + embedded code, you have two options: + + 1. Make your entire config file be Zisp code written in a DSL. + + 2. Wrap code snippets in one layer of quoting like `'(...)` which + will effectively protect nested uses of `#QUOTE` from the data + decoder, since decoding is a breadth-first operation. + +See here for full documentation of Zisp expressions as implemented: + +- [Informal docs](https://git.tkammer.de/zisp/tree/docs/parser.md) +- [Formal spec](https://git.tkammer.de/zisp/tree/spec/syntax.md) +- [ABNF](https://git.tkammer.de/zisp/tree/spec/syntax.abnf) -- cgit v1.2.3