Language Syntax
goose has a minimal syntax that aims to be highly readable. In this section, we'll cover the syntax rules and conventions of the goose language in-depth.
If you're new to goose, we recommend starting with the Language Tour to get a quick overview of the language.
Syntax Rules
goose classifies code into statements and
expressions. A statement can be thought of an action, while
an expression represents a usable value. For example, let x = 5
is a statement that assigns the value 5
to the variable
x
, while 5 + 5
is an expression that evaluates to
10
.
Statements can only be written in certain contexts, like the top-level of a file or inside a function. Expressions, however, can be written almost anywhere, including where statements are expected.
// statement context
let x = 5
x // expression as statement
if /* expression context */ x > 0
// new statement context
end
if let y = x + 5 // invalid statement where expression is expected
println(y)
end
Statements don't need to be separated by a semicolon or any other delimiter. In fact, statements don't even need to be on separate lines! The parser can work out where one statement ends and another begins based on the syntax rules of the language. However, it is recommended to use new lines to separate statements for readability.
// completely valid! but not recommended
let x = 5 let y = 10 println(x + y)
// equivalent to:
let x = 5
let y = 10
println(x + y)
Inside blocks, whitespace isn't significant either, but indenting each level by 2 spaces is recommended for readability and clarity.
if x > 5
println("x is greater than 5")
end
// equivalent to:
if x > 5
println("x is greater than 5")
end
Comments
goose supports both single-line and multi-line comments. Single-line
comments start with //
and continue until the end of the line.
Multi-line comments start with /*
and end with */
.
Multi-line comments cannot be nested.
// this is a single-line comment
/*
This is a multi-line comment
that spans multiple lines
*/
Identifiers
Identifiers are used to name variables, functions, and other entities in goose. An identifier must start with a letter or an underscore and can contain letters, numbers, and underscores. Identifiers are case-sensitive. By convention, identifiers should be written in snake_case.
More formally, all valid identifiers must match the regular expression
[a-zA-Z_][a-zA-Z0-9_]*
.
let my_variable = 5
fn hello_world()
println("Hello, World!")
end
// invalid identifiers
let 1variable = 5 // cannot start with a number
let my-variable = 5 // cannot contain hyphens
let $varia@ble = 5 // cannot contain special characters (except underscore)
Keywords
goose has a set of reserved keywords that cannot be used as identifiers. These keywords are used to define the structure of the language and cannot be redefined or shadowed.
The following is a list of all the keywords in goose:
let const symbol if then else
repeat while forever times for in
break continue fn end return memo
import export as show is generator
yield to step struct init operator
try catch finally throw do async
await native match when frozen