
%{
	const ast = require('./ast');

	// copy abstract syntax tree constructors onto global scope object
	Object.assign(global, ast);
%}


%start grammar

/* enable EBNF grammar syntax */
%ebnf

%%
/* ------------------------ */
/* language grammar */
/* ------------------------ */

grammar
	: section* EOF
		{ return Program($1) }
	;

section
	: body_section
	| macro
	;

include
	: '@include' js -> Include($js)
	;

body_section
	: VERBATIM -> Verbatim($VERBATIM)
	| if
	| let
	| inline
	| suppressed
	| suppressed_line
	| include
	;

if
	: '@if' js body_section* elseif* else? '@end' -> If($js, $3, $4, $5)
	;

elseif
	: '@elseif' js body_section* -> Elseif($js, $3)
	;

else
	: '@else' body_section* -> $2
	;

let
	: '@let' js -> Assignment($js)
	;

inline
	: '@{' js '}' -> Inline($js)
	;

suppressed
	: '@.{' js '}' -> Inline($js, true)
	;

suppressed_line
	: '@.' js -> Inline($js, true)
	;

macro
	: '@def' js body_section* '@end' -> Macro($js, $3)
	;

js
	: JM*
	;
