001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.ext.grammar; 021 022import static java.util.Objects.requireNonNull; 023 024import java.util.List; 025import java.util.function.Function; 026 027import io.jenetics.ext.grammar.Cfg.NonTerminal; 028import io.jenetics.ext.grammar.Cfg.Symbol; 029 030/** 031 * Generator interface for generating <em>sentences</em>/<em>derivation trees</em> 032 * from a given grammar. 033 * 034 * @param <T> the terminal token type of the grammar 035 * @param <R> the result type of the generator 036 * 037 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 038 * @since 7.1 039 * @version 7.1 040 */ 041@FunctionalInterface 042public interface Generator<T, R> { 043 044 /** 045 * Generates a new sentence from the given grammar. If the generation of the 046 * sentence fails, an empty list is returned. 047 * 048 * @param cfg the generating grammar 049 * @return a newly created result 050 */ 051 R generate(final Cfg<? extends T> cfg); 052 053 /** 054 * Maps the generated result from type {@code R} to type {@code R1}. 055 * 056 * @param f the mapping function 057 * @param <R1> the target type 058 * @return a new generator with target type {@code R1} 059 * @throws NullPointerException if the mapping function is {@code null} 060 */ 061 default <R1> Generator<T, R1> map(final Function<? super R, ? extends R1> f) { 062 requireNonNull(f); 063 return cfg -> f.apply(generate(cfg)); 064 } 065 066 /** 067 * Standard algorithm for selecting a list of alternative symbols from the 068 * given {@code rule}. 069 * 070 * @param rule the rule to select the alternative from 071 * @param cfg the grammar to select the alternative from 072 * @param index the symbol selection strategy 073 * @param <T> the terminal type 074 * @return the selected symbols 075 * @throws NullPointerException if one of the arguments is {@code null} 076 */ 077 static <T> List<Symbol<T>> select( 078 final NonTerminal<T> rule, 079 final Cfg<T> cfg, 080 final SymbolIndex index 081 ) { 082 return cfg.rule(rule) 083 .map(r -> r.alternatives() 084 .get(index.next(r, r.alternatives().size())) 085 .symbols()) 086 .orElse(List.of()); 087 } 088 089}