@preprocessor typescript

@{%
import { Expr } from "./parsed";
%}

expr -> term {% id %}

term -> term _ "+" _ factor
		{% ([left, _0, _1, _2, right]): Expr =>
			({ exprType: "binary", binaryType: "add", left, right }) %}
	| term _ "-" _ factor
		{% ([left, _0, _1, _2, right]): Expr =>
			({ exprType: "binary", binaryType: "subtract", left, right }) %}
	| factor {% id %}

factor -> factor _ "*" _ unary
		{% ([left, _0, _1, _2, right]): Expr =>
			({ exprType: "binary", binaryType: "multiply", left, right }) %}
	| factor _ "/" _ unary
		{% ([left, _0, _1, _2, right]): Expr =>
			({ exprType: "binary", binaryType: "divide", left, right }) %}
	| unary {% id %}

unary -> "+" _ unary
		{% ([_0, _1, subject]): Expr =>
			({ exprType: "unary", unaryType: "plus", subject }) %}
	| "-" _ unary
		{% ([_0, _1, subject]): Expr =>
			({ exprType: "unary", unaryType: "negate", subject }) %}
	| operand {% id %}

operand -> int {% id %}
	| group {% id %}
	| block {% id %}
	| if {% id %}

int -> [0-9]:+
		{% ([token]): Expr =>
			({ exprType: "int", value: parseInt(token.join("")) }) %}

group -> "(" _ expr _ ")" {% (v): Expr => v[2] %}

block -> "{" _ expr _ "}" {% (v): Expr => ({ exprType: "block", expr: v[2] }) %}

if -> "if" __ expr _ block _ "else" _ block
	{%
		(v): Expr => ({
			exprType: "if",
			condition: v[2],
			truthy: v[4],
			falsy: v[8]
		})
	%}

_ -> __:?
__ -> ws:+

ws -> [ \t\r\n]