-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
884 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
plugins { | ||
id 'application' | ||
// Used to create a single executable jar file with all dependencies | ||
// see task "shadowJar" below | ||
// https://imperceptiblethoughts.com/shadow/ | ||
id 'com.github.johnrengelman.shadow' version "8.1.1" | ||
} | ||
|
||
dependencies { | ||
//logging implementation used by the slf4j | ||
implementation 'ch.qos.logback:logback-classic:1.5.6' | ||
implementation(project(":key.core")) | ||
} | ||
|
||
shadowJar { | ||
archiveClassifier.set("exe") | ||
archiveBaseName.set("key-format") | ||
mergeServiceFiles() | ||
} | ||
|
||
application { | ||
mainClassName = "de.uka.ilkd.key.nparser.format.KeYFileFormatter" | ||
} |
137 changes: 137 additions & 0 deletions
137
key.format/src/main/java/de/uka/ilkd/key/nparser/format/ExpressionVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package de.uka.ilkd.key.nparser.format; | ||
|
||
import de.uka.ilkd.key.nparser.KeYLexer; | ||
import de.uka.ilkd.key.nparser.KeYParser; | ||
import de.uka.ilkd.key.nparser.KeYParserBaseVisitor; | ||
import org.antlr.v4.runtime.CommonTokenStream; | ||
import org.antlr.v4.runtime.tree.TerminalNode; | ||
|
||
import java.util.Arrays; | ||
|
||
public class ExpressionVisitor extends KeYParserBaseVisitor<Void> { | ||
private static final int[] OPERATORS = { | ||
KeYLexer.LESS, | ||
KeYLexer.LESSEQUAL, | ||
KeYLexer.GREATER, | ||
KeYLexer.GREATEREQUAL, | ||
KeYLexer.EQUALS, | ||
KeYLexer.NOT_EQUALS, | ||
KeYLexer.IMP, | ||
KeYLexer.SEQARROW, | ||
KeYLexer.NOT_EQUALS, | ||
KeYLexer.AND, | ||
KeYLexer.OR, | ||
KeYLexer.PARALLEL, | ||
KeYLexer.EXP, | ||
KeYLexer.PERCENT, | ||
KeYLexer.STAR, | ||
KeYLexer.MINUS, | ||
KeYLexer.PLUS, | ||
KeYLexer.EQV, | ||
KeYLexer.ASSIGN, | ||
}; | ||
|
||
private final CommonTokenStream ts; | ||
private final Output output; | ||
|
||
public ExpressionVisitor(CommonTokenStream ts, Output output) { | ||
this.ts = ts; | ||
this.output = output; | ||
} | ||
|
||
private static void outputModality(String text, Output output) { | ||
var normalized = text.replaceAll("\t", Output.getIndent(1)); | ||
var lines = normalized.split("\n"); | ||
lines[0] = lines[0].trim(); | ||
|
||
// Find the smallest indent of all lines except the first | ||
int minIndent = Integer.MAX_VALUE; | ||
for (int i = 1; i < lines.length; i++) { | ||
var line = lines[i]; | ||
lines[i] = line.stripTrailing(); | ||
var indent = line.length() - line.stripLeading().length(); | ||
minIndent = Math.min(minIndent, indent); | ||
} | ||
|
||
output.token(lines[0]); | ||
if (lines.length > 1) { | ||
output.enterIndent(); | ||
|
||
for (int i = 1; i < lines.length; i++) { | ||
output.newLine(); | ||
var line = lines[i]; | ||
if (!line.isEmpty()) { | ||
output.token(line.substring(minIndent)); | ||
} | ||
} | ||
output.exitIndent(); | ||
} | ||
output.spaceBeforeNext(); | ||
} | ||
|
||
@Override | ||
public Void visitTerminal(TerminalNode node) { | ||
var token = node.getSymbol().getType(); | ||
|
||
boolean isLBrace = token == KeYLexer.LBRACE || token == KeYLexer.LPAREN | ||
|| token == KeYLexer.LBRACKET || token == KeYLexer.LGUILLEMETS; | ||
if (token == KeYLexer.RBRACE || token == KeYLexer.RPAREN || token == KeYLexer.RBRACKET | ||
|| token == KeYLexer.RGUILLEMETS) { | ||
output.noSpaceBeforeNext(); | ||
output.exitIndent(); | ||
} | ||
|
||
var isOperator = Arrays.stream(OPERATORS).anyMatch(v -> v == token); | ||
var isUnaryMinus = token == KeYLexer.MINUS && | ||
node.getParent() instanceof KeYParser.Unary_minus_termContext; | ||
// Unary minus has a "soft" leading space, we allow it if the token before wants it but | ||
// don't require it | ||
if ((isOperator && !isUnaryMinus) || token == KeYLexer.AVOID) { | ||
output.spaceBeforeNext(); | ||
} | ||
|
||
String text = node.getSymbol().getText(); | ||
if (token == KeYLexer.MODALITY) { | ||
outputModality(text, output); | ||
} else { | ||
output.token(text); | ||
} | ||
|
||
if (!isLBrace && ((isOperator && !isUnaryMinus) || | ||
token == KeYLexer.COMMA || | ||
token == KeYLexer.SUBST || | ||
token == KeYLexer.AVOID || | ||
token == KeYLexer.EXISTS || | ||
token == KeYLexer.FORALL || | ||
token == KeYLexer.SEMI)) { | ||
output.spaceBeforeNext(); | ||
} | ||
|
||
if (isLBrace) { | ||
output.enterIndent(); | ||
} | ||
|
||
KeYFileFormatter.processHiddenTokensAfterCurrent(node.getSymbol(), ts, output); | ||
return super.visitTerminal(node); | ||
} | ||
|
||
@Override | ||
public Void visitIfThenElseTerm(KeYParser.IfThenElseTermContext ctx) { | ||
for (int i = 0; i < ctx.getChildCount(); i++) { | ||
var child = ctx.getChild(i); | ||
if (child instanceof TerminalNode) { | ||
var token = ((TerminalNode) child).getSymbol().getType(); | ||
if (token == KeYParser.THEN) { | ||
output.enterIndent(); | ||
} | ||
|
||
if (token == KeYParser.THEN || token == KeYParser.ELSE) { | ||
output.spaceBeforeNext(); | ||
} | ||
} | ||
visit(child); | ||
} | ||
output.exitIndent(); | ||
return null; | ||
} | ||
} |
Oops, something went wrong.