Language Foundations

Lexical Structure & Layout

See how names, literals, comments, and line breaks form a Topaz source file.

Use this page when a .tpz file looks valid one line at a time, but you are unsure where one item ends or which spellings form a name or literal. Topaz accepts Unicode names and usually treats a completed line as a completed item. Parentheses, brackets, and continuation tokens let an expression continue without adding a special line-continuation character.

Start with a complete source file

Save this as lexical-layout.tpz:

TOPAZ
let ready = true
let archived = false
let missing = null
let 상태 = "ready"

let total =
    40 +
    2

print("{상태}: {ready}, {archived}, {missing}, {total}")

Check and run it:

BASH
topaz check lexical-layout.tpz
topaz run lexical-layout.tpz

The output is:

Output
ready: true, false, null, 42

Across the five bindings, the program shows four literal families: booleans true and false, the absence value null, a string, and decimal numbers. 상태 is an ordinary identifier. Keywords such as let, true, false, and null keep their English spelling, but your own names may use Unicode letters, underscores, numbers after the first character, and emoji.

Read the line breaks from what the parser can see

The first four bindings each finish on one line, so each newline separates one top-level item from the next. The total expression continues because = and then + occur at the end of a line. A trailing operator tells the parser that another operand is still required.

Inside parentheses, brackets, record braces, parameter lists, and other delimiter lists, newlines are spacing rather than item separators. Blocks, match bodies, and concurrent bodies are different: their contents are statement lists, so a completed line may end an item. When a long expression would be ambiguous, wrap it in parentheses instead of relying on indentation. Indentation helps people read the program; delimiter and continuation rules decide its structure.

You want to…Prefer
End a complete top-level item or block statementPut the next item on a new line
Continue arithmetic or a pipelineLeave the operator at the end of the previous line
Break an argument or collection listKeep the items inside its delimiters
Remove any doubt about groupingAdd parentheses

Semicolons are accepted as explicit separators where statements are allowed, but canonical Topaz examples omit them. A newline before else still belongs to the same if or timed concurrent expression.

Names, comments, and strings

An identifier starts with a Unicode letter, _, or emoji and may then include Unicode numbers. The single _ is reserved: it is a wildcard in patterns and a placeholder inside pipeline call arguments, not a value you can read or a name you can bind. Names such as _internal remain ordinary identifiers.

Use // for a line comment and /* ... */ for a block comment. Block comments do not nest. Integer and floating-point literals are decimal; alternate bases and underscore digit separators are not canonical.

Double-quoted strings use escapes such as \n and interpolate with {expression}. Triple-quoted strings are the multiline form. Their closing delimiter fixes the exact spaces-and-tabs prefix removed from every nonblank line. Topaz preserves the Unicode scalar sequence and performs no implicit normalization.

Common correction

Do not move a binary operator to the beginning of a fresh statement-looking line when it could also be read as unary + or -. Keep + or - at the end of the previous line, or add parentheses around the whole expression. Also do not use s[i], s.length, or slice syntax for text. Strings are inspected through s.scalars(); the Strings & Templates page shows that choice.

Token recognition uses the longest valid spelling. This is why ..., .., ..<, ?., and postfix ? remain distinct. Single-quoted strings, character literals, nested block comments, string slicing, grapheme-cluster APIs, and implicit Unicode normalization are not part of the current surface.

Continue with Operators & Expressions for value-producing expressions and Types for annotations and inference. Use Forbidden & Deferred Forms when a familiar spelling is rejected.