Erbb Grammar
This document describes what sequence of tokens form valid inputs of the language.
How to Read the Grammar
The notation used to describe the formal grammar of erbb
has the following conventions:
An arrow (→) is used to mark grammar productions and can be read as “can consist of”,
Alternative grammar productions are either separated by verticals bars (|) or are broken into multiple grammar production rules lines,
Keywords and symbols are indicated using
bold inline code
style text,Optional syntactic categories and literals are marked by a trailing subscript (opt),
Syntactic category or literal repetitions of 0 or more are marked by a trailing subscript (0+),
Syntactic category or literal repetitions of 1 or more are marked by a trailing subscript (1+).
Global namespace
The global namespace is the root of the grammar. One and only one module declaration is valid.
Grammar
global-namespace → use-strict-statementopt module-declaration
use strict
This statement enables more compile-time checks by enabling all warnings and turning them into errors. When this statement is not used, the compiler will use its default configuration, which has reduced warning checks and doesn’t report them as errors.
Grammar
use-strict-statement →
use
strict
module
A module
defines a physical module, a unique piece of hardware to produce.
it is a set of multiple import
, sources
, base
, define
, etc. declarations.
Grammar
module-declaration →
module
module-name{
module-entity0+}
module-name → identifier
module-entity → import-declaration
module-entity → define-declaration
module-entity → sources-declaration
module-entity → resources-declaration
module-entity → base-declaration
import
An import
merges the parsed content of the associated path into the parent module
.
The path is relative to the current parsed file.
Grammar
import-declaration →
import
path-literal
base
A base
defines a header search path for the module
sources
.
The path is relative to the current parsed file. This is typically used in libraries, to disambiguate file includes with the same name.
Grammar
base-declaration →
base
path-literal
define
A define
adds a key/value pair for the underlying language preprocessor,
available to the module
sources
.
Grammar
define-declaration →
define
define-key=
define-value
define-key → identifier
define-value → literal
Language Bindings
define-key is exported to the target language preprocessor.
For example the following erbb
source code:
module Foo {
define MY_FLAG=1
sources {
file "Foo.cpp"
file "Foo.h"
}
}
Defines MY_FLAG
for all sources
in the module
:
// Foo.cpp
void process () {
#if MY_FLAG == 1
// do something
#else
// do something else
#endif
}
Predefined keys
Some predefined keys are available for the system and are prefixed by erb_
. This allows
for example to instrument the buffer size or tell the SdRam system how much memory it
can allocate at max.
sources
The sources
defines the source code of the module.
Grammar
sources-declaration →
sources
{
sources-entity0+}
sources-entity → file-declaration
file
A file
defines a file to compile in the module
sources
.
The path is relative to the current parsed file.
This is typically C++ source and header files, audio sample files, but can be also the erbb
file.
Grammar
file-declaration →
file
path-literal
resources
The resources
defines the resources of the module, like an audio sample.
They are piece of data compiled with the program for convenience.
Grammar
resources-declaration →
resources
{
resources-entity0+}
resources-entity → data-declaration
data
A data
is an element of the module that represents a resource.
Grammar
data-declaration →
data
data-name data-typeopt{
data-entity0+}
data-name → identifier
data-type → identifier
data-entity → file-declaration
data-entity → stream-declaration
Language Bindings
data-name is exported to the target language used to develop the module DSP, such as C++ or Max.
For example the following erbb
source code:
module Foo {
data osc_sample AudioSample {
file "osc_sample.wav"
}
}
Exports the osc_sample
in C++:
void process () {
float val = data.osc_sample.frames [0].channels [0];
// 'data.osc_sample' is a 'erb::AudioSample <float, length, nbr_channels>'
// where 'length' and 'nbr_channels' are automatically deduced from
// the input file.
}
Omitting data-type results in raw data.
module Foo {
data raw {
file "raw.bin"
}
}
uint8_t val = data.raw [0];
// 'data.raw' is a 'std::array <uint8_t, size>' where 'size' is the size of
// the input file.
Supported Types
AudioSample
: Creates aerb::AudioSample
value from an audio sample file.FormatSsd130x
: Creates astd::array <uint8_t, ...>
value from an image file.
stream
A stream
defines the representation of frames, channels and samples for an AudioSample
data
type. When not specified, mono audio samples are assumed mono
and multi-channels
audio samples are assumed interleaved
, to maximize cache coherency and simplify
processing using SIMD instructions.
Grammar
stream-declaration →
stream
stream-format
stream-format →mono
stream-format →interleaved
stream-format →planar
Language Bindings
The generated instance will have the types AudioSampleMono
, AudioSampleInterleaved
and AudioSamplePlanar
.
AudioSampleMono
stores the sample as a single array for floating point values,AudioSampleInterleaved
stores the sample as an array of frames, each frame being an array of channels,AudioSamplePlanar
stores the sample as an array of channels, each channel being an array of samples.