2004-06-30 21:35:26 +04:00
########################
# ASN.1 Parse::Yapp parser
# Copyright (C) Stefan (metze) Metzmacher <metze@samba.org>
2008-03-28 09:08:49 +03:00
# released under the GNU GPL version 3 or later
2004-06-30 21:35:26 +04:00
# the precedence actually doesn't matter at all for this grammer, but
# by providing a precedence we reduce the number of conflicts
# enormously
%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ']' ':' ',' ';'
################
# grammer
%%
2004-07-02 02:39:25 +04:00
asn1:
identifier asn1_definitions asn1_delimitter asn1_begin asn1_decls asn1_end
{{
"OBJECT" => "ASN1_DEFINITION",
"IDENTIFIER" => $_[1],
"DATA" => $_[5]
}}
;
asn1_delimitter:
delimitter
;
asn1_definitions:
'DEFINITIONS'
;
asn1_begin:
'BEGIN'
;
asn1_end:
'END'
;
asn1_decls:
2004-06-30 21:35:26 +04:00
asn1_def
{ [ $_[1] ] }
2004-07-02 02:39:25 +04:00
| asn1_decls asn1_def
2004-06-30 21:35:26 +04:00
{ push(@{$_[1]}, $_[2]); $_[1] }
;
2004-07-02 02:39:25 +04:00
2004-06-30 21:35:26 +04:00
asn1_def:
2004-07-02 02:39:25 +04:00
asn1_target asn1_delimitter asn1_application asn1_type
2004-06-30 21:35:26 +04:00
{{
"OBJECT" => "ASN1_DEF",
"IDENTIFIER" => $_[1],
"APPLICATION" => $_[3],
"STRUCTURE" => $_[4]
}}
;
asn1_target:
identifier
;
asn1_application:
#empty
| '[' 'APPLICATION' constant ']'
{ $_[3] }
;
asn1_type:
asn1_boolean
| asn1_integer
| asn1_bit_string
| asn1_octet_string
| asn1_null
| asn1_object_identifier
| asn1_real
| asn1_enumerated
2004-07-02 02:39:25 +04:00
| asn1_sequence
| identifier
2004-06-30 21:35:26 +04:00
;
asn1_boolean:
'BOOLEAN'
{{
"TYPE" => "BOOLEAN",
"TAG" => 1
}}
;
asn1_integer:
'INTEGER'
{{
"TYPE" => "INTEGER",
"TAG" => 2
}}
| 'INTEGER' '(' constant '.' '.' constant ')'
{{
"TYPE" => "INTEGER",
"TAG" => 2,
"RANGE_LOW" => $_[3],
"RENAGE_HIGH" => $_[6]
}}
;
asn1_bit_string:
'BIT' 'STRING'
{{
"TYPE" => "BIT STRING",
"TAG" => 3
}}
;
asn1_octet_string:
'OCTET' 'STRING'
{{
"TYPE" => "OCTET STRING",
"TAG" => 4
}}
;
asn1_null:
'NULL'
{{
"TYPE" => "NULL",
"TAG" => 5
}}
;
asn1_object_identifier:
'OBJECT' 'IDENTIFIER'
{{
"TYPE" => "OBJECT IDENTIFIER",
"TAG" => 6
}}
;
asn1_real:
'REAL'
{{
"TYPE" => "REAL",
"TAG" => 9
}}
;
asn1_enumerated:
'ENUMERATED'
{{
"TYPE" => "ENUMERATED",
"TAG" => 10
}}
;
asn1_sequence:
'SEQUENCE' '{' asn1_var_dec_list '}'
{{
"TYPE" => "SEQUENCE",
"TAG" => 16,
"STRUCTURE" => $_[3]
}}
;
asn1_var_dec_list:
asn1_var_dec
{ [ $_[1] ] }
| asn1_var_dec_list ',' asn1_var_dec
{ push(@{$_[1]}, $_[3]); $_[1] }
;
asn1_var_dec:
identifier asn1_type
{{
"NAME" => $_[1],
"TYPE" => $_[2]
}}
;
anytext: #empty { "" }
| identifier | constant | text
| anytext '-' anytext { "$_[1]$_[2]$_[3]" }
| anytext '.' anytext { "$_[1]$_[2]$_[3]" }
| anytext '*' anytext { "$_[1]$_[2]$_[3]" }
| anytext '>' anytext { "$_[1]$_[2]$_[3]" }
| anytext '|' anytext { "$_[1]$_[2]$_[3]" }
| anytext '&' anytext { "$_[1]$_[2]$_[3]" }
| anytext '/' anytext { "$_[1]$_[2]$_[3]" }
| anytext '+' anytext { "$_[1]$_[2]$_[3]" }
| anytext '(' anytext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
;
2004-07-02 01:57:51 +04:00
delimitter: DELIMITTER
;
2004-06-30 21:35:26 +04:00
identifier: IDENTIFIER
;
constant: CONSTANT
;
text: TEXT { "\"$_[1]\"" }
;
#####################################
# start code
%%
use util;
sub _ASN1_Error {
if (exists $_[0]->YYData->{ERRMSG}) {
print $_[0]->YYData->{ERRMSG};
delete $_[0]->YYData->{ERRMSG};
return;
};
my $line = $_[0]->YYData->{LINE};
my $last_token = $_[0]->YYData->{LAST_TOKEN};
my $file = $_[0]->YYData->{INPUT_FILENAME};
print "$file:$line: Syntax error near '$last_token'\n";
}
sub _ASN1_Lexer($)
{
my($parser)=shift;
$parser->YYData->{INPUT}
or return('',undef);
again:
$parser->YYData->{INPUT} =~ s/^[ \t]*//;
for ($parser->YYData->{INPUT}) {
if (/^\#/) {
if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
$parser->YYData->{LINE} = $1-1;
$parser->YYData->{INPUT_FILENAME} = $2;
goto again;
}
if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
$parser->YYData->{LINE} = $1-1;
$parser->YYData->{INPUT_FILENAME} = $2;
goto again;
}
if (s/^(\#.*)$//m) {
goto again;
}
}
if (s/^(\n)//) {
$parser->YYData->{LINE}++;
goto again;
}
2004-07-02 02:39:25 +04:00
if (s/^(--.*\n)//) {
$parser->YYData->{LINE}++;
goto again;
}
if (s/^(::=)//) {
2004-07-02 01:57:51 +04:00
$parser->YYData->{LAST_TOKEN} = $1;
return('DELIMITTER',$1);
}
2004-06-30 21:35:26 +04:00
if (s/^\"(.*?)\"//) {
$parser->YYData->{LAST_TOKEN} = $1;
return('TEXT',$1);
}
if (s/^(\d+)(\W|$)/$2/) {
$parser->YYData->{LAST_TOKEN} = $1;
return('CONSTANT',$1);
}
2004-07-02 02:39:25 +04:00
if (s/^([\w_-]+)//) {
2004-06-30 21:35:26 +04:00
$parser->YYData->{LAST_TOKEN} = $1;
if ($1 =~
/^(SEQUENCE|INTEGER|OCTET|STRING|
APPLICATION|OPTIONAL|NULL|COMPONENTS|OF|
2004-07-02 02:39:25 +04:00
BOOLEAN|ENUMERATED|CHOISE|REAL|BIT|OBJECT|IDENTIFIER|
DEFAULT|FALSE|TRUE|SET|DEFINITIONS|BEGIN|END)$/x) {
2004-06-30 21:35:26 +04:00
return $1;
}
return('IDENTIFIER',$1);
}
if (s/^(.)//s) {
$parser->YYData->{LAST_TOKEN} = $1;
return($1,$1);
}
}
}
sub parse_asn1($$)
{
my $self = shift;
my $filename = shift;
my $saved_delim = $/;
undef $/;
my $cpp = $ENV{CPP};
if (! defined $cpp) {
$cpp = "cpp"
}
2009-02-10 01:29:41 +03:00
my $data = `$cpp -xc $filename`;
2004-06-30 21:35:26 +04:00
$/ = $saved_delim;
$self->YYData->{INPUT} = $data;
$self->YYData->{LINE} = 0;
$self->YYData->{LAST_TOKEN} = "NONE";
return $self->YYParse( yylex => \&_ASN1_Lexer, yyerror => \&_ASN1_Error );
}