From 392bd814e3584e666c07d8a4b65d6a8a219c7e2f Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Mon, 1 Dec 2025 08:48:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=88=E5=86=99=E4=B8=80=E7=82=B9=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/util/snbt/SnbtGrammar.java | 67 ++++++++++++++----- .../core/util/snbt/SnbtOperations.java | 3 +- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtGrammar.java b/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtGrammar.java index 3dfa6cbde..c61899b05 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtGrammar.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtGrammar.java @@ -246,11 +246,12 @@ public class SnbtGrammar { T falseValue = ops.createBoolean(false); T emptyMapValue = ops.emptyMap(); T emptyList = ops.emptyList(); - T nullString = ops.createString("null"); - boolean isJavaType = "null".equals(nullString); // 确定是 Java 类型的 + T nullString = ops.createString(SnbtOperations.BUILTIN_NULL); + boolean isJavaType = SnbtOperations.BUILTIN_NULL.equals(nullString); // 确定是 Java 类型的 Dictionary rules = new Dictionary<>(); + // 符号解析规则 Atom sign = Atom.of("sign"); rules.put( sign, @@ -261,6 +262,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(sign) ); + // 整数后缀解析规则 Atom integerSuffix = Atom.of("integer_suffix"); rules.put( integerSuffix, @@ -291,15 +293,19 @@ public class SnbtGrammar { scope -> scope.getOrThrow(integerSuffix) ); + // 二进制解析规则 Atom binaryNumeral = Atom.of("binary_numeral"); rules.put(binaryNumeral, BINARY_NUMERAL); + // 十进制解析规则 Atom decimalNumeral = Atom.of("decimal_numeral"); rules.put(decimalNumeral, DECIMAL_NUMERAL); + // 十六进制解析规则 Atom hexNumeral = Atom.of("hex_numeral"); rules.put(hexNumeral, HEX_NUMERAL); + // 整数常量解析规则 Atom integerLiteral = Atom.of("integer_literal"); NamedRule integerLiteralRule = rules.put( integerLiteral, @@ -336,6 +342,7 @@ public class SnbtGrammar { } ); + // 浮点型后缀解析规则 Atom floatTypeSuffix = Atom.of("float_type_suffix"); rules.put( floatTypeSuffix, @@ -346,6 +353,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(floatTypeSuffix) ); + // 浮点数指数部分解析规则 Atom> floatExponentPart = Atom.of("float_exponent_part"); rules.put( floatExponentPart, @@ -357,8 +365,9 @@ public class SnbtGrammar { scope -> new Signed<>(scope.getOrDefault(sign, Sign.PLUS), scope.getOrThrow(decimalNumeral)) ); - Atom floatWholePart = Atom.of("float_whole_part"); - Atom floatFractionPart = Atom.of("float_fraction_part"); + // 浮点数常量解析规则 + Atom floatWholePart = Atom.of("float_whole_part"); // 整数部分 + Atom floatFractionPart = Atom.of("float_fraction_part"); // 小数部分 Atom floatLiteral = Atom.of("float_literal"); rules.putComplex( floatLiteral, @@ -404,18 +413,23 @@ public class SnbtGrammar { } ); + // 二位十六进制字符串解析规则 Atom stringHex2 = Atom.of("string_hex_2"); rules.put(stringHex2, new SimpleHexLiteralParseRule(2)); + // 四位十六进制字符串解析规则 Atom stringHex4 = Atom.of("string_hex_4"); rules.put(stringHex4, new SimpleHexLiteralParseRule(4)); + // 八位十六进制字符串解析规则 Atom stringHex8 = Atom.of("string_hex_8"); rules.put(stringHex8, new SimpleHexLiteralParseRule(8)); + // Unicode名称字符串解析规则 Atom stringUnicodeName = Atom.of("string_unicode_name"); rules.put(stringUnicodeName, new GreedyPatternParseRule(UNICODE_NAME, ERROR_INVALID_CHARACTER_NAME)); + // 字符串转义序列解析规则 Atom stringEscapeSequence = Atom.of("string_escape_sequence"); rules.putComplex( stringEscapeSequence, @@ -468,11 +482,15 @@ public class SnbtGrammar { } ); + // 纯文本字符串解析规则 Atom stringPlainContents = Atom.of("string_plain_contents"); rules.put(stringPlainContents, PLAIN_STRING_CHUNK); - Atom> stringChunks = Atom.of("string_chunks"); - Atom stringContents = Atom.of("string_contents"); + // 字符串解析规则 + Atom> stringChunks = Atom.of("string_chunks"); // 字符串块 + Atom stringContents = Atom.of("string_contents"); // 字符串内容 + + // 单引号字符串块解析规则 Atom singleQuotedStringChunk = Atom.of("single_quoted_string_chunk"); NamedRule singleQuotedStringChunkRule = rules.put( singleQuotedStringChunk, @@ -483,6 +501,8 @@ public class SnbtGrammar { ), scope -> scope.getOrThrow(stringContents) ); + + // 单引号字符串内容解析规则 Atom singleQuotedStringContents = Atom.of("single_quoted_string_contents"); rules.put( singleQuotedStringContents, @@ -490,6 +510,7 @@ public class SnbtGrammar { scope -> joinList(scope.getOrThrow(stringChunks)) ); + // 双引号字符串块解析规则 Atom doubleQuotedStringChunk = Atom.of("double_quoted_string_chunk"); NamedRule doubleQuotedStringChunkRule = rules.put( doubleQuotedStringChunk, @@ -500,6 +521,8 @@ public class SnbtGrammar { ), scope -> scope.getOrThrow(stringContents) ); + + // 双引号字符串内容解析规则 Atom doubleQuotedStringContents = Atom.of("double_quoted_string_contents"); rules.put( doubleQuotedStringContents, @@ -507,6 +530,7 @@ public class SnbtGrammar { scope -> joinList(scope.getOrThrow(stringChunks)) ); + // 带引号的字符串字面量解析规则 Atom quotedStringLiteral = Atom.of("quoted_string_literal"); rules.put( quotedStringLiteral, @@ -526,14 +550,16 @@ public class SnbtGrammar { scope -> scope.getOrThrow(stringContents) ); + // 不带引号的字符串解析规则 Atom unquotedString = Atom.of("unquoted_string"); rules.put( unquotedString, new UnquotedStringParseRule(1, ERROR_EXPECTED_UNQUOTED_STRING) ); - Atom literal = Atom.of("literal"); - Atom> argumentList = Atom.of("arguments"); + // 列表解析规则 + Atom literal = Atom.of("literal"); // 字面量 + Atom> argumentList = Atom.of("arguments"); // 参数 rules.put( argumentList, Term.repeatedWithTrailingSeparator( @@ -544,6 +570,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(argumentList) ); + // 不带引号的字符串或内置表达式解析规则 Atom unquotedStringOrBuiltIn = Atom.of("unquoted_string_or_builtin"); rules.putComplex( unquotedStringOrBuiltIn, @@ -558,9 +585,9 @@ public class SnbtGrammar { state -> { Scope scope = state.scope(); String contents = scope.getOrThrow(unquotedString); - if (!contents.isEmpty() && isAllowedToStartUnquotedString(contents.charAt(0))) { + if (!contents.isEmpty() && isAllowedToStartUnquotedString(contents.charAt(0))) { // 非空且是合法开头字符 List arguments = scope.get(argumentList); - if (arguments != null) { + if (arguments != null) { // 带参数尝试解析内置表达式 SnbtOperations.BuiltinKey key = new SnbtOperations.BuiltinKey(contents, arguments.size()); SnbtOperations.BuiltinOperation operation = SnbtOperations.BUILTIN_OPERATIONS.get(key); if (operation != null) { @@ -568,16 +595,17 @@ public class SnbtGrammar { } state.errorCollector().store(state.mark(), DelayedException.create(ERROR_NO_SUCH_OPERATION, key.toString())); return null; - } else if (contents.equalsIgnoreCase("true")) { + } else if (contents.equalsIgnoreCase(SnbtOperations.BUILTIN_TRUE)) { // 解析不带引号的 true 为布尔值 return trueValue; - } else if (contents.equalsIgnoreCase("false")) { + } else if (contents.equalsIgnoreCase(SnbtOperations.BUILTIN_FALSE)) { // 解析不带引号的 false 为布尔值 return falseValue; - } else if (contents.equalsIgnoreCase("null")) { - return Objects.requireNonNullElseGet(ops.empty(), () -> { + } else if (contents.equalsIgnoreCase(SnbtOperations.BUILTIN_NULL)) { // 解析不带引号的 null 为空值,该功能并非标准 SNBT 语法 + return Objects.requireNonNullElseGet(ops.empty() /*一般来说这里都不会是null*/, () -> { if (isJavaType) { + // 如果是 null 一般就是使用 Object 对象的 Java 类型,可以安全的强行转换 return (T) CachedParseState.JAVA_NULL_VALUE_MARKER; } - return nullString; + return nullString; // 意外情况保持 SNBT 默认行为 }); } return ops.createString(contents); @@ -587,6 +615,7 @@ public class SnbtGrammar { } ); + // 映射键解析规则 Atom mapKey = Atom.of("map_key"); rules.put( mapKey, @@ -597,6 +626,7 @@ public class SnbtGrammar { scope -> scope.getAnyOrThrow(quotedStringLiteral, unquotedString) ); + // 映射条目解析规则 Atom> mapEntry = Atom.of("map_entry"); NamedRule> mapEntryRule = rules.putComplex( mapEntry, @@ -617,6 +647,7 @@ public class SnbtGrammar { } ); + // 映射条目集合解析规则 Atom>> mapEntries = Atom.of("map_entries"); rules.put( mapEntries, @@ -628,6 +659,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(mapEntries) ); + // 映射字面量解析规则 Atom mapLiteral = Atom.of("map_literal"); rules.put( mapLiteral, @@ -651,6 +683,7 @@ public class SnbtGrammar { } ); + // 列表条目集合解析规则 Atom> listEntries = Atom.of("list_entries"); rules.put( listEntries, @@ -662,6 +695,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(listEntries) ); + // 数组前缀解析规则 Atom arrayPrefix = Atom.of("array_prefix"); rules.put( arrayPrefix, @@ -673,6 +707,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(arrayPrefix) ); + // 整数数组条目集合解析规则 Atom> intArrayEntries = Atom.of("int_array_entries"); rules.put( intArrayEntries, @@ -684,6 +719,7 @@ public class SnbtGrammar { scope -> scope.getOrThrow(intArrayEntries) ); + // 列表字面量解析规则 Atom listLiteral = Atom.of("list_literal"); rules.putComplex( listLiteral, @@ -713,6 +749,7 @@ public class SnbtGrammar { } ); + // 基本规则解析规则 NamedRule literalRule = rules.putComplex( literal, Term.alternative( diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtOperations.java b/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtOperations.java index 589426cad..53a6fa7f0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtOperations.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/snbt/SnbtOperations.java @@ -23,6 +23,7 @@ public class SnbtOperations { ); public static final String BUILTIN_TRUE = "true"; public static final String BUILTIN_FALSE = "false"; + public static final String BUILTIN_NULL = "null"; public static final Map BUILTIN_OPERATIONS = Map.of( new BuiltinKey("bool", 1), new BuiltinOperation() { @Override @@ -67,7 +68,7 @@ public class SnbtOperations { ); public static final SuggestionSupplier BUILTIN_IDS = new SuggestionSupplier<>() { private final Set keys = Stream.concat( - Stream.of(BUILTIN_FALSE, BUILTIN_TRUE), SnbtOperations.BUILTIN_OPERATIONS.keySet().stream().map(BuiltinKey::id) + Stream.of(BUILTIN_FALSE, BUILTIN_TRUE, BUILTIN_NULL), SnbtOperations.BUILTIN_OPERATIONS.keySet().stream().map(BuiltinKey::id) ) .collect(Collectors.toSet());