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

The Grammar of Teal

Here is the complete syntax of Teal in extended BNF, based on the Lua 5.4 grammar. Lines starting with + are existing lines from the Lua grammar with additions; lines marked with * are entirely new.

As usual in extended BNF, {A} means 0 or more As, and [A] means an optional A. For a description of the terminals Name, Numeral, and LiteralString, see Section 3.1 of the Lua 5.3 Reference Manual. For operator precedence, see below.

   chunk ::= block

   block ::= {stat} [retstat]

   stat ::=  ‘;’ |
       varlist ‘=’ explist |
       functioncall |
       label |
       ‘break’ |
       ‘goto’ Name |
       ‘do’ block ‘end’ |
       ‘while’ exp ‘do’ block ‘end’ |
       ‘repeat’ block ‘until’ exp |
       ‘if’ exp ‘then’ block {‘elseif’ exp ‘then’ block} [‘else’ block] ‘end’ |
       ‘for’ Name ‘=’ exp ‘,’ exp [‘,’ exp] ‘do’ block ‘end’ |
       ‘for’ namelist ‘in’ explist ‘do’ block ‘end’ |
       ‘function’ funcname funcbody |
+      ‘local’ attnamelist [‘:’ typelist] [‘=’ explist] |
       ‘local’ ‘function’ Name funcbody |
*      ‘local’ ‘record’ Name recordbody |
*      ‘local’ ‘interface’ Name recordbody |
*      ‘local’ ‘enum’ Name enumbody |
*      ‘local’ ‘type’ Name ‘=’ newtype |
*      ‘global’ attnamelist ‘:’ typelist [‘=’ explist] |
*      ‘global’ attnamelist ‘=’ explist |
*      ‘global’ ‘function’ Name funcbody |
*      ‘global’ ‘record’ Name recordbody |
*      ‘global’ ‘interface’ Name recordbody |
*      ‘global’ ‘enum’ Name enumbody |
*      ‘global’ ‘type’ Name [‘=’ newtype]

   attnamelist ::=  Name [attrib] {‘,’ Name [attrib]}

   attrib ::= ‘<’ Name ‘>’

   retstat ::= ‘return’ [explist] [‘;’]

   label ::= ‘::’ Name ‘::’

+  funcname ::= Name {‘.’ Name} ‘:’ Name | Name {‘.’ Name} ‘.’ Name

   varlist ::= var {‘,’ var}

   var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name

   namelist ::= Name {‘,’ Name}

   explist ::= exp {‘,’ exp}

   exp ::=  ‘nil’ | ‘false’ | ‘true’ | Numeral | LiteralString | ‘...’ | functiondef |
       prefixexp | tableconstructor | exp binop exp | unop exp |
*      exp ‘as’ type | exp ‘as’ ‘(’ typelist ‘)’ | Name ‘is’ type

   prefixexp ::= var | functioncall | ‘(’ exp ‘)’

   functioncall ::=  prefixexp args | prefixexp ‘:’ Name args

   args ::=  ‘(’ [explist] ‘)’ | tableconstructor | LiteralString

   functiondef ::= ‘function’ funcbody

+  funcbody ::= [typeargs] ‘(’ [parlist] ‘)’ [‘:’ retlist] block ‘end’

+  parlist ::= parnamelist [‘,’ ‘...’ [‘:’ type]] | ‘...’ [‘:’ type]

   tableconstructor ::= ‘{’ [fieldlist] ‘}’

   fieldlist ::= field {fieldsep field} [fieldsep]

   field ::= ‘[’ exp ‘]’ ‘=’ exp |
+      Name [‘:’ type] ‘=’ exp |
       exp

   fieldsep ::= ‘,’ | ‘;’

   binop ::=  ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ |
       ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ |
       ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ |
       ‘and’ | ‘or’

   unop ::= ‘-’ | ‘not’ | ‘#’ | ‘~’

*  type ::= ‘(’ type ‘)’ | basetype {‘|’ basetype}

*  nominal ::= Name {{‘.’ Name }} [typeargs]

*  basetype ::= ‘string’ | ‘boolean’ | ‘nil’ | ‘number’ |
*      ‘{’ type {',' type} ‘}’ | ‘{’ type ‘:’ type ‘}’ | functiontype
*      | nominal

*  typelist ::= type {‘,’ type}

*  retlist ::= ‘(’ [typelist] [‘...’] ‘)’ | typelist [‘...’]

*  typeargs ::= ‘<’ Name {‘,’ Name } ‘>’

*  newtype ::= ‘record’ recordbody | ‘enum’ enumbody | type
*      | ‘require’ ‘(’ LiteralString ‘)’ {‘.’ Name }

*  interfacelist ::= nominal {‘,’ nominal} |
*      ‘{’ type ‘}’ {‘,’ nominal}

*  recordbody ::= [typeargs] [‘is’ interfacelist]
*      [‘where’ exp] {recordentry} ‘end’

*  recordentry ::= ‘userdata’ |
*      ‘type’ Name ‘=’ newtype | [‘metamethod’] recordkey ‘:’ type |
*      ‘record’ Name recordbody | ‘enum’ Name enumbody

*  recordkey ::= Name | ‘[’ LiteralString ‘]’

*  enumbody ::= {LiteralString} ‘end’

*  functiontype ::= ‘function’ [typeargs] ‘(’ partypelist ‘)’ [‘:’ retlist]

*  partypelist ::= partype {‘,’ partype}

*  partype ::= Name [‘?’] ‘:’ type | [‘?’] type

*  parnamelist ::= parname {‘,’ parname}

*  parname ::= Name [‘?’] [‘:’ type]

Operator precedence

Operator precedence in Teal follows the table below, from lower to higher priority:

     or
     and
     is
     <     >     <=    >=    ~=    ==
     |
     ~
     &
     <<    >>
     ..
     +     -
     *     /     //    %
     unary operators (not   #     -     ~)
     ^
     as

As usual, you can use parentheses to change the precedences of an expression. The concatenation (..) and exponentiation (^) operators are right associative. All other binary operators are left associative.