All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.petitparser.tools.CompositeParser Maven / Gradle / Ivy

package org.petitparser.tools;

import org.petitparser.parser.Parser;
import org.petitparser.parser.combinators.DelegateParser;
import org.petitparser.parser.combinators.SettableParser;
import org.petitparser.parser.primitive.FailureParser;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

/**
 * Helper to compose complex grammars from various primitive parsers.
 * 

* Note, this class is deprecated in favor of {@link GrammarDefinition} that provides a more * flexible way to define composite parsers. *

* To create a new composite grammar subclass {@link CompositeParser}. Override the method {@link * #initialize} and for every production call {@link CompositeParser#def(String, * org.petitparser.parser.Parser)} giving the parsers a name. The start production must be named * 'start'. *

* To refer to other productions use {@link CompositeParser#ref(String)}. To redefine or attach * actions to productions use {@link CompositeParser#redef(String, Function)}, {@link * CompositeParser#redef(String, org.petitparser.parser.Parser)} and {@link * CompositeParser#action(String, Function)}. */ @Deprecated public abstract class CompositeParser extends DelegateParser { private boolean completed = false; private Map defined = new HashMap<>(); private Map undefined = new HashMap<>(); public CompositeParser() { super(FailureParser.withMessage("Undefined start production")); initialize(); complete(); } /** * Automatically called by the framework to initialize the grammar. */ protected abstract void initialize(); /** * Internal method that completes the initialization. */ private void complete() { replace(delegate, ref("start")); for (Map.Entry entry : undefined.entrySet()) { if (!defined.containsKey(entry.getKey())) { throw new IllegalStateException("Undefined production: " + entry.getKey()); } entry.getValue().replace(entry.getValue().get(), defined.get(entry.getKey())); } replace(delegate, ref("start")); defined = Collections.unmodifiableMap(defined); undefined = Collections.unmodifiableMap(new HashMap<>()); completed = true; } /** * Returns a reference to the production with the given {@code name}. *

* This method works during initialization and after completion of the initialization. During the * initialization it returns delegate parsers that are eventually replaced by the real parsers. * Afterwards it returns the defined parser (mostly useful for testing). */ public final Parser ref(String name) { if (completed) { if (!defined.containsKey(name)) { throw new IllegalStateException("Undefined production: " + name); } return defined.get(name); } else if (undefined.containsKey(name)) { return undefined.get(name); } else { SettableParser parser = SettableParser.undefined("Uninitialized production: " + name); undefined.put(name, parser); return parser; } } /** * Defines a production with a {@code name} and a {@code parser}. Only call this method during * initialization. */ protected final void def(String name, Parser parser) { if (completed) { throw new IllegalStateException("Completed parsers cannot be redefined"); } if (defined.containsKey(name)) { throw new IllegalStateException("Duplicate production: " + name); } defined.put(Objects.requireNonNull(name), Objects.requireNonNull(parser)); } /** * Redefines an existing production with a {@code name} and a new {@code parser}. Only call this * method during initialization. */ protected final void redef(String name, Parser parser) { if (completed) { throw new IllegalStateException("Completed parsers cannot be redefined"); } if (!defined.containsKey(name)) { throw new IllegalStateException("Undefined production: " + name); } defined.put(Objects.requireNonNull(name), Objects.requireNonNull(parser)); } /** * Redefines an existing production with a {@code name} and a {@code function} producing a new * parser. Only call this method during initialization. */ protected final void redef(String name, Function function) { if (!defined.containsKey(name)) { throw new IllegalStateException("Undefined production: " + name); } redef(name, function.apply(defined.get(name))); } /** * Attaches an action {@code function} to an existing production {@code name}. Only call this * method during initialization. */ protected final void action(String name, Function function) { redef(name, parser -> parser.map(function)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy