Strucked

From Esolang
Jump to navigation Jump to search

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.