Skip to content
This repository has been archived by the owner on Jul 16, 2023. It is now read-only.

Commit

Permalink
Fix recursive toString in Grammar, Token and Pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimitry Ivanov committed Jul 23, 2018
1 parent 25acbb4 commit cb4a133
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.noties.prism4j;

import org.junit.Test;

import ru.noties.prism4j.annotations.PrismBundle;

@PrismBundle(includeAll = true, grammarLocatorClassName = ".GrammarLocatorToStringTest")
public class ToStringTest {

@Test
public void test() {

final GrammarLocator locator = new GrammarLocatorToStringTest();
final Prism4j prism4j = new Prism4j(locator);

Prism4j.Grammar grammar;

for (String language : locator.languages()) {
grammar = prism4j.grammar(language);
if (grammar != null) {
System.err.printf("language: %s, toString: %s%n", language, ToString.toString(grammar));
}
}
}
}
5 changes: 1 addition & 4 deletions prism4j/src/main/java/ru/noties/prism4j/GrammarImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ public List<Prism4j.Token> tokens() {

@Override
public String toString() {
return "GrammarImpl{" +
"name='" + name + '\'' +
", tokens=" + tokens +
'}';
return ToString.toString(this);
}
}
8 changes: 1 addition & 7 deletions prism4j/src/main/java/ru/noties/prism4j/PatternImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ public Prism4j.Grammar inside() {

@Override
public String toString() {
return "PatternImpl{" +
"regex=" + regex +
", lookbehind=" + lookbehind +
", greedy=" + greedy +
", alias='" + alias + '\'' +
", inside=" + inside +
'}';
return ToString.toString(this);
}
}
153 changes: 153 additions & 0 deletions prism4j/src/main/java/ru/noties/prism4j/ToString.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package ru.noties.prism4j;

import android.support.annotation.NonNull;

import java.util.HashSet;
import java.util.Set;

abstract class ToString {

@NonNull
static String toString(@NonNull Prism4j.Grammar grammar) {
final StringBuilder builder = new StringBuilder();
toString(builder, new CacheImpl(), grammar);
return builder.toString();
}

@NonNull
static String toString(@NonNull Prism4j.Token token) {
final StringBuilder builder = new StringBuilder();
toString(builder, new CacheImpl(), token);
return builder.toString();
}

@NonNull
static String toString(@NonNull Prism4j.Pattern pattern) {
final StringBuilder builder = new StringBuilder();
toString(builder, new CacheImpl(), pattern);
return builder.toString();
}

private ToString() {
}

private interface Cache {

boolean visited(@NonNull Object o);

void markVisited(@NonNull Object o);
}

private static void toString(@NonNull StringBuilder builder, @NonNull Cache cache, @NonNull Prism4j.Grammar grammar) {

builder
.append("Grammar{id=0x")
.append(Integer.toHexString(System.identityHashCode(grammar)))
.append(",name=\"")
.append(grammar.name())
.append('\"');

if (cache.visited(grammar)) {
builder.append(",[...]");
} else {
cache.markVisited(grammar);
builder.append(",tokens=[");
boolean first = true;
for (Prism4j.Token token : grammar.tokens()) {
if (first) {
first = false;
} else {
builder.append(',');
}
toString(builder, cache, token);
}
builder.append(']');
}

builder.append('}');
}

private static void toString(@NonNull StringBuilder builder, @NonNull Cache cache, @NonNull Prism4j.Token token) {

builder
.append("Token{id=0x")
.append(Integer.toHexString(System.identityHashCode(token)))
.append(",name=\"")
.append(token.name())
.append('\"');

if (cache.visited(token)) {
builder.append(",[...]");
} else {
cache.markVisited(token);
builder.append(",patterns=[");
boolean first = true;
for (Prism4j.Pattern pattern : token.patterns()) {
if (first) {
first = false;
} else {
builder.append(',');
}
toString(builder, cache, pattern);
}
builder.append(']');
}
builder.append('}');
}

private static void toString(@NonNull StringBuilder builder, @NonNull Cache cache, @NonNull Prism4j.Pattern pattern) {

builder
.append("Pattern{id=0x")
.append(Integer.toHexString(System.identityHashCode(pattern)));

if (cache.visited(pattern)) {
builder.append(",[...]");
} else {

cache.markVisited(pattern);

builder.append(",regex=\"").append(pattern.regex()).append('\"');

if (pattern.lookbehind()) {
builder.append(",lookbehind=true");
}

if (pattern.greedy()) {
builder.append(",greedy=true");
}

if (pattern.alias() != null) {
builder.append(",alias=\"").append(pattern.alias()).append('\"');
}

final Prism4j.Grammar inside = pattern.inside();
if (inside != null) {
builder.append(",inside=");
toString(builder, cache, inside);
}
}

builder.append('}');
}

private static class CacheImpl implements Cache {

private final Set<Integer> cache = new HashSet<>(3);

@Override
public boolean visited(@NonNull Object o) {
return cache.contains(key(o));
}

@Override
public void markVisited(@NonNull Object o) {
cache.add(key(o));
}

@NonNull
private static Integer key(@NonNull Object o) {
return System.identityHashCode(o);
}
}
}
5 changes: 1 addition & 4 deletions prism4j/src/main/java/ru/noties/prism4j/TokenImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ public List<Prism4j.Pattern> patterns() {

@Override
public String toString() {
return "TokenImpl{" +
"name='" + name + '\'' +
", patterns=" + patterns +
'}';
return ToString.toString(this);
}
}

0 comments on commit cb4a133

Please sign in to comment.