package tc.oc.pgm.xml.parser;
import tc.oc.commons.core.reflect.AutoReified;
import tc.oc.pgm.xml.InvalidXMLException;
import tc.oc.pgm.xml.Node;
import tc.oc.pgm.xml.Parseable;
/**
* Base interface for parsers of any particular type {@link T}, which can be anything
* from simple primitives to elaborate data structures. Subtypes only have to
* implement {@link #parseInternal(Node)} to convert a {@link Node} into a {@link T},
* or throw {@link InvalidXMLException} if that fails.
*
* There is no special mechanism for passing context or dependencies to parsers,
* they simply use injection to get whatever they need.
*
* Parsers MAY be scoped, so callers should always inject a {@link javax.inject.Provider}
* and get a fresh instance every time they want to use the parser.
*
* Every parser subtype T should somehow bind itself to {@link Parser<T>}, so
* that it's simple to inject a parser for any type, even dynamically.
* {@link ParserBinders} can be helpful for doing that.
*
* Reflective parsers, i.e. {@link Parseable}s, expect such bindings to exist for all
* the types they are composed of. In the future, we may also use this system to
* implement various higher-order parsers.
*/
public interface Parser<T> extends AutoReified<T> {
T parseInternal(Node node) throws InvalidXMLException;
default String readableTypeName() {
return paramToken().getRawType().getSimpleName().toLowerCase();
}
default T parse(Node node) throws InvalidXMLException {
return InvalidXMLException.offeringNode(node, () -> parseInternal(node));
}
}