Strucked
Strucked is an esoteric programming language thought up by User:1hals. It is a Declarative Programming Language for describing simple binary file formats. The name is a pun on the word "struct". The main difference between this a C-style structs is that the size of further fields can depend on the value of previous fields. The purpose of this is to be a simple schema for defining scary file formats where the sizes of the fields can be different depending on the file's data (via the size expressions).
File contents
A file is a series of declarations that determine the file format via field types. Declarations consist of a name/identifier, size, and type. Identifiers must appear in a previous declaration before they can be used in subsequent ones.
Size expressions
When specifying the size of a type, an RPN expression involving previously defined identifiers is allowed. Also, the RPN expression may use the following stack operators:
*
(2 operands) multiply+
(2 operands) add/
(2 operands) divide-
(2 operands) subtract&
(2 operands) bit-and|
(2 operands) bit-or<<
(2 operands) left shift>>
(2 operands) right shift=
(1 operand) duplicate$
(no operands) swap_
(no operands) drop
- An empty size, written as (), represents a freely variable-sized array (like [] in C), which may or may not be valid, depending on the context
Data types
The basic types are:
bbyte
: big-endian bytes (when more than 1)lbyte
: little-endian bytes (when more than 1)
Compound types are constructed by surrounding a series of declarations within [square brackets]. Note: only fields can be named, not types, so if you need to use a type in multiple places, you just have to copy-and-paste the field definitions.
Syntax
EBNF grammar (ignoring whitespace):
whole file = decl, { decl } decl = name, "(", [ expression ], ")", type type = "bbyte" | "lbyte" | compound compound = "[", decl, { decl }, "]" expression = ( name | number ), { name | number | operator } operator = "*" | "+" | "/" | "-" | "&" | "|" | "<<" | ">>" | "=" | "$" | "_" name = ? Word not starting with a 0-9 ? number = 0-9, { 0-9 }
Examples
In the examples below, the #
symbol is used for comments.
String file
width (1) bbyte # identifier "width" is 1 byte at the beginning of the file (endianness doesn't matter for size of 1) count (width) lbyte # identifier "count" is "width" bytes refering back to the identifier, little endian string_pointers (count) # identifier "string_pointers" is "count" instances of the following group made by the brackets [ offset (width) lbyte # indentation is ignored/optional length (width) lbyte ] strings () # identifier "strings" is an unlimited array
Using math
half_count (4) lbyte data (half_count 2 * 1 -) [ # here we calculate (half_count * 2) - 1 x (4) lbyte y (4) lbyte ]
Challenge
If you want a programming challenge/project, implement an API for reading/writing files using a given Strucked schema.