Module

Tramaj.Parser

Package
purescript-tramaj-purs
Repository
lucasdicioccio/purescript-tramaj-purs

Surface syntax to core AST. Everything the surface offers beyond Tramaj.Ast's constructors is desugared here rather than represented:

  • @name=expr binding lines become nested Lets;
  • string interpolation becomes Concat over the str builtin;
  • branch(fallback, p1, v1, ...) becomes nested Branch;
  • object shorthand {foo} becomes {"foo": $foo};
  • ?shape(key, shape) becomes a Let of its key and the shape, each ~name marker in it an Alloc at the form's one site;
  • escape sequences are resolved into the StringLit they denote.

The grammar keeps three leader characters from v1: . introduces a document, $ reads a binding, @ defines one. What changed is that there is now a single expression grammar — v1's separate template-phase productions (node, nodeArg, childArg, templateSpecialForm, pathOrCallChild) are gone, because documents are expressions.

A fourth character is lexical rather than grammatical: -- begins a comment that runs to the end of the line. It is discarded by skipSpaces along with whitespace, so it never reaches the AST and there is nothing to desugar.

Two conventions are load-bearing and carried over deliberately:

  • A special form's try covers name recognition only. Once import or map has matched, its shape is parsed without backtracking, so a malformed one is a hard parse error instead of silently falling through to a meaningless Call that would only fail much later at eval time. The same holds for every form, not only the special ones: a try covers what tells a form from its alternatives (name(, key:, (params) =>) and never the form's body. A try around a body throws away the error inside it, and the program is then reported as wrong at wherever the outermost alternative started — line 1, column 1 for an unclosed bracket anywhere in a document. Each closer also names its opener and where it is (closing).
  • A field-access suffix is parsed with no whitespace skipped before it, so f().rendered is a field access while f() followed by a newline and .div(...) is two separate things.

Kept in lockstep with ../tramaj-hs/src/Tramaj/Parser.hs.

#parseProgram Source

parseProgram :: String -> Either ParseError Program

A program is a sequence of statements and a root expression. Which kind of program it is follows from the root's own form — a document root is exactly one written as a document — so there is no mode to declare and no separate entry point to pick.