Refactoring: make Grammar an abstract class
This commit is contained in:
parent
c9c1454f90
commit
301eaaf98d
18 changed files with 395 additions and 163 deletions
|
@ -1,89 +1,18 @@
|
|||
package com.albertoventurini.parsley.grammar;
|
||||
|
||||
import com.albertoventurini.parsley.grammar.rules.AnyCharacter;
|
||||
import com.albertoventurini.parsley.grammar.rules.MatchCharacter;
|
||||
import com.albertoventurini.parsley.grammar.rules.MatchString;
|
||||
import com.albertoventurini.parsley.grammar.rules.OneOf;
|
||||
import com.albertoventurini.parsley.grammar.rules.OneOrMore;
|
||||
import com.albertoventurini.parsley.grammar.rules.Rule;
|
||||
import com.albertoventurini.parsley.grammar.rules.Sequence;
|
||||
import com.albertoventurini.parsley.grammar.rules.TakeWhileCharacter;
|
||||
import com.albertoventurini.parsley.grammar.rules.UntilString;
|
||||
import com.albertoventurini.parsley.grammar.rules.Wrapper;
|
||||
import com.albertoventurini.parsley.grammar.rules.ZeroOrMore;
|
||||
import com.albertoventurini.parsley.grammar.rules.ZeroOrOne;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class Grammar {
|
||||
public abstract class Grammar {
|
||||
|
||||
private final Rule startRule;
|
||||
protected abstract Rule startRule();
|
||||
|
||||
private final Rule commentRule;
|
||||
|
||||
public Grammar(
|
||||
final Rule startRule,
|
||||
final Rule commentRule) {
|
||||
this.startRule = startRule;
|
||||
this.commentRule = commentRule;
|
||||
|
||||
// TODO: better than this
|
||||
if (commentRule != null) {
|
||||
commentRule.setComment(true);
|
||||
}
|
||||
}
|
||||
protected abstract Rule commentRule();
|
||||
|
||||
public Optional<ParseTree> parse(final String text) {
|
||||
final var ctx = new GrammarContext(text, commentRule);
|
||||
return startRule.apply(ctx);
|
||||
final var ctx = new GrammarContext(text, commentRule());
|
||||
return startRule().apply(ctx);
|
||||
}
|
||||
|
||||
public static MatchCharacter character(final char c) {
|
||||
return new MatchCharacter(c);
|
||||
}
|
||||
|
||||
public static AnyCharacter anyChar() {
|
||||
return new AnyCharacter();
|
||||
}
|
||||
|
||||
public static MatchString string(final String s) {
|
||||
return new MatchString(s);
|
||||
}
|
||||
|
||||
public static TakeWhileCharacter token() {
|
||||
return new TakeWhileCharacter();
|
||||
}
|
||||
|
||||
public static TakeWhileCharacter takeWhile(final Predicate<Character> characterPredicate) {
|
||||
return new TakeWhileCharacter(characterPredicate);
|
||||
}
|
||||
|
||||
public static UntilString until(final String s) {
|
||||
return new UntilString(s);
|
||||
}
|
||||
|
||||
public static Sequence sequence(final Rule... rules) {
|
||||
return new Sequence(rules);
|
||||
}
|
||||
|
||||
public static OneOf oneOf(final Rule... rules) {
|
||||
return new OneOf(rules);
|
||||
}
|
||||
|
||||
public static ZeroOrMore zeroOrMore(final Rule childRule) {
|
||||
return new ZeroOrMore(childRule);
|
||||
}
|
||||
|
||||
public static ZeroOrOne zeroOrOne(final Rule childRule) {
|
||||
return new ZeroOrOne(childRule);
|
||||
}
|
||||
|
||||
public static OneOrMore oneOrMore(final Rule childRule) {
|
||||
return new OneOrMore(childRule);
|
||||
}
|
||||
|
||||
public static Wrapper wrapper() {
|
||||
return new Wrapper();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.albertoventurini.parsley.grammar;
|
||||
|
||||
import com.albertoventurini.parsley.grammar.rules.Rule;
|
||||
|
||||
public class GrammarFactory {
|
||||
|
||||
public static Grammar newGrammar(final Rule startRule, final Rule commentRule) {
|
||||
// TODO: better than this
|
||||
|
||||
if (commentRule != null) {
|
||||
commentRule.setComment(true);
|
||||
}
|
||||
|
||||
return new Grammar() {
|
||||
|
||||
@Override
|
||||
protected Rule startRule() {
|
||||
return startRule;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rule commentRule() {
|
||||
return commentRule;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package com.albertoventurini.parsley.grammar;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ParseContext {
|
||||
class ParseContext {
|
||||
private final char[] charArr;
|
||||
private int cursor;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ParseTree {
|
||||
public abstract class ParseTree {
|
||||
|
||||
private final String text;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ public final class MatchCharacter extends Rule {
|
|||
|
||||
public MatchCharacter(final char c) {
|
||||
this.c = c;
|
||||
|
||||
discard = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ public abstract class Rule {
|
|||
|
||||
public abstract Optional<ParseTree> tryApply(final GrammarContext ctx);
|
||||
|
||||
public void setComment(final boolean comment) {
|
||||
public Rule setComment(final boolean comment) {
|
||||
isComment = comment;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package com.albertoventurini.parsley.grammar.rules;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class Rules {
|
||||
|
||||
public static MatchCharacter character(final char c) {
|
||||
return new MatchCharacter(c);
|
||||
}
|
||||
|
||||
public static AnyCharacter anyChar() {
|
||||
return new AnyCharacter();
|
||||
}
|
||||
|
||||
public static MatchString string(final String s) {
|
||||
return new MatchString(s);
|
||||
}
|
||||
|
||||
public static TakeWhileCharacter token() {
|
||||
return new TakeWhileCharacter();
|
||||
}
|
||||
|
||||
public static TakeWhileCharacter takeWhile(final Predicate<Character> characterPredicate) {
|
||||
return new TakeWhileCharacter(characterPredicate);
|
||||
}
|
||||
|
||||
public static UntilString until(final String s) {
|
||||
return new UntilString(s);
|
||||
}
|
||||
|
||||
public static Sequence sequence(final Rule... rules) {
|
||||
return new Sequence(rules);
|
||||
}
|
||||
|
||||
public static OneOf oneOf(final Rule... rules) {
|
||||
return new OneOf(rules);
|
||||
}
|
||||
|
||||
public static ZeroOrMore zeroOrMore(final Rule childRule) {
|
||||
return new ZeroOrMore(childRule);
|
||||
}
|
||||
|
||||
public static ZeroOrOne zeroOrOne(final Rule childRule) {
|
||||
return new ZeroOrOne(childRule);
|
||||
}
|
||||
|
||||
public static OneOrMore oneOrMore(final Rule childRule) {
|
||||
return new OneOrMore(childRule);
|
||||
}
|
||||
|
||||
public static Wrapper wrapper() {
|
||||
return new Wrapper();
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ public final class Sequence extends Rule {
|
|||
final int start = ctx.getCursor();
|
||||
final List<ParseTree> children = new ArrayList<>(rules.length);
|
||||
|
||||
for (final com.albertoventurini.parsley.grammar.rules.Rule rule : rules) {
|
||||
for (final Rule rule : rules) {
|
||||
if (!ctx.hasNext()) {
|
||||
ctx.setCursor(start);
|
||||
return Optional.empty();
|
||||
|
|
|
@ -5,13 +5,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.character;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.oneOf;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.sequence;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.string;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.takeWhile;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.token;
|
||||
import static com.albertoventurini.parsley.grammar.Grammar.zeroOrMore;
|
||||
import static com.albertoventurini.parsley.grammar.rules.Rules.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
@ -24,7 +18,7 @@ public class GrammarTest {
|
|||
takeWhile(Character::isLetterOrDigit),
|
||||
oneOf(string("/>"), character('>')));
|
||||
|
||||
final Grammar grammar = new Grammar(tag, null);
|
||||
final Grammar grammar = GrammarFactory.newGrammar(tag, null);
|
||||
|
||||
final var parseTree1 = grammar.parse("<tag1>");
|
||||
|
||||
|
@ -49,7 +43,7 @@ public class GrammarTest {
|
|||
zeroOrMore(attribute),
|
||||
oneOf(string("/>"), character('>')));
|
||||
|
||||
final Grammar grammar = new Grammar(tag, null);
|
||||
final Grammar grammar = GrammarFactory.newGrammar(tag, null);
|
||||
|
||||
assertTrue(grammar.parse("<tag1>").isPresent());
|
||||
|
||||
|
@ -111,7 +105,7 @@ public class GrammarTest {
|
|||
zeroOrMore(attribute),
|
||||
oneOf(string("/>"), character('>')));
|
||||
|
||||
final Grammar grammar = new Grammar(tag, null);
|
||||
final Grammar grammar = GrammarFactory.newGrammar(tag, null);
|
||||
|
||||
assertTrue(grammar.parse("<graphml xmlns='http://graphml.graphdrawing.org/xmlns'>").isPresent());
|
||||
}
|
||||
|
@ -140,7 +134,7 @@ public class GrammarTest {
|
|||
tagFunc.apply("key"),
|
||||
closingTagFunc.apply("key"));
|
||||
|
||||
final Grammar grammar = new Grammar(key, null);
|
||||
final Grammar grammar = GrammarFactory.newGrammar(key, null);
|
||||
|
||||
assertTrue(grammar.parse("<key id='type' for='node' attr.name='type' attr.type='string'></key>").isPresent());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue