Completely rework SNBT Parser

(NOTE: ChatGPT Was used for regex only)
This commit is contained in:
zontreck 2024-08-29 06:55:12 -07:00
parent 7c87ef444f
commit 84192c69db
11 changed files with 150 additions and 107 deletions

View file

@ -1,3 +1,5 @@
import 'dart:core';
import 'Stream.dart';
import 'impl/ByteArrayTag.dart';
import 'impl/ByteTag.dart';
@ -42,109 +44,112 @@ enum TagType {
}
static const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static TagType getStringifiedTagType(StringReader reader) {
reader.startSeek();
reader.startSeek(); // Enter fake read mode
TagType ret = TagType.End;
bool isNumber = true;
bool isAlpha = true; // Is digits only
bool isQuoted = false;
bool isNumeric = true; // Assume true until proven otherwise
bool isAlpha = true; // Assume true until proven otherwise
StringBuffer buffer = StringBuffer();
// Start to determine the next tag type
while (reader.canRead && ret == TagType.End) {
var val = reader.next().toUpperCase();
if (ALPHABET.indexOf(val) == -1) isAlpha = false;
while (reader.canRead) {
var val =
reader.peek(); // Peek at the next character without consuming it
switch (val) {
case "{":
{
ret = TagType.Compound;
break;
}
case "[":
{
// Check for a type Prefix
var X = reader.readUntil(";");
switch (X.toUpperCase()) {
case "B":
{
ret = TagType.ByteArray;
break;
}
case "I":
{
ret = TagType.IntArray;
break;
}
case "L":
{
ret = TagType.LongArray;
break;
}
default:
{
ret = TagType.List;
break;
}
}
break;
}
case "B":
{
ret = TagType.Byte;
break;
}
case "D":
{
ret = TagType.Double;
break;
}
case "F":
{
ret = TagType.Float;
break;
}
case "I":
{
ret = TagType.Int;
break;
}
case "L":
{
ret = TagType.Long;
break;
}
case "S":
{
ret = TagType.Short;
break;
}
case "\"":
{
ret = TagType.String;
break;
}
case ",":
case "\n":
{
if (reader.getSeeked >= 1) ret = TagType.String;
if (isNumber) ret = TagType.Int;
if (val == ',' || val == '\n' || val == "]" || val == "}") {
break; // Stop at comma or newline
}
if (val == '"') {
reader.next(); // Consume the quote character
isQuoted = true; // Toggle quoted state
break;
}
if (val == '{') {
ret = TagType.Compound; // Detected a CompoundTag
reader.next(); // Consume '{'
reader.endSeek(); // Restore the original stream position
return ret;
}
if (val == '[') {
reader.next(); // Consume '['
// Peek ahead to differentiate between List and Array
var prefix = reader.readUntil(";", 2).toUpperCase();
switch (prefix) {
case "B":
ret = TagType.ByteArray;
break;
}
default:
{
if (!reader.isDigit(val)) {
if (isNumber) isNumber = false;
}
case "I":
ret = TagType.IntArray;
break;
}
case "L":
ret = TagType.LongArray;
break;
default:
ret = TagType.List; // No type prefix, it's a List
break;
}
reader.endSeek(); // Restore the original stream position
return ret;
}
// Adjusting numeric and alphabetic checks
var current = reader.next(); // Consume the character
buffer.write(current);
// Check if current character is a digit or numeric suffix
if (!RegExp(r'^[0-9]$').hasMatch(current) &&
!RegExp(r'^[sSbBiIlLfFdD]$').hasMatch(current)) {
isNumeric = false; // Not purely numeric with possible suffix
}
// Check if current character is purely alphabetical
if (!RegExp(r'^[A-Za-z]$').hasMatch(current)) {
isAlpha = false; // Not purely alphabetical
}
}
reader.endSeek();
if (!isNumber && isAlpha) ret = TagType.String;
var input = buffer.toString().trim();
reader.endSeek(); // Restore the original stream position
return ret;
if (input.isEmpty) {
return TagType.String; // No input detected
}
if (isQuoted) {
return TagType.String; // Quoted string
}
if (isNumeric) {
// Check the last character for type indicator (only for numeric input)
var lastChar = input.substring(input.length - 1).toUpperCase();
switch (lastChar) {
case 'S':
return TagType.Short;
case 'B':
return TagType.Byte;
case 'I':
return TagType.Int;
case 'F':
return TagType.Float;
case 'D':
return TagType.Double;
case 'L':
return TagType.Long;
default:
return TagType
.Int; // Default to Int if purely numeric with no specific suffix
}
} else if (isAlpha && !input.contains(' ')) {
return TagType.String; // Unquoted purely alphabetical string
} else {
return TagType.String; // Unquoted string with mixed content or spaces
}
}
}
@ -264,7 +269,7 @@ abstract class Tag {
bool shouldQuote(String value) {
if (value == "") {
return false;
return true;
} else {
String letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < value.length; i++) {