181 lines
5.1 KiB
ObjectPascal
181 lines
5.1 KiB
ObjectPascal
unit Unit1;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
|
Dialogs, StdCtrls,
|
|
regexpr;
|
|
|
|
type
|
|
TForm1 = class(TForm)
|
|
Memo1: TMemo;
|
|
generate: TButton;
|
|
Edit1: TEdit;
|
|
Memo2: TMemo;
|
|
parse: TButton;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Button1: TButton;
|
|
procedure generateClick(Sender: TObject);
|
|
procedure parseClick(Sender: TObject);
|
|
procedure Button1Click(Sender: TObject);
|
|
private
|
|
{ Private declarations }
|
|
public
|
|
{ Public declarations }
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
{$R *.dfm}
|
|
|
|
type
|
|
tstrpair = record
|
|
sFrom: string;
|
|
sTo: string;
|
|
end;
|
|
|
|
const
|
|
conversionTypes: array [0..1] of tstrpair = (
|
|
(sFrom: 'str'; sTo: 'RawUTF8'),
|
|
(sFrom: 'int'; sTo: 'integer')
|
|
);
|
|
|
|
function aliasToType(s: string) : string ;
|
|
var i: integer;
|
|
begin
|
|
result:= s;
|
|
s:= lowercase(s);
|
|
for i:= low(conversionTypes) to high(conversionTypes) do
|
|
if conversionTypes[i].sFrom = s then
|
|
begin
|
|
result:= conversionTypes[i].sTo;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
function typeToAlias(s: string) : string ;
|
|
var i: integer;
|
|
begin
|
|
result:= s;
|
|
s:= lowercase(s);
|
|
for i:= low(conversionTypes) to high(conversionTypes) do
|
|
if lowercase(conversionTypes[i].sTo) = s then
|
|
begin
|
|
result:= conversionTypes[i].sFrom;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.generateClick(Sender: TObject);
|
|
var
|
|
r: TRegExpr;
|
|
clsname,
|
|
priv, publ,
|
|
functs, impl,
|
|
stype, sname,
|
|
fwrite, fread: string;
|
|
begin
|
|
clsname:= 'TSQL'+edit1.Text;
|
|
|
|
r:= TRegExpr.Create;
|
|
r.Expression:= '(\s+)?(\w+)(\s+)?:(\s+)?(\w+)(\s+)?(\;r)?(\;w)?';
|
|
if r.Exec(memo1.Text) then
|
|
repeat
|
|
stype:= aliasToType( r.match[5] );
|
|
sname:= r.match[2];
|
|
|
|
if (length(r.Match[7]) > 0) then
|
|
begin
|
|
fread := 'Get'+sname;
|
|
functs:= functs + #13#10#9#9 + format('function Get%s():%s;'#13#10, [sname, stype]);
|
|
impl:= impl + #13#10 + format('function %s.Get%s():%s;'#13#10'begin'#13#10#9'result:= f%s;'#13#10'end;'#13#10, [clsname, sname, stype, sname]);
|
|
end
|
|
else
|
|
fRead:= 'f'+sname;
|
|
|
|
if (length(r.Match[8]) > 0) then
|
|
begin
|
|
fwrite := 'Set'+sname;
|
|
functs:= functs + #13#10#9#9 + format('procedure Set%s(const AValue: %s);'#13#10, [sname, stype]);
|
|
impl:= impl + #13#10 + format('procedure %s.Set%s(const AValue: %s);'#13#10'begin'#13#10#9'f%s:= AValue;'#13#10'end;'#13#10, [clsname, sname, stype, sname]);
|
|
end
|
|
else
|
|
fWrite:= 'f'+sname;
|
|
|
|
priv:= priv + #9#9 + format('f%s: %s;'#13#10, [sname, stype]);
|
|
publ:= publ + #9#9 + format('property %s: %s read %s write %s;'#13#10, [sname, stype, fread, fwrite]);
|
|
until not r.ExecNext;
|
|
memo2.Text:=
|
|
format(
|
|
#9'%s = class(TSQLRecord)'#13#10 +
|
|
#9'private'#13#10'%s'#13#10'%s'+
|
|
#9'published'#13#10'%s'#13#10+
|
|
#9'end;'#13#10#13#10#13#10'%s',
|
|
[clsname, priv, functs, publ, impl]);
|
|
end;
|
|
|
|
procedure TForm1.parseClick(Sender: TObject);
|
|
var
|
|
r: TRegExpr;
|
|
def: string;
|
|
begin
|
|
r:= TRegExpr.Create;
|
|
|
|
r.Expression:= '\s+?TSQL(\w+)\s*=\s*class';
|
|
if r.Exec(memo2.Text) then
|
|
edit1.Text:= r.Match[1];
|
|
|
|
r.Expression:= 'property\s+(\w+)(\s+)?:(\s+)?(\w+)\s*(read (\w+))?\s*(write (\w+))?';
|
|
//r.Expression:= '(\w+):(\w+)';
|
|
//r.ModifierM
|
|
if r.Exec(memo2.Text) then
|
|
repeat
|
|
def:= def + r.Match[1] + ':'+ typeToAlias( r.Match[4] );
|
|
//showmessage(r.Match[6]);
|
|
if Copy(r.match[6], 1, 3) = 'Get' then
|
|
def:= def + ';r';
|
|
if Copy(r.match[8], 1, 3) = 'Set' then
|
|
def:= def + ';w';
|
|
|
|
def:= def + #13#10;
|
|
until not r.ExecNext;
|
|
memo1.Text:=def;
|
|
end;
|
|
|
|
procedure TForm1.Button1Click(Sender: TObject);
|
|
const
|
|
sHelp =
|
|
'This simple application speeds up defining SQL Records classes for Synopse mORMot Framework'#13#10+
|
|
'Since some versions of Delphi (including mine) does not have class completion, declaring properties,'#13#10+
|
|
'their setters / getters and so on is a huge waste of time.'#13#10+
|
|
'Thus I''ve written this simple tool which introduces so-called meta-language for defining SQL Records'#13#10+
|
|
'which is later converted to Delphi code.'#13#10+
|
|
'It is simply list of field declarations we want to have in our SQL Record.'#13#10#13#10+
|
|
'Syntax:'#13#10+
|
|
'each line is a declaration of one field. It consists of field name and it''s type'#13#10+
|
|
'the type might be shortened using aliases (see below).'#13#10+
|
|
'additionally, each field can be marked with ";r" and/or ";w" flags'#13#10+
|
|
'which will make the code generator to use respectively getter and/or setter for the specific field'#13#10+
|
|
'The tool also makes it possible to parse back from Delphi class declaration to meta-code'#13#10+
|
|
'Please note this will only work if the Delphi class follows naming pattern used in meta2pas generatorion'#13#10+
|
|
#13#10'List of available aliases:'#13#10'%s'#13#10+
|
|
'================'#13#10+
|
|
'enjoy!'#13#10+
|
|
'Michal migajek Gajek'#13#10'http://migajek.com'#13#10'migajek@gmail.com';
|
|
var
|
|
i: integer;
|
|
tmp: string;
|
|
begin
|
|
for i:= low(conversionTypes) to high(conversionTypes) do
|
|
tmp:= tmp + conversionTypes[i].sFrom + ' = ' + conversionTypes[i].sTo + #13#10;
|
|
|
|
MessageBox(handle, PChar(Format(sHelp, [tmp])), 'Help', MB_ICONINFORMATION);
|
|
end;
|
|
|
|
end.
|