Internal documentation — Work in progress
This page has not been confirmed as accurate or approved for publication. Current documentation version: 0.1.0-internal.1.
Expressions
The tokenizer recognizes identifiers, literals, grouping and collection
delimiters, member access, safe access ?., calls, spread ..., assignment
with value :=, =>, comparisons, arithmetic, logical words, increment,
decrement, and compound-assignment tokens.
Settled design: ^ means exponentiation; and, or, not, and
! are logical operators; ? ... ; ... is the conditional expression; and
prefix/postfix increment return new/old values respectively.
Provisional design: lambdas and the semantic rules for spread, safe access, dictionary-key hashability, and assignment expressions.
String expressions
Ordinary single- and double-quoted strings, raw strings, and triple-double-quoted multiline strings are parsed as expressions. An interpolated string retains an ordered sequence of decoded text and embedded expression nodes:
let status = "mission ${mission.name}: altitude ${ship.position.altitude}"
let path = r"C:\simulation\${literal_text}"
Interpolation accepts a complete Sagan expression and therefore follows the
same precedence rules as an expression outside a string. ${} is a syntax
error because every interpolation requires an expression. Raw strings never
interpolate; ${literal_text} in the raw example is ordinary text.
Collection expressions
The parser implements four collection forms:
let values = [1, 2, ...additional_values,]
let metadata = {"name": "Voyager", active_key: true, ...defaults,}
let direction = <1.0, 0.0, 0.0,>
let position = (100.0, 200.0, 300.0,)
Arrays and dictionaries may be empty. Dictionary keys accept any expression;
semantic analysis will determine whether a key's type is hashable. Vectors and
coordinates require at least two elements, so <>, <1>, and (1,) are
syntax errors. (value) remains a grouped expression.
Calls and all collection forms permit trailing commas. ...value creates a
spread node; later semantic analysis will validate whether its surrounding call
or collection supports the value being expanded. A spread dictionary entry
does not use a colon.
At the top level of a vector element, > closes the vector. Parentheses make a
greater-than comparison explicit inside a vector, as in
<(left > right), true>. Outside a vector-opening expression position, < and
> retain their comparison meanings.
Implemented precedence
From highest to lowest:
- calls, indexing, member access, safe member access, and postfix
++and--; - right-associative
^; - prefix
++,--,!,not,..., unary+, and unary-; *,/,%;+,-;<,<=,>,>=,is;==,!=;and;or;- right-associative
? ... ; ...; - right-associative
:=.
Exponentiation binds more tightly than unary minus. Chained comparisons are a
syntax error and must be written as separate comparisons joined with and.
Postfix forms chain from left to right. For example,
fleet[index]?.navigator.course(origin).magnitude() first indexes fleet,
safely accesses navigator, accesses and calls course, then accesses and
calls magnitude.
Evaluation order, short-circuit behavior, assignability, overload resolution,
and coercion remain semantic-analysis work.