build: upgrade Java
This commit is contained in:
@@ -7,7 +7,7 @@ group = "ru.di9.fluent"
|
|||||||
version = "1.0-SNAPSHOT"
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
java.toolchain {
|
java.toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import ru.di9.fluent.syntax.ast.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static ru.di9.fluent.syntax.StringUtils.inRange_09;
|
import static ru.di9.fluent.syntax.utils.StringUtils.inRange_09;
|
||||||
import static ru.di9.fluent.syntax.parser.FluentStream.*;
|
import static ru.di9.fluent.syntax.parser.FluentStream.*;
|
||||||
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.*;
|
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.*;
|
||||||
|
|
||||||
@@ -18,13 +18,13 @@ public class FluentParser {
|
|||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
List<TopLevel> entries = new ArrayList<>();
|
List<TopLevel> entries = new ArrayList<>();
|
||||||
Comment lastComment = null;
|
Comment lastComment = null;
|
||||||
var blankLines = ps.skipBlankBlock();
|
String blankLines = ps.skipBlankBlock();
|
||||||
if (!blankLines.isEmpty()) {
|
if (!blankLines.isEmpty()) {
|
||||||
entries.add(new Whitespace(blankLines));
|
entries.add(new Whitespace(blankLines));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ps.currentChar().isPresent()) {
|
while (ps.currentChar().isPresent()) {
|
||||||
var entry = getEntryOrJunk(ps);
|
TopLevel entry = getEntryOrJunk(ps);
|
||||||
blankLines = ps.skipBlankBlock();
|
blankLines = ps.skipBlankBlock();
|
||||||
|
|
||||||
// Regular Comments require special logic. Comments may be attached to
|
// Regular Comments require special logic. Comments may be attached to
|
||||||
@@ -78,7 +78,7 @@ public class FluentParser {
|
|||||||
int entryStartPos = ps.index;
|
int entryStartPos = ps.index;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var entry = getEntry(ps);
|
Entry entry = getEntry(ps);
|
||||||
ps.expectLineEnd();
|
ps.expectLineEnd();
|
||||||
return entry;
|
return entry;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
@@ -91,7 +91,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a Junk instance
|
// Create a Junk instance
|
||||||
var slice = ps.string.substring(entryStartPos, nextEntryStart);
|
String slice = ps.string.substring(entryStartPos, nextEntryStart);
|
||||||
var junk = new Junk(slice);
|
var junk = new Junk(slice);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
junk.addSpan(entryStartPos, nextEntryStart);
|
junk.addSpan(entryStartPos, nextEntryStart);
|
||||||
@@ -107,7 +107,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Entry getEntry(FluentStream ps) {
|
private Entry getEntry(FluentStream ps) {
|
||||||
var currentChar = ps.currentChar();
|
Optional<Character> currentChar = ps.currentChar();
|
||||||
|
|
||||||
if (currentChar.filter(v -> v == '#').isPresent()) {
|
if (currentChar.filter(v -> v == '#').isPresent()) {
|
||||||
return getComment(ps);
|
return getComment(ps);
|
||||||
@@ -126,13 +126,13 @@ public class FluentParser {
|
|||||||
|
|
||||||
private Message getMessage(FluentStream ps) {
|
private Message getMessage(FluentStream ps) {
|
||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
var id = getIdentifier(ps);
|
Identifier id = getIdentifier(ps);
|
||||||
|
|
||||||
ps.skipBlankInline();
|
ps.skipBlankInline();
|
||||||
ps.expectChar('=');
|
ps.expectChar('=');
|
||||||
|
|
||||||
var value = maybeGetPattern(ps);
|
Pattern value = maybeGetPattern(ps);
|
||||||
var attrs = getAttributes(ps);
|
Collection<Attribute> attrs = getAttributes(ps);
|
||||||
|
|
||||||
if (value == null && attrs.isEmpty()) {
|
if (value == null && attrs.isEmpty()) {
|
||||||
throw new ParseException(E0005, id.getName());
|
throw new ParseException(E0005, id.getName());
|
||||||
@@ -150,17 +150,17 @@ public class FluentParser {
|
|||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
|
|
||||||
ps.expectChar('-');
|
ps.expectChar('-');
|
||||||
var id = getIdentifier(ps);
|
Identifier id = getIdentifier(ps);
|
||||||
|
|
||||||
ps.skipBlankInline();
|
ps.skipBlankInline();
|
||||||
ps.expectChar('=');
|
ps.expectChar('=');
|
||||||
|
|
||||||
var value = maybeGetPattern(ps);
|
Pattern value = maybeGetPattern(ps);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new ParseException(E0006, id.getName());
|
throw new ParseException(E0006, id.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
var attrs = getAttributes(ps);
|
Collection<Attribute> attrs = getAttributes(ps);
|
||||||
var term = new Term(id, value);
|
var term = new Term(id, value);
|
||||||
term.getAttributes().addAll(attrs);
|
term.getAttributes().addAll(attrs);
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ public class FluentParser {
|
|||||||
ps.peekBlank();
|
ps.peekBlank();
|
||||||
while (ps.isAttributeStart()) {
|
while (ps.isAttributeStart()) {
|
||||||
ps.skipToPeek();
|
ps.skipToPeek();
|
||||||
var attr = getAttribute(ps);
|
Attribute attr = getAttribute(ps);
|
||||||
attrs.add(attr);
|
attrs.add(attr);
|
||||||
ps.peekBlank();
|
ps.peekBlank();
|
||||||
}
|
}
|
||||||
@@ -187,12 +187,12 @@ public class FluentParser {
|
|||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
ps.expectChar('.');
|
ps.expectChar('.');
|
||||||
|
|
||||||
var key = getIdentifier(ps);
|
Identifier key = getIdentifier(ps);
|
||||||
|
|
||||||
ps.skipBlankInline();
|
ps.skipBlankInline();
|
||||||
ps.expectChar('=');
|
ps.expectChar('=');
|
||||||
|
|
||||||
var value = maybeGetPattern(ps);
|
Pattern value = maybeGetPattern(ps);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new ParseException(E0012);
|
throw new ParseException(E0012);
|
||||||
}
|
}
|
||||||
@@ -234,8 +234,8 @@ public class FluentParser {
|
|||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
// A block pattern is a pattern which starts on a new line. Store and
|
// A block pattern is a pattern which starts on a new line. Store and
|
||||||
// measure the indent of this first line for the dedentation logic.
|
// measure the indent of this first line for the dedentation logic.
|
||||||
var blankStart = ps.index;
|
int blankStart = ps.index;
|
||||||
var firstIndent = ps.skipBlankInline();
|
String firstIndent = ps.skipBlankInline();
|
||||||
elements.add(getIndent(ps, firstIndent, blankStart));
|
elements.add(getIndent(ps, firstIndent, blankStart));
|
||||||
commonIndentLength = firstIndent.length();
|
commonIndentLength = firstIndent.length();
|
||||||
}
|
}
|
||||||
@@ -243,14 +243,14 @@ public class FluentParser {
|
|||||||
Optional<Character> opt;
|
Optional<Character> opt;
|
||||||
elements:
|
elements:
|
||||||
while ((opt = ps.currentChar()).isPresent()) {
|
while ((opt = ps.currentChar()).isPresent()) {
|
||||||
var ch = opt.get();
|
Character ch = opt.get();
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case EOL -> {
|
case EOL -> {
|
||||||
var blankStart = ps.index;
|
int blankStart = ps.index;
|
||||||
var blankLines = ps.peekBlankBlock();
|
String blankLines = ps.peekBlankBlock();
|
||||||
if (ps.isValueContinuation()) {
|
if (ps.isValueContinuation()) {
|
||||||
ps.skipToPeek();
|
ps.skipToPeek();
|
||||||
var indent = ps.skipBlankInline();
|
String indent = ps.skipBlankInline();
|
||||||
commonIndentLength = Math.min(commonIndentLength, indent.length());
|
commonIndentLength = Math.min(commonIndentLength, indent.length());
|
||||||
elements.add(getIndent(ps, blankLines + indent, blankStart));
|
elements.add(getIndent(ps, blankLines + indent, blankStart));
|
||||||
continue;
|
continue;
|
||||||
@@ -267,7 +267,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var dedented = dedent(elements, commonIndentLength);
|
List<PatternElement> dedented = dedent(elements, commonIndentLength);
|
||||||
var pattern = new Pattern(dedented);
|
var pattern = new Pattern(dedented);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
pattern.addSpan(spanStart, ps.index);
|
pattern.addSpan(spanStart, ps.index);
|
||||||
@@ -281,7 +281,7 @@ public class FluentParser {
|
|||||||
private List<PatternElement> dedent(Collection<PatternElement> elements, int commonIndent) {
|
private List<PatternElement> dedent(Collection<PatternElement> elements, int commonIndent) {
|
||||||
ArrayList<PatternElement> trimmed = new ArrayList<>();
|
ArrayList<PatternElement> trimmed = new ArrayList<>();
|
||||||
|
|
||||||
for (var element : elements) {
|
for (PatternElement element : elements) {
|
||||||
if (element instanceof Placeable pl) {
|
if (element instanceof Placeable pl) {
|
||||||
trimmed.add(pl);
|
trimmed.add(pl);
|
||||||
continue;
|
continue;
|
||||||
@@ -296,22 +296,10 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!trimmed.isEmpty()) {
|
if (!trimmed.isEmpty()) {
|
||||||
var prev = trimmed.get(trimmed.size() - 1);
|
PatternElement prev = trimmed.getLast();
|
||||||
if (prev instanceof TextElement prevTE) {
|
if (prev instanceof TextElement prevTE) {
|
||||||
// Join adjacent TextElements by replacing them with their sum.
|
// Join adjacent TextElements by replacing them with their sum.
|
||||||
String newVal;
|
TextElement sum = getTextElement(element, prevTE);
|
||||||
if (element instanceof TextElement elmTE) {
|
|
||||||
newVal = elmTE.getValue();
|
|
||||||
} else if (element instanceof Indent elmInd) {
|
|
||||||
newVal = elmInd.getValue();
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unexpected PatternElement type");
|
|
||||||
}
|
|
||||||
|
|
||||||
var sum = new TextElement(prevTE.getValue() + newVal);
|
|
||||||
if (withSpans && prevTE.getSpan().isPresent() && element.getSpan().isPresent()) {
|
|
||||||
sum.addSpan(prevTE.getSpan().get().getStart(), element.getSpan().get().getEnd());
|
|
||||||
}
|
|
||||||
|
|
||||||
trimmed.set(trimmed.size() - 1, sum);
|
trimmed.set(trimmed.size() - 1, sum);
|
||||||
continue;
|
continue;
|
||||||
@@ -335,17 +323,34 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Trim trailing whitespace from the Pattern.
|
// Trim trailing whitespace from the Pattern.
|
||||||
var lastElement = trimmed.get(trimmed.size() - 1);
|
PatternElement lastElement = trimmed.getLast();
|
||||||
if (lastElement instanceof TextElement lastElmTE) {
|
if (lastElement instanceof TextElement lastElmTE) {
|
||||||
lastElmTE.setValue(TRAILING_WS_RE.matcher(lastElmTE.getValue()).replaceAll(""));
|
lastElmTE.setValue(TRAILING_WS_RE.matcher(lastElmTE.getValue()).replaceAll(""));
|
||||||
if (lastElmTE.getValue().isEmpty()) {
|
if (lastElmTE.getValue().isEmpty()) {
|
||||||
trimmed.remove(trimmed.size() - 1);
|
trimmed.removeLast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TextElement getTextElement(PatternElement element, TextElement prevTE) {
|
||||||
|
String newVal;
|
||||||
|
if (element instanceof TextElement elmTE) {
|
||||||
|
newVal = elmTE.getValue();
|
||||||
|
} else if (element instanceof Indent elmInd) {
|
||||||
|
newVal = elmInd.getValue();
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected PatternElement type");
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum = new TextElement(prevTE.getValue() + newVal);
|
||||||
|
if (withSpans && prevTE.getSpan().isPresent() && element.getSpan().isPresent()) {
|
||||||
|
sum.addSpan(prevTE.getSpan().get().getStart(), element.getSpan().get().getEnd());
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
private TextElement getTextElement(FluentStream ps) {
|
private TextElement getTextElement(FluentStream ps) {
|
||||||
var buffer = new StringBuilder();
|
var buffer = new StringBuilder();
|
||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
@@ -375,13 +380,13 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PatternElement getPlaceable(FluentStream ps) {
|
private PatternElement getPlaceable(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
ps.expectChar('{');
|
ps.expectChar('{');
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
|
|
||||||
SyntaxNode expression;
|
SyntaxNode expression;
|
||||||
if (ps.currentChar().filter(v -> v == '{').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '{').isPresent()) {
|
||||||
var child = getPlaceable(ps);
|
PatternElement child = getPlaceable(ps);
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
expression = child;
|
expression = child;
|
||||||
} else {
|
} else {
|
||||||
@@ -401,7 +406,7 @@ public class FluentParser {
|
|||||||
private Expression getExpression(FluentStream ps) {
|
private Expression getExpression(FluentStream ps) {
|
||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
|
|
||||||
var selector = getInlineExpression(ps);
|
Expression selector = getInlineExpression(ps);
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
|
|
||||||
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
||||||
@@ -425,7 +430,7 @@ public class FluentParser {
|
|||||||
ps.skipBlankInline();
|
ps.skipBlankInline();
|
||||||
ps.expectLineEnd();
|
ps.expectLineEnd();
|
||||||
|
|
||||||
var variants = getVariants(ps);
|
List<Variant> variants = getVariants(ps);
|
||||||
|
|
||||||
var selectExpression = new SelectExpression(selector, variants);
|
var selectExpression = new SelectExpression(selector, variants);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
@@ -448,7 +453,7 @@ public class FluentParser {
|
|||||||
|
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
while (ps.isVariantStart()) {
|
while (ps.isVariantStart()) {
|
||||||
var variant = getVariant(ps, hasDefault);
|
Variant variant = getVariant(ps, hasDefault);
|
||||||
|
|
||||||
if (variant.isDefault()) {
|
if (variant.isDefault()) {
|
||||||
hasDefault = true;
|
hasDefault = true;
|
||||||
@@ -486,13 +491,13 @@ public class FluentParser {
|
|||||||
|
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
|
|
||||||
var key = getVariantKey(ps);
|
VariantKey key = getVariantKey(ps);
|
||||||
|
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
ps.expectChar(']');
|
ps.expectChar(']');
|
||||||
|
|
||||||
//val value = this.maybeGetPattern(ps) ?: throw ParseError("E0012")
|
//val value = this.maybeGetPattern(ps) ?: throw ParseError("E0012")
|
||||||
var value = maybeGetPattern(ps);
|
Pattern value = maybeGetPattern(ps);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new ParseException(E0012);
|
throw new ParseException(E0012);
|
||||||
}
|
}
|
||||||
@@ -515,7 +520,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Expression getInlineExpression(FluentStream ps) {
|
private Expression getInlineExpression(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
|
|
||||||
if (ps.isNumberStart()) {
|
if (ps.isNumberStart()) {
|
||||||
return getNumber(ps);
|
return getNumber(ps);
|
||||||
@@ -527,7 +532,7 @@ public class FluentParser {
|
|||||||
|
|
||||||
if (ps.currentChar().filter(v -> v == '$').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '$').isPresent()) {
|
||||||
ps.next();
|
ps.next();
|
||||||
var id = getIdentifier(ps);
|
Identifier id = getIdentifier(ps);
|
||||||
|
|
||||||
var variableReference = new VariableReference(id);
|
var variableReference = new VariableReference(id);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
@@ -539,7 +544,7 @@ public class FluentParser {
|
|||||||
|
|
||||||
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
||||||
ps.next();
|
ps.next();
|
||||||
var id = getIdentifier(ps);
|
Identifier id = getIdentifier(ps);
|
||||||
|
|
||||||
Identifier attr = null;
|
Identifier attr = null;
|
||||||
if (ps.currentChar().filter(v -> v == '.').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '.').isPresent()) {
|
||||||
@@ -563,7 +568,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ps.isIdentifierStart()) {
|
if (ps.isIdentifierStart()) {
|
||||||
var id = getIdentifier(ps);
|
Identifier id = getIdentifier(ps);
|
||||||
ps.peekBlank();
|
ps.peekBlank();
|
||||||
|
|
||||||
if (ps.currentPeek().filter(v -> v == '(').isPresent()) {
|
if (ps.currentPeek().filter(v -> v == '(').isPresent()) {
|
||||||
@@ -573,7 +578,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ps.skipToPeek();
|
ps.skipToPeek();
|
||||||
var args = getCallArguments(ps);
|
CallArguments args = getCallArguments(ps);
|
||||||
var functionReference = new FunctionReference(id, args);
|
var functionReference = new FunctionReference(id, args);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
functionReference.addSpan(spanStart, ps.index);
|
functionReference.addSpan(spanStart, ps.index);
|
||||||
@@ -599,7 +604,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CallArguments getCallArguments(FluentStream ps) {
|
private CallArguments getCallArguments(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
List<Expression> positional = new ArrayList<>();
|
List<Expression> positional = new ArrayList<>();
|
||||||
List<NamedArgument> named = new ArrayList<>();
|
List<NamedArgument> named = new ArrayList<>();
|
||||||
Set<String> argumentNames = new HashSet<>();
|
Set<String> argumentNames = new HashSet<>();
|
||||||
@@ -612,7 +617,7 @@ public class FluentParser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var arg = getCallArgument(ps);
|
CallArgument arg = getCallArgument(ps);
|
||||||
if (arg instanceof NamedArgument na) {
|
if (arg instanceof NamedArgument na) {
|
||||||
if (argumentNames.contains(na.getName().getName())) {
|
if (argumentNames.contains(na.getName().getName())) {
|
||||||
throw new ParseException(E0022);
|
throw new ParseException(E0022);
|
||||||
@@ -648,8 +653,8 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CallArgument getCallArgument(FluentStream ps) {
|
private CallArgument getCallArgument(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
var exp = getInlineExpression(ps);
|
Expression exp = getInlineExpression(ps);
|
||||||
|
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
|
|
||||||
@@ -661,7 +666,7 @@ public class FluentParser {
|
|||||||
ps.next();
|
ps.next();
|
||||||
ps.skipBlank();
|
ps.skipBlank();
|
||||||
|
|
||||||
var value = getLiteral(ps);
|
Literal value = getLiteral(ps);
|
||||||
|
|
||||||
var namedArgument = new NamedArgument(mr.getId(), value);
|
var namedArgument = new NamedArgument(mr.getId(), value);
|
||||||
if (withSpans) {
|
if (withSpans) {
|
||||||
@@ -687,7 +692,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StringLiteral getString(FluentStream ps) {
|
private StringLiteral getString(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
|
|
||||||
ps.expectChar('"');
|
ps.expectChar('"');
|
||||||
var value = new StringBuilder();
|
var value = new StringBuilder();
|
||||||
@@ -695,7 +700,7 @@ public class FluentParser {
|
|||||||
Predicate<Character> filter = x -> x != '"' && x != EOL;
|
Predicate<Character> filter = x -> x != '"' && x != EOL;
|
||||||
Optional<Character> opt;
|
Optional<Character> opt;
|
||||||
while ((opt = ps.takeChar(filter)).isPresent()) {
|
while ((opt = ps.takeChar(filter)).isPresent()) {
|
||||||
var ch = opt.get();
|
Character ch = opt.get();
|
||||||
value.append(ch == '\\' ? getEscapeSequence(ps) : ch);
|
value.append(ch == '\\' ? getEscapeSequence(ps) : ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,12 +719,12 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getEscapeSequence(FluentStream ps) {
|
private String getEscapeSequence(FluentStream ps) {
|
||||||
var nextOpt = ps.currentChar();
|
Optional<Character> nextOpt = ps.currentChar();
|
||||||
if (nextOpt.isEmpty()) {
|
if (nextOpt.isEmpty()) {
|
||||||
throw new ParseException(E0025, (Character) null);
|
throw new ParseException(E0025, (Character) null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var next = nextOpt.get();
|
Character next = nextOpt.get();
|
||||||
return switch (next) {
|
return switch (next) {
|
||||||
case '\\', '"' -> {
|
case '\\', '"' -> {
|
||||||
ps.next();
|
ps.next();
|
||||||
@@ -736,7 +741,7 @@ public class FluentParser {
|
|||||||
|
|
||||||
var sequence = new StringBuilder();
|
var sequence = new StringBuilder();
|
||||||
for (int i = 0; i < digits; i++) {
|
for (int i = 0; i < digits; i++) {
|
||||||
var opt = ps.takeHexDigit();
|
Optional<Character> opt = ps.takeHexDigit();
|
||||||
if (opt.isEmpty()) {
|
if (opt.isEmpty()) {
|
||||||
throw new ParseException(E0026, "\\%s%s%s".formatted(u, sequence, ps.currentChar().orElseThrow()));
|
throw new ParseException(E0026, "\\%s%s%s".formatted(u, sequence, ps.currentChar().orElseThrow()));
|
||||||
}
|
}
|
||||||
@@ -747,7 +752,7 @@ public class FluentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NumberLiteral getNumber(FluentStream ps) {
|
private NumberLiteral getNumber(FluentStream ps) {
|
||||||
var spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
var value = new StringBuilder();
|
var value = new StringBuilder();
|
||||||
|
|
||||||
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
if (ps.currentChar().filter(v -> v == '-').isPresent()) {
|
||||||
@@ -794,7 +799,7 @@ public class FluentParser {
|
|||||||
private Identifier getIdentifier(FluentStream ps) {
|
private Identifier getIdentifier(FluentStream ps) {
|
||||||
int spanStart = ps.index;
|
int spanStart = ps.index;
|
||||||
|
|
||||||
var name = new StringBuilder().append(ps.takeIDStart());
|
StringBuilder name = new StringBuilder().append(ps.takeIDStart());
|
||||||
Optional<Character> opt;
|
Optional<Character> opt;
|
||||||
while ((opt = ps.takeIDChar()).isPresent()) {
|
while ((opt = ps.takeIDChar()).isPresent()) {
|
||||||
name.append(opt.get());
|
name.append(opt.get());
|
||||||
@@ -816,11 +821,11 @@ public class FluentParser {
|
|||||||
final int GROUP_COMMENT = 1;
|
final int GROUP_COMMENT = 1;
|
||||||
final int RESOURCE_COMMENT = 2;
|
final int RESOURCE_COMMENT = 2;
|
||||||
|
|
||||||
var level = ANY;
|
int level = ANY;
|
||||||
var content = new StringBuilder();
|
var content = new StringBuilder();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var i = -1;
|
int i = -1;
|
||||||
|
|
||||||
int thisLevel;
|
int thisLevel;
|
||||||
if (level == ANY) {
|
if (level == ANY) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package ru.di9.fluent.syntax.parser;
|
package ru.di9.fluent.syntax.parser;
|
||||||
|
|
||||||
import ru.di9.fluent.syntax.MathUtils;
|
import ru.di9.fluent.syntax.utils.MathUtils;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static ru.di9.fluent.syntax.StringUtils.*;
|
import static ru.di9.fluent.syntax.utils.StringUtils.*;
|
||||||
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.E0003;
|
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.E0003;
|
||||||
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.E0004;
|
import static ru.di9.fluent.syntax.parser.ParseException.ErrorCode.E0004;
|
||||||
|
|
||||||
@@ -29,17 +29,17 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String skipBlankInline() {
|
public String skipBlankInline() {
|
||||||
var blank = peekBlankInline();
|
String blank = peekBlankInline();
|
||||||
skipToPeek();
|
skipToPeek();
|
||||||
return blank;
|
return blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String peekBlankBlock() {
|
public String peekBlankBlock() {
|
||||||
var blank = new StringBuilder();
|
StringBuilder blank = new StringBuilder();
|
||||||
while (true) {
|
while (true) {
|
||||||
var lineStart = peekOffset;
|
int lineStart = peekOffset;
|
||||||
peekBlankInline();
|
peekBlankInline();
|
||||||
var currentPeek = currentPeek();
|
Optional<Character> currentPeek = currentPeek();
|
||||||
if (currentPeek.filter(v -> v == EOL).isPresent()) {
|
if (currentPeek.filter(v -> v == EOL).isPresent()) {
|
||||||
blank.append(EOL);
|
blank.append(EOL);
|
||||||
peek();
|
peek();
|
||||||
@@ -56,7 +56,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String skipBlankBlock() {
|
public String skipBlankBlock() {
|
||||||
var blank = peekBlankBlock();
|
String blank = peekBlankBlock();
|
||||||
skipToPeek();
|
skipToPeek();
|
||||||
return blank;
|
return blank;
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void expectLineEnd() {
|
public void expectLineEnd() {
|
||||||
var opt = currentChar();
|
Optional<Character> opt = currentChar();
|
||||||
|
|
||||||
if (opt.isEmpty()/*EOF*/) {
|
if (opt.isEmpty()/*EOF*/) {
|
||||||
// EOF is a valid line end in Fluent.
|
// EOF is a valid line end in Fluent.
|
||||||
@@ -97,7 +97,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Character> takeChar(Predicate<Character> f) {
|
public Optional<Character> takeChar(Predicate<Character> f) {
|
||||||
var ch = currentChar().filter(f);
|
Optional<Character> ch = currentChar().filter(f);
|
||||||
ch.ifPresent(x -> next());
|
ch.ifPresent(x -> next());
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNumberStart() {
|
public boolean isNumberStart() {
|
||||||
var opt = currentChar();
|
Optional<Character> opt = currentChar();
|
||||||
if (opt.filter(v -> v == '-').isPresent()) {
|
if (opt.filter(v -> v == '-').isPresent()) {
|
||||||
opt = peek();
|
opt = peek();
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValueContinuation() {
|
public boolean isValueContinuation() {
|
||||||
var column1 = peekOffset;
|
int column1 = peekOffset;
|
||||||
peekBlankInline();
|
peekBlankInline();
|
||||||
|
|
||||||
if (currentPeek().filter(v -> v == '{').isPresent()) {
|
if (currentPeek().filter(v -> v == '{').isPresent()) {
|
||||||
@@ -156,7 +156,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lvl = MathUtils.clamp(level, -1, 2);
|
int lvl = MathUtils.clamp(level, -1, 2);
|
||||||
var i = 0;
|
int i = 0;
|
||||||
while (i <= lvl || (lvl == -1 && i < 3)) {
|
while (i <= lvl || (lvl == -1 && i < 3)) {
|
||||||
if (peek().filter(v -> v != '#').isPresent()) {
|
if (peek().filter(v -> v != '#').isPresent()) {
|
||||||
if (i <= lvl && lvl != -1) {
|
if (i <= lvl && lvl != -1) {
|
||||||
@@ -175,7 +175,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVariantStart() {
|
public boolean isVariantStart() {
|
||||||
var currentPeekOffset = peekOffset;
|
int currentPeekOffset = peekOffset;
|
||||||
if (currentPeek().filter(v -> v == '*').isPresent()) {
|
if (currentPeek().filter(v -> v == '*').isPresent()) {
|
||||||
peek();
|
peek();
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void skipToNextEntryStart(int junkStart) {
|
public void skipToNextEntryStart(int junkStart) {
|
||||||
var lastNewline = string.lastIndexOf(EOL, index);
|
int lastNewline = string.lastIndexOf(EOL, index);
|
||||||
if (junkStart < lastNewline) {
|
if (junkStart < lastNewline) {
|
||||||
// Last seen newline is _after_ the junk start. It's safe to rewind
|
// Last seen newline is _after_ the junk start. It's safe to rewind
|
||||||
// without the risk of resuming at the same broken entry.
|
// without the risk of resuming at the same broken entry.
|
||||||
@@ -205,7 +205,7 @@ public class FluentStream extends ParserStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Break if the first char in this line looks like an entry start.
|
// Break if the first char in this line looks like an entry start.
|
||||||
var firstOpt = next();
|
Optional<Character> firstOpt = next();
|
||||||
if (firstOpt.isEmpty()/*EOF*/) {
|
if (firstOpt.isEmpty()/*EOF*/) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ public class FluentStream extends ParserStream {
|
|||||||
|
|
||||||
public char takeIDStart() {
|
public char takeIDStart() {
|
||||||
if (currentChar().map(this::isCharIdStart).orElse(false)) {
|
if (currentChar().map(this::isCharIdStart).orElse(false)) {
|
||||||
var ret = currentChar();
|
Optional<Character> ret = currentChar();
|
||||||
if (ret.isPresent()) {
|
if (ret.isPresent()) {
|
||||||
next();
|
next();
|
||||||
return ret.get();
|
return ret.get();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ru.di9.fluent.syntax.parser;
|
|||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static ru.di9.fluent.syntax.StringUtils.getCharAt;
|
import static ru.di9.fluent.syntax.utils.StringUtils.getCharAt;
|
||||||
|
|
||||||
public class ParserStream {
|
public class ParserStream {
|
||||||
|
|
||||||
@@ -71,9 +71,10 @@ public class ParserStream {
|
|||||||
// beginning of the compound CRLF sequence. This ensures slices of
|
// beginning of the compound CRLF sequence. This ensures slices of
|
||||||
// [inclusive, exclusive) continue to work properly.
|
// [inclusive, exclusive) continue to work properly.
|
||||||
|
|
||||||
var ch = getCharAt(string, offset);
|
Optional<Character> ch = getCharAt(string, offset);
|
||||||
var opt = ch.filter(v -> v == '\r')
|
Optional<Character> opt = ch.filter(v -> v == '\r')
|
||||||
.flatMap(x -> getCharAt(string, offset + 1).filter(v -> v == '\n'));
|
.flatMap(x -> getCharAt(string, offset + 1)
|
||||||
|
.filter(v -> v == '\n'));
|
||||||
|
|
||||||
return opt.isPresent() ? opt : ch;
|
return opt.isPresent() ? opt : ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,33 +17,25 @@ public class FluentSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String serialize(TopLevel topLevel) {
|
public String serialize(TopLevel topLevel) {
|
||||||
if (topLevel instanceof Entry entry) {
|
return switch (topLevel) {
|
||||||
return serializeEntry(entry);
|
case Entry entry -> serializeEntry(entry);
|
||||||
} else if (topLevel instanceof Whitespace whitespace) {
|
case Whitespace whitespace -> whitespace.getContent();
|
||||||
return whitespace.getContent();
|
case Junk junk -> withJunk ? junk.getContent() : "";
|
||||||
} else if (topLevel instanceof Junk junk) {
|
default -> throw new SerializeException("Unknown top-level entry type '%s'".formatted(topLevel.getClass()));
|
||||||
return withJunk ? junk.getContent() : "";
|
};
|
||||||
} else {
|
|
||||||
throw new SerializeException("Unknown top-level entry type '%s'".formatted(topLevel.getClass()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PRIVATE ////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/// PRIVATE ////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private String serializeEntry(Entry entry) {
|
private String serializeEntry(Entry entry) {
|
||||||
if (entry instanceof Message message) {
|
return switch (entry) {
|
||||||
return serializeMessage(message);
|
case Message message -> serializeMessage(message);
|
||||||
} else if (entry instanceof Term term) {
|
case Term term -> serializeTerm(term);
|
||||||
return serializeTerm(term);
|
case Comment comment -> serializeComment(comment, "#");
|
||||||
} else if (entry instanceof Comment comment) {
|
case GroupComment comment -> serializeComment(comment, "##");
|
||||||
return serializeComment(comment, "#");
|
case ResourceComment comment -> serializeComment(comment, "###");
|
||||||
} else if (entry instanceof GroupComment comment) {
|
default -> throw new SerializeException("Unknown entry type '%s'".formatted(entry.getClass()));
|
||||||
return serializeComment(comment, "##");
|
};
|
||||||
} else if (entry instanceof ResourceComment comment) {
|
|
||||||
return serializeComment(comment, "###");
|
|
||||||
} else {
|
|
||||||
throw new SerializeException("Unknown entry type '%s'".formatted(entry.getClass()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String serializeMessage(Message message) {
|
private String serializeMessage(Message message) {
|
||||||
@@ -129,27 +121,22 @@ public class FluentSerializer {
|
|||||||
|
|
||||||
private String serializePlaceable(Placeable placeable) {
|
private String serializePlaceable(Placeable placeable) {
|
||||||
InsidePlaceable expression = placeable.getExpression();
|
InsidePlaceable expression = placeable.getExpression();
|
||||||
if (expression instanceof Placeable placeable1) {
|
return switch (expression) {
|
||||||
return "{" + serializePlaceable(placeable1) + "}";
|
case Placeable placeable1 -> "{" + serializePlaceable(placeable1) + "}";
|
||||||
} else if (expression instanceof SelectExpression selectExpression) {
|
case SelectExpression selectExpression -> "{ " + serializeExpression(selectExpression) + "}";
|
||||||
return "{ " + serializeExpression(selectExpression) + "}";
|
case Expression expression1 -> "{ " + serializeExpression(expression1) + " }";
|
||||||
} else if (expression instanceof Expression expression1) {
|
default -> throw new SerializeException("Unknown placeable type '%s'".formatted(expression.getClass()));
|
||||||
return "{ " + serializeExpression(expression1) + " }";
|
};
|
||||||
} else {
|
|
||||||
throw new SerializeException("Unknown placeable type '%s'".formatted(expression.getClass()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String serializeExpression(Expression expression) {
|
private String serializeExpression(Expression expression) {
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
if (expression instanceof StringLiteral stringLiteral) {
|
switch (expression) {
|
||||||
builder.append('"').append(stringLiteral.getValue()).append('"');
|
case StringLiteral stringLiteral -> builder.append('"').append(stringLiteral.getValue()).append('"');
|
||||||
} else if (expression instanceof NumberLiteral numberLiteral) {
|
case NumberLiteral numberLiteral -> builder.append(numberLiteral.getValue());
|
||||||
builder.append(numberLiteral.getValue());
|
case VariableReference variableReference -> builder.append('$').append(variableReference.getId().getName());
|
||||||
} else if (expression instanceof VariableReference variableReference) {
|
case TermReference termReference -> {
|
||||||
builder.append('$').append(variableReference.getId().getName());
|
|
||||||
} else if (expression instanceof TermReference termReference) {
|
|
||||||
builder.append('-').append(termReference.getId().getName());
|
builder.append('-').append(termReference.getId().getName());
|
||||||
|
|
||||||
termReference.getAttribute().ifPresent(attribute ->
|
termReference.getAttribute().ifPresent(attribute ->
|
||||||
@@ -157,23 +144,24 @@ public class FluentSerializer {
|
|||||||
|
|
||||||
termReference.getArguments().ifPresent(arguments ->
|
termReference.getArguments().ifPresent(arguments ->
|
||||||
builder.append(serializeCallArguments(arguments)));
|
builder.append(serializeCallArguments(arguments)));
|
||||||
} else if (expression instanceof MessageReference messageReference) {
|
}
|
||||||
|
case MessageReference messageReference -> {
|
||||||
builder.append(messageReference.getId().getName());
|
builder.append(messageReference.getId().getName());
|
||||||
|
|
||||||
messageReference.getAttribute().ifPresent(attribute ->
|
messageReference.getAttribute().ifPresent(attribute ->
|
||||||
builder.append('.').append(attribute.getName()));
|
builder.append('.').append(attribute.getName()));
|
||||||
} else if (expression instanceof FunctionReference functionReference) {
|
}
|
||||||
builder
|
case FunctionReference functionReference -> builder
|
||||||
.append(functionReference.getId().getName())
|
.append(functionReference.getId().getName())
|
||||||
.append(serializeCallArguments(functionReference.getArguments()));
|
.append(serializeCallArguments(functionReference.getArguments()));
|
||||||
} else if (expression instanceof SelectExpression selectExpression) {
|
case SelectExpression selectExpression -> {
|
||||||
builder.append(serializeExpression(selectExpression.getSelector())).append(" ->");
|
builder.append(serializeExpression(selectExpression.getSelector())).append(" ->");
|
||||||
for (Variant variant : selectExpression.getVariants()) {
|
for (Variant variant : selectExpression.getVariants()) {
|
||||||
builder.append(serializeVariant(variant));
|
builder.append(serializeVariant(variant));
|
||||||
}
|
}
|
||||||
builder.append('\n');
|
builder.append('\n');
|
||||||
} else {
|
}
|
||||||
throw new SerializeException("Unknown expression type '%s".formatted(expression.getClass()));
|
default -> throw new SerializeException("Unknown expression type '%s".formatted(expression.getClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
@@ -185,7 +173,7 @@ public class FluentSerializer {
|
|||||||
var builder = new StringBuilder("(");
|
var builder = new StringBuilder("(");
|
||||||
|
|
||||||
if (hasPositional) {
|
if (hasPositional) {
|
||||||
var positional = callArguments.getPositional()
|
String positional = callArguments.getPositional()
|
||||||
.stream()
|
.stream()
|
||||||
.map(this::serializeExpression)
|
.map(this::serializeExpression)
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining(", "));
|
||||||
@@ -193,7 +181,7 @@ public class FluentSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasNamed) {
|
if (hasNamed) {
|
||||||
var named = callArguments.getNamed()
|
String named = callArguments.getNamed()
|
||||||
.stream()
|
.stream()
|
||||||
.map(this::serializeNamedArgument)
|
.map(this::serializeNamedArgument)
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining(", "));
|
||||||
@@ -209,8 +197,8 @@ public class FluentSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String serializeVariant(Variant variant) {
|
private String serializeVariant(Variant variant) {
|
||||||
var key = serializeVariantKey(variant.getKey());
|
String key = serializeVariantKey(variant.getKey());
|
||||||
var value = serializePattern(variant.getValue()).replaceAll("\n", "\n ");
|
String value = serializePattern(variant.getValue()).replaceAll("\n", "\n ");
|
||||||
var builder = new StringBuilder("\n ");
|
var builder = new StringBuilder("\n ");
|
||||||
|
|
||||||
if (variant.isDefault()) {
|
if (variant.isDefault()) {
|
||||||
@@ -240,7 +228,7 @@ public class FluentSerializer {
|
|||||||
boolean isMultiline = pattern.getElements().stream().anyMatch(it -> isSelectExpr(it) || includesLine(it));
|
boolean isMultiline = pattern.getElements().stream().anyMatch(it -> isSelectExpr(it) || includesLine(it));
|
||||||
if (isMultiline) {
|
if (isMultiline) {
|
||||||
if (!pattern.getElements().isEmpty()) {
|
if (!pattern.getElements().isEmpty()) {
|
||||||
var firstElement = pattern.getElements().get(0);
|
PatternElement firstElement = pattern.getElements().getFirst();
|
||||||
if (firstElement instanceof TextElement te) {
|
if (firstElement instanceof TextElement te) {
|
||||||
if (!te.getValue().isEmpty()) {
|
if (!te.getValue().isEmpty()) {
|
||||||
char firstChar = te.getValue().charAt(0);
|
char firstChar = te.getValue().charAt(0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.di9.fluent.syntax;
|
package ru.di9.fluent.syntax.utils;
|
||||||
|
|
||||||
public interface MathUtils {
|
public interface MathUtils {
|
||||||
static int clamp(int value, int min, int max) {
|
static int clamp(int value, int min, int max) {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.di9.fluent.syntax;
|
package ru.di9.fluent.syntax.utils;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -2,8 +2,7 @@ package ru.di9.fluent.syntax.ast;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
|
||||||
|
|
||||||
class BaseNodeTest {
|
class BaseNodeTest {
|
||||||
|
|
||||||
@@ -13,12 +12,11 @@ class BaseNodeTest {
|
|||||||
var m11 = new Message(new Identifier("test-id"), new Pattern(new TextElement("localized")));
|
var m11 = new Message(new Identifier("test-id"), new Pattern(new TextElement("localized")));
|
||||||
var m2 = new Message(new Identifier("test-id"), new Pattern(new TextElement("different")));
|
var m2 = new Message(new Identifier("test-id"), new Pattern(new TextElement("different")));
|
||||||
|
|
||||||
assertEquals(m1, m11);
|
assertThat(m1)
|
||||||
assertNotEquals(m1, m2);
|
.isEqualTo(m11)
|
||||||
assertEquals(m1.getId(), m2.getId());
|
.isNotEqualTo(m2);
|
||||||
assertNotEquals(m1.getValue(), m2.getValue());
|
|
||||||
//Шта?
|
assertThat(m1.getId()).isEqualTo(m2.getId());
|
||||||
assertNotEquals(m1, null);
|
assertThat(m1.getValue()).isNotEqualTo(m2.getValue());
|
||||||
assertNotEquals(null, m1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ package ru.di9.fluent.syntax.parser;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.DynamicTest;
|
import org.junit.jupiter.api.DynamicTest;
|
||||||
import org.junit.jupiter.api.TestFactory;
|
import org.junit.jupiter.api.TestFactory;
|
||||||
import ru.di9.fluent.test.utils.AstAssert;
|
import ru.di9.fluent.syntax.ast.Resource;
|
||||||
|
import ru.di9.fluent.syntax.test.utils.AstAssert;
|
||||||
import ru.di9.fluent.test.utils.Tuple3;
|
import ru.di9.fluent.test.utils.Tuple3;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -43,7 +44,7 @@ public abstract class AbstractFixturesTest {
|
|||||||
var parser = new FluentParser();
|
var parser = new FluentParser();
|
||||||
parser.withSpans = isWithSpans(tuple.value1());
|
parser.withSpans = isWithSpans(tuple.value1());
|
||||||
parser.withJunkAnnotations = isWithJunkAnnotations(tuple.value1());
|
parser.withJunkAnnotations = isWithJunkAnnotations(tuple.value1());
|
||||||
var resource = parser.parse(tuple.value2());
|
Resource resource = parser.parse(tuple.value2());
|
||||||
|
|
||||||
AstAssert.assertThat(resource)
|
AstAssert.assertThat(resource)
|
||||||
.isEqualAstJson(tuple.value3());
|
.isEqualAstJson(tuple.value3());
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class FluentStreamTest {
|
|||||||
assertThatNoException().isThrownBy(ps2::expectLineEnd);
|
assertThatNoException().isThrownBy(ps2::expectLineEnd);
|
||||||
|
|
||||||
var ps3 = new FluentStream(" ");
|
var ps3 = new FluentStream(" ");
|
||||||
var catchException = catchThrowableOfType(ps3::expectLineEnd, ParseException.class);
|
ParseException catchException = catchThrowableOfType(ps3::expectLineEnd, ParseException.class);
|
||||||
assertThat(catchException.getCode()).isEqualTo(E0003);
|
assertThat(catchException.getCode()).isEqualTo(E0003);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ class FluentStreamTest {
|
|||||||
void testExpectChar() {
|
void testExpectChar() {
|
||||||
var ps = new FluentStream("z");
|
var ps = new FluentStream("z");
|
||||||
assertThatNoException().isThrownBy(() -> ps.expectChar('z'));
|
assertThatNoException().isThrownBy(() -> ps.expectChar('z'));
|
||||||
var catchException = catchThrowableOfType(() -> ps.expectChar('a'), ParseException.class);
|
ParseException catchException = catchThrowableOfType(() -> ps.expectChar('a'), ParseException.class);
|
||||||
assertThat(catchException.getCode()).isEqualTo(E0003);
|
assertThat(catchException.getCode()).isEqualTo(E0003);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.di9.fluent.syntax.serializer;
|
package ru.di9.fluent.syntax.serializer;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import ru.di9.fluent.syntax.ast.TopLevel;
|
||||||
import ru.di9.fluent.syntax.parser.FluentParser;
|
import ru.di9.fluent.syntax.parser.FluentParser;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -14,10 +15,10 @@ class SerializeEntryTest {
|
|||||||
key = Value""";
|
key = Value""";
|
||||||
|
|
||||||
var parser = new FluentParser();
|
var parser = new FluentParser();
|
||||||
var topLevel = parser.parse(input).getBody().get(0);
|
TopLevel topLevel = parser.parse(input).getBody().getFirst();
|
||||||
|
|
||||||
var serializer = new FluentSerializer();
|
var serializer = new FluentSerializer();
|
||||||
var serialized = serializer.serialize(topLevel).trim();
|
String serialized = serializer.serialize(topLevel).trim();
|
||||||
|
|
||||||
assertThat(serialized).isEqualTo(input);
|
assertThat(serialized).isEqualTo(input);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.di9.fluent.test.utils;
|
package ru.di9.fluent.syntax.test.utils;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
@@ -7,6 +7,8 @@ import org.json.JSONException;
|
|||||||
import org.skyscreamer.jsonassert.JSONAssert;
|
import org.skyscreamer.jsonassert.JSONAssert;
|
||||||
import org.skyscreamer.jsonassert.JSONCompareMode;
|
import org.skyscreamer.jsonassert.JSONCompareMode;
|
||||||
import ru.di9.fluent.syntax.ast.BaseNode;
|
import ru.di9.fluent.syntax.ast.BaseNode;
|
||||||
|
import ru.di9.fluent.test.utils.BaseNodeJsonSerializer;
|
||||||
|
import ru.di9.fluent.test.utils.NullIgnoreComparator;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
@@ -26,13 +28,13 @@ public class AstAssert extends AbstractAssert<AstAssert, BaseNode> {
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public AstAssert printAstJson(PrintStream printStream) {
|
public AstAssert printAstJson(PrintStream printStream) {
|
||||||
var json = gson.toJson(actual);
|
String json = gson.toJson(actual);
|
||||||
printStream.println(json);
|
printStream.println(json);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AstAssert isEqualAstJson(String astJson) {
|
public AstAssert isEqualAstJson(String astJson) {
|
||||||
var actualJson = gson.toJson(actual);
|
String actualJson = gson.toJson(actual);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSONAssert.assertEquals(astJson, actualJson, nullIgnoreComparator);
|
JSONAssert.assertEquals(astJson, actualJson, nullIgnoreComparator);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.di9.fluent.syntax;
|
package ru.di9.fluent.syntax.utils;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.di9.fluent.syntax;
|
package ru.di9.fluent.syntax.utils;
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions;
|
import org.assertj.core.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -3,10 +3,7 @@ package ru.di9.fluent.syntax.visitor;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import ru.di9.fluent.syntax.ast.Identifier;
|
import ru.di9.fluent.syntax.ast.*;
|
||||||
import ru.di9.fluent.syntax.ast.Pattern;
|
|
||||||
import ru.di9.fluent.syntax.ast.TextElement;
|
|
||||||
import ru.di9.fluent.syntax.ast.Variant;
|
|
||||||
import ru.di9.fluent.syntax.parser.FluentParser;
|
import ru.di9.fluent.syntax.parser.FluentParser;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -29,7 +26,7 @@ class VisitorTest {
|
|||||||
msg = foo {$var ->
|
msg = foo {$var ->
|
||||||
*[other] bar
|
*[other] bar
|
||||||
} baz""";
|
} baz""";
|
||||||
var res = parser.parse(source);
|
Resource res = parser.parse(source);
|
||||||
visitor.visit(res);
|
visitor.visit(res);
|
||||||
assertEquals(3, visitor.wordCount);
|
assertEquals(3, visitor.wordCount);
|
||||||
assertEquals(2, visitor.patternCount);
|
assertEquals(2, visitor.patternCount);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class BaseNodeJsonSerializer implements JsonSerializer<BaseNode> {
|
|||||||
var root = new JsonObject();
|
var root = new JsonObject();
|
||||||
root.add("type", new JsonPrimitive(baseNode.getClass().getSimpleName()));
|
root.add("type", new JsonPrimitive(baseNode.getClass().getSimpleName()));
|
||||||
|
|
||||||
var fields = Reflect.on(baseNode).fields();
|
Map<String, Reflect> fields = Reflect.on(baseNode).fields();
|
||||||
|
|
||||||
for (Map.Entry<String, Reflect> field : fields.entrySet()) {
|
for (Map.Entry<String, Reflect> field : fields.entrySet()) {
|
||||||
String name = field.getKey().equalsIgnoreCase("isDefault") ? "default" : field.getKey();
|
String name = field.getKey().equalsIgnoreCase("isDefault") ? "default" : field.getKey();
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import java.nio.file.Path;
|
|||||||
public interface FileUtils {
|
public interface FileUtils {
|
||||||
|
|
||||||
static String getExt(String fileName) {
|
static String getExt(String fileName) {
|
||||||
var idx = fileName.lastIndexOf('.');
|
int idx = fileName.lastIndexOf('.');
|
||||||
if (idx < 0) return "";
|
if (idx < 0) return "";
|
||||||
return fileName.substring(idx + 1);
|
return fileName.substring(idx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getName(String fileName) {
|
static String getName(String fileName) {
|
||||||
var idx = fileName.lastIndexOf('.');
|
int idx = fileName.lastIndexOf('.');
|
||||||
if (idx < 0) return fileName;
|
if (idx < 0) return fileName;
|
||||||
return fileName.substring(0, idx);
|
return fileName.substring(0, idx);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user