JParsec 2.0.1 で動作する最も単純なパーサーを取得しようとしていますが、うまくいきません。次の AST クラスがあります。
public abstract class Node {
}
public final class ConstantNode extends Node {
private final String value;
public ConstantNode(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
}
そして、次のテスト コード:
import junit.framework.Assert;
import org.codehaus.jparsec.Parser;
import org.codehaus.jparsec.Parsers;
import org.codehaus.jparsec.Scanners;
import org.codehaus.jparsec.Terminals;
import org.codehaus.jparsec.Token;
import org.codehaus.jparsec.functors.Map;
import org.junit.Test;
import ast.ConstantNode;
import ast.Node;
public class ParserTest {
private static final Parser<Token> CONSTANT_LEXER = Parsers
.or(Terminals.StringLiteral.SINGLE_QUOTE_TOKENIZER,
Terminals.StringLiteral.DOUBLE_QUOTE_TOKENIZER)
.token();
private static final Parser<Node> CONSTANT_PARSER = CONSTANT_LEXER.map(new Map<Token, Node>() {
@Override
public Node map(Token from) {
return new ConstantNode(from.toString());
}
});
private static final Parser<Void> IGNORED = Scanners.WHITESPACES;
@Test
public void testParser() {
Object result = null;
// this passes
result = CONSTANT_LEXER.parse("'test'");
Assert.assertEquals("test org.codehaus.jparsec.Token", result + " " + result.getClass().getName());
// this fails with exception: org.codehaus.jparsec.error.ParserException: Cannot scan characters on tokens.
result = CONSTANT_PARSER.from(CONSTANT_LEXER, IGNORED).parse("'test'");
Assert.assertEquals("test ast.ConstantNode", result + " " + result.getClass().getName());
}
}
レクサーはトークンへの文字列入力を正常に解析していますが、パーサーは JParsec 例外のためにそれらのトークンを消費できません。私はこのコードを何度も研究してきましたが、これは jparsec のバグであるか、明らかな何かを誤解しているとしか思えません。
ここで私が間違っていることを誰かに教えてもらえますか?
更新:元の問題は再帰参照によるものだと思います。私CONSTANT_PARSER
は を使用してCONSTANT_LEXER
おり、後で を呼び出しますCONSTANT_PARSER.from(CONSTANT_LEXER...)
。my を次のように変更するCONSTANT_PARSER
と、テストに合格しました。
private static final Parser<Node> CONSTANT_PARSER = Parsers.tokenType(Token.class, "constant").map(new Map<Token, Node>() {
@Override
public Node map(Token from) {
return new ConstantNode(from.toString());
}
});
ただし、これはまだ完全にはクリックされていません。これを行うためのより良い方法があると思うので、まだアイデアに非常に興味があります.