<<Grammar Name="BER"
encoding_class="binary"
reference="http://en.wikipedia.org/wiki/Basic_encoding_rules"
comment="Minimal tree generating BER decoder"
>>
{
int tag,length,n,@byte;
bool init_() {tag=0;length=0; return true;}
bool add_Tag_() {tag*=128;tag+=n; return true;}
bool addLength_(){length*=256;length+=@byte;return true;}
}
[1] ProtocolDataUnit: TLV;
[2] ^^TLV: init_
( &BITS<6,#1> Tag ( #x80 CompositeDelimValue #0#0 / Length CompositeValue )
/ Tag Length PrimitiveValue
);
[3] Tag: OneOctetTag / MultiOctetTag / FATAL<"illegal TAG">;
[4] ^^OneOctetTag: !BITS<1-5,#b11111> BITS<1-5,.,:tag>;
[5] ^^MultiOctetTag: . (&BITS<8,#1> BITS<1-7,.,:n> add_Tag_)* BITS<1-7,.,:n> add_Tag_;
[6] Length : OneOctetLength / MultiOctetLength
/ FATAL<"illegal LENGTH">;
[7] ^^OneOctetLength: &BITS<8,#0> BITS<1-7,.,:length>;
[8]^^MultiOctetLength: &BITS<8,#1> BITS<1-7,.,:n> ( .:byte addLength_){:n};
[9]^^PrimitiveValue: .{:length} / FATAL<"BER input ends before VALUE ends">;
[10]^^CompositeDelimValue: (!(#0#0) TLV)*;
[11]^^CompositeValue
{
int len;
PegBegEnd begEnd;
bool save_() {len= length;return true;}
bool at_end_(){return len<=0;}
bool decr_() {len-= begEnd.posEnd_-begEnd.posBeg_;return len>=0;}
} : save_ (!at_end_ TLV:begEnd
(decr_/FATAL<"illegal length">))*;
<</Grammar>>