Ich versuche, mit Jparsec meine recht einfache Grammatik zu definieren und zu verwenden, bin aber völlig verwirrt darüber, wie ich vorgehen soll. Ich weiß an dieser Stelle nicht, ob es mein unzureichendes Verständnis des Problembereichs oder die spärliche und wenig informative Dokumentation von jparsec ist. Oder beides.Verwechslung in jparsec
Ich habe einen grammer etwas wie folgt aus:
foo='abc' AND bar<>'def' OR (biz IN ['a', 'b', 'c'] AND NOT baz = 'foo')
So können Sie es unterstützt Operatoren wie AND
, OR
, NOT
, IN
, =
, <>
sehen. Es unterstützt auch beliebig verschachtelte Klammern, um Vorrang zu geben.
Ich denke, dass ich mit Tokenizing ziemlich weit gekommen bin. Hier ist, was ich habe:
public final class NewParser {
// lexing
private static final Terminals OPERATORS = Terminals.operators("=", "OR", "AND", "NOT", "(", ")", "IN", "[", "]", ",", "<>");
private static final Parser<?> WHITESPACE = Scanners.WHITESPACES;
private static final Parser<?> FIELD_NAME_TOKENIZER = Terminals.Identifier.TOKENIZER;
private static final Parser<?> QUOTED_STRING_TOKENIZER = Terminals.StringLiteral.SINGLE_QUOTE_TOKENIZER.or(Terminals.StringLiteral.DOUBLE_QUOTE_TOKENIZER);
private static final Parser<?> IGNORED = Parsers.or(Scanners.WHITESPACES).skipMany();
private static final Parser<?> TOKENIZER = Parsers.or(OPERATORS.tokenizer(), WHITESPACE, FIELD_NAME_TOKENIZER, QUOTED_STRING_TOKENIZER).many();
@Test
public void test_tokenizer() {
Object result = TOKENIZER.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_tokenizer
Pässe, so Ich denke, es funktioniert OK.
Jetzt habe ich bereits eine Typhierarchie, die die Syntax darstellt. Zum Beispiel habe ich Klassen genannt Node
, BinaryNode
, FieldNode
, LogicalAndNode
, ConstantNode
und so weiter. Und was ich versuche zu tun, ist eine Parser
erstellen, die meine Tokens und spuckt eine Node
. Und hier bleibe ich stecken.
Ich dachte, ich mit etwas wirklich einfach wie diese beginnen würde:
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());
}
});
Ich dachte, ich wäre in der Lage, dies zu tun:
public static Parser<Node> parser = fieldNodeParser.from(TOKENIZER);
Aber das gibt mir einen Compiler-Fehler:
Es sieht also so aus, als ob meine Generika irgendwo hingeworfen werden, aber ich habe keine Ahnung wo oder wie ich das beheben kann. Ich bin mir nicht einmal sicher, ob ich das richtig mache. Kann mich jemand aufklären?