Support Markdown lists
This commit is contained in:
parent
301eaaf98d
commit
90f84950d2
24 changed files with 307 additions and 88 deletions
|
@ -46,9 +46,9 @@ public class GrammarGraphMLParser implements GraphMLParser {
|
|||
}
|
||||
|
||||
private Node processNodeElem(final ParseTree nodeElem) {
|
||||
final String id = extractAttribute(nodeElem.child("tag:node"), "id");
|
||||
final String id = extractAttribute(nodeElem.getChild("tag:node"), "id");
|
||||
|
||||
final Map<String, String> data = nodeElem.child("content").getChildren()
|
||||
final Map<String, String> data = nodeElem.getChild("content").getChildren()
|
||||
.stream()
|
||||
.map(this::extractDataElemContent)
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
|
@ -57,11 +57,11 @@ public class GrammarGraphMLParser implements GraphMLParser {
|
|||
}
|
||||
|
||||
private Edge processEdgeElem(final ParseTree edgeElem) {
|
||||
final String id = extractAttribute(edgeElem.child("tag:edge"), "id");
|
||||
final String source = extractAttribute(edgeElem.child("tag:edge"), "source");
|
||||
final String target = extractAttribute(edgeElem.child("tag:edge"), "target");
|
||||
final String id = extractAttribute(edgeElem.getChild("tag:edge"), "id");
|
||||
final String source = extractAttribute(edgeElem.getChild("tag:edge"), "source");
|
||||
final String target = extractAttribute(edgeElem.getChild("tag:edge"), "target");
|
||||
|
||||
final Map<String, String> data = edgeElem.child("content").getChildren()
|
||||
final Map<String, String> data = edgeElem.getChild("content").getChildren()
|
||||
.stream()
|
||||
.map(this::extractDataElemContent)
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
|
@ -70,16 +70,16 @@ public class GrammarGraphMLParser implements GraphMLParser {
|
|||
}
|
||||
|
||||
private Map.Entry<String, String> extractDataElemContent(final ParseTree dataElem) {
|
||||
final var attribute = extractAttribute(dataElem.child("tag:data"), "key");
|
||||
final var content = dataElem.child(1).getText();
|
||||
final var attribute = extractAttribute(dataElem.getChild("tag:data"), "key");
|
||||
final var content = dataElem.getChild(1).getText();
|
||||
return Map.entry(attribute, content);
|
||||
}
|
||||
|
||||
private String extractAttribute(final ParseTree tag, final String attributeKey) {
|
||||
return tag.child("attributes").getChildren()
|
||||
return tag.getChild("attributes").getChildren()
|
||||
.stream()
|
||||
.filter(a -> a.child(0).getText().equals(attributeKey))
|
||||
.map(a -> a.child(1).getText())
|
||||
.filter(a -> a.getChild(0).getText().equals(attributeKey))
|
||||
.map(a -> a.getChild(1).getText())
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
|
|
@ -7,21 +7,68 @@ import static com.albertoventurini.parsley.grammar.rules.Rules.*;
|
|||
|
||||
public class MarkdownGrammar extends Grammar {
|
||||
|
||||
private final char NEWLINE = '\n';
|
||||
|
||||
private final char BOLD_DELIMITER = '*';
|
||||
|
||||
private final char ITALIC_DELIMITER = '_';
|
||||
|
||||
private final Rule h1 = sequence(
|
||||
character('#'),
|
||||
takeWhile(c -> c != '\n')
|
||||
);
|
||||
takeWhile(c -> c != NEWLINE).as("text")
|
||||
).as("h1");
|
||||
|
||||
private final Rule h2 = sequence(
|
||||
string("##"),
|
||||
takeWhile(c -> c != NEWLINE).as("text")
|
||||
).as("h2");
|
||||
|
||||
private final Rule h3 = sequence(
|
||||
string("###"),
|
||||
takeWhile(c -> c != NEWLINE).as("text")
|
||||
).as("h3");
|
||||
|
||||
private final Rule headers = sequence(oneOf(h3, h2, h1), zeroOrMore(character(NEWLINE)));
|
||||
|
||||
private final Rule plainText = takeWhile(c ->
|
||||
c != NEWLINE
|
||||
&& c != BOLD_DELIMITER
|
||||
&& c != ITALIC_DELIMITER
|
||||
).as("text");
|
||||
|
||||
private final Rule bold = sequence(
|
||||
character(BOLD_DELIMITER),
|
||||
takeWhile(c -> c != NEWLINE && c != BOLD_DELIMITER).as("bold"),
|
||||
character(BOLD_DELIMITER)
|
||||
).as("boldWrapper");
|
||||
|
||||
private final Rule italic = sequence(
|
||||
character(ITALIC_DELIMITER),
|
||||
takeWhile(c -> c != NEWLINE && c != ITALIC_DELIMITER).as("italic"),
|
||||
character(ITALIC_DELIMITER)
|
||||
).as("italicWrapper");
|
||||
|
||||
private final Rule text = oneOf(
|
||||
bold,
|
||||
italic,
|
||||
plainText);
|
||||
|
||||
private final Rule paragraph = sequence(
|
||||
character('\n'),
|
||||
takeWhile(c -> c != '\n')
|
||||
);
|
||||
oneOrMore(text).as("paragraph"),
|
||||
zeroOrMore(character(NEWLINE))
|
||||
).as("paragraphWrapper");
|
||||
|
||||
private final Rule element = oneOf(h1, paragraph);
|
||||
private final Rule listItem = sequence(
|
||||
oneOf(string("* "), string("- ")),
|
||||
takeWhile(c -> c != NEWLINE).as("listItem"),
|
||||
character(NEWLINE)
|
||||
).as("listItemWrapper");
|
||||
|
||||
private final Rule elements = sequence(element);
|
||||
private final Rule list = sequence(oneOrMore(listItem).as("list"), zeroOrMore(character(NEWLINE)));
|
||||
|
||||
private final Rule document = zeroOrMore(elements);
|
||||
private final Rule element = oneOf(headers, list, paragraph);
|
||||
|
||||
private final Rule document = zeroOrMore(element);
|
||||
|
||||
@Override
|
||||
public Rule startRule() {
|
||||
|
@ -32,4 +79,9 @@ public class MarkdownGrammar extends Grammar {
|
|||
protected Rule commentRule() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean whitespace(final char c) {
|
||||
return c != '\n' && Character.isWhitespace(c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package com.albertoventurini.parsley.examples.graphml;
|
||||
|
||||
import com.albertoventurini.parsley.examples.markdown.MarkdownGrammar;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class MarkdownGrammarTest {
|
||||
|
||||
@Test
|
||||
public void markdownGrammar_withH1AndParagraph_shouldParse() {
|
||||
final MarkdownGrammar grammar = new MarkdownGrammar();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.albertoventurini.parsley.examples.markdown;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class MarkdownGrammarTest {
|
||||
|
||||
private final MarkdownGrammar grammar = new MarkdownGrammar();
|
||||
|
||||
@Test
|
||||
public void shouldParseH1() {
|
||||
final var parseResult = grammar.parse("# hello world");
|
||||
|
||||
assertTrue(parseResult.isPresent());
|
||||
assertEquals("# hello world", parseResult.get().getText());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("h1").isPresent());
|
||||
assertEquals("# hello world", parseResult.get().getFirstDescendantByName("h1").get().getText());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("text").isPresent());
|
||||
assertEquals("hello world", parseResult.get().getFirstDescendantByName("text").get().getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseH2() {
|
||||
final var parseResult = grammar.parse("## hello world");
|
||||
|
||||
assertTrue(parseResult.isPresent());
|
||||
assertEquals("## hello world", parseResult.get().getText());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("h2").isPresent());
|
||||
assertEquals("## hello world", parseResult.get().getFirstDescendantByName("h2").get().getText());
|
||||
assertNotNull(parseResult.get().getFirstDescendantByName("text"));
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("text").isPresent());
|
||||
assertEquals("hello world", parseResult.get().getFirstDescendantByName("text").get().getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseParagraph() {
|
||||
final var parseResult = grammar.parse("hello world");
|
||||
|
||||
assertTrue(parseResult.isPresent());
|
||||
assertEquals("hello world", parseResult.get().getText());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("paragraph").isPresent());
|
||||
assertEquals("hello world", parseResult.get().getFirstDescendantByName("paragraph").get().getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseParagraphWithBoldText() {
|
||||
final var parseResult = grammar.parse("hello world *bold text* normal text");
|
||||
|
||||
assertTrue(parseResult.isPresent());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("paragraph").isPresent());
|
||||
assertEquals(3, parseResult.get().getFirstDescendantByName("paragraph").get().getChildren().size());
|
||||
assertEquals("bold text", parseResult.get().getFirstDescendantByName("bold").get().getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldParseList() {
|
||||
final var parseResult = grammar.parse("hello world\n" +
|
||||
"\n" +
|
||||
"* first item\n" +
|
||||
"* second item\n" +
|
||||
"");
|
||||
|
||||
assertTrue(parseResult.isPresent());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("paragraph").isPresent());
|
||||
assertEquals("hello world", parseResult.get().getFirstDescendantByName("paragraph").get().getText());
|
||||
assertTrue(parseResult.get().getFirstDescendantByName("list").isPresent());
|
||||
assertEquals(2, parseResult.get().getFirstDescendantByName("list").get().getChildren().size());
|
||||
assertEquals("first item", parseResult.get().getFirstDescendantByName("list").get().getChildren().get(0).getFirstDescendantByName("listItem").get().getText());
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue