aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/zwobble/mammoth/styles/StyleMapParser.java103
-rw-r--r--src/main/java/org/zwobble/mammoth/styles/parsing/HtmlPathParser.java68
-rw-r--r--src/main/java/org/zwobble/mammoth/styles/parsing/ListVar.java34
-rw-r--r--src/main/java/org/zwobble/mammoth/styles/parsing/Parsing.java23
-rw-r--r--src/test/java/org/zwobble/mammoth/tests/styles/HtmlPathParsingTests.java23
5 files changed, 139 insertions, 112 deletions
diff --git a/src/main/java/org/zwobble/mammoth/styles/StyleMapParser.java b/src/main/java/org/zwobble/mammoth/styles/StyleMapParser.java
index be0a268..1092353 100644
--- a/src/main/java/org/zwobble/mammoth/styles/StyleMapParser.java
+++ b/src/main/java/org/zwobble/mammoth/styles/StyleMapParser.java
@@ -1,110 +1,7 @@
package org.zwobble.mammoth.styles;
-import com.google.common.collect.ImmutableList;
import org.parboiled.BaseParser;
-import org.parboiled.Parboiled;
-import org.parboiled.Rule;
-import org.parboiled.parserunners.ReportingParseRunner;
-import org.parboiled.support.ParsingResult;
-import org.parboiled.support.Var;
-
-import java.util.List;
-
-import static org.zwobble.mammoth.util.MammothLists.list;
-import static org.zwobble.mammoth.util.MammothMaps.map;
public class StyleMapParser extends BaseParser<HtmlPath> {
- public static HtmlPath parseHtmlPath(String value) {
- StyleMapParser parser = Parboiled.createParser(StyleMapParser.class);
- ReportingParseRunner<HtmlPath> runner = new ReportingParseRunner<>(parser.HtmlPath());
- ParsingResult<HtmlPath> result = runner.run(value);
- if (result.hasErrors()) {
- // TODO: wrap in result
- throw new RuntimeException("Parse error");
- } else {
- return result.valueStack.peek();
- }
- }
-
- Rule HtmlPath() {
- ListVar<HtmlPathElement> elements = new ListVar<>();
- return Sequence(Optional(HtmlPathElements(elements)), EOI, push(new HtmlPath(elements.build())));
- }
-
- Rule HtmlPathElements(ListVar<HtmlPathElement> elements) {
- Var<HtmlPathElement> element = new Var<>();
- return Sequence(
- HtmlPathElement(element),
- elements.append(element),
- ZeroOrMore(Sequence(Whitespace(), Ch('>'), Whitespace(), HtmlPathElement(element), elements.append(element))));
- }
-
- Rule HtmlPathElement(Var<HtmlPathElement> element) {
- ListVar<String> tagNames = new ListVar<>();
- ListVar<String> classNames = new ListVar<>();
- Var<Boolean> fresh = new Var<>();
- return Sequence(
- TagNames(tagNames),
- ClassNames(classNames),
- Fresh(fresh),
- element.set(new HtmlPathElement(
- tagNames.build(),
- classNames.isEmpty() ? map() : map("class", String.join(" ", classNames.build())),
- !fresh.get())));
- }
-
- Rule TagNames(ListVar<String> tagNames) {
- return Sequence(
- Identifier(),
- tagNames.append(match()),
- ZeroOrMore(Sequence("|", Identifier(), tagNames.append(match()))));
- }
-
- Rule ClassNames(ListVar<String> classNames) {
- Var<String> className = new Var<>();
- return ZeroOrMore(Sequence(ClassName(className), classNames.append(className)));
- }
-
- Rule ClassName(Var<String> className) {
- return Sequence(".", Identifier(), className.set(match()));
- }
-
- Rule Fresh(Var<Boolean> fresh) {
- return Sequence(fresh.set(false), Optional(":fresh", fresh.set(true)));
- }
-
- Rule Identifier() {
- return Sequence(
- FirstOf(CharRange('a', 'z'), CharRange('A', 'Z')),
- ZeroOrMore(FirstOf(CharRange('a', 'z'), CharRange('A', 'Z'), CharRange('0', '9'), Ch('-'), Ch('_'))));
- }
-
- Rule Whitespace() {
- return ZeroOrMore(AnyOf(" \t"));
- }
-
- class ListVar<T> extends Var<ImmutableList.Builder<T>> {
- boolean append(Var<T> element) {
- return append(element.get());
- }
-
- boolean append(T element) {
- if (get() == null) {
- set(ImmutableList.builder());
- }
- return set(get().add(element));
- }
-
- public List<T> build() {
- if (get() == null) {
- return list();
- } else {
- return get().build();
- }
- }
- public boolean isEmpty() {
- return get() == null;
- }
- }
}
diff --git a/src/main/java/org/zwobble/mammoth/styles/parsing/HtmlPathParser.java b/src/main/java/org/zwobble/mammoth/styles/parsing/HtmlPathParser.java
new file mode 100644
index 0000000..18e1107
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/styles/parsing/HtmlPathParser.java
@@ -0,0 +1,68 @@
+package org.zwobble.mammoth.styles.parsing;
+
+import org.parboiled.BaseParser;
+import org.parboiled.Rule;
+import org.parboiled.support.Var;
+import org.zwobble.mammoth.styles.HtmlPath;
+import org.zwobble.mammoth.styles.HtmlPathElement;
+
+import static org.zwobble.mammoth.util.MammothMaps.map;
+
+public class HtmlPathParser extends BaseParser<HtmlPath> {
+ public Rule HtmlPath() {
+ ListVar<HtmlPathElement> elements = new ListVar<>();
+ return Sequence(Optional(HtmlPathElements(elements)), EOI, push(new HtmlPath(elements.build())));
+ }
+
+ Rule HtmlPathElements(ListVar<HtmlPathElement> elements) {
+ Var<HtmlPathElement> element = new Var<>();
+ return Sequence(
+ HtmlPathElement(element),
+ elements.append(element),
+ ZeroOrMore(Sequence(Whitespace(), Ch('>'), Whitespace(), HtmlPathElement(element), elements.append(element))));
+ }
+
+ Rule HtmlPathElement(Var<HtmlPathElement> element) {
+ ListVar<String> tagNames = new ListVar<>();
+ ListVar<String> classNames = new ListVar<>();
+ Var<Boolean> fresh = new Var<>();
+ return Sequence(
+ TagNames(tagNames),
+ ClassNames(classNames),
+ Fresh(fresh),
+ element.set(new HtmlPathElement(
+ tagNames.build(),
+ classNames.isEmpty() ? map() : map("class", String.join(" ", classNames.build())),
+ !fresh.get())));
+ }
+
+ Rule TagNames(ListVar<String> tagNames) {
+ return Sequence(
+ Identifier(),
+ tagNames.append(match()),
+ ZeroOrMore(Sequence("|", Identifier(), tagNames.append(match()))));
+ }
+
+ Rule ClassNames(ListVar<String> classNames) {
+ Var<String> className = new Var<>();
+ return ZeroOrMore(Sequence(ClassName(className), classNames.append(className)));
+ }
+
+ Rule ClassName(Var<String> className) {
+ return Sequence(".", Identifier(), className.set(match()));
+ }
+
+ Rule Fresh(Var<Boolean> fresh) {
+ return Sequence(fresh.set(false), Optional(":fresh", fresh.set(true)));
+ }
+
+ Rule Identifier() {
+ return Sequence(
+ FirstOf(CharRange('a', 'z'), CharRange('A', 'Z')),
+ ZeroOrMore(FirstOf(CharRange('a', 'z'), CharRange('A', 'Z'), CharRange('0', '9'), Ch('-'), Ch('_'))));
+ }
+
+ Rule Whitespace() {
+ return ZeroOrMore(AnyOf(" \t"));
+ }
+}
diff --git a/src/main/java/org/zwobble/mammoth/styles/parsing/ListVar.java b/src/main/java/org/zwobble/mammoth/styles/parsing/ListVar.java
new file mode 100644
index 0000000..e23acf8
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/styles/parsing/ListVar.java
@@ -0,0 +1,34 @@
+package org.zwobble.mammoth.styles.parsing;
+
+
+import com.google.common.collect.ImmutableList;
+import org.parboiled.support.Var;
+
+import java.util.List;
+
+import static org.zwobble.mammoth.util.MammothLists.list;
+
+class ListVar<T> extends Var<ImmutableList.Builder<T>> {
+ boolean append(Var<T> element) {
+ return append(element.get());
+ }
+
+ boolean append(T element) {
+ if (get() == null) {
+ set(ImmutableList.builder());
+ }
+ return set(get().add(element));
+ }
+
+ public List<T> build() {
+ if (get() == null) {
+ return list();
+ } else {
+ return get().build();
+ }
+ }
+
+ public boolean isEmpty() {
+ return get() == null;
+ }
+}
diff --git a/src/main/java/org/zwobble/mammoth/styles/parsing/Parsing.java b/src/main/java/org/zwobble/mammoth/styles/parsing/Parsing.java
new file mode 100644
index 0000000..761e7b8
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/styles/parsing/Parsing.java
@@ -0,0 +1,23 @@
+package org.zwobble.mammoth.styles.parsing;
+
+import org.parboiled.BaseParser;
+import org.parboiled.Parboiled;
+import org.parboiled.Rule;
+import org.parboiled.parserunners.ReportingParseRunner;
+import org.parboiled.support.ParsingResult;
+
+import java.util.function.Function;
+
+public class Parsing {
+ public static <T, U extends BaseParser<T>> T parse(Class<U> parserType, Function<U, Rule> rule, String value) {
+ U parser = Parboiled.createParser(parserType);
+ ReportingParseRunner<T> runner = new ReportingParseRunner<>(rule.apply(parser));
+ ParsingResult<T> result = runner.run(value);
+ if (result.hasErrors()) {
+ // TODO: wrap in result
+ throw new RuntimeException("Parse error");
+ } else {
+ return result.valueStack.peek();
+ }
+ }
+}
diff --git a/src/test/java/org/zwobble/mammoth/tests/styles/HtmlPathParsingTests.java b/src/test/java/org/zwobble/mammoth/tests/styles/HtmlPathParsingTests.java
index b2a4433..c6d0cb1 100644
--- a/src/test/java/org/zwobble/mammoth/tests/styles/HtmlPathParsingTests.java
+++ b/src/test/java/org/zwobble/mammoth/tests/styles/HtmlPathParsingTests.java
@@ -3,7 +3,8 @@ package org.zwobble.mammoth.tests.styles;
import org.junit.Test;
import org.zwobble.mammoth.styles.HtmlPath;
import org.zwobble.mammoth.styles.HtmlPathElement;
-import org.zwobble.mammoth.styles.StyleMapParser;
+import org.zwobble.mammoth.styles.parsing.HtmlPathParser;
+import org.zwobble.mammoth.styles.parsing.Parsing;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.zwobble.mammoth.tests.DeepReflectionMatcher.deepEquals;
@@ -14,53 +15,57 @@ public class HtmlPathParsingTests {
@Test
public void canParseEmptyPath() {
assertThat(
- StyleMapParser.parseHtmlPath(""),
+ parseHtmlPath(""),
deepEquals(HtmlPath.EMPTY));
}
@Test
public void canReadSingleElement() {
assertThat(
- StyleMapParser.parseHtmlPath("p"),
+ parseHtmlPath("p"),
deepEquals(HtmlPath.collapsibleElement("p")));
}
@Test
public void canReadElementWithChoiceOfTagNames() {
assertThat(
- StyleMapParser.parseHtmlPath("ul|ol"),
+ parseHtmlPath("ul|ol"),
deepEquals(HtmlPath.collapsibleElement(list("ul", "ol"))));
assertThat(
- StyleMapParser.parseHtmlPath("ul|ol|p"),
+ parseHtmlPath("ul|ol|p"),
deepEquals(HtmlPath.collapsibleElement(list("ul", "ol", "p"))));
}
@Test
public void canReadNestedElements() {
assertThat(
- StyleMapParser.parseHtmlPath("ul > li"),
+ parseHtmlPath("ul > li"),
deepEquals(new HtmlPath(list(HtmlPathElement.collapsible("ul"), HtmlPathElement.collapsible("li")))));
}
@Test
public void canReadClassOnElement() {
assertThat(
- StyleMapParser.parseHtmlPath("p.tip"),
+ parseHtmlPath("p.tip"),
deepEquals(HtmlPath.collapsibleElement("p", map("class", "tip"))));
}
@Test
public void canReadMultipleClassesOnElement() {
assertThat(
- StyleMapParser.parseHtmlPath("p.tip.help"),
+ parseHtmlPath("p.tip.help"),
deepEquals(HtmlPath.collapsibleElement("p", map("class", "tip help"))));
}
@Test
public void canReadWhenElementMustBeFresh() {
assertThat(
- StyleMapParser.parseHtmlPath("p:fresh"),
+ parseHtmlPath("p:fresh"),
deepEquals(HtmlPath.element("p")));
}
+
+ private HtmlPath parseHtmlPath(String input) {
+ return Parsing.parse(HtmlPathParser.class, HtmlPathParser::HtmlPath, input);
+ }
}