Skip to content

Commit

Permalink
Draft node extended
Browse files Browse the repository at this point in the history
  • Loading branch information
kniazkov committed May 30, 2024
1 parent c51292b commit 52025a6
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
42 changes: 36 additions & 6 deletions src/main/java/org/cqfn/astranaut/core/DraftNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Draft node for wrapping the results of third-party parsers
Expand Down Expand Up @@ -121,16 +124,35 @@ public String toString() {
*/
@SuppressWarnings("PMD.ProhibitPublicStaticMethods")
public static Node createByDescription(final String description) {
return DraftNode.createByDescription(description, null);
}

/**
* Creates a tree from draft nodes based on description.
* Description format: A(B,C(...),...) where 'A' is the type name
* (it consists only of letters) followed by child nodes (in the same format) in parentheses
* separated by commas.
* @param description Description
* @param nodes Collection in which to place the nodes to be created, sorted by type name
* @return Root node of the tree created by description
*/
@SuppressWarnings("PMD.ProhibitPublicStaticMethods")
public static Node createByDescription(
final String description,
final Map<String, Set<Node>> nodes) {
final CharacterIterator iterator = new StringCharacterIterator(description);
return DraftNode.createByDescription(iterator);
return DraftNode.createByDescription(iterator, nodes);
}

/**
* Creates a tree based on its description (recursive method).
* @param iterator Iterator by description characters
* @param nodes Collection in which to place the nodes to be created, sorted by type name
* @return Node of the tree with its children, created by description
*/
private static Node createByDescription(final CharacterIterator iterator) {
private static Node createByDescription(
final CharacterIterator iterator,
final Map<String, Set<Node>> nodes) {
char symbol = iterator.current();
final Node result;
final StringBuilder name = new StringBuilder();
Expand All @@ -146,9 +168,14 @@ private static Node createByDescription(final CharacterIterator iterator) {
symbol = iterator.current();
}
if (symbol == '(') {
builder.setChildrenList(DraftNode.parseChildrenList(iterator));
builder.setChildrenList(DraftNode.parseChildrenList(iterator, nodes));
}
result = builder.createNode();
if (nodes != null) {
final Set<Node> set =
nodes.computeIfAbsent(result.getTypeName(), k -> new HashSet<>());
set.add(result);
}
} else {
result = null;
}
Expand Down Expand Up @@ -181,15 +208,18 @@ private static String parseData(final CharacterIterator iterator) {
/**
* Parses children list from description.
* @param iterator Iterator by description characters
* @param nodes Collection in which to place the nodes to be created, sorted by type name
* @return Children list, created by description
*/
private static List<Node> parseChildrenList(final CharacterIterator iterator) {
private static List<Node> parseChildrenList(
final CharacterIterator iterator,
final Map<String, Set<Node>> nodes) {
assert iterator.current() == '(';
final List<Node> children = new LinkedList<>();
char next;
do {
iterator.next();
final Node child = DraftNode.createByDescription(iterator);
final Node child = DraftNode.createByDescription(iterator, nodes);
if (child != null) {
children.add(child);
}
Expand All @@ -213,7 +243,7 @@ private static class TypeImpl implements Type {

/**
* Constructor.
* @param name The type name
* @param name The type name`
*/
TypeImpl(final String name) {
this.name = name;
Expand Down
34 changes: 34 additions & 0 deletions src/test/java/org/cqfn/astranaut/core/DraftNodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
package org.cqfn.astranaut.core;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -76,6 +80,36 @@ void constructorTest() {
Assertions.assertEquals(serialized, ctor.createNode().toString());
}

/**
* Testing {@link DraftNode#createByDescription(String, Map)} method.
*/
@Test
void testExtendedDescriptorProcessor() {
final Map<String, Set<Node>> nodes = new TreeMap<>();
final Node root = DraftNode.createByDescription("X(A,A,B(C,D))", nodes);
Assertions.assertSame(
root,
nodes.computeIfAbsent(
"X",
s -> Collections.singleton(EmptyTree.INSTANCE)
).iterator().next()
);
Assertions.assertEquals(
2,
nodes.computeIfAbsent(
"A",
s -> Collections.singleton(EmptyTree.INSTANCE)
).size()
);
Assertions.assertEquals(
2,
nodes.computeIfAbsent(
"B",
s -> Collections.singleton(EmptyTree.INSTANCE)
).iterator().next().getChildCount()
);
}

/**
* Testing {@link DraftNode#createByDescription(String)} and
* {@link DraftNode#toString()} methods (testing of one case).
Expand Down

0 comments on commit 52025a6

Please sign in to comment.