Lexical structure
A statement ends at the end of its line, a name is ASCII while text is not, a block comment ends at its first `*/`, three keywords are never reserved, and a member may be named after a reserved one.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Every .trb file is built from the same small set of tokens: two comment forms and a doc comment, a statement that ends
at the end of its line, and a fixed list of reserved keywords. This page is the mechanics a reader needs before any
construct, because it decides where one statement stops and the next begins.
Example#
/** Moves a point along one axis. */
fn move(from: Int, to: Int): Int {
to - from
}
// The total distance moved so far.
var total = 0
/* Block comment: it ends at the first star-slash. */
total = total +
1
print "moved {move(from: 3, to: 10)}, total {total}"Syntax#
// text a line comment, to the end of the line
/* text */ a block comment; ends at the first `*/`, does not nest
/** text */ a doc comment; belongs to the declaration written directly after itRules#
A statement ends at the end of its line. There are no semicolons.
Kompiliert nichtconst total = 1; // error: There are no semicolons. A statement ends at the end of its lineA statement continues onto the next line under two conditions. The current line ends with a binary operator, a comma or an open bracket, or the next line starts with
.,?., a binary operator,withorwhere. Thetotal = total +example above continues onto its next line for the first reason.A block comment ends at its first
*/and does not nest. Text that looks like a nested comment ends the outer one, and whatever follows is read as code.Kompiliert nicht/* outer /* inner */ still here */ // error: Cannot find `still` here // error: Expected an expression, found `/` // error: Expected an expression, found the end of the fileA doc comment belongs to the declaration written directly after it. Everything that can be declared can have one - a function, a field, a parameter, a case. See Doc comments.
A fixed list of words is reserved, and four words never are.
const,var,fn,type,trait,extend,foreign,case,use,public,private,native,shared,lazy,if,else,match,for,in,while,break,continue,return,true,false,void,self,Self,withandwhereare reserved.from,as,byandprotectedare contextual: the lexer reads them as ordinary names everywhere, which is whatuse Name from "./module",type Seconds with Compare by valueandprotected var count: Intrely on.protectedis a word only in front of a member of a type, so a field namedprotectedis reached bare as well as after a.(Fields, rule 3).rawis contextual too, but at the lexer rather than the parser: it starts a raw string (raw"text",raw"""text""") only directly in front of", and is an ordinary name everywhere else -const raw = 1andfn raw(): Intboth declare araw. See Literals, rule 9.A field, a method, a case field and a label may be named after a reserved word. Where a name can only be a name, a keyword is one: declared inside a type body (
type: String,var in: Int,fn match(...), a case fieldcase Click(type: String)), after a.(event.type,event.match("click")) and as a label of an argument or a pattern (Event(type: "click"),.Click(type: kind)). A bare keyword is always the keyword, so inside the type the member is reached asself.type- in a method and in a receiver closure alike. DerivedEncodeandDecodeuse the field's name as the key, so a JSON"type"needs no rename.type Event { type: String var in: Int = 0 fn match(pattern: String): Bool { self.type == pattern } } const event = Event type: "click" print "{event.type} {event.in} {event.match("click")}"Kompiliert nichttype Event { var type: String } fn configure(block: (var self: Event) => Void): Event { var event = Event(type: "") block event event } print configure({ type = "click" }).type // error: `type` is a keyword and cannot be assigned bareA receiver closure writes
self.type = "click": its bare names are the receiver's fields, but a baretypeat the start of a line begins a declaration there as everywhere else.A parameter, a binding, a function and a type cannot be named after a keyword. A parameter has no
self.to reach it through, so a keyword there would be a name the body can never read. The message names the participle a reader is looking for. A label only reaches a parameter that exists, soaccept(in: 3)is a message about the parameter, not about the keyword.fn move(from: Int, to: Int): Int { to - from } print move(from: 3, to: 10)Kompiliert nichtfn accept(value: Int): Int { value } print accept(in: 3) // error: `accept` has no parameter `in`Kompiliert nichtfn move(where: Int) { print "moving" } // error: `where` is a keyword and cannot be used as a name hereA name is
[A-Za-z_][A-Za-z0-9_]*. The lexer reads the whole word and reports one problem for it, whatever the letters in it are, so a name written in another script is one diagnostic and not one per character.Kompiliert nichtconst größe = 1 // error: A name is written in ASCII letters, digits and `_`Text is not. A string, a character literal, a comment and a doc comment may contain anything Unicode has - only names are limited, so an identifier is the same text in every editor, every terminal and every back end.
/** Grüßt zurück. 👋 */ const greeting = "Grüße 👋" print greeting
What this is not#
A block comment is not nestable. Text that looks like a nested comment ends the outer one at its first */.
const first = "a"
const second = "b"
print "{first}{second}"/* This mentions /* a comment */ that ends early. */
// error: Cannot find `that` here
// error: Expected the end of the statement, found a nameThe second block parses as two comments and leftover code, not as one long comment - the lexer does not count nesting
depth for /*.
Related#
- Doc comments - what the text of a
/** */comment may contain and which headings it uses. - Command calls - argument labels, and where a call needs no parentheses.
- Naming - the other rule about a name: which case its first letter is, and what is only a convention.
- Bindings -
constandvar, the two keywords a statement most often starts with.