Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 95 additions & 12 deletions src/main/java/org/example/ebnfFormatter/render/TemplateRenderer.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package org.example.ebnfFormatter.render;

import com.github.javaparser.JavaToken;
import com.github.javaparser.TokenRange;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.AssignExpr;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.UnaryExpr;
import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.type.PrimitiveType;
import com.github.javaparser.metamodel.PropertyMetaModel;
import com.github.javaparser.printer.Stringable;
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
import org.example.ebnfFormatter.match.AppliedRuleValue;
import org.example.ebnfFormatter.match.Bindings;
import org.example.ebnfFormatter.match.BoundValue;
Expand Down Expand Up @@ -96,13 +90,93 @@ private void renderJoin(
RenderContext context
) {
List<BoundValue> items = bindings.findValues(join.placeholderName());
boolean hasEmptySeparator = isEmptyFormat(join.separator());

for (int i = 0; i < items.size(); i++) {
BoundValue item = items.get(i);
if (i > 0) {
renderInto(join.separator(), bindings, nestedRuleRenderer, context);
if (hasEmptySeparator) {
appendOriginalGapBetween(items.get(i - 1), item, context);
} else {
renderInto(join.separator(), bindings, nestedRuleRenderer, context);
}
}
renderBoundValue(join.placeholderName(), item, nestedRuleRenderer, context);
}

if (hasEmptySeparator && !items.isEmpty()) {
appendOriginalGapAfter(items.getLast(), context);
}
}

private boolean isEmptyFormat(FormatAst format) {
return switch (format) {
case FormatText text -> text.text().isEmpty();
case FormatSeq seq -> seq.items().stream().allMatch(this::isEmptyFormat);
case FormatGroup group -> isEmptyFormat(group.body());
default -> false;
};
}

private void appendOriginalGapBetween(BoundValue left, BoundValue right, RenderContext context) {
originalGapBetween(left.legacyValue(), right.legacyValue()).ifPresent(context::appendText);
}

private void appendOriginalGapAfter(BoundValue value, RenderContext context) {
originalGapAfter(value.legacyValue()).ifPresent(context::appendText);
}

private Optional<String> originalGapBetween(Object left, Object right) {
Optional<TokenRange> leftRange = tokenRange(left);
Optional<TokenRange> rightRange = tokenRange(right);
if (leftRange.isEmpty() || rightRange.isEmpty()) {
return Optional.empty();
}

JavaToken end = rightRange.get().getBegin();
Optional<JavaToken> current = leftRange.get().getEnd().getNextToken();
StringBuilder text = new StringBuilder();

while (current.isPresent() && current.get() != end) {
JavaToken token = current.get();
if (!token.getCategory().isWhitespaceOrComment()) {
return Optional.empty();
}
renderBoundValue(join.placeholderName(), items.get(i), nestedRuleRenderer, context);
text.append(token.getText());
current = token.getNextToken();
}

return current.isPresent() ? Optional.of(text.toString()) : Optional.empty();
}

private Optional<String> originalGapAfter(Object value) {
Optional<TokenRange> range = tokenRange(value);
if (range.isEmpty()) {
return Optional.empty();
}

Optional<JavaToken> current = range.get().getEnd().getNextToken();
StringBuilder text = new StringBuilder();

while (current.isPresent() && current.get().getCategory().isWhitespaceOrComment()) {
JavaToken token = current.get();
text.append(token.getText());
current = token.getNextToken();
}

return Optional.of(text.toString());
}

private Optional<TokenRange> tokenRange(Object value) {
if (value instanceof Node node) {
return node.getTokenRange();
}

if (value instanceof Optional<?> optional) {
return optional.flatMap(this::tokenRange);
}

return Optional.empty();
}

private void renderBoundValue(
Expand Down Expand Up @@ -224,7 +298,16 @@ private void renderNode(Node node, NestedRuleRenderer nestedRuleRenderer, Render
return;
}

context.appendText(node.toString());
context.appendText(sourceText(node));
}

private String sourceText(Node node) {
if (LexicalPreservingPrinter.isAvailableOn(node)) { // может быть полезно для маштабирования
return LexicalPreservingPrinter.print(node);
}
return node.getTokenRange()
.map(TokenRange::toString)
.orElseGet(() -> LexicalPreservingPrinter.print(node));
}

private String stripQuantifierSuffix(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

public class ALotOfEndToEndTest {

private static final String ALL_RULES = """
private static final String ALL_RULES = """
<CompilationUnit> ::= CompilationUnit(packageDeclaration?=<PackageDeclaration>, imports=[<ImportDeclaration>*], types=[<ClassOrInterfaceDeclaration>*])
=> ifpresent(PackageDeclaration, <PackageDeclaration> nl nl)
ifpresent(ImportDeclaration, join(<ImportDeclaration>, nl) nl nl)
Expand Down Expand Up @@ -70,7 +70,7 @@ public class ALotOfEndToEndTest {

<ElseStmt> ::= <NestedIf>
=> sp <NestedIf>;

<NestedIf> ::= IfStmt(condition=<CondExpr>, thenStmt=<ThenStmt>, elseStmt?=<ElseStmt>)
=> "if" sp "(" <CondExpr> ")" <ThenStmt>
ifpresent(ElseStmt, nl "else" <ElseStmt>);
Expand Down Expand Up @@ -189,7 +189,7 @@ public class MathBox{public static int sum(int a,int b){return a+b;}}
"""
public class MathBox {
public static int sum(int a, int b) {
return a + b;
return a+b;
}
}"""
);
Expand Down Expand Up @@ -223,7 +223,7 @@ class Branches{int max(int a,int b){if(a>b)return a;else return b;}}
"""
class Branches {
int max(int a, int b) {
if (a > b)
if (a>b)
return a;
else
return b;
Expand All @@ -241,9 +241,9 @@ class Branches{int choose(int a,int b){if(a>b)return a;else if(a==b)return 0;els
"""
class Branches {
int choose(int a, int b) {
if (a > b)
if (a>b)
return a;
else if (a == b)
else if (a==b)
return 0;
else
return b;
Expand All @@ -261,7 +261,7 @@ class Branches{int max(int a,int b){if(a>b){a++;return a;}else{b++;return b;}}}
"""
class Branches {
int max(int a, int b) {
if (a > b) {
if (a>b) {
a++;
return a;
}
Expand Down Expand Up @@ -299,7 +299,7 @@ class Loop{void run(){for(i=0,j=1;i<10;i++,j++)step();}}
"""
class Loop {
void run() {
for (i = 0, j = 1; i < 10; i++, j++)
for (i=0, j=1; i<10; i++, j++)
step();
}
}"""
Expand All @@ -315,7 +315,7 @@ class Loop{void run(){for(i=0,j=1;;i++,j++)step();}}
"""
class Loop {
void run() {
for (i = 0, j = 1;; i++, j++)
for (i=0, j=1;; i++, j++)
step();
}
}"""
Expand All @@ -331,7 +331,7 @@ class Loop{void run(){for(i=0;i<3;i++){step();step();}}}
"""
class Loop {
void run() {
for (i = 0; i < 3; i++) {
for (i=0; i<3; i++) {
step();
step();
}
Expand Down Expand Up @@ -367,7 +367,7 @@ class Counter{int run(){int x=1;x++;return x;}}
"""
class Counter {
int run() {
int x = 1;
int x=1;
x++;
return x;
}
Expand Down Expand Up @@ -484,8 +484,8 @@ class Complex{int run(int x){if(x>0)for(i=0;i<3;i++)tick();else return x;}}
"""
class Complex {
int run(int x) {
if (x > 0)
for (i = 0; i < 3; i++)
if (x>0)
for (i=0; i<3; i++)
tick();
else
return x;
Expand All @@ -503,10 +503,10 @@ class Complex{int run(int x){if(x>0)return x;else for(i=0;i<2;i++){tick();tick()
"""
class Complex {
int run(int x) {
if (x > 0)
if (x>0)
return x;
else
for (i = 0; i < 2; i++) {
for (i=0; i<2; i++) {
tick();
tick();
}
Expand All @@ -524,8 +524,8 @@ class Scanner{int scan(int limit){for(i=0;i<limit;i++){if(i==2)return i;step();}
"""
class Scanner {
int scan(int limit) {
for (i = 0; i < limit; i++) {
if (i == 2)
for (i=0; i<limit; i++) {
if (i==2)
return i;
step();
}
Expand All @@ -544,8 +544,8 @@ class NestedLoop{void run(){for(i=0;i<2;i++){for(j=0;j<2;j++)tick();step();}}}
"""
class NestedLoop {
void run() {
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++)
for (i=0; i<2; i++) {
for (j=0; j<2; j++)
tick();
step();
}
Expand All @@ -563,8 +563,8 @@ class BlockFlow{int run(int a){if(a>0){for(i=0;i<a;i++)work();return a;}else{a--
"""
class BlockFlow {
int run(int a) {
if (a > 0) {
for (i = 0; i < a; i++)
if (a>0) {
for (i=0; i<a; i++)
work();
return a;
}
Expand Down Expand Up @@ -600,7 +600,7 @@ int fallback() {

class Derived {
int run(int a) {
if (a > 1)
if (a>1)
return a;
else
return 1;
Expand All @@ -622,14 +622,14 @@ void boot() {
}

int choose(int a, int b) {
if (a > b)
if (a>b)
return a;
else
return b;
}

void spin() {
for (i = 0; i < 3; i++)
for (i=0; i<3; i++)
tick();
}
}"""
Expand All @@ -652,9 +652,9 @@ int id() {

class Second {
int pick(int a, int b, int c) {
if (a > b)
if (a>b)
return a;
else if (b > c)
else if (b>c)
return b;
else
return c;
Expand Down Expand Up @@ -683,7 +683,7 @@ class Empty {}

class Worker {
void go() {
for (i = 0; i < 1; i++) {
for (i=0; i<1; i++) {
step();
}
}
Expand All @@ -700,16 +700,16 @@ class Deep{int run(int a,int b){if(a>b){for(i=0;i<a;i++){if(i==b)return i;tick()
"""
class Deep {
int run(int a, int b) {
if (a > b) {
for (i = 0; i < a; i++) {
if (i == b)
if (a>b) {
for (i=0; i<a; i++) {
if (i==b)
return i;
tick();
}
return a;
}
else if (a == b) {
for (i = 0;; i++)
else if (a==b) {
for (i=0;; i++)
step();
}
else {
Expand Down Expand Up @@ -746,12 +746,10 @@ else if (a == b) {
class Deep {
int run(int a, int b) {
if (a > b) {
while (i < a) {
if (i == b)
return i;
tick();
++i;
}
while (i < a) {
if (i == b)
return i;tick();++i;
}
return a;
}
else if (a == b) {
Expand Down
Loading
Loading