198 lines
6.0 KiB
Perl
198 lines
6.0 KiB
Perl
package DBD::Parser;
|
|
require Exporter;
|
|
|
|
@ISA = qw(Exporter);
|
|
@EXPORT = qw(&ParseDBD);
|
|
|
|
use DBD;
|
|
use DBD::Base;
|
|
use DBD::Breaktable;
|
|
use DBD::Device;
|
|
use DBD::Driver;
|
|
use DBD::Menu;
|
|
use DBD::Recordtype;
|
|
use DBD::Recfield;
|
|
use DBD::Registrar;
|
|
use DBD::Function;
|
|
use DBD::Variable;
|
|
|
|
my $RXnam = qr/[a-zA-Z0-9_\-:.<>;]+/o;
|
|
my $RXnum = qr/-? (?: \d+ ) | (?: \d* \. \d+ ) (?: [eE] [-+]? \d+ )?/ox;
|
|
my $RXdqs = qr/" (?: [^"] | \\" )* "/ox;
|
|
my $RXsqs = qr/' (?: [^'] | \\' )* '/ox;
|
|
my $string = qr/ ( $RXnam | $RXnum | $RXdqs | $RXsqs ) /ox;
|
|
|
|
our $debug=0;
|
|
|
|
sub ParseDBD {
|
|
my $dbd = shift;
|
|
$_ = shift;
|
|
while (1) {
|
|
parseCommon();
|
|
if (m/\G menu \s* \( \s* $string \s* \) \s* \{/oxgc) {
|
|
print "Menu: $1\n" if $debug;
|
|
parse_menu($dbd, $1);
|
|
}
|
|
elsif (m/\G driver \s* \( \s* $string \s* \)/oxgc) {
|
|
print "Driver: $1\n" if $debug;
|
|
$dbd->add(DBD::Driver->new($1));
|
|
}
|
|
elsif (m/\G registrar \s* \( \s* $string \s* \)/oxgc) {
|
|
print "Registrar: $1\n" if $debug;
|
|
$dbd->add(DBD::Registrar->new($1));
|
|
}
|
|
elsif (m/\G function \s* \( \s* $string \s* \)/oxgc) {
|
|
print "Function: $1\n" if $debug;
|
|
$dbd->add(DBD::Function($1));
|
|
}
|
|
elsif (m/\G breaktable \s* \( \s* $string \s* \) \s* \{/oxgc) {
|
|
print "Breaktable: $1\n" if $debug;
|
|
parse_breaktable($dbd, $1);
|
|
}
|
|
elsif (m/\G recordtype \s* \( \s* $string \s* \) \s* \{/oxgc) {
|
|
print "Recordtype: $1\n" if $debug;
|
|
parse_recordtype($dbd, $1);
|
|
}
|
|
elsif (m/\G variable \s* \( \s* $string \s* \)/oxgc) {
|
|
print "Variable: $1\n" if $debug;
|
|
$dbd->add(DBD::Variable->new($1, 'int'));
|
|
}
|
|
elsif (m/\G variable \s* \( \s* $string \s* , \s* $string \s* \)/oxgc) {
|
|
print "Variable: $1, $2\n" if $debug;
|
|
$dbd->add(DBD::Variable->new($1, $2));
|
|
}
|
|
elsif (m/\G device \s* \( \s* $string \s* , \s* $string \s* ,
|
|
\s* $string \s* , \s*$string \s* \)/oxgc) {
|
|
print "Device: $1, $2, $3, $4\n" if $debug;
|
|
my $rtyp = $dbd->recordtype($1);
|
|
dieContext("Unknown record type '$1'") unless defined $rtyp;
|
|
$rtyp->add_device(DBD::Device->new($2, $3, $4));
|
|
} else {
|
|
last unless m/\G (.*) $/moxgc;
|
|
dieContext("Syntax error in '$1'");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub parseCommon {
|
|
while (1) {
|
|
# Skip leading whitespace
|
|
m/\G \s* /oxgc;
|
|
|
|
if (m/\G \# /oxgc) {
|
|
if (m/\G \#!BEGIN\{ ( [^}]* ) \}!\#\# \n/oxgc) {
|
|
print "File-Begin: $1\n" if $debug;
|
|
pushContext("file '$1'");
|
|
}
|
|
elsif (m/\G \#!END\{ ( [^}]* ) \}!\#\# \n?/oxgc) {
|
|
print "File-End: $1\n" if $debug;
|
|
popContext("file '$1'");
|
|
}
|
|
else {
|
|
m/\G (.*) \n/oxgc;
|
|
print "Comment: $1\n" if $debug;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
sub parse_menu {
|
|
my ($dbd, $name) = @_;
|
|
pushContext("menu($name)");
|
|
my $menu = DBD::Menu->new($name);
|
|
while(1) {
|
|
parseCommon();
|
|
if (m/\G choice \s* \( \s* $string \s* , \s* $string \s* \)/oxgc) {
|
|
print " Menu-Choice: $1, $2\n" if $debug;
|
|
$menu->add_choice($1, $2);
|
|
}
|
|
elsif (m/\G \}/oxgc) {
|
|
print " Menu-End:\n" if $debug;
|
|
$dbd->add($menu);
|
|
popContext("menu($name)");
|
|
return;
|
|
} else {
|
|
m/\G (.*) $/moxgc or dieContext("Unexpected end of input");
|
|
dieContext("Syntax error in '$1'");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub parse_breaktable {
|
|
my ($dbd, $name) = @_;
|
|
pushContext("breaktable($name)");
|
|
my $bt = DBD::Breaktable->new($name);
|
|
while(1) {
|
|
parseCommon();
|
|
if (m/\G point\s* \(\s* $string \s* , \s* $string \s* \)/oxgc) {
|
|
print " Breaktable-Point: $1, $2\n" if $debug;
|
|
$bt->add_point($1, $2);
|
|
}
|
|
elsif (m/\G $string \s* (?: , \s*)? $string (?: \s* ,)?/oxgc) {
|
|
print " Breaktable-Data: $1, $2\n" if $debug;
|
|
$bt->add_point($1, $2);
|
|
}
|
|
elsif (m/\G \}/oxgc) {
|
|
print " Breaktable-End:\n" if $debug;
|
|
$dbd->add($bt);
|
|
popContext("breaktable($name)");
|
|
return;
|
|
} else {
|
|
m/\G (.*) $/moxgc or dieContext("Unexpected end of input");
|
|
dieContext("Syntax error in '$1'");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub parse_recordtype {
|
|
my ($dbd, $name) = @_;
|
|
pushContext("recordtype($name)");
|
|
my $rtyp = DBD::Recordtype->new($name);
|
|
while(1) {
|
|
parseCommon();
|
|
if (m/\G field \s* \( \s* $string \s* , \s* $string \s* \) \s* \{/oxgc) {
|
|
print " Recordtype-Field: $1, $2\n" if $debug;
|
|
parse_field($rtyp, $1, $2);
|
|
}
|
|
elsif (m/\G \}/oxgc) {
|
|
print " Recordtype-End:\n" if $debug;
|
|
$dbd->add($rtyp);
|
|
popContext("recordtype($name)");
|
|
return;
|
|
}
|
|
elsif (m/\G % (.*) \n/oxgc) {
|
|
print " Recordtype-Cdef: $1\n" if $debug;
|
|
$rtyp->add_cdef($1);
|
|
} else {
|
|
m/\G (.*) $/moxgc or dieContext("Unexpected end of input");
|
|
dieContext("Syntax error in '$1'");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub parse_field {
|
|
my ($rtyp, $name, $field_type) = @_;
|
|
my $fld = DBD::Recfield->new($name, $field_type);
|
|
pushContext("field($name, $field_type)");
|
|
while(1) {
|
|
parseCommon();
|
|
if (m/\G (\w+) \s* \( \s* $string \s* \)/oxgc) {
|
|
print " Field-Attribute: $1, $2\n" if $debug;
|
|
$fld->add_attribute($1, $2);
|
|
}
|
|
elsif (m/\G \}/oxgc) {
|
|
print " Field-End:\n" if $debug;
|
|
$rtyp->add_field($fld);
|
|
popContext("field($name, $field_type)");
|
|
return;
|
|
} else {
|
|
m/\G (.*) $/moxgc or dieContext("Unexpected end of input");
|
|
dieContext("Syntax error in '$1'");
|
|
}
|
|
}
|
|
}
|
|
|
|
1;
|