Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Syntax Overview

Tundra uses a clean, Python‐inspired syntax with significant (indentation) whitespace and familiar control constructs. Below is the high‐level grammar:

<program>        ::= ( <simple_stmt> | <compound_stmt> )* EOF

<simple_stmt>    ::= <small_stmt> NEWLINE
<small_stmt>     ::= <var_decl>
                   | <expression_stmt>
                   | <print_stmt>

<compound_stmt>  ::= <if_stmt>
                   | <for_stmt>
                   | <while_stmt>
                   | <fun_decl>
                   | <class_decl>

<suite>          ::= <simple_stmt>
                   | NEWLINE INDENT
                       ( <simple_stmt> | <compound_stmt> )+
                     DEDENT

<var_decl>       ::= "var" IDENTIFIER [ "=" <expression> ]

<fun_decl>       ::= "fun" IDENTIFIER "(" [ <parameters> ] ")" ":" <suite>

<class_decl>     ::= "class" IDENTIFIER ":" <suite>

<if_stmt>        ::= "if" "(" <expression> ")" ":" <suite>
                   [ "else" ":" <suite> ]

<for_stmt>       ::= "for" IDENTIFIER "in" <expression> ":" <suite>

<while_stmt>     ::= "while" "(" <expression> ")" ":" <suite>

<print_stmt>     ::= "print" "(" <expression> ")"

<expression_stmt>::= <expression>

<expression>     ::= <assignment>

<assignment>     ::= IDENTIFIER "=" <expression>
                   | <logic_or>

<logic_or>       ::= <logic_and> { "or"  <logic_and> }

<logic_and>      ::= <equality> { "and" <equality> }

<equality>       ::= <comparison> { ( "==" | "!=" ) <comparison> }

<comparison>     ::= <term> { ( "<" | "<=" | ">" | ">=" ) <term> }

<term>           ::= <factor> { ( "+" | "-" ) <factor> }

<factor>         ::= <unary> { ( "*" | "/" | "//" | "%" ) <unary> }

<unary>          ::= ( "!" | "-" ) <unary>
                   | <primary>

<primary>        ::= <atom> { <trailer> }

<atom>           ::= IDENTIFIER
                   | INT_LITERAL
                   | FLOAT_LITERAL
                   | STRING_LITERAL
                   | CHAR_LITERAL
                   | BOOL_LITERAL
                   | "none"
                   | "(" <expression> ")"
                   | <array_literal>

<array_literal>  ::= "[" [ <expression> { "," <expression> } ] "]"

<trailer>        ::= "(" [ <argument_list> ] ")"
                   | "." IDENTIFIER
                   | "[" <expression> "]"

<parameters>     ::= IDENTIFIER { "," IDENTIFIER }

<argument_list>  ::= <expression> { "," <expression> }

  • Statements end with a newline; compound statements introduce a suite indented one level deeper.

  • Expressions follow usual precedence (assignment, or/and, equality, comparison, term, factor, unary, exponent, call, primary).

  • Identifiers: start with a letter or underscore, followed by letters, digits, or underscores.

  • Block structure: changing indentation at the start of a line emits Indent/Dedent tokens; mixing tabs/spaces is disallowed.

Sample Code

var x = 10
fun greet(name):
    print("Hello, " + name)

greet("World")

Disassembled Bytecode

== == Disassembled Bytecode == ==
0000 Line    2    LoadConstant(0, Value { value: Int(10) })
0001 Line    2    DefineGlobal(0, "x")
0002 Line    6    LoadConstant(0, Value { value: Function(RefCell { value: FunctionObject { name: "greet", arity: 1, chunk: RefCell { value: Chunk { code: [LoadConstant(1, Value { value: String("\"Hello, \"") }), Move(2, 1), GetLocal(3, 0), Add(4, 2, 3), Print(4), Return(0)], constants: [], lines: [4, 4, 4, 4, 4, 6], max_register: 5 } }, jitted: None } }) })
0003 Line    6    DefineGlobal(0, "greet")
0004 Line    6    GetGlobal(0, "greet")
0005 Line    6    LoadConstant(1, Value { value: String("\"World\"") })
0006 Line    6    Call(2, 0, 1)
0007 Line    6    Pop(2)
0008 Line    7    Return(2)

Output

""Hello, ""World""