Java JParsec在简单测试中失败

Java JParsec在简单测试中失败,java,parsing,jparsec,Java,Parsing,Jparsec,我正在尝试使用尽可能最简单的解析器来处理JPARSEC2.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

我正在尝试使用尽可能最简单的解析器来处理JPARSEC2.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中的扫描仪和令牌解析器:

CONSTANT\u PARSER.from(CONSTANT\u LEXER,忽略)。parse('test')

本质上说,常量语法分析器应该以令牌流的形式从常量语法分析器获取其输入,并将忽略作为分隔符。问题是常量语法分析器是由“映射”常量语法分析器定义的,这意味着它使用语法分析器解析输入,而不是映射结果。这会引发以下错误:

org.codehaus.jparsec.error.ParserException:无法扫描令牌上的字符。

通过将常量解析器定义为
Parsers.tokenType(Token.class,“CONSTANT”)
可以有效地说解析器使用一个令牌流,将它们命名为
CONSTANT
。然而,我认为这并不像您期望的那样有效,因为这将匹配任何类型的令牌,而不仅仅是常量

这当然是JParsec中文档较少的部分之一,而且也没有很好的文档记录

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());
    }
});