HNHacker News
TopNewBestAskShowJobs

djedr

191 karma · joined January 2, 2017

https://djedr.github.io
submissionscomments
djedr··on Elements of a great markup language
I was talking about is making up a new markup language, which doesn't have to inherit the distinctions and behaviors of HTML.

If, in this language, you wanted to have this feature in combination with what I proposed, you could simply mark the attribute-like children, to inform the engine that it should apply different defaults for them and unmarked children that it doesn't recognize.

This is what I do in the first variant of my language:

  a [
    href=[...]
    [...]
  ]
the `=` appended to `href` marks it as an attribute.

This certainly simplifies things when translating to HTML.

But if we were not constrained by the legacy of HTML then perhaps bothering with this when designing a new language would be unnecessary. Maybe not having this default behavior does not matter in practice and you can have a simpler language without it.

To determine whether that's the case it would help to answer: when is the feature you described useful in HTML? And also: when is this feature harmful?

djedr··on Elements of a great markup language
Surely you mean S-expressions. They're great, but not as a markup language.

What I show here is in fact even simpler and more flexible than S-exps[0].

[0] For some details and polemic see this thread: https://news.ycombinator.com/item?id=33334789 | TL;DR: Jevko is well-defined, basically just unicode text + escapeable brackets for making trees; it doesn't treat whitespace as a separator/atmosphere (particularly important in markup); it takes advantage of natural name-value pairing tendencies (like tag-children); and it's closed under concatenation by design

djedr··on Elements of a great markup language
> More or less, what I want from markup is to convert a text string into a document tree:

  enum Element {
    Text(String),
    Node {
      tag: String,
      attributes: Map<String, String>
      children: Vec<Element>,
    }
  }

  fn parse_markup(input: &str) -> Element { ... }
> Markup language which nails this perfectly is HTML.

The reason HTML nails it perfectly is because this is modeled after HTML.

If I were to make up a markup language, I wouldn't follow that model.

In particular I would get rid of attributes which to me are a restricted kind of children with a specialized syntax.

This is both unnecessary and undesirable in many cases.

The major problem with attributes is the <String, String> mapping. Once something is defined to be an attribute, it cannot be sensibly extended without creating an unnecessary problem.

For example the `class` attribute in HTML looks like it was originally designed to hold a single class name. Then people realized that it would be desirable to have multiple classes per element.

So, to keep things backwards-compatible, the value of the attribute was extended to hold a space-separated list of classes instead. Essentially creating a little DSL inside of the attribute's value.

If `class` was instead a kind of child, initially limited to a single instance per element, extending to multiple instances in a backward-compatible manner would not require introducing the DSL. It would be natural. Just allow many `class` children.

A valid argument in HTML in favor of attributes is conciseness. But that's an artifact of the syntax.

We could make up a language with syntax for nodes as concise as HTML attributes, eliminating that argument.

> It feels like there’s a smaller, simpler language somewhere

Certainly.

I have experimented with many different designs for such a markup language on top of Jevko[0]. One interesting design that trivially maps to HTML looks like this:

  h1 [Title]

  p [
    paragraph
  ]

  p [
    [paragraph with a ]
    a [
      href=[...]
      [link]
    ]
  ]
Another one looks like this:

  [h1][Title]

  [p][paragraph]

  [p][
    paragraph with a
    [href[...] a][link]
  ]
Both are extremely simple and minimal, but also extensible and lend themselves to writing by hand.

[0] https://news.ycombinator.com/item?id=33287620

djedr··on Jevko: a minimal general-purpose syntax
If this standard is abstract/modular enough then it should be easy to use/adapt it for use with Jevko. A Jevko-based markup format combined with that would then be similar to XML+XDM, albeit much more minimal.

This would be in line with how Jevko is intended to be used.

djedr··on Jevko: a minimal general-purpose syntax
Thank you for your feedback. Can you clarify?

What is the "first page" that you are referring to?

Can you paste a link to it along with the broken examples link?

This Hacker News submission features the blog post under this URL:

https://djedr.github.io/posts/jevko-2022-02-22.html

Clearly, you are not talking about this page, as that contains multiple links rather than a singular link.

Perhaps you are talking about the specification which is here:

https://github.com/jevko/specifications/blob/master/spec-sta...

(linked from the blog post)

and here:

https://jevko.org/spec.html

(linked from jevko.org)

All three link to Jevko examples here:

https://github.com/jevko/examples

but all these examples links seem to be correct on my end.

I agree about the importance of examples, and I try to lead with them on jevko.org and jevko.github.io (which are the front pages of Jevko -- possibly I should merge them into one).

However a formal specification is not necessarily the place to put the leading examples.

This is also where the Subjevko rule is defined. It isn't quite introduced as "known knowledge" -- the purpose of a specification is to define the unknown, more or less from the ground up. This is also why specifications tend to get a little abstract. Jevko's spec is no exception. This should be in line with expectations of authors of tools such as parsers, validators, generators, or other kinds of processors, for which the spec is the authoritative reference.

It is not necessarily the best first place to look for explanation, if you are approaching from a more casual side.

I agree that from that side a clear picture of what Jevko is and how it can be used is still lacking. I certainly should add more examples and explain the concepts with analogies.

So I appreciate the essence of your advice and hope I'll manage to improve on that.

djedr··on Jevko: a minimal general-purpose syntax
If you ever publish the project, send me a gmail at darius.j.chuck

I'd love to feature it here: https://github.com/jevko/community

djedr··on Jevko: a minimal general-purpose syntax
Thanks! I put it here: https://github.com/jevko/community

Cheerio

djedr··on Jevko: a minimal general-purpose syntax
> I don't think your revision of the "S-expression" grammar is in accordance with the normal use of the term; it says ()() is an S-expression, when conventionally it's considered to be two of them. If that's what you want, then adding the outer *() is fine, but you should probably drop the leading * on the recursive call *ex, because otherwise the grammar is ambiguous.

You're totally right, sorry! It's an important aspect of S-exps that I overlooked. I forgot that a typical Lisp file is not a valid S-expression, but a concatenation of a bunch of them. Plus maybe some whitespace/comments prepended.

So an S-expression syntax, as normally defined, is not closed under concatenation like Jevko.

To solve that (assuming it's a desirable feature as I do) purely syntactically, without talking about the REPL, you'd need another top-level syntax.

So why not simplify things and make one that meets this criterion by itself?

Which makes me think of another aspect where Jevko is simpler.

The restrictions Jevko puts on a unicode sequence are that the escape character must be followed by itself or a square bracket and that unescaped square brackets must be balanced.

This is pretty much an exhaustive one-sentence description that would allow you to validate or generate a Jevko.

A similarly simple description is impossible to state for S-expressions.

I tried and I came up with (for your minimal defnition of S-exp):

The restrictions S-expr puts on a unicode sequence are that it must conform to one of three alternatives:

* it must be wrapped in parens (list),

* it must be wrapped in quotes (string),

* it must not include whitespace or parens (symbol).

Also:

* If it's a list then different parts of the sequence may conform to one of these three alternatives.

* If it's a string then anything goes, provided that quote is escaped.

I don't think this is exhaustive and certainly not as clear and simple as the Jevko version. Can you come up with a simpler description?

> If you want to allow binary strings you'd probably want to define the language over bytes rather than Unicode code points, though Markus Kuhn's UTF-8B (implemented in Python as "surrogateescape") can give you the best of both worlds.

Yeah, I don't know why I thought your syntax allows binary strings. Clearly, I was confused.

Thanks for the reference, saved.

> Yes, I agree that "S-expression" is rather vague, much like "CSV".

This is an issue I want to avoid with Jevko.

The best syntax in this regard is JSON, with a relatively clear and concise specification. It does have some holes which cause problems, but I don't know anything better.

I'd like Jevko to be better.

> If you disallow having anything other than whitespace in a Jevko with >0 children, Jevko becomes a rose-tree notation, except that the root is unlabeled, so really it's more like a rose-forest notation.

Yes, depending on how you define these terms.

Important thing to note here again is that in accordance with how I intend Jevko to be used, you wouldn't be changing Jevko itself, but defining a format on top of Jevko[0].

The input of the parser/processor for this format is a Jevko syntax tree.

The output would be a rose tree. A nonblank suffix would be a (syntax) error in this format.

> If you want a rose-forest notation, you can get it in a less irregular way by declaring that Jevko infers an extra [] following a suffix containing any non-whitespace character, so foo[bar] is equivalent to foo[bar[]], foo[bar[]baz] is equivalent to foo[bar[]baz[]], and a[b]c is equivalent to a[b[]]c[], but foo[bar[] ] is equivalent to foo[bar[]] and not foo[bar[][]].

> This change would foreclose the possibility of having significant leading or trailing whitespace in some places but not others, the way I was suggesting.

Sure, you could also define a format that works like this.

Input a Jevko tree and output another tree with these extra subtrees "inferred".

The point is that you don't modify Jevko, but use it as a building block.

> Rose trees or rose forests are definitely simpler than Jevko's current data model, and they are equally powerful.

I think defining Jevko in terms of rose trees wouldn't be as straightforward as the inverse, so I disagree. But I wouldn't want to argue about this. I say go with whatever is simpler/more powerful/works for you.

> With respect to diagrams, git clone http://canonical.org/~kragen/sw/pavnotes2.git and look at {horse,johnsmith,player}.{jpg,jevko,dot}.

This is wonderful! I love it!

Thank you for putting it in the public domain.

I'd like to put this somewhere on a Jevko-related page(s), giving credit to you, linking to http://canonical.org/~kragen/.

If you prefer a different way of attribution or none at all, please let me know here or send me a gmail at darius.j.chuck

> For the diagrams I've taken the liberty of ignoring leading and trailing whitespace on arc labels (prefixes), as well as suffixes consisting only of whitespace. johnsmith and horse are your examples, but they just use Jevko as a terser syntax for JSON that suffers a whitespace problem.

Makes sense. Trimming whitespace is what is usually wanted, except in markup formats.

Perhaps it would be sensible to devise a very thin format on top of Jevko for making diagrams of this kind. It would take care of the trimming and have explicitly attached the semantics you mentioned before as proposed a tagline for Jevko:

> A minimal Unicode syntax for ordered trees with labeled nodes and labeled arcs.

It could be used as a tagline for this format!

Did you generate these diagrams from Jevko or write them by hand?

A tool to autogenerate diagrams from this format could be a good application for it.

Anyway, just throwing out ideas. Now to implement them...

> player.jevko is an example I cooked up based on Minetest's relational database schema, recast as a hierarchical schema. It also takes advantage of the ordered nature of subJevkos, the possibility of multiple identical prefixes in the same parent node, and the possibility of having both "headers" (subJevkos) and a "body" (suffix) in the same node.

That's a really nice use of suffixes!

This is really awesome work, thanks for caring and putting in the time. I'd love to see more stuff like this, people making use of Jevko. That's what it's made for!

Cheers!

[0] Another important thing to state, which I suspect may be causing some confusion in our discussion is that Jevko by design has no semantics at all. You attach the semantics on the format layer above Jevko.

djedr··on Jevko: a minimal general-purpose syntax
I suppose there is a bit of confusion.

User23> For example, a Common Lisp hosted Jevko parser implementation might choose to represent Jevko text objects as symbols.

This is right.

gnulinux> These are not strings. These are symbols.

This might be confusing. @gnulinux seems to be using the word `symbols` loosely here, not in the Lisp sense. I suppose that's unfortunate in this context.

What may be adding to the confusion is that Jevko spec also talks about Symbols, which are still a different thing.

So the word symbol is much too overloaded here. Let's forget about for the sake of trying to solve this thread once and for all.

The comment that started it was:

Nullabillity> I wish we could stop making up new languages in 2022 that use unenclosed strings...

And then people were trying to explain how there are no strings in Jevko.

Indeed, Jevko the syntax (Jevko is not a language) does not involve anything named string.

It does involve a rule named Text. When parsing a sequence of unicode code points, a specific parser implementation may choose to store a fragment of the sequence that conforms to this rule using a specialized object or a data structure to explicitly represent also the subfragments that conform to rules that Text is defined in terms of. But it may also choose to use a string type.

`jevkoToHtml`[0] relies on an implementation that stores the Text fragments as JS strings.

Thus:

> It's operating on a nested list of strings, whereby it's making a semantic decision whether a string in a certain position of a nested item in the structure ends in the = character.

That "nested list of strings" (not exactly an accurate description) is the syntax tree.

Those strings represent the Text fragments. This is a very convenient implementation, because most of the time we don't want to go lower than that. If we do, Symbols and Digraphs are still easily accessible and identifiable in this representation. They are just not explicitly reified.

So looking whether there is a `=` character in the string is the same as looking whether there is a `=` Character in the Text.

This happens as part of the second pass of parsing I was talking about above.

This pass does not result in any discernible intermediate representation -- it just directly guides the process of constructing an HTML string[1].

This mental model is the best for understanding this code, because it's essentially the one used to create it.

There is no intention anywhere to lie or insult the semantics or philosophy of Lisp in there, trust me.

I'm telling you this as the author of both the specification and the code.

Ultimately, you can understand this any way you like. If thinking about this as strings or numbers or whatever works for you, great!

A common mental model and agreed upon language is useful to achieve productive results in collaboration. If that's not the goal, then it's not necessary.

Anyway, thank you for looking into the specification and taking the time to understand it. Have a good night!

[0] Have in mind that these 14 lines of JS were not really written to be examined in this detail or to present the best way to do something. I just needed a quick sketch to try out an idea. It's not for use in production or lectures on parsing. :D

[1] Which is not nice, but [0]

djedr··on Jevko: a minimal general-purpose syntax
This analysis would be valid if we were talking about lambda calculus or a Lisp with square brackets.

Jevko isn't that. It's not a programming language[0]. It's just syntax, with even less semantics than JSON and even simpler than S-expressions.

There are no symbols or references in Jevko.

It's important here to separate syntax and semantics. S-expressions are not Lisp. They are its syntax. Semantics is a separate matter.

@gnulinux and @User23 have it right.

Strings are an implementation detail. You could store the parsed text as numbers or you could Gödel-encode the entire tree into one giant number.

Saying then that Jevko is nothing but numbers is conflating things.

---

Just to clarify, in Jevko `[b b]` doesn't parse to what your description implies you think it does. `b[b]` or `[[b][b]]` would be closer to that. If you are interested in the details, please have a look at the specification or diagrams:

* https://jevko.org/spec.html

* https://jevko.org/diagram.xhtml

From there you should be able to easily write a parser in your favorite Lisp! ;)

---

> can you explain what

  mid.endsWith('=')? "attr": "tag"
> is doing? It sure looks to me like it's asking whether a symbol (i.e. indivisible atom) ends with an equal sign, which is semantic gibberish.

There are no symbols or indivisible atoms here.

What's happening here is parsing. `jevkoToHtml` is a kind of parser-transpiler which operates on a syntax tree, rather than a sequence of characters or tokens.

The syntax tree is the output of an earlier stage of parsing, done by the Jevko parser.

So you can think of this as multi-pass parsing, by analogy with multi-pass compilation.

At the same time as this second pass of parsing is happening, translation to HTML is happening as well.

Hope this clarifies things!

---

[0] To clearly see the point, here is a toy programming language which uses Jevko as its syntax: https://github.com/jevko/jevkalk

djedr··on Jevko: a minimal general-purpose syntax
Would you mind if I feature this somewhere on a Jevko-related page with attribution to your GitHub user account (or whatever you want)?
djedr··on Jevko: a minimal general-purpose syntax
Responding to some points I left off here https://news.ycombinator.com/item?id=33336789

I guess the main one is this:

> If your audience is people like me, I think it would probably be worthwhile for you to spend some time up front describing the intended semantics of a data model, as I've attempted above, rather than leaving people to infer it from the grammar. (Maybe OCaml is not a good way to explain it, though.) You might also want to specify that leading and trailing whitespace in prefixes is not significant, though it is in the suffix ("body"); this would enable people to format their name-value pairs readably without corrupting the data. As far as I can tell, this addendum wouldn't interfere with any of your existing uses for Jevko, though in some cases it would simplify their implementations.

You're right, things should be explained more clearly (TODO). Especially the exact role of Jevko and treatment of whitespace. I'll try to improve that.

Here is a sketch of an explanation.

Plain Jevko is meant to be a low-level syntactic layer.

It takes care of turning a unicode sequence into a tree.

On this level, all whitespace is preserved in the tree.

To represent key-value pairs and other data, you most likely want another layer above Jevko -- this would be a Jevko-based format, such as queryjevko (somewhat explained below) or, a very similar one, easyjevko, implemented and very lightly documented here: https://github.com/jevko/easyjevko.js

Or you could have a markup format, such as https://github.com/jevko/markup-experiments#asttoxml5

This format layer defines certain restrictions which may make a subset of Jevkos invalid in it.

It also specifies how to interpret the valid Jevkos. This includes the treatment of whitespace, e.g. that a leading or trailing whitespace in prefixes is insignificant, but conditionally significant in suffixes, etc.

Different formats will define different restrictions and interpretations.

For example:

# queryjevko

queryjevko is a format which uses (a variant of) Jevko as a syntax. Only a subset of Jevko is valid queryjevko.

> I think this is a more useful level of abstraction, and it's more or less the level used by, for example, queryjevko.js's jevkoToJs, although that erroneously uses () instead of [].

The `()` are used on purpose -- queryjevko is meant to be used in URL query strings and be readable. If square brackets were used, things like JS' encodeURIComponent would escape them, making the string unreadable. Using `()` solves that. "~" is used instead of "`" for the same reason. So technically we are dealing not with a spec-compliant Jevko, but a trivial variant of it. Maybe I should write a meta-spec which allows one to pick the three special characters before instantiating itself into a spec. Anyway the parser implementation is configurable in that regard, so I simply configure it to use "~()" instead of "`[]".

> (Also, contrary to your assertion above that this is an example of "leaving [Jevko's data model] as-is", it forgets the order of the name-value pairs as well as I guess all but one of any duplicate set of fields with the same name and also the possibility that there could be both fields and a body.)

I meant [whitespace] rather than [Jevko's data model].

Again, queryjevko is a format which uses Jevko as an underlying syntax. It specifies how syntax trees are converted to JS values, by restricting the range of valid Jevkos. It also specifies conversion in the opposite direction, likewise placing restrictions on JS values that can be safely converted to queryjevko.

The order of name-value pairs happens to get preserved (because of the way JS works), but that's not necessarily relevant. If I were to write a cross-language spec for queryjevko, I'd probably specify that this shouldn't be relied upon.

Duplicate fields and Jevkos with both fields and a non-whitespace body will produce an error when converting Jevko->JS.

I hope this clarifies things somewhat.

Lastly, I'll respond to this for completeness:

> (By the way, if you want to attribute your JSON example for copyright reasons, you need to attribute it to its author or authors, not to the Wikipedia, which is just the site they posted it on.)

According to this:

https://en.wikipedia.org/wiki/Wikipedia:Reusing_Wikipedia_co...

there are 3 options, one of them being what I did, which is to include a link.

I think that's all.

Have a good one!

djedr··on Jevko: a minimal general-purpose syntax
> Thank you for your thought-provoking explorations, for the unwarranted flattery, and for taking the time to respond! Clearly we share an interest in flexible simplicity.

Indeed we do! :)

> As for S-expressions, I agree that what I wrote above is a pretty minimal definition of S-expressions, but I still think it's valid as a definition of "S-expression", even though you'd use a modified definition in some environments. In particular, I think it successfully analyzes the structure of the S-expressions you use as examples. And I agree that it doesn't match the same strings as those modified versions; for example, it doesn't recognize $ as a symbol, or allow '.

For anybody trying to parse your definition:

  ex = ("(" *ex ")" / *%x2a-10ffff / %x22 *(%x22 %x22 / %x0-21 / %x23-10ffff) %x22 ) *%x0-20
it's missing `*()` around the right-hand side:

  ex = *(("(" *ex ")" / *%x2a-10ffff / %x22 *(%x22 %x22 / %x0-21 / %x23-10ffff) %x22 ) *%x0-20)
;P

Other than that it's a indeed lovely minimal definition. And it allows binary strings!

Now if such a definition was accessible as some formal spec and implemented in various languages the way JSON is, I'd probably not be inclined to rolling my own. Or maybe I still would, because it's fun! ;)

> The lexical syntax specified in R⁷RS §7.1.2 is, I think, a lot more complex than S-expressions, and it does not purport to define S-expressions; it includes Unicode, booleans, bytevectors, strings, piped symbols, vectors, circular references, quote, quasiquote, unquote, unquote-splicing, hexadecimal numbers, octal numbers, binary numbers, floating-point numbers, and so on. LISP 1.5 couldn't handle any of these, but I would be very uneasy with the assertion, "LISP 1.5 couldn't read S-expressions."

Sure. So, would you agree that with proliferation of Lisp variants the term "S-expression" became rather vague?

> As an example of a more fleshed-out S-expression language, a few years ago when I wrote Ur-Scheme (a Scheme-subset compiler in the language it compiles), my S-expression parser supported lists (with optional dotted tails), quote, string literals, symbols, comments, signed decimal integers, booleans, and character literals. (Check out the section "Actual Parsing" in http://canonical.org/~kragen/sw/urscheme/compiler.scm.html.) This is evidently enough to conveniently write a compiler in, and I think some of it doesn't really belong to S-expressions per se — quote, comments, and booleans, for example.

Holy moly, this looks very nice! I like the style. Kudos.

> One problem of my suggested data model is that, although the language is closed under concatenation (unlike, say, HTML, XML, JSON, or RFC-822), that concatenation is not semantics-preserving. Given these two Jevko documents:

    x [y] z
    a [b] c
> concatenating them changes the label for [b] from "a" to "z\na", and perhaps more damningly, erases the whitespace before "z". But, since none of the alternative formats (except ndjson and I guess plain uninterpreted binary, ASCII, or Unicode) is closed under concatenation, maybe that's less important.

Yes, being closed under concatenation is a feature I was aiming for and it indeed does bring with it this issue.

Just something to have in mind when devising formats. A simple solution here is to disallow having anything other than whitespace in the suffix of a Jevko with > 0 children. Then, if a format converts these labels to keys in a map, trimming leading and trailing whitespace, there is no problem. This is how I did it here:

* https://github.com/jevko/easyjevko.js

> I don't know if you saw the last time this topic came up I linked to https://ogdl.org/, which seems pretty close to a minimal rose-tree notation.

Yes, I've seen OGDL before. It's pretty nice. A similar one is https://treenotation.org/

I have experimented with indentation-based syntaxes myself, before settling on brackets.

I have found them to be problematic, at least because:

* For complex structures they become less compact.

* A grammar that correctly captures significant indentation can't really be written in pure *BNF. The way OGDL does it is this:

  [12] space(n) ::= char_space*n ; where n is the equivalent number of spaces (can be 0)
  [13] block(n) ::= '\' (comment|break) (space(>n) string break)+
I had the same idea. Simple enough, but still. Brackets are simpler to formalize and implement and not harder to explain.

> They also put some thought into designing a query language for their rose-tree-like data model, which might be adaptable to Jevko — though they label only nodes, and Jevko labels both nodes (with suffixes) and arcs (with prefixes).

Yes, that might be interesting to look at, thanks for pointing it out. I have thought about this and came up with some ideas, but haven't decided on anything. I was thinking more along the lines of having the path DSL be simply implemented on top of Jevko, not as a completely separate grammar.

> Maybe that's the subtitle for Jevko? "A minimal Unicode syntax for ordered trees with labeled nodes and labeled arcs." If that's the intended semantics it would be pretty easy to whip up a diagram in Dot to illustrate it.

It's a nice description, but I think a little to detailed and technical to fit into a tagline. Maybe a little explanatory article with the diagram included. Would probably look something like this:

https://github.com/jevko/writing/blob/main/2022-01-10-jevko-...

Although I'd gladly see your take on it. ;)

djedr··on Jevko: a minimal general-purpose syntax
Yes, it has the same spirit of S-expressions and shares the lovely square brackets with Rebol. The major difference is that Jevko is whitespace-agnostic: it has no notion of elements separated with whitespace.

Generally it's a simpler, more low-level thing. It could be used to build a Rebol-like language. You could add whitespace rules on that level.

A toy example: https://github.com/jevko/jevkalk

This one does not use whitespace as a separator, allowing spaces in identifiers at the expense of more brackets.

djedr··on Jevko: a minimal general-purpose syntax
Awesome, very happy to hear this!

For a simple higher-level format, have look at Easy Jevko:

* https://github.com/jevko/easyjevko.lua – implementation in Lua

* https://github.com/jevko/easyjevko.js – implementation in JS

A way to complicate it is to add a schema like: https://github.com/jevko/interjevko.js

A lousy demo of that (with syntax coloring!) is here: https://jevko.github.io/interjevko.bundle.html

I hope to work out simple specs for these formats eventually.

djedr··on Jevko: a minimal general-purpose syntax
By all means! If you run into any trouble let me know.

Some tips and useful links are here: https://lobste.rs/s/xm6mm4/jevko_minimal_general_purpose_syn...

Thanks for the interest! :)

djedr··on Jevko: a minimal general-purpose syntax
Yes, S-expressions come in many flavors, some more minimal than others, some binary. They are all truly wonderful.

The most wonderful to me are the simplest ones, and Jevko grows out of the same spirit as them.

However, it does not attempt to be a new flavor of S-expressions and diverges in ways which to me are worth looking at. I hope it can appeal and be useful not only to minimalist syntax enthusiasts.

BTW Some time ago I've been also experimenting with binary versions of Jevko, certainly with inspiration from both netstrings and Rivest's csexps:

https://github.com/jevko/binary-experiments#asttolengthprefi...

Since then I had some more ideas which I hope to get around to implementing at some point.

djedr··on Jevko: a minimal general-purpose syntax
Plain Jevko is a notch below JSON/XML/S-expr -- it's not really a format, but a syntax that can be leveraged to build a format.

This is where the rules for whitespace would be specified. These can then be taken advantage of by tools to reformat, etc.

The simplest format that I came up with and should specify next that will most likely do what you want is Easy Jevko. For details see this rabbit hole: https://news.ycombinator.com/item?id=33337098

For an alternative minimal syntax which is based around whitespace check out:

* https://ogdl.org/

* https://treenotation.org/

djedr··on Jevko: a minimal general-purpose syntax
This is a valid concern, but on a higher-level.

Jevko leaves whitespace handling not to clients, but to formats built on Jevko which would be the thing the clients typically use (rather than plain Jevko). Such formats of course should be clearly specified, which is something I hope to get around to soon.

I already have a good candidate format for specifying first, which has 2 implementations:

* https://github.com/jevko/easyjevko.js

* https://github.com/jevko/easyjevko.lua

For more details see also:

* https://news.ycombinator.com/item?id=33335181

* https://github.com/jevko/specifications/issues/1

djedr··on Jevko: a minimal general-purpose syntax
I love your comment. Thanks for taking the time to look so deeply into this!

I'll respond to the main points and then expand on the details later.

I'm not sure what the authoritative source on S-expressions is (or even if there is one, which to me is a problem and part of the value proposition here), so I'll take R^7RS[1] as a reference.

If you look at the formal definition there (chapter 7), it's significantly more complex than both Jevko and what you beautifully constructed here.

And indeed, you have just freestyled a simplifed version of S-expressions (impressive!), but this is not the real thing.

If you would keep refactoring it with the constraints I had in mind for Jevko, you'd eventually end up with Jevko.

> though of course the name-value pairing is lost there (because S-expressions lack it).

Indeed, and that's another part of the value proposition of Jevko. The grammar is designed purposefully to take advantage of natural syntactic name-value (prefix-subjevko) pairing tendencies.

Which brings me to the next point.

**

You are absolutely correct that the abbreviated grammar matches the same strings, but doesn't have the same structure.

*The correct grammar is the one in the specification*.

I have shown the condensed version of it to illustrate the point that Jevko is indeed extremely simple. The single line captures all the essential elements and, again, matches the same strings as the full grammar.

This is unlike the similar condensed grammar for S-expressions which you sketched out here. If you would continue, it would get significantly more complex before it matches the same strings.

The OCaml type definition you wrote down should do the job of capturing the structure, although I prefer to name the elements (which may be not-so-convenient, depending on the language, so it's fine).

**

Indeed, I also think that this is an extremely useful data model. Thanks for pointing out the similarity to e-mail messages and other references which I'd love to dig into (please send if you have any links or resources about these databases).

Thanks for all the pointers, I'll take them into account.

And thanks again for your time.

[0] this seems kinda official, but there is no single standard here: https://www.s-expressions.org/standards

[1] https://standards.scheme.org/official/r7rs.pdf

djedr··on Jevko: a minimal general-purpose syntax
Nice find!

Jevko is the evolved version of that (I'm the author).

djedr··on Jevko: a minimal general-purpose syntax
Author here, thanks for posting this.

If anybody has any technical questions or comments, ask away!

djedr··on Jevko: a minimal general-purpose syntax
Thanks for taking the time to look at this. ;)

What you are getting is the plain Jevko parse tree.

The examples explicitly talk about a format built on top of that. See this answer: https://news.ycombinator.com/item?id=33334314

djedr··on Jevko: a minimal general-purpose syntax
> 1. It relies on later stages to do things like convert to native values or remove whitespace. As such an intermediary can't really "understand" the document very well. E.g., if you are using this syntax to express key/value then you can only know the keys if you know the whitespace rules that will be used to interpret the keys.

From the point of view of Jevko, handling whitespace is a higher-level concern. Indeed, you typically will need additional rules to communicate effectively with it.

This is where you should specify a format (which should be standardized) that you use, e.g.:

* https://github.com/jevko/easyjevko.lua

Note: this is just a simple library I wrote recently that does the most straightforward thing imaginable. I haven't yet wrote a spec for the format.

> 2. It reminds me more of XML than S-Expressions. If you are familiar with the ElementTree [1] representation of XML then these parsed examples become more familiar, just a prefix instead of suffix, and no attribute children.

Yes, Jevko has the features of both XML and S-expressions (or neither, depending on how you look). It's supposed to be uniquely suitable for both markup and encoding of data/code in a simple way.

> 3. Connecting whitespace and XML, I suppose this explains why so many XML formats ended up only using attributes for text values, and used tags and children only for nesting. Otherwise interpretation requires understanding how to interpret these mixed documents with unclear whitespace rules. But Jevko doesn't have attributes.

A markup format built on Jevko can have the notion of attributes and rules for whitespace, e.g. see https://news.ycombinator.com/item?id=33334774 -- a nice thing about this particular format is that text nodes are explicitly specified, so you know exactly where your significant whitespace goes.

The nice thing about attributes made with Jevko over XML attributes is that you could naturally make them extensible (which is a pain in XML -- if you want to turn your unstructured string value stored in an attribute into a tree you have a problem).

> 5. I don't see any escaping rules so including literal [] seems... impossible? You can essentially deserialize the parsed value to reintroduce them, but that's weird and awkward, and only works with balanced brackets anyway.

That's not correct. There are only 3 special symbols (delimiters) and they can all be escaped. It's all in the specification.

> 6. No way to embed binary data, or otherwise uninterpreted data. JSON has the same problem. Base64 encoding things is yet another way in which the data is not interpretable by intermediaries.

Indeed, Jevko is not a binary format. Although I've been experimenting with binary equivalents, e.g.:

https://github.com/jevko/binary-experiments

At some point I might go forward with one, but that's not the focus right now.

djedr··on Jevko: a minimal general-purpose syntax
One comparison is here: https://jevko.github.io/compactness.html

To see how it's syntactically simpler than S-exps note that the grammar of Jevko can be condensed into one short line of ABNF:

  Jevko = *("[" Jevko "]" / "`" ("`" / "[" / "]") / %x0-5a / %x5c / %x5e-5f / %x61-10ffff)
The grammar of S-exps on the other hand, I won't quote here, but I assure you it's much more complicated. How much depends on your flavor (Jevko is also simpler in this regard: there is only one flavor, clearly specified).

There is no (intended) ambiguity around whitespace in Jevko: whitespace does not occur explicitly in the grammar. Whitespace characters are just characters. This is the defining feature of the syntax.

For this reason Jevko is more low-level: if you want to treat whitespace in some special way, you have to do that yourself. Although for most use-cases this is very similar and simple, e.g. https://news.ycombinator.com/item?id=33334314

But the point is that you can also leave it as-is, e.g.: https://github.com/jevko/queryjevko.js

or do something else -- it's up to your format.

djedr··on Jevko: a minimal general-purpose syntax
Certainly!

The advantage of a Jevko-based format over the above is that it has the simplicity and elegance parameters (IMO) cranked up to maximum! ;)

Now, for the tool support...

djedr··on Jevko: a minimal general-purpose syntax
Nice find and you understand correctly! ;)

This is one way. I've experimented with many others. Some semi-documented here:

https://github.com/jevko/markup-experiments

Some ways don't need additional level of nesting, but it's a trade-off.

In the end something like the way you linked is my favorite, because it's very simple.

It also gives you explicit control over your text nodes.

Attributes can also be added in many ways, but I think I prefer them simply looking like child nodes, except with `=` appended to attribute name:

  p [class=[sth] [content]]
Technically you can mix attributes and elements this way, but it does no harm.
djedr··on Jevko: a minimal general-purpose syntax
This is correct.

Every time I've written or otherwise dealt with JSON/XML/etc. I wished I was dealing with something simpler, so I created it. If I had Jevko as a full-fledged alternative to JSON or XML, supported by tools, etc., I'd pick Jevko in a heartbeat. I like minimalism. Some people like it too, so perhaps Jevko can serve them well. There are many good reasons.

> But is seems trivial to implement on very low-level, older, less bloated, or less powerful systems.

Indeed, this is THE feature and a realistic application. I hope!

For a naive unrealistic vision that I sketched out some time ago see:

https://github.com/jevko/writing/blob/main/2022-01-13-vision...

djedr··on Jevko: a minimal general-purpose syntax
Indeed, in most of the formats I built on Jevko this is how it works.

To use the nomenclature from the spec, if there are no subjevkos (subtrees) in a jevko (tree), then it is interpreted as a string (which is made from its suffix).

djedr··on Jevko: a minimal general-purpose syntax
Good question!

Jevko itself, defined by the spec, is not the same as a format based on Jevko.

If you use a plain spec-compliant Jevko parser you for this you indeed should have all whitespace included. Although it will look more like this:

  {
    subjevkos: [
      { prefix: "first name ", jevko: { subjevkos: [Array], suffix: "John" } },
      { prefix: "\nlast name ", jevko: { subjevkos: [Array], suffix: "Smith" } },
      { prefix: "\nis alive ", jevko: { subjevkos: [Array], suffix: "true" } },
      { prefix: "\nage ", jevko: { subjevkos: [Array], suffix: "27" } },
      { prefix: "\naddress ", jevko: { subjevkos: [Array], suffix: "\n" } }
    ],
    suffix: ""
  }
Now on top of that you can build a format that specifies what happens to whitespace, etc. Usually you'd want it trimmed if the prefixes mean keys in a map.

The simplest format/library that does just that is this:

* https://github.com/jevko/easyjevko.lua

* https://github.com/jevko/easyjevko.js

That will give you the JSON (or equivalent) that you expect (with autotrimmed keys).

← PreviousPage 2 of 5Next →