2.2.2. Grammars¶
Contents
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 theforeach
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