Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java jparsec中的混乱_Java_Jparsec - Fatal编程技术网

Java jparsec中的混乱

Java jparsec中的混乱,java,jparsec,Java,Jparsec,我试图使用jparsec来定义和使用我相当简单的语法,但我完全不知道如何去做。我不知道这是因为我对问题空间的理解不够,还是因为jparsec的文档稀疏且缺乏信息。或者两者兼而有之 我有一个类似这样的语法: foo='abc' AND bar<>'def' OR (biz IN ['a', 'b', 'c'] AND NOT baz = 'foo') private static Parser<FieldNode> fieldNodeParser = Parser

我试图使用jparsec来定义和使用我相当简单的语法,但我完全不知道如何去做。我不知道这是因为我对问题空间的理解不够,还是因为jparsec的文档稀疏且缺乏信息。或者两者兼而有之

我有一个类似这样的语法:

foo='abc' AND bar<>'def' OR (biz IN ['a', 'b', 'c'] AND NOT baz = 'foo')
private static Parser<FieldNode> fieldNodeParser =
    Parsers.sequence(FIELD_NAME_TOKENIZER)
    .map(new Map<Object, FieldNode>() {
        @Override
        public FieldNode map(Object from) {
            Fragment fragment = (Fragment)from;
            return new FieldNode(fragment.text());
        }
    });
test\u标记器
通过,所以我认为它工作正常

现在,我已经有了一个表示语法的类型层次结构。例如,我有名为
节点
二进制节点
字段节点
逻辑节点
常量节点
等的类。我要做的是创建一个
解析器
,它获取我的令牌并吐出一个
节点
。这就是我一直被卡住的地方

我想我应该从这样简单的事情开始:

foo='abc' AND bar<>'def' OR (biz IN ['a', 'b', 'c'] AND NOT baz = 'foo')
private static Parser<FieldNode> fieldNodeParser =
    Parsers.sequence(FIELD_NAME_TOKENIZER)
    .map(new Map<Object, FieldNode>() {
        @Override
        public FieldNode map(Object from) {
            Fragment fragment = (Fragment)from;
            return new FieldNode(fragment.text());
        }
    });
专用静态解析器fieldNodeParser=
序列(字段\名称\标记器)
.map(新地图(){
@凌驾
公共字段节点映射(来自的对象){
Fragment Fragment=(Fragment)from;
返回新的FieldNode(fragment.text());
}
});
我想我能做到这一点:

public static Parser<Node> parser = fieldNodeParser.from(TOKENIZER);
publicstaticparser=fieldNodeParser.from(标记器);
但这给了我一个编译错误:

The method from(Parser<? extends Collection<Token>>) in the type Parser<FieldNode> is not applicable for the arguments (Parser<capture#6-of ?>)
来自(解析器)的方法

所以看起来我的泛型在某个地方被搜索到了,但我不知道在哪里或者如何修复它。我甚至不确定我是否以正确的方式来处理这件事。有人能给我一些启发吗?

您混合了两种不同级别的“解析器”:字符串级别的解析器。扫描器或词法分析器,以及令牌级解析器。这就是JParsec实现传统的词汇和语法分析分离的方式

为了使代码能够干净地编译,您可以在解析器定义的末尾添加对
.cast()
方法的调用,但这不会解决您的问题,因为您将遇到的下一个错误类似于
无法在令牌级别运行字符级别的解析器。这个问题源于使用
.from()
来定义顶级解析器,它隐式地设置了两个世界之间的边界

以下是解析器的工作实现(和单元测试):

public class SampleTest {


private static Parser<FieldNode> fieldNodeParser = Parsers.sequence(Terminals.fragment(Tokens.Tag.IDENTIFIER).map(new Map<String, FieldNode>() {
            @Override
            public FieldNode map(String from) {
                String fragment = from;
                return new FieldNode(fragment);
            }
        })).cast();

public static Parser<FieldNode> parser = fieldNodeParser.from(NewParser.TOKENIZER, Scanners.WHITESPACES);


@Test
public void test_tokenizer() {
    Object result = Parsers.or(NewParser.TOKENIZER, Scanners.WHITESPACES.cast()).many().parse("foo='abc' AND bar<>'def' OR (biz IN ['a', 'b', 'c'] AND NOT baz = 'foo')");
    Assert.assertEquals("[foo, =, abc, null, AND, null, bar, <>, def, null, OR, null, (, biz, null, IN, null, [, a, ,, null, b, ,, null, c, ], null, AND, null, NOT, null, baz, null, =, null, foo, )]", result.toString());
}

@Test
public void test_parser() throws Exception {
    FieldNode foo = parser.parse("foo");
    assertEquals(foo.text, "foo");
}

public static final class NewParser {
    // lexing
    static final Terminals OPERATORS = Terminals.operators("=", "OR", "AND", "NOT", "(", ")", "IN", "[", "]", ",", "<>");
    static final Parser<String> FIELD_NAME_TOKENIZER = Terminals.Identifier.TOKENIZER.source();
    static final Parser<?> QUOTED_STRING_TOKENIZER = Terminals.StringLiteral.SINGLE_QUOTE_TOKENIZER.or(Terminals.StringLiteral.DOUBLE_QUOTE_TOKENIZER);
    static final Terminals TERMINALS = Terminals.caseSensitive(new String[] { "=", "(", ")", "[", "]", ",", "<>" }, new String[] { "OR", "AND", "NOT", "IN" });
    static final Parser<?> TOKENIZER = Parsers.or(TERMINALS.tokenizer(), QUOTED_STRING_TOKENIZER);
}

private static class FieldNode {
    final String text;

    public FieldNode(String text) {

        this.text = text;
    }
}
公共类抽样测试{
私有静态解析器fieldNodeParser=Parsers.sequence(Terminals.fragment(Tokens.Tag.IDENTIFIER).map(newmap()){
@凌驾
公共字段节点映射(字符串来自){
字符串片段=来自;
返回新的FieldNode(片段);
}
})).cast();
public static Parser Parser=fieldNodeParser.from(NewParser.TOKENIZER、Scanners.WHITESPACES);
@试验
公共无效测试\标记器(){
Object result=Parsers.or(NewParser.TOKENIZER,Scanners.WHITESPACES.cast()).many().parse(“foo='abc'和bar'def'或(biz IN['a','b','c']而非baz='foo');
Assert.assertEquals(“[foo,=,abc,null,AND,null,bar,def,null,OR,null,(,biz,null,IN,null,[,a,null,b,null,null,null,c,],null,AND,null,NOT,null,baz,null,=,null,foo,)”,result.toString());
}
@试验
public void test_parser()引发异常{
FieldNode foo=parser.parse(“foo”);
资产质量(foo.text,“foo”);
}
公共静态最终类NewParser{
//lexing
静态最终端子运算符=端子。运算符(“=”、“或”、“和”、“非“、”(“、”)、“、”、“[”、“]”、“、”、”);
静态最终解析器字段_NAME_TOKENIZER=Terminals.Identifier.TOKENIZER.source();
静态最终解析器QUOTED_STRING_TOKENIZER=Terminals.StringLiteral.SINGLE_QUOTE_TOKENIZER.or(Terminals.StringLiteral.DOUBLE_QUOTE_TOKENIZER);
静态最终端子端子=端子。区分大小写(新字符串[]{“=”,“(“,”),“[”,“],”,“,”,“},新字符串[]{”或“,”和“,”不“,”在“});
静态最终解析器标记器=Parsers.or(TERMINALS.TOKENIZER(),QUOTED_STRING_TOKENIZER);
}
私有静态类FieldNode{
最终字符串文本;
公共字段节点(字符串文本){
this.text=文本;
}
}
}

我改变的是:

  • 我使用
    Terminals.caseSensitive
    方法仅为终端(关键字、运算符和标识符)创建lexer。所使用的标识符lexer隐式地由jParsec提供(例如,
    终端。identifier
  • 我使用
    .from()
    方法和标记器以及
    空格作为分隔符
  • fieldNodeParser
    使用
    Terminals.fragment(…)
    解析标记而不是字符
希望有帮助, 阿诺