TPP (Work in Progress)

Frank Mitchell

Posted: 2023-07-12
Last Modified: 2023-07-20
Word Count: 608
Tags: lua programming python ruby

Table of Contents

Until I can spec this out properly, I’ll quote an old post:

TPP stands for either Text Pre-Parser or Template Pre-Parser. The original design derived from the C pre-processor and a simplified Eiffel version. Having encountered StringTemplate, however, I thought of doing a Lua interpretation of that instead. (Maybe with a more readable syntax.)

Preprocessor

Conditionals

Leaving aside operator precedence for a moment, this is the EBNF for all conditional expressions in an ifdef and ifndef

condition ::= SYMBOL
                | condition ( boolop condition )+
                | "!" condition
                | "(" condition ")"

boolop    ::= "&&" | "||"

SYMBOL    ::= [A-Z][A-Z0-9a-z_]*

Directives

define

#define <symbol>

error

#error "<msg>"

undefine

#undefine <symbol>

ifdef

#ifdef <condition>

...

#else

...

#endif [<condition>]

ifndef

#ifndef <condition>

...

#else

...

#endif [<condition>]

include

#include "<path>"

warning

#warning "<msg>"

Template Language

While the Preprocessor simply acts on flags, the Template Language processes a data model to generate HTML, code, or anything else.

It incorporates the commands of the Preprocessor, plus those listed below.

The Data Model

TODO

True and False

TODO

Notably, 0 and 0.0 are treated as true, although NaN is considered false.

Expressions

Ignoring the blurry line between syntax and functions in the Lisp-like expression language, here’s the syntax for expressions:

expr    ::= boolexpr | cntexp | ifexpr | funcall | path | const | "(" expr ")"

const   ::= STRING | INTEGER | NUMBER | "true" | "false" | "null"

boolexp ::= expr boolop expr

boolop  ::= "&&" | "||" | "!"
            | "==" | "!=" | "<" | "<=" | ">" | ">="
            | "??" | "!?"

cntexp  ::= "#" path

ifexpr  ::= boolexpr "?" expr ":" expr

funcall ::= fcnname "(" expr* ")"

fcnname ::= SYMBOL

path    ::= SYMBOL ( ( "." SYMBOL ) | ( "[" expr "]" ) )*

SYMBOL  ::= [A-Za-z][A-Za-z0-9_]*

STRING  ::= "\"" ( [^"]* | "\\"" )* "\""

INTEGER ::= "0" | [+-][1-9][0-9]*

NUMBER  ::= INTEGER ( "." [0-9]* )? ( [eE] [+-]? [0-9]+ )?

VAR     ::= SYMBOL | "_"

WS      ::= ( " " | "\t" )*

Substitutions

${<path>}

TODO

$(<expr>)

TODO

Directives

if

#if <expr>

...

#elseif <expr>

...

#else

...

#endif

TODO

foreach (Array)

#foreach <symbol> <array-expr>

...

#else

...

#endfor

TODO

foreach (Object)

#foreach <var> <var> <object-expr>

...

#else

...

#endfor

TODO

Syntax

and

expr && expr ⇒ Boolean

TODO

count

# array ⇒ Integer

Count the number of elements in an Array.

# object ⇒ Integer

Count the number of keys in an Object.

# string ⇒ Integer

Count the number of characters in an Array or Object.

defined

?? symbol ⇒ Boolean

TODO

?? expr ⇒ Boolean

TODO

eq

expr == expr ⇒ Boolean

TODO

ge

expr >= expr ⇒ Boolean

TODO

gt

expr > expr ⇒ Boolean

TODO

if

boolexpr ? expr1 : expr2

If boolexpr evaluates to true, evaluate and substitute expr1. Otherwise, evaluate and substitute expr2.

le

expr <= expr ⇒ Boolean

TODO

lt

expr < expr ⇒ Boolean

TODO

neq

expr != expr ⇒ Boolean

TODO

not

! expr ⇒ Boolean

TODO

or

expr || expr ⇒ Boolean

TODO

undefined

?! symbol ⇒ Boolean

TODO

?! expr ⇒ Boolean

TODO

Functions

TODO

A future release may allow users to define their own functions. Until then, add function results to the data model and refer to that.

join

join (<str>, <array-or-object>) ⇒ String

Join the elements of an array or object into a single string, separated by the string object.

tojson

tojson (<expr>) ⇒ String

Convert the expression to a JSON string.