Add a code generator for my database meta-language
This code generator is still in a prototyping phase. It'll probably get rewritten entirely. git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5358 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
c152583935
commit
9db4235480
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
package CG;
|
||||
use strict;
|
||||
|
||||
# Code generator for C struct definitions
|
||||
|
||||
my @structQualifierCount;
|
||||
my @structQualifiers;
|
||||
my @nestFieldCount;
|
||||
my @fieldDecls;
|
||||
my @nestNames;
|
||||
my @curComment;
|
||||
|
||||
sub blankLine()
|
||||
{
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub beginStructDef()
|
||||
{
|
||||
push @nestNames, $_[0];
|
||||
push @nestFieldCount, 0;
|
||||
push @structQualifierCount, 0;
|
||||
}
|
||||
|
||||
sub endStructDef()
|
||||
{
|
||||
my $name = pop(@nestNames);
|
||||
my $fieldCount = pop(@nestFieldCount);
|
||||
my $qualifierCount = pop(@structQualifierCount);
|
||||
|
||||
# Fetch qualifier list from stack and reverse it
|
||||
my @qualifiers;
|
||||
while ($qualifierCount)
|
||||
{
|
||||
push @qualifiers, pop(@structQualifiers);
|
||||
|
||||
$qualifierCount--;
|
||||
}
|
||||
|
||||
# Fetch field list from stack and reverse it
|
||||
my @fields;
|
||||
while ($fieldCount)
|
||||
{
|
||||
push @fields, pop(@fieldDecls);
|
||||
|
||||
$fieldCount--;
|
||||
}
|
||||
|
||||
# Start printing the structure
|
||||
print "typedef struct\n{\n";
|
||||
|
||||
# Process struct qualifiers
|
||||
foreach (@qualifiers)
|
||||
{
|
||||
if (/^prefix\s+\"([^\"]+)\"$/)
|
||||
{
|
||||
$name = $1 . $name;
|
||||
}
|
||||
elsif (/^abstract$/) {}
|
||||
else
|
||||
{
|
||||
die "Unknown qualifier: `$_'\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Print fields
|
||||
while (@fields)
|
||||
{
|
||||
print pop(@fields) . "\n";
|
||||
|
||||
# Seperate field defintions by blank lines
|
||||
print "\n" if @fields;
|
||||
}
|
||||
|
||||
print "} ${name};\n";
|
||||
}
|
||||
|
||||
sub addStructQualifier()
|
||||
{
|
||||
push @structQualifiers, $_[0];
|
||||
$structQualifierCount[@structQualifierCount - 1]++;
|
||||
}
|
||||
|
||||
sub fieldDeclaration()
|
||||
{
|
||||
my ($type, $qualifier, $name) = @_;
|
||||
|
||||
my $fieldDecl = "";
|
||||
|
||||
$_ = $type;
|
||||
if (/count/) { $type = "unsigned int "; }
|
||||
elsif (/string/) { $type = "const char* "; }
|
||||
elsif (/real/) { $type = "float "; }
|
||||
elsif (/bool/) { $type = "bool "; }
|
||||
else { die "UKNOWN TYPE: $_"; }
|
||||
|
||||
my $set = "";
|
||||
|
||||
if ($qualifier)
|
||||
{
|
||||
foreach ($qualifier)
|
||||
{
|
||||
if (/set/)
|
||||
{
|
||||
$set = "\[]";
|
||||
}
|
||||
elsif (/unique/)
|
||||
{
|
||||
# Separate this notice from the rest of the comment if there's any
|
||||
push @curComment, "" if @curComment;
|
||||
|
||||
push @curComment, " Unique across all instances";
|
||||
}
|
||||
else
|
||||
{
|
||||
die "UNKNOWN QUALIFIER: $_";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If there's a comment, "open" it
|
||||
$fieldDecl .= "\t/**" if @curComment;
|
||||
|
||||
while (@curComment)
|
||||
{
|
||||
$fieldDecl .= shift(@curComment) . "\n";
|
||||
|
||||
if (@curComment)
|
||||
{
|
||||
$fieldDecl .= "\t * ";
|
||||
}
|
||||
else
|
||||
{
|
||||
$fieldDecl .= "\t */\n";
|
||||
}
|
||||
}
|
||||
|
||||
$fieldDecl .= "\t${type}${name}${set};";
|
||||
|
||||
push @fieldDecls, $fieldDecl;
|
||||
$nestFieldCount[@nestFieldCount - 1]++;
|
||||
}
|
||||
|
||||
sub pushComment()
|
||||
{
|
||||
push @curComment, substr($_[0], 1);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
my $out_lang = shift or die "Missing output language";
|
||||
$out_lang .= "_cg.pm";
|
||||
require $out_lang or die "Couldn't load $out_lang";
|
||||
|
||||
# Read and parse the file
|
||||
my $name;
|
||||
while (<>)
|
||||
{
|
||||
chomp;
|
||||
|
||||
if (/^\s*(\#.*)?$/) { CG::blankLine(); if ($1) { CG::pushComment($1); } }
|
||||
elsif (/^\s*struct\s+(\w+)\s*$/) { CG::beginStructDef($1); }
|
||||
elsif (/^\s*end\s+struct\s*;\s*$/) { CG::endStructDef() }
|
||||
elsif (/^\s*%(.*)\s*;\s*$/) { CG::addStructQualifier($1); }
|
||||
elsif (/^\s*(count|string|real|bool)\s+(unique\s+|set\s+)?(\w+)\s*;\s*$/) { CG::fieldDeclaration($1, $2, $3); }
|
||||
else { print "Unmatched line: $_\n"; }
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
package CG;
|
||||
use strict;
|
||||
|
||||
# Code generator for SQL table definitions
|
||||
|
||||
my @structQualifierCount;
|
||||
my @structQualifiers;
|
||||
my @nestFieldCount;
|
||||
my @fieldDecls;
|
||||
my @nestNames;
|
||||
my @curComment;
|
||||
|
||||
sub blankLine()
|
||||
{
|
||||
print "\n";
|
||||
}
|
||||
|
||||
sub beginStructDef()
|
||||
{
|
||||
push @nestNames, $_[0];
|
||||
push @nestFieldCount, 0;
|
||||
push @structQualifierCount, 0;
|
||||
}
|
||||
|
||||
sub endStructDef()
|
||||
{
|
||||
my $name = pop(@nestNames);
|
||||
my $fieldCount = pop(@nestFieldCount);
|
||||
my $qualifierCount = pop(@structQualifierCount);
|
||||
|
||||
# Fetch qualifier list from stack and reverse it
|
||||
my @qualifiers;
|
||||
while ($qualifierCount)
|
||||
{
|
||||
push @qualifiers, pop(@structQualifiers);
|
||||
|
||||
$qualifierCount--;
|
||||
}
|
||||
|
||||
# Fetch field list from stack and reverse it
|
||||
my @fields;
|
||||
while ($fieldCount)
|
||||
{
|
||||
push @fields, pop(@fieldDecls);
|
||||
|
||||
$fieldCount--;
|
||||
}
|
||||
|
||||
# Start printing the structure
|
||||
print "CREATE TABLE `${name}` (\n";
|
||||
|
||||
# Process struct qualifiers
|
||||
foreach (@qualifiers)
|
||||
{
|
||||
if (/^prefix\s+\"([^\"]+)\"$/) {}
|
||||
elsif (/^abstract$/)
|
||||
{
|
||||
print "\t-- Automatically generated ID to link the inheritance hierarchy.\n"
|
||||
."\tunique_inheritance_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Unknown qualifier: `$_'\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Print fields
|
||||
while (@fields)
|
||||
{
|
||||
print pop(@fields);
|
||||
|
||||
# Seperate field defintions by commas and blank lines
|
||||
print ",\n" if @fields;
|
||||
|
||||
# Make sure to terminate lines of field definitions
|
||||
print "\n";
|
||||
}
|
||||
|
||||
print ");\n";
|
||||
}
|
||||
|
||||
sub addStructQualifier()
|
||||
{
|
||||
push @structQualifiers, $_[0];
|
||||
$structQualifierCount[@structQualifierCount - 1]++;
|
||||
}
|
||||
|
||||
sub fieldDeclaration()
|
||||
{
|
||||
my ($type, $qualifier, $name) = @_;
|
||||
|
||||
my $fieldDecl = "";
|
||||
|
||||
$_ = $type;
|
||||
if (/count/) { $type = "INTEGER NOT NULL"; }
|
||||
elsif (/string/) { $type = "TEXT NOT NULL"; }
|
||||
elsif (/real/) { $type = "NUMERIC NOT NULL"; }
|
||||
elsif (/bool/) { $type = "INTEGER NOT NULL"; }
|
||||
else { die "UKNOWN TYPE: $_"; }
|
||||
|
||||
my $set = "";
|
||||
|
||||
if ($qualifier)
|
||||
{
|
||||
foreach ($qualifier)
|
||||
{
|
||||
if (/set/)
|
||||
{
|
||||
$set = "\[]";
|
||||
}
|
||||
elsif (/unique/)
|
||||
{
|
||||
# Separate this notice from the rest of the comment if there's any
|
||||
push @curComment, "" if @curComment;
|
||||
|
||||
push @curComment, " Unique across all instances";
|
||||
}
|
||||
else
|
||||
{
|
||||
die "UNKNOWN QUALIFIER: $_";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (@curComment)
|
||||
{
|
||||
$fieldDecl .= "\t--" . shift(@curComment) . "\n";
|
||||
}
|
||||
|
||||
$fieldDecl .= "\t${name} ${type}";
|
||||
|
||||
push @fieldDecls, $fieldDecl;
|
||||
$nestFieldCount[@nestFieldCount - 1]++;
|
||||
}
|
||||
|
||||
sub pushComment()
|
||||
{
|
||||
push @curComment, substr($_[0], 1);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,56 @@
|
|||
struct BASE
|
||||
%abstract;
|
||||
%prefix "STATS_";
|
||||
|
||||
# Unique language independant name that can be used to identify a specific
|
||||
# stats instance
|
||||
string unique id;
|
||||
|
||||
# short name, describing the component, must be translateable
|
||||
string name;
|
||||
end struct;
|
||||
|
||||
enum TECH_LEVEL
|
||||
ONE
|
||||
TWO
|
||||
THREE
|
||||
end enum;
|
||||
|
||||
struct COMPONENT
|
||||
%inherit BASE;
|
||||
|
||||
# Technology level(s) of this component
|
||||
set TECH_LEVEL level;
|
||||
|
||||
# Power required to build this component
|
||||
real buildPower;
|
||||
|
||||
# Build points (which are rate-limited in the construction units) required
|
||||
# to build this component.
|
||||
real buildPoints;
|
||||
|
||||
# Weight of this component
|
||||
real weight;
|
||||
|
||||
# Indicates whether this component is "designable" and can thus be used in
|
||||
# the design screen.
|
||||
bool designable;
|
||||
|
||||
# @TODO devise some kind of type to refer to IMD models; perhaps just
|
||||
# filenames will suffice?
|
||||
#
|
||||
# We'll name it IMD_model for now.
|
||||
#
|
||||
# The "base" IMD model representing this component in 3D space.
|
||||
IMD_model baseModel;
|
||||
end struct;
|
||||
|
||||
struct BODY
|
||||
%inherit COMPONENT;
|
||||
|
||||
# The number of available weaponSlots slots on the body
|
||||
count weaponSlots;
|
||||
|
||||
# Engine output of this body's engine
|
||||
real powerOutput;
|
||||
end struct;
|
Loading…
Reference in New Issue