Grammaire complète
Référence syntaxique condensée du langage, dans l'esprit de l'annexe « The Complete Syntax of Lua » du manuel de référence Lua : toute la grammaire, sans réexpliquer la sémantique déjà décrite dans les autres pages de cette section. Si une règle vous semble obscure, la page thématique correspondante (liée depuis index.md) en donne le sens et des exemples.
Notation
{A}: zéro, une ou plusieurs répétitions deA.[A]:Aest optionnel.'xxx': mot-clé ou symbole littéral.- Les autres mots en minuscules italiques sont des non-terminaux ;
Name,NumeraletLiteralStringsont des terminaux lexicaux (identifiants, littéraux numériques, littéraux chaîne — voir Types et valeurs et Types et valeurs pour leur forme exacte).
Chunk et blocs
chunk ::= block
block ::= {stat} [retstat]
Un script constitue à lui seul un chunk : il est toujours variadique (... y est utilisable,
voir Variables), même s'il n'est pas défini comme une
fonction explicite.
Instructions
stat ::= ';' |
varlist '=' explist |
functioncall |
label |
break | continue |
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 function Name funcbody |
local attnamelist ['=' explist]
attnamelist ::= Name attrib {',' Name attrib}
attrib ::= ['<' Name '>']
retstat ::= return [explist] [';']
label ::= '::' Name '::'
retstat ne peut apparaître qu'en dernière position d'un block (rien ne suit un return, à
l'exception d'un ; optionnel) — voir Structures de contrôle.
attrib est accepté syntaxiquement pour tout nom, mais seuls <const> et <close> sont reconnus
par le parseur — voir Variables ; tout autre nom
reste rejeté avec une erreur de syntaxe.
funcname ::= Name {'.' Name} [':' Name]
varlist ::= var {',' var}
var ::= Name | prefixexp '[' exp ']' | prefixexp '.' Name
namelist ::= Name {',' Name}
explist ::= exp {',' exp}
Au niveau d'une instruction, varlist '=' explist et functioncall partagent le même préfixe : le
parseur lit d'abord un prefixexp (Name ou '(' exp ')', avec ses suffixes ./[...]/:/appel
éventuels), puis choisit entre affectation et appel selon ce qui suit — (f)() est donc une
instruction valide au même titre qu'une sous-expression, comme en Lua. Une instruction ne peut en
revanche pas être une expression parenthésée sans suffixe ((1 + 2) seul, ni appel ni affectation),
ni une affectation à une expression parenthésée sans suffixe ((t) = 5 — (t).x = 5 reste valide).
Expressions
exp ::= primary | functiondef | binary | unary
primary ::= nil | false | true | Numeral | LiteralString | '...' |
prefixexp | tableconstructor
prefixexp ::= var | functioncall | '(' exp ')'
functioncall ::= prefixexp args | prefixexp ':' Name args
args ::= '(' [explist] ')' | tableconstructor | LiteralString
functiondef ::= function funcbody
funcbody ::= '(' [parlist] ')' block end
parlist ::= namelist [',' '...'] | '...'
function t:m(...) ... end (voir Fonctions) désucre en une
funcbody dont le premier paramètre implicite est self ; ce paramètre n'apparaît pas dans
parlist tel qu'écrit par l'auteur du script.
tableconstructor ::= '{' [fieldlist] '}'
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= '[' exp ']' '=' exp | Name '=' exp | exp
fieldsep ::= ',' | ';'
Opérateurs
binary ::= exp binop exp
unary ::= unop exp
binop ::= '+' | '-' | '*' | '/' | '//' | '^' | '%' |
'&' | '~' | '|' | '>>' | '<<' | '..' |
'<' | '<=' | '>' | '>=' | '==' | '~=' |
and | or
unop ::= '-' | not | '#' | '~' | '+'
Précédence, associativité et sémantique de chaque opérateur : voir
Expressions et opérateurs. Le +
unaire est syntaxiquement accepté (unop) mais purement décoratif : le parseur l'ignore sans
produire de nœud — voir Expressions.
Point d'attention : ambiguïté classique avec une instruction commençant par (
prefixexp inclut '(' exp ')' (ci-dessus) aussi bien en position d'expression qu'en position
d'instruction : (f)(), (t.x).y, (g()).hello() sont tous valides, y compris comme instruction
autonome ((f)() seule sur sa ligne).
Cela réintroduit l'ambiguïté classique de Lua : l'absence de point-virgule n'étant pas une fin
d'instruction, deux instructions consécutives où la seconde commence par ( peuvent fusionner en
une seule si la première se termine par une expression :
local g = f
(g)() -- lu comme f(g)(), PAS comme deux instructions distinctes
Ajoutez un ; explicite avant une instruction commençant par ( si l'instruction précédente se
termine par une expression, pour lever l'ambiguïté :
local g = f;
(g)() -- deux instructions distinctes, sans ambiguïté