2.2.2. Grammars

2.2.2.1. Global Definitions

global
TODO.
const
TODO.
import
TODO.
type
TODO.
Statements
Statements at the global level will execute once as a module is initialized for the first time by the host application.

2.2.2.2. Units

TODO.

2.2.2.2.1. Variables

TODO.

2.2.2.2.2. Properties

%byteorder
TODO.
%description
TODO.
%mimetype
TODO.
%port
TODO.

2.2.2.3. Hooks

A hook is code that is will be executed during parsing at certain points of time. There are three types of hooks, field hooks, unit hooks, and item hooks.

Inside all hooks, the self identifier refers to the unit being parsed.

Unit Hooks

Unit hooks are not tied to a specific field but apply to the parsing process of the unit they are part of. They are always defined using the on <hook-name> syntax, e.g.:

type Foo = unit {
    ...
    on %init { <code> }
    ...
}

Currently, Spicy defines these unit hooks:

%init
Executed when the parsing of a unit is about to start. All of the fields and variables will have their default values at the time the hook’s code executes (which may be unset and thus trigger an exception when being read).
%done
Executed when the parsing of a unit instance has completed. All fields and variables will have their final values.
%debug
Executed when the parsing of a unit instance has completed and debugging is activated (i.e., has been compiled in and is enabled at run-time, see Debugging Support).
Field and Variable Hooks

Field hooks are associated with a specific field and execute whenver that field has been fully parsed. For example, the following code snippet adds a hook to the uri, in this case simply printing the field’s content:

uri: Token {
    print self.uri;
    }

Note how self still refers to the unit, not the field.

Often, a field hook will store information in other Variables , like in this toy example:

uri : Token {
    if ( self.uri.startswith("http://") )
        self.proxy = True;
    }

var proxy : bool;

Field hooks can also be specified at the unit level using the on <field-name> syntax:

 type Foo = unit {
      ...

      uri: Token;

      ...

      on uri {
          print self.uri;
      }
}
Item Hooks

Item hooks are associated with container types (e.g., list, vector) and execute each time one container items has beed parsed. These hooks are marked with the foreach keyword, and they have access to the current item via the reserved $$ identifier. Example:

lines: list<Item> &until($$.line == b"---\n")
                  foreach { print $$; }

While this is parsing list elements, each will be printed out. (Note how the list’s &until also has access to $$.)

In addition to specifying hooks inside a unit, they can all also be provided externally at the global level, using again the on <hook-name> syntax where <hook-name> is now the fully qualified name:

type RequestLine = unit {
    ...
    uri:     Token;
    ...
};

on RequestLine::uri {
    print self.uri;
    }

on RequestLine::%done {
    ...
    }

Note that parsing will always execute all relevant hooks defined anywhere in the input specification. It’s perfectly fine to define a field hook inline and later add more external hooks to the same field; all of them will be executed (in an undefined order). This even works across units: if you import the Request module into the another specification, you can add a hook to it like this:

on Request::RequestLine::uri {
    print self.uri;
    }

2.2.2.4. Conditional Parsing

switch if

2.2.2.5. Random Access

2.2.2.6. Sinks

2.2.2.7. Filters

2.2.2.8. Fields

Standard attributes
&default

2.2.2.9. Types

2.2.2.9.1. Bytes

&length &until &eod regexp

2.2.2.9.2. List

2.2.2.9.3. Vector

2.2.2.9.4. Integer

2.2.2.9.5. Subunit