function parseJinjaStatement()

in packages/jinja/src/parser.ts [102:197]


	function parseJinjaStatement(): Statement {
		// Consume {% token
		expect(TOKEN_TYPES.OpenStatement, "Expected opening statement token");

		// next token must be Identifier whose .value tells us which statement
		if (tokens[current].type !== TOKEN_TYPES.Identifier) {
			throw new SyntaxError(`Unknown statement, got ${tokens[current].type}`);
		}
		const name = tokens[current].value;
		let result: Statement;
		switch (name) {
			case "set":
				++current;
				result = parseSetStatement();
				break;
			case "if":
				++current;
				result = parseIfStatement();
				// expect {% endif %}
				expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
				expectIdentifier("endif");
				expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
				break;
			case "macro":
				++current;
				result = parseMacroStatement();
				// expect {% endmacro %}
				expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
				expectIdentifier("endmacro");
				expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
				break;
			case "for":
				++current;
				result = parseForStatement();
				// expect {% endfor %}
				expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
				expectIdentifier("endfor");
				expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
				break;
			case "call": {
				++current; // consume 'call'
				let callerArgs: Statement[] | null = null;
				if (is(TOKEN_TYPES.OpenParen)) {
					// Optional caller arguments, e.g. {% call(user) dump_users(...) %}
					callerArgs = parseArgs();
				}
				const callee = parsePrimaryExpression();
				if (callee.type !== "Identifier") {
					throw new SyntaxError(`Expected identifier following call statement`);
				}
				const callArgs = parseArgs();
				expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
				const body: Statement[] = [];
				while (!isStatement("endcall")) {
					body.push(parseAny());
				}
				expect(TOKEN_TYPES.OpenStatement, "Expected '{%'");
				expectIdentifier("endcall");
				expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
				const callExpr = new CallExpression(callee, callArgs);
				result = new CallStatement(callExpr, callerArgs, body);
				break;
			}
			case "break":
				++current;
				expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
				result = new Break();
				break;
			case "continue":
				++current;
				expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
				result = new Continue();
				break;
			case "filter": {
				++current; // consume 'filter'
				let filterNode = parsePrimaryExpression();
				if (filterNode instanceof Identifier && is(TOKEN_TYPES.OpenParen)) {
					filterNode = parseCallExpression(filterNode);
				}
				expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
				const filterBody: Statement[] = [];
				while (!isStatement("endfilter")) {
					filterBody.push(parseAny());
				}
				expect(TOKEN_TYPES.OpenStatement, "Expected '{%'");
				expectIdentifier("endfilter");
				expect(TOKEN_TYPES.CloseStatement, "Expected '%}'");
				result = new FilterStatement(filterNode as Identifier | CallExpression, filterBody);
				break;
			}
			default:
				throw new SyntaxError(`Unknown statement type: ${name}`);
		}

		return result;
	}