@Algorithm(lalr, 1)

// This is a test grammar for a pseudo programming language.
// The most interesting thing about this is that it uses an intricate ordering of
// rules to specify the precedence of 'Expr' nodes. As such, it is purely LALR,and
// does not require any annotations to disambiguate expressions.

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: Logic
Logic: Logic AND Equal
	| Logic OR  Equal
	| Logic XOR Equal
	| Equal
Equal: Equal == Ord
	| Equal != Ord
	| Ord
Ord: Ord < Term
	| Ord > Term
	| Ord <= Term
	| Ord >= Term
	| Term
Term: Term + Fact
	| Term - Fact
	| Fact
Fact: Fact * Pow
	| Fact / Pow
	| Pow
Pow: Pow ^ Modulo
	| Modulo
Modulo: Modulo % Index
	| Index
Index: Index [ Expr ]
	| Index ( Args )
	| Index . ID
	| Not
Args: Expr , Args
	| Expr
	|
Not: NOT Not
	| - Not
	| Final
Final: Constant
	| INT
	| FLOAT
	| STRING
	| ID
	| ( Expr )
	| FN ( FunctionArgs ) Statements END
	| { TableFields }

Constant: TRUE
	| FALSE
	| NIL

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

TableFields: TableField , TableFields
	| TableField
	|

TableField: ID = Expr

@example(RETURN { ID = INT + INT / - INT })
@example(GLOBAL ID ; BREAK ; CONTINUE)
@example(IF INT == INT THEN CONTINUE ; BREAK ; ELSE RETURN STRING END)
@example(FN ID ( ID , ID ) ID += ID ; RETURN ID - STRING END)