9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

格式化

This commit is contained in:
jhqwqmc
2025-12-01 07:57:46 +08:00
parent 16aedafbe4
commit edfdf083e0
2 changed files with 334 additions and 224 deletions

View File

@@ -24,7 +24,7 @@ import java.util.stream.LongStream;
public class SnbtGrammar {
private static final DynamicCommandExceptionType ERROR_NUMBER_PARSE_FAILURE = new LocalizedDynamicCommandExceptionType(
number -> new LocalizedMessage("warning.config.type.snbt.parser.number_parse_failure", String.valueOf(number))
message -> new LocalizedMessage("warning.config.type.snbt.parser.number_parse_failure", String.valueOf(message))
);
static final DynamicCommandExceptionType ERROR_EXPECTED_HEX_ESCAPE = new LocalizedDynamicCommandExceptionType(
length -> new LocalizedMessage("warning.config.type.snbt.parser.expected_hex_escape", String.valueOf(length))
@@ -248,7 +248,9 @@ public class SnbtGrammar {
T emptyList = ops.emptyList();
T nullString = ops.createString("null");
boolean isJavaType = "null".equals(nullString); // 确定是 Java 类型的
Dictionary<StringReader> rules = new Dictionary<>();
Atom<Sign> sign = Atom.of("sign");
rules.put(
sign,
@@ -258,6 +260,7 @@ public class SnbtGrammar {
),
scope -> scope.getOrThrow(sign)
);
Atom<IntegerSuffix> integerSuffix = Atom.of("integer_suffix");
rules.put(
integerSuffix,
@@ -265,43 +268,19 @@ public class SnbtGrammar {
Term.sequence(
StringReaderTerms.characters('u', 'U'),
Term.alternative(
Term.sequence(
StringReaderTerms.characters('b', 'B'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.BYTE))
),
Term.sequence(
StringReaderTerms.characters('s', 'S'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.SHORT))
),
Term.sequence(
StringReaderTerms.characters('i', 'I'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.INT))
),
Term.sequence(
StringReaderTerms.characters('l', 'L'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.LONG))
)
Term.sequence(StringReaderTerms.characters('b', 'B'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.BYTE))),
Term.sequence(StringReaderTerms.characters('s', 'S'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.SHORT))),
Term.sequence(StringReaderTerms.characters('i', 'I'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.INT))),
Term.sequence(StringReaderTerms.characters('l', 'L'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.UNSIGNED, TypeSuffix.LONG)))
)
),
Term.sequence(
StringReaderTerms.characters('s', 'S'),
Term.alternative(
Term.sequence(
StringReaderTerms.characters('b', 'B'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.BYTE))
),
Term.sequence(
StringReaderTerms.characters('s', 'S'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.SHORT))
),
Term.sequence(
StringReaderTerms.characters('i', 'I'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.INT))
),
Term.sequence(
StringReaderTerms.characters('l', 'L'),
Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.LONG))
)
Term.sequence(StringReaderTerms.characters('b', 'B'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.BYTE))),
Term.sequence(StringReaderTerms.characters('s', 'S'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.SHORT))),
Term.sequence(StringReaderTerms.characters('i', 'I'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.INT))),
Term.sequence(StringReaderTerms.characters('l', 'L'), Term.marker(integerSuffix, new IntegerSuffix(SignedPrefix.SIGNED, TypeSuffix.LONG)))
)
),
Term.sequence(StringReaderTerms.characters('b', 'B'), Term.marker(integerSuffix, new IntegerSuffix(null, TypeSuffix.BYTE))),
@@ -311,12 +290,16 @@ public class SnbtGrammar {
),
scope -> scope.getOrThrow(integerSuffix)
);
Atom<String> binaryNumeral = Atom.of("binary_numeral");
rules.put(binaryNumeral, BINARY_NUMERAL);
Atom<String> decimalNumeral = Atom.of("decimal_numeral");
rules.put(decimalNumeral, DECIMAL_NUMERAL);
Atom<String> hexNumeral = Atom.of("hex_numeral");
rules.put(hexNumeral, HEX_NUMERAL);
Atom<IntegerLiteral> integerLiteral = Atom.of("integer_literal");
NamedRule<StringReader, IntegerLiteral> integerLiteralRule = rules.put(
integerLiteral,
@@ -344,14 +327,15 @@ public class SnbtGrammar {
if (decimalContents != null) {
return new IntegerLiteral(signValue, Base.DECIMAL, decimalContents, suffix);
}
String string1 = scope.get(hexNumeral);
if (string1 != null) {
return new IntegerLiteral(signValue, Base.HEX, string1, suffix);
String hexContents = scope.get(hexNumeral);
if (hexContents != null) {
return new IntegerLiteral(signValue, Base.HEX, hexContents, suffix);
}
String string2 = scope.getOrThrow(binaryNumeral);
return new IntegerLiteral(signValue, Base.BINARY, string2, suffix);
String binaryContents = scope.getOrThrow(binaryNumeral);
return new IntegerLiteral(signValue, Base.BINARY, binaryContents, suffix);
}
);
Atom<TypeSuffix> floatTypeSuffix = Atom.of("float_type_suffix");
rules.put(
floatTypeSuffix,
@@ -361,12 +345,18 @@ public class SnbtGrammar {
),
scope -> scope.getOrThrow(floatTypeSuffix)
);
Atom<Signed<String>> floatExponentPart = Atom.of("float_exponent_part");
rules.put(
floatExponentPart,
Term.sequence(StringReaderTerms.characters('e', 'E'), Term.optional(rules.named(sign)), rules.named(decimalNumeral)),
Term.sequence(
StringReaderTerms.characters('e', 'E'),
Term.optional(rules.named(sign)),
rules.named(decimalNumeral)
),
scope -> new Signed<>(scope.getOrDefault(sign, Sign.PLUS), scope.getOrThrow(decimalNumeral))
);
Atom<String> floatWholePart = Atom.of("float_whole_part");
Atom<String> floatFractionPart = Atom.of("float_fraction_part");
Atom<T> floatLiteral = Atom.of("float_literal");
@@ -390,8 +380,17 @@ public class SnbtGrammar {
Term.optional(rules.named(floatExponentPart)),
Term.optional(rules.named(floatTypeSuffix))
),
Term.sequence(rules.namedWithAlias(decimalNumeral, floatWholePart), rules.named(floatExponentPart), Term.cut(), Term.optional(rules.named(floatTypeSuffix))),
Term.sequence(rules.namedWithAlias(decimalNumeral, floatWholePart), Term.optional(rules.named(floatExponentPart)), rules.named(floatTypeSuffix))
Term.sequence(
rules.namedWithAlias(decimalNumeral, floatWholePart),
rules.named(floatExponentPart),
Term.cut(),
Term.optional(rules.named(floatTypeSuffix))
),
Term.sequence(
rules.namedWithAlias(decimalNumeral, floatWholePart),
Term.optional(rules.named(floatExponentPart)),
rules.named(floatTypeSuffix)
)
)
),
state -> {
@@ -404,14 +403,19 @@ public class SnbtGrammar {
return createFloat(ops, wholeSign, whole, fraction, exponent, typeSuffix, state);
}
);
Atom<String> stringHex2 = Atom.of("string_hex_2");
rules.put(stringHex2, new SimpleHexLiteralParseRule(2));
Atom<String> stringHex4 = Atom.of("string_hex_4");
rules.put(stringHex4, new SimpleHexLiteralParseRule(4));
Atom<String> stringHex8 = Atom.of("string_hex_8");
rules.put(stringHex8, new SimpleHexLiteralParseRule(8));
Atom<String> stringUnicodeName = Atom.of("string_unicode_name");
rules.put(stringUnicodeName, new GreedyPatternParseRule(UNICODE_NAME, ERROR_INVALID_CHARACTER_NAME));
Atom<String> stringEscapeSequence = Atom.of("string_escape_sequence");
rules.putComplex(
stringEscapeSequence,
@@ -428,7 +432,12 @@ public class SnbtGrammar {
Term.sequence(StringReaderTerms.character('x'), rules.named(stringHex2)),
Term.sequence(StringReaderTerms.character('u'), rules.named(stringHex4)),
Term.sequence(StringReaderTerms.character('U'), rules.named(stringHex8)),
Term.sequence(StringReaderTerms.character('N'), StringReaderTerms.character('{'), rules.named(stringUnicodeName), StringReaderTerms.character('}'))
Term.sequence(
StringReaderTerms.character('N'),
StringReaderTerms.character('{'),
rules.named(stringUnicodeName),
StringReaderTerms.character('}')
)
),
state -> {
Scope scope = state.scope();
@@ -440,8 +449,7 @@ public class SnbtGrammar {
if (hexEscape != null) {
int codePoint = HexFormat.fromHexDigits(hexEscape);
if (!Character.isValidCodePoint(codePoint)) {
state.errorCollector()
.store(state.mark(), DelayedException.create(ERROR_INVALID_CODEPOINT, String.format(Locale.ROOT, "U+%08X", codePoint)));
state.errorCollector().store(state.mark(), DelayedException.create(ERROR_INVALID_CODEPOINT, String.format(Locale.ROOT, "U+%08X", codePoint)));
return null;
}
return Character.toString(codePoint);
@@ -459,12 +467,14 @@ public class SnbtGrammar {
return Character.toString(codePoint);
}
);
Atom<String> stringPlainContents = Atom.of("string_plain_contents");
rules.put(stringPlainContents, PLAIN_STRING_CHUNK);
Atom<List<String>> stringChunks = Atom.of("string_chunks");
Atom<String> stringContents = Atom.of("string_contents");
Atom<String> singleQuotedStringChunk = Atom.of("single_quoted_string_chunk");
NamedRule<StringReader, String> namedRule1 = rules.put(
NamedRule<StringReader, String> singleQuotedStringChunkRule = rules.put(
singleQuotedStringChunk,
Term.alternative(
rules.namedWithAlias(stringPlainContents, stringContents),
@@ -474,9 +484,14 @@ public class SnbtGrammar {
scope -> scope.getOrThrow(stringContents)
);
Atom<String> singleQuotedStringContents = Atom.of("single_quoted_string_contents");
rules.put(singleQuotedStringContents, Term.repeated(namedRule1, stringChunks), scope -> joinList(scope.getOrThrow(stringChunks)));
rules.put(
singleQuotedStringContents,
Term.repeated(singleQuotedStringChunkRule, stringChunks),
scope -> joinList(scope.getOrThrow(stringChunks))
);
Atom<String> doubleQuotedStringChunk = Atom.of("double_quoted_string_chunk");
NamedRule<StringReader, String> namedRule2 = rules.put(
NamedRule<StringReader, String> doubleQuotedStringChunkRule = rules.put(
doubleQuotedStringChunk,
Term.alternative(
rules.namedWithAlias(stringPlainContents, stringContents),
@@ -486,31 +501,59 @@ public class SnbtGrammar {
scope -> scope.getOrThrow(stringContents)
);
Atom<String> doubleQuotedStringContents = Atom.of("double_quoted_string_contents");
rules.put(doubleQuotedStringContents, Term.repeated(namedRule2, stringChunks), scope -> joinList(scope.getOrThrow(stringChunks)));
rules.put(
doubleQuotedStringContents,
Term.repeated(doubleQuotedStringChunkRule, stringChunks),
scope -> joinList(scope.getOrThrow(stringChunks))
);
Atom<String> quotedStringLiteral = Atom.of("quoted_string_literal");
rules.put(
quotedStringLiteral,
Term.alternative(
Term.sequence(
StringReaderTerms.character('"'), Term.cut(), Term.optional(rules.namedWithAlias(doubleQuotedStringContents, stringContents)), StringReaderTerms.character('"')
StringReaderTerms.character('"'),
Term.cut(),
Term.optional(rules.namedWithAlias(doubleQuotedStringContents, stringContents)),
StringReaderTerms.character('"')
),
Term.sequence(StringReaderTerms.character('\''), Term.optional(rules.namedWithAlias(singleQuotedStringContents, stringContents)), StringReaderTerms.character('\''))
Term.sequence(
StringReaderTerms.character('\''),
Term.optional(rules.namedWithAlias(singleQuotedStringContents, stringContents)),
StringReaderTerms.character('\'')
)
),
scope -> scope.getOrThrow(stringContents)
);
Atom<String> unquotedString = Atom.of("unquoted_string");
rules.put(unquotedString, new UnquotedStringParseRule(1, ERROR_EXPECTED_UNQUOTED_STRING));
rules.put(
unquotedString,
new UnquotedStringParseRule(1, ERROR_EXPECTED_UNQUOTED_STRING)
);
Atom<T> literal = Atom.of("literal");
Atom<List<T>> argumentList = Atom.of("arguments");
rules.put(
argumentList, Term.repeatedWithTrailingSeparator(rules.forward(literal), argumentList, StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)), scope -> scope.getOrThrow(argumentList)
argumentList,
Term.repeatedWithTrailingSeparator(
rules.forward(literal),
argumentList,
StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)
),
scope -> scope.getOrThrow(argumentList)
);
Atom<T> unquotedStringOrBuiltIn = Atom.of("unquoted_string_or_builtin");
rules.putComplex(
unquotedStringOrBuiltIn,
Term.sequence(
rules.named(unquotedString),
Term.optional(Term.sequence(StringReaderTerms.character('('), rules.named(argumentList), StringReaderTerms.character(')')))
Term.optional(Term.sequence(
StringReaderTerms.character('('),
rules.named(argumentList),
StringReaderTerms.character(')')
))
),
state -> {
Scope scope = state.scope();
@@ -543,11 +586,26 @@ public class SnbtGrammar {
return null;
}
);
Atom<String> mapKey = Atom.of("map_key");
rules.put(mapKey, Term.alternative(rules.named(quotedStringLiteral), rules.named(unquotedString)), scope -> scope.getAnyOrThrow(quotedStringLiteral, unquotedString));
rules.put(
mapKey,
Term.alternative(
rules.named(quotedStringLiteral),
rules.named(unquotedString)
),
scope -> scope.getAnyOrThrow(quotedStringLiteral, unquotedString)
);
Atom<Entry<String, T>> mapEntry = Atom.of("map_entry");
NamedRule<StringReader, Entry<String, T>> mapEntryRule = rules.putComplex(
mapEntry, Term.sequence(rules.named(mapKey), StringReaderTerms.character(TagParser.NAME_VALUE_SEPARATOR), rules.named(literal)), state -> {
mapEntry,
Term.sequence(
rules.named(mapKey),
StringReaderTerms.character(TagParser.NAME_VALUE_SEPARATOR),
rules.named(literal)
),
state -> {
Scope scope = state.scope();
String key = scope.getOrThrow(mapKey);
if (key.isEmpty()) {
@@ -558,26 +616,52 @@ public class SnbtGrammar {
return Map.entry(key, value);
}
);
Atom<List<Entry<String, T>>> mapEntries = Atom.of("map_entries");
rules.put(mapEntries, Term.repeatedWithTrailingSeparator(mapEntryRule, mapEntries, StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)), scope -> scope.getOrThrow(mapEntries));
rules.put(
mapEntries,
Term.repeatedWithTrailingSeparator(
mapEntryRule,
mapEntries,
StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)
),
scope -> scope.getOrThrow(mapEntries)
);
Atom<T> mapLiteral = Atom.of("map_literal");
rules.put(mapLiteral, Term.sequence(StringReaderTerms.character('{'), Scope.increaseDepth(), rules.named(mapEntries), Scope.decreaseDepth(), StringReaderTerms.character('}')), scope -> {
rules.put(
mapLiteral,
Term.sequence(
StringReaderTerms.character('{'),
Scope.increaseDepth(),
rules.named(mapEntries),
Scope.decreaseDepth(),
StringReaderTerms.character('}')
),
scope -> {
List<Entry<String, T>> entries = scope.getOrThrow(mapEntries);
if (entries.isEmpty()) {
return emptyMapValue;
}
Builder<T, T> builder = ImmutableMap.builderWithExpectedSize(entries.size());
for (Entry<String, T> e : entries) {
builder.put(ops.createString(e.getKey()), e.getValue());
}
return ops.createMap(builder.buildKeepingLast());
});
}
);
Atom<List<T>> listEntries = Atom.of("list_entries");
rules.put(
listEntries, Term.repeatedWithTrailingSeparator(rules.forward(literal), listEntries, StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)), scope -> scope.getOrThrow(listEntries)
listEntries,
Term.repeatedWithTrailingSeparator(
rules.forward(literal),
listEntries,
StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)
),
scope -> scope.getOrThrow(listEntries)
);
Atom<ArrayPrefix> arrayPrefix = Atom.of("array_prefix");
rules.put(
arrayPrefix,
@@ -588,15 +672,32 @@ public class SnbtGrammar {
),
scope -> scope.getOrThrow(arrayPrefix)
);
Atom<List<IntegerLiteral>> intArrayEntries = Atom.of("int_array_entries");
rules.put(intArrayEntries, Term.repeatedWithTrailingSeparator(integerLiteralRule, intArrayEntries, StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)), scope -> scope.getOrThrow(intArrayEntries));
rules.put(
intArrayEntries,
Term.repeatedWithTrailingSeparator(
integerLiteralRule,
intArrayEntries,
StringReaderTerms.character(TagParser.ELEMENT_SEPARATOR)
),
scope -> scope.getOrThrow(intArrayEntries)
);
Atom<T> listLiteral = Atom.of("list_literal");
rules.putComplex(
listLiteral,
Term.sequence(
StringReaderTerms.character('['),
Scope.increaseDepth(),
Term.alternative(Term.sequence(rules.named(arrayPrefix), StringReaderTerms.character(';'), rules.named(intArrayEntries)), rules.named(listEntries)),
Term.alternative(
Term.sequence(
rules.named(arrayPrefix),
StringReaderTerms.character(';'),
rules.named(intArrayEntries)
),
rules.named(listEntries)
),
Scope.decreaseDepth(),
StringReaderTerms.character(']')
),
@@ -611,13 +712,32 @@ public class SnbtGrammar {
return entries.isEmpty() ? emptyList : ops.createList(entries.stream());
}
);
NamedRule<StringReader, T> literalRule = rules.putComplex(
literal,
Term.alternative(
Term.sequence(Term.positiveLookahead(NUMBER_LOOKEAHEAD), Term.alternative(rules.namedWithAlias(floatLiteral, literal), rules.named(integerLiteral))),
Term.sequence(Term.positiveLookahead(StringReaderTerms.characters('"', '\'')), Term.cut(), rules.named(quotedStringLiteral)),
Term.sequence(Term.positiveLookahead(StringReaderTerms.character('{')), Term.cut(), rules.namedWithAlias(mapLiteral, literal)),
Term.sequence(Term.positiveLookahead(StringReaderTerms.character('[')), Term.cut(), rules.namedWithAlias(listLiteral, literal)),
Term.sequence(
Term.positiveLookahead(NUMBER_LOOKEAHEAD),
Term.alternative(
rules.namedWithAlias(floatLiteral, literal),
rules.named(integerLiteral)
)
),
Term.sequence(
Term.positiveLookahead(StringReaderTerms.characters('"', '\'')),
Term.cut(),
rules.named(quotedStringLiteral)
),
Term.sequence(
Term.positiveLookahead(StringReaderTerms.character('{')),
Term.cut(),
rules.namedWithAlias(mapLiteral, literal)
),
Term.sequence(
Term.positiveLookahead(StringReaderTerms.character('[')),
Term.cut(),
rules.namedWithAlias(listLiteral, literal)
),
rules.namedWithAlias(unquotedStringOrBuiltIn, literal)
),
state -> {
@@ -630,6 +750,7 @@ public class SnbtGrammar {
return integer != null ? integer.create(ops, state) : scope.getOrThrow(literal);
}
);
return new Grammar<>(rules, literalRule);
}
@@ -646,16 +767,13 @@ public class SnbtGrammar {
@Override
public <T> T create(DynamicOps<T> ops, List<IntegerLiteral> entries, ParseState<?> state) {
ByteList result = new ByteArrayList();
for (IntegerLiteral entry : entries) {
Number number = this.buildNumber(entry, state);
if (number == null) {
return null;
}
result.add(number.byteValue());
}
return ops.createByteList(ByteBuffer.wrap(result.toByteArray()));
}
},
@@ -669,16 +787,13 @@ public class SnbtGrammar {
@Override
public <T> T create(DynamicOps<T> ops, List<IntegerLiteral> entries, ParseState<?> state) {
IntStream.Builder result = IntStream.builder();
for (IntegerLiteral entry : entries) {
Number parsedNumber = this.buildNumber(entry, state);
if (parsedNumber == null) {
return null;
}
result.add(parsedNumber.intValue());
}
return ops.createIntList(result.build());
}
},
@@ -692,16 +807,13 @@ public class SnbtGrammar {
@Override
public <T> T create(DynamicOps<T> ops, List<IntegerLiteral> entries, ParseState<?> state) {
LongStream.Builder result = LongStream.builder();
for (IntegerLiteral entry : entries) {
Number parsedNumber = this.buildNumber(entry, state);
if (parsedNumber == null) {
return null;
}
result.add(parsedNumber.longValue());
}
return ops.createLongList(result.build());
}
};
@@ -717,7 +829,6 @@ public class SnbtGrammar {
public boolean isAllowed(TypeSuffix type) {
return type == this.defaultType || this.additionalTypes.contains(type);
}
public abstract <T> T create(DynamicOps<T> ops);
@Nullable
@@ -742,7 +853,6 @@ public class SnbtGrammar {
return !this.isAllowed(type) ? null : type;
}
}
enum Base {
BINARY,
DECIMAL,

View File

@@ -10,7 +10,7 @@ import java.util.Optional;
import java.util.function.Supplier;
public class LocalizedCommandSyntaxException extends CommandSyntaxException {
public static final int CONTEXT_AMOUNT = 10;
public static final int CONTEXT_AMOUNT = 50;
public static final String PARSE_ERROR_NODE = "warning.config.type.snbt.invalid_syntax.parse_error";
public static final String HERE_NODE = "warning.config.type.snbt.invalid_syntax.here";
private final Message message;