You are here: Formal Grammar

A Formal Grammar for Decoder Scripts

Here we provide precise specifications for the syntax of decoder executable statements using a BNF-type grammar. We have simplified the grammar a little and, we trust, made it much easier to read by skipping definition of the blank space that separates items. The rule for such space is that any consecutive items must be separated by at least one unit of white space (a space character or an end of line) and may be separated by several.

You may want to print out this chapter and stick the hardcopy to your wall as a reference.

Some notes about the forms used to define the grammar:

  • A parenthesized expression within a non-terminal is a comment. Thus, in "<(size)method>" the "size" is a note to tell you that a Size Method is required in the context but the syntax is defined simply by "<method>".
  • A phrase such as "1*<x>" means a string of one or more <x>'s. Similarly, "*1-16<y>" means a sequence of between one and sixteen <y>'s.
  • An ellipsis means the preceding item may be repeated any number of times.
  • A name/string must be enclosed in double quotes if it contains spaces or characters other than letters, numbers, and underscores.

And here is the grammar:

decoder ::= <header> DECODE <table>... <statement>...

 

header ::= [<comment>] <name> <decoder_id> [<data_order>] [<comment> [<header_item>]...

 

decoder_id ::= <number>

 

data_order ::= NETWORK_DATA_ORDER | HOST_DATA_ORDER

 

header_item ::= PREPROCESSING <(preprocessing)method> |

POSTPROCESSING <(postprocessing)method> |

NEXT_PROTOCOL <(next_protocol)method> |

NEXT_PROTOCOL_OFFSET <(next_protocol_offset)method> |

NEXT_PROTOCOL_SIZE <(next_protocol_size)method> |

FRAME_BEFORE_DECODING <(frame_transformer)method> |

FRAME_AFTER_DECODING <(frame_transformer)method> |

RECOGNIZER <(recognizer)method> |

PAYLOAD_IS_BYTE_STREAM |

BYTE_STREAM_FRAMER <(ByteStreamFramer)Method> |

SUMMARY_COLUMNS <column list> |

 

column list ::= "{" <summary_label> <column_width> ... "}"

summary_label ::= <string>

 

column_width ::= <number>

 

table ::= TABLE <name> <table_entry>... ENDTABLE

| TABLE <name> "@" <filename>

 

table_entry ::= "{" <match> [<match_hi>] <summary_string> [<detail_string>] [<user_data>] [<branch_field>] "}"

 

match ::= <number> | DEFAULT

 

match_hi ::= <number>

 

summary_string ::= <string>

 

detail_string ::= <string>

 

user_data ::= <number>

 

branch_field ::= <(field)name>

 

statement ::= <branch> | <field> | <group> | <group-field> | <reserved>

 

branch ::= BRANCH <(branch)method>

 

field ::= <field_definition> | <field_reference>

 

Note: Because of the complexity and importance of the FIELD statement, mandatory fields are highlighted <...> to aid the programmer. These fields will appear in every Field statement.

field_definition ::= FIELD <(field)name> [<startbit_clause>] <(size)method> [<conditional_clause>] [<retrieve_clause>] [<processing_clause>] <format> [<summary_tag_clause>] <(decode_pane)string> [<tag_clause>] [<margin_text_clause>][<info>][<nomove>] [<data_order>] [<verify_clause>][<store-clause>]

 

summary_tag ::= IN_SUMMARY | IN_SUMMARY_ONLY | IN_COLLAPSED

 

field_reference ::= FIELD <(field)name> ;

 

group ::= GROUP <(group)name> [<if_clause>] [<repeat_clause>] [<(detail)string>] { 1*<statement>}

 

group-field :: = GROUP <field_definition>

 

<reserved> ::= RESERVED <(field)name> <(size)method>

 

atom_char ::= <letter> | <digit> | <underscore>

 

conditional_clause ::= <if_clause> | <print_if_clause>

 

decimal ::= [<minus>]1*<digit>

 

data_order ::= HOST_DATA_ORDER | NETWORK_DATA_ORDER

 

digit ::= 0 ‐ 9

 

float ::= [<minus>]0*<digit>.1*<digit> | [<minus>]1*<digit>.0*<digit>

 

format ::= <(format)method> [ALSO <(format)method>]

 

hex ::= 1*<hexit>

 

hexit ::= <digit> | a ‐ f, A - F

 

if_clause ::= IF [NOT] <(boolean)method> [ELSE_SKIP <(size)method>]

 

IN_SUMMARY_clause ::= IN_SUMMARY <(summary_column)string> <(column_width)number>

 

info ::= INFO

 

letter ::= a ‐ z, A ‐ Z

 

margin_text_clause ::= MARGIN_TEXT <(format)method>

 

method :: = (<(method)name>) | (<(method)name> *1-15<param>)

 

minus ::= -

 

name ::= 1*<atom_char>

 

name_char ::= <space> | <atom_char>

 

nomove ::= NO_MOVE

 

number ::= <decimal> | <hex> | <float>

 

param ::= <string> | <number> | <(field/variable)name> | <table_name>

 

print_if_clause ::= PRINT_IF [NOT] <(verify)method>

 

repeat_clause ::= REPEAT UNTIL <(boolean)method> | REPEAT COUNT <(size)

method> | REPEAT SIZE <(size)method> [ TRUNCATED_FIELD_OK ]

 

retrieve_clause ::= RETRIEVE <(retrieve)method> [ALSO <(retrieve)method>]…

 

processing_clause ::= PROCESSING <(processing)method> [ALSO <(processing)method>]…

 

space :: = space character

 

startbit_clause ::= START_BIT <(startbit)method>

 

store_clause ::= STORE <(variable>name> [<retrieve_clause>]

 

string ::= 1*<atom_char> | "1*<name_char>"

 

tag_clause ::=TAG <(tag)method>

 

underscore ::= _

 

verify_clause ::= VERIFY | SUPPRESS_IF_VERIFIED [NOT] <(verify)method> | VERIFY <(crc)method> [ALSO [NOT] <(verify)method>| ALSO <(crc)method>]