Raku Land

ASN::Grammar

zef:Altai-man

ASN::Grammar

This module contains a grammar for parsing ASN.1 specification files.

Warnings

Synopsis

my $spec = q:to/SPECEND/;
WorldSchema

DEFINITIONS IMPLICIT TAGS ::= BEGIN
Rocket ::= SEQUENCE
{
   name      UTF8String,
   message   UTF8String DEFAULT "Hello World",
   fuel      ENUMERATED {
       solid(0),
       liquid(1),
       gas(2)
   },
   speed     CHOICE
   {
      mph    [0] INTEGER,
      kmph   [1] INTEGER
   }  OPTIONAL,
   payload   SEQUENCE OF UTF8String
}
END
SPECEND

use ASN::Grammar;

# ASN::Module represents ASN.1 module
my $module = parse-ASN($spec);
say $module.name; # WorldSchema
say $module.schema; # IMPLICIT

# TypeAssignment and ValueAssignment represent top-level ASN.1 custom definitions
my ASN::TypeAssignment $type = $module.types[0];

say $type.name; # Rocket
my ASN::RawType $rocket-type = $type.type;
say $rocket-type.type; # 'SEQUENCE'

# `.params` method returns a hash of various
# information about type, in this case,
# only `fields` key that returns descriptions
# of complex type (SEQUENCE) components is present
for $rocket-type.params<fields><> -> $field {
    say $field;
}
# Code above results in:
# Field `name` of type `UTF8String`, no parameters
# ASN::RawType.new(name => "name", type => "UTF8String", params => {})

# Field `message` of type `UTF8String`, defaults to `Hello World`
# ASN::RawType.new(name => "message", type => "UTF8String", params => {:default("\"Hello World\"")})

# Field `fuel` of type `ENUMERATED`,
# has options presented as hash by `defs`(definitions) key
# ASN::RawType.new(name => "fuel", type => "ENUMERATED", params => {:defs(${:gas(2), :liquid(1), :solid(0)})})

# Field `speed` of type `CHOICE`, has `optional` flag in params,
# has choices exposed as a mapping of a textual key into ASN::Tag class and integer value
# ASN::RawType.new(name => "speed", type => "CHOICE", params => {:choices(${:kmph((ASN::Tag.new(class => "CONTEXT-SPECIFIC", value => 1)) => "INTEGER"), :mph((ASN::Tag.new(class => "CONTEXT-SPECIFIC", value => 0)) => "INTEGER")}), :optional})

# Field `payload` of type `SEQUENCE OF` with `of` parameter that represents type of elements as ASN::RawType
# ASN::RawType.new(name => "payload", type => "SEQUENCE OF", params => {:of(ASN::RawType.new(name => "UTF8String", type => "UTF8String", params => {}))})

Room for improvement