Skip to content

Instantly share code, notes, and snippets.

@intsuc
Last active February 27, 2025 16:45
Show Gist options
  • Save intsuc/36ed892f7fcda4c10d9b6b900cb815a1 to your computer and use it in GitHub Desktop.
Save intsuc/36ed892f7fcda4c10d9b6b900cb815a1 to your computer and use it in GitHub Desktop.
[25w09b] SNBT grammar without rules
/* https://www.minecraft.net/en-us/article/minecraft-snapshot-25w09a */
simple_hex_literal =
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
unicode_name =
(
| '-'
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
| '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
| ' '
)+
is_allowed_in_unquoted_string =
| '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
| '_' | '-' | '.' | '+'
can_start_number =
'+' | '-' | '.' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
sign =
| '+'
| '-'
/* Type suffixes have been extended: */
integer_suffix =
/* Integer type suffixes (b or B - byte, s or S - short, i or I - integer, l or L) can now be prefixed with s (signed) or u unsigned */
| ('u' | 'U') (('b' | 'B') | ('s' | 'S') | ('i' | 'I') | ('l' | 'L'))
| ('s' | 'S') (('b' | 'B') | ('s' | 'S') | ('i' | 'I') | ('l' | 'L'))
| ('b' | 'B')
| ('s' | 'S')
| ('i' | 'I')
| ('l' | 'L')
/* Numbers can now contain _ character between sequences of digits (but not at the start or the end of sequence) */
/* Example: 0b10_01, 0xAB_CD, 1_2.3_4__5f, 1_2e3_4 */
binary_numeral =
!'_' ('0' | '1' | '_')+ !'_'
decimal_numeral =
!'_' ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '_')+ !'_'
hex_numeral =
!'_' ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f')+ !'_'
integer_literal =
sign? (
| '0' ↑ (
/* Integer numbers can now be prefixed with 0x to represent hexadecimal numbers and 0b to represent binary numbers */
/* Example: 0xbad (equal to 2989), 0xCAFE (equal to 51966), 0b101 (equal to 5) */
| ('x' | 'X') ↑ hex_numeral
| ('b' | 'B') binary_numeral
/* Integer numbers now can't start with 0 */
/* Normally it would mean number is in base-8, but we are restricting it to avoid accidental use */
| decimal_numeralfail
)
| decimal_numeral
)
float_type_suffix =
| ('f' | 'F')
| ('d' | 'D')
float_exponent_part =
/* Float numbers now use E notation */
/* Example: both 1.2e3 and 1.2E3, 1.2E+3, 12000e-1 are now a valid way to represent 1200.0 */
('e' | 'E') sign? decimal_numeral
/* NaN, Inf or hexadecimal float representation are NOT supported */
float_literal =
sign? (
/* Either whole or fraction parts of a float number can be omitted */
/* Examples: .1 and 1. are valid now */
| decimal_numeral '.'decimal_numeral? float_exponent_part? float_type_suffix?
| '.'decimal_numeral float_exponent_part? float_type_suffix?
| decimal_numeral float_exponent_partfloat_type_suffix?
| decimal_numeral float_exponent_part? float_type_suffix
)
string_hex_2 =
simple_hex_literal simple_hex_literal+
string_hex_4 =
simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal+
string_hex_8 =
simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal simple_hex_literal+
string_unicode_name =
unicode_name
/* Quoted strings can now use escape sequences beyond ', " and \: */
string_escape_sequence =
/* Built-in escape sequences: */
/* \b - backspace, Unicode \x08 */
| 'b'
/* \s - space, Unicode \x20 */
| 's'
/* \t - horizontal tab, Unicode \x09 */
| 't'
/* \n - linefeed, Unicode \u0a */
| 'n'
/* \f - form feed, Unicode \u0c */
| 'f'
/* \r - carriage return, Unicode \u0d */
| 'r'
| '\\'
| '\''
| '"'
/* Unicode escapes: */
/* \x - two digit escape, like \x42 */
| 'x' string_hex_2
/* \u - four digit escape, like \u2603 */
| 'u' string_hex_4
/* \U - eight digit escape, like \U00002603 */
| 'U' string_hex_8
/* \N{<name>} - named Unicode character, like \N{Snowman} */
| 'N' '{' string_unicode_name '}'
string_plain_contents =
(!('"' | '\'' | '\\'))+
single_quoted_string_chunk =
| string_plain_contents
| '\\' string_escape_sequence
| '"'
single_quoted_string_contents =
single_quoted_string_chunk*
double_quoted_string_chunk =
| string_plain_contents
| '\\' string_escape_sequence
| '\''
double_quoted_string_contents =
double_quoted_string_chunk*
quoted_string_literal =
| '"'double_quoted_string_contents? '"'
| '\'' single_quoted_string_contents? '\''
unquoted_string =
is_allowed_in_unquoted_string+
unquoted_string_or_builtin =
unquoted_string
map_key =
| quoted_string_literal
| unquoted_string
map_entry =
map_key ':' literal
map_entries =
/* Compounds (maps) now accept trailing commas */
/* Example: {a:b,} */
/* Only one trailing comma is allowed, and it must come after a valid key-value pair - both {,} and {a:b,,} are invalid */
(map_entry (',' map_entry)* ','?)?
map_literal =
'{' map_entries '}'
list_entries =
/* Lists now accept trailing commas */
/* Example: [1,2,] is valid and equivalent to [1,2] */
/* Only one trailing comma is allowed, and it must come after a valid element - both [,] and [1,,] are invalid */
(literal (',' literal)* ','?)?
array_prefix =
| 'B'
| 'L'
| 'I'
int_array_entries =
(integer_literal (',' integer_literal)* ','?)?
list_literal =
'[' (
| array_prefix ';' int_array_entries
| list_entries
) ']'
literal =
| &can_start_number (float_literal | integer_literal)
| &('"' | '\'') ↑ quoted_string_literal
| &'{'map_literal
| &'['list_literal
| unquoted_string_or_builtin
top =
literal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment