项目是这样的:
https://github.com/ChrisBrenton/grappa-parsetree
目标是为最终用户提供API,使得包易于使用。目前,this是提案。
首先,使用示例:
final ParseTree<Void, SentenceNode> parseTree = ParseTree
.usingParser(SentenceParser.class)
.withRule(SentenceParser::sentence)
.withRoot(SentenceNode.class);
通过上面的链接实现此目的的代码在这里复制(省略了import / package声明):
public final class ParseTree<T, N extends ParseNode>
{
private final Rule rule;
private final ParseNodeConstructorProvider provider;
private final Class<N> nodeClass;
public static <T, P extends BaseParser<T>> ParseTreeBootstrap<T, P>
usingParser(final Class<P> parserClass)
{
Objects.requireNonNull(parserClass);
return new ParseTreeBootstrap<>(parserClass);
}
ParseTree(final Rule rule, final ParseNodeConstructorProvider provider,
final Class<N> nodeClass)
{
this.rule = rule;
this.provider = provider;
this.nodeClass = nodeClass;
}
public N parse(final CharSequence input)
{
final ParseRunner<T> runner = new ParseRunner<>(rule);
final ParseTreeBuilder<T> builder = new ParseTreeBuilder<>(provider);
runner.registerListener(builder);
if (!runner.run(input).isSuccess())
throw new GrappaException("parsing failed! Cannot retrieve the tree");
return nodeClass.cast(builder.getTree());
}
}
public final class ParseTreeBootstrap<T, P extends BaseParser<T>>
{
private final P parser;
private final ParseNodeConstructorProvider provider;
ParseTreeBootstrap(final Class<P> parserClass)
{
parser = Grappa.createParser(parserClass);
provider = new ParseNodeConstructorProvider(parserClass);
}
public ParseTreeRule<T, P> withRule(final Function<? super P, Rule> fn)
{
Objects.requireNonNull(fn);
return new ParseTreeRule<>(parser, provider, fn);
}
}
public final class ParseTreeRule<T, P extends BaseParser<T>>
{
private final Rule rule;
private final ParseNodeConstructorProvider provider;
ParseTreeRule(final P parser, final ParseNodeConstructorProvider provider,
final Function<? super P, Rule> fn)
{
rule = fn.apply(parser);
this.provider = provider;
}
public <N extends ParseNode> ParseTree<T, N> withRoot(final Class<N> nodeClass)
{
Objects.requireNonNull(nodeClass);
return new ParseTree<>(rule, provider, nodeClass);
}
}
我在这里遇到的问题是ParseTree的初始声明:
final ParseTree<Void, SentenceNode> parseTree = ...
第一个类型参数是因为它是解析器本身的类型参数:
public class SentenceParser
extends BaseParser<Void>
但是在生成解析树时,此类型与最终用户无关。
我试图忽略它,但问题来自ParseTree
中的这个方法:
public N parse(final CharSequence input)
{
final ParseRunner<T> runner = new ParseRunner<>(rule);
final ParseTreeBuilder<T> builder = new ParseTreeBuilder<>(provider);
runner.registerListener(builder);
if (!runner.run(input).isSuccess())
throw new GrappaException("parsing failed! Cannot retrieve the tree");
return nodeClass.cast(builder.getTree());
}
我无法在N
替换?
,因为如果我这样做,那么我就不能.registerListener()
(捕获不同)。
一种解决方案可能是使用原始类型;但是如果可能的话,我想避免这种情况。
您如何避免在此声明第一个类型参数?