package it.cavallium.warppi.math.rules.dsl;

import it.cavallium.warppi.math.rules.Rule;
import it.cavallium.warppi.math.rules.dsl.frontend.Lexer;
import it.cavallium.warppi.math.rules.dsl.frontend.Parser;
import it.cavallium.warppi.math.rules.dsl.patterns.SubFunctionPattern;

import java.util.*;

public class RulesDsl {
	private RulesDsl() {}

	public static List<Rule> makeRules(final String source) throws DslAggregateException {
		final List<DslError> errors = new ArrayList<>();

		final Lexer lexer = new Lexer(source, errors::add);
		final Parser parser = new Parser(lexer.lex(), errors::add);
		final List<PatternRule> rules = parser.parse();

		for (final PatternRule rule : rules) {
			undefinedSubFunctions(rule).stream()
					.flatMap(subFunc -> parser.getSubFunctionIdentifiers(rule, subFunc).stream())
					.map(UndefinedSubFunction::new)
					.forEach(errors::add);
		}

		if (!errors.isEmpty()) {
			throw new DslAggregateException(errors);
		}

		return Collections.unmodifiableList(rules);
	}

	/**
	 * Finds any sub-functions that are used in the replacement patterns of a <code>PatternRule</code>
	 * without being defined (captured) in the target pattern.
	 *
	 * @param rule The rule to analyze.
	 * @return The (possibly empty) set of undefined sub-functions.
	 */
	private static Set<SubFunctionPattern> undefinedSubFunctions(final PatternRule rule) {
		final Set<SubFunctionPattern> defined = rule.getTarget().getSubFunctions();
		final Set<SubFunctionPattern> undefined = new HashSet<>();
		for (final Pattern replacement : rule.getReplacements()) {
			undefined.addAll(replacement.getSubFunctions());
		}
		undefined.removeAll(defined);
		return undefined;
	}


}

@@ -296,55 +296,382 @@
 *;%0A%0A
-public class RulesDsl %7B%0A%09private RulesDsl() %7B%7D%0A
+/**%0A * Implements a domain-specific language (DSL) for the definition of %7B@link Rule%7Ds.%0A */%0Apublic class RulesDsl %7B%0A%09private RulesDsl() %7B%7D%0A%0A%09/**%0A%09 * Creates rules from DSL source code.%0A%09 *%0A%09 * @param source The source code.%0A%09 * @return An unmodifiable list containing the rules defined in the DSL code.%0A%09 * @throws DslAggregateException if the code contains any errors.%0A%09 */
 %0A%09pu

Document the RulesDsl class and its makeRules method