@Algorithm(lalr, 1)

// The parser catches a forgotten precedence annotation.

Start: Statements

Statements: Statement ; Statements
	| Statement
	|

Statement: RETURN Expr
	| GLOBAL ID
	| BREAK
	| CONTINUE
	| IfStm
	| WhileStm
	| ForStm
	| FunctionStm
	| Expr AssignOp Expr
	| Expr

IfStm: IF Expr THEN Statements ElseBranch? END

ElseBranch: ELSE Statements

WhileStm: WHILE Expr DO Statements END

ForStm: FOR ID IN Expr DO Statements END

FunctionStm: FN ID ( FunctionArgs ) Statements END

FunctionArgs: ID , FunctionArgs
	| ID
	|

Expr: Expr LogicOp      Expr
	| Expr EqualOp      Expr
	| Expr ComparisonOp Expr
	| Expr TermOp       Expr
	| Expr FactorOp     Expr
	| Expr ^ Expr
	| Expr % Expr
	| Expr [ Expr ]
	| Expr ( Args )
	| Expr . ID
	| NOT Expr
	| - Expr
	| Constant
	| INT
	| FLOAT
	| STRING
	| ID
	| ( Expr )
	| FN ( FunctionArgs ) Statements END
	| { TableFields }

Constant: TRUE
	| FALSE
	| NIL

AssignOp: =
	| +=
	| -=
	| *=
	| /=

LogicOp: AND
	| OR
	| XOR

EqualOp: ==
	| !=

ComparisonOp: <
	| >
	| <=
	| >=

TermOp: +
	| -

FactorOp: *
	| /

TableFields: TableField , TableFields
	| TableField
	|

TableField: ID = Expr

// WHOOPS: we forgot to specify a precedence for the right-hand side of '%' !

// AND OR XOR
@precedence(Expr, 0, left = 1, right = 2)
// == !=
@precedence(Expr, 1, left = 3, right = 4)
// < > <= >=
@precedence(Expr, 2, left = 5, right = 6)
// + -
@precedence(Expr, 3, left = 7, right = 8)
// * /
@precedence(Expr, 4, left = 9, right = 10)
// ^
@precedence(Expr, 5, left = 11, right = 12)
// %
// THE ERROR IS HERE !
@precedence(Expr, 6, left = 13)
// [] () .
@precedence(Expr, 7, left = 15)
@precedence(Expr, 8, left = 15)
@precedence(Expr, 9, left = 15)
// NOT -
@precedence(Expr, 10, right = 16)
@precedence(Expr, 11, right = 16)