Преглед на файлове

* refactored exceptions

* started implementation of code generation
master
Bergmann89 преди 11 години
родител
ревизия
5426ac2513
променени са 20 файла, в които са добавени 712 реда и са изтрити 231 реда
  1. +44
    -3
      uengShaderCodeGenerator.pas
  2. +88
    -22
      uengShaderFile.pas
  3. +33
    -30
      uengShaderFileExpression.pas
  4. +4
    -4
      uengShaderFileHelper.pas
  5. +10
    -13
      uengShaderFileParser.pas
  6. +329
    -46
      uengShaderFileTypes.pas
  7. +69
    -39
      uengShaderPart.pas
  8. +5
    -5
      uengShaderPartCall.pas
  9. +36
    -11
      uengShaderPartClass.pas
  10. +1
    -1
      uengShaderPartCntr.pas
  11. +1
    -1
      uengShaderPartComment.pas
  12. +3
    -3
      uengShaderPartEcho.pas
  13. +23
    -5
      uengShaderPartIf.pas
  14. +10
    -20
      uengShaderPartInclude.pas
  15. +32
    -5
      uengShaderPartKeyValuePair.pas
  16. +8
    -8
      uengShaderPartMeta.pas
  17. +4
    -4
      uengShaderPartParameter.pas
  18. +9
    -9
      uengShaderPartProc.pas
  19. +1
    -0
      uengShaderPartScope.pas
  20. +2
    -2
      uengShaderPartText.pas

+ 44
- 3
uengShaderCodeGenerator.pas Целия файл

@@ -7,15 +7,56 @@ interface

uses
Classes, SysUtils,
uengShaderPartCntr;
uengShaderFileParser, uengShaderPart, uengShaderPartScope, uengShaderPartKeyValuePair;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderCodeGenerator = class(TengShaderPartCntr)

TengShaderCodeGenerator = class(TengShaderPartScope)
{ Code Loading & Storage }
private
fProperties: TengShaderPartPropertyMap;

protected
fInherited: TengShaderPartList;
procedure UpdateInherited; virtual;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ General }
public
constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
end;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderCodeGenerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.UpdateInherited;
begin
// TODO
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
result := inherited ParseIntern(aArgs, aParams);
UpdateInherited;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart);
begin
inherited Create(aParent);
fInherited := TengShaderPartList.Create(false);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengShaderCodeGenerator.Destroy;
begin
FreeAndNil(fInherited);
inherited Destroy;
end;

end.


+ 88
- 22
uengShaderFile.pas Целия файл

@@ -12,7 +12,7 @@ interface

uses
Classes, sysutils,
uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes
uengShaderPart, uengShaderPartClass, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes

{$IFDEF USE_BITSPACE_UTILS}
, uutlSerialization
@@ -27,17 +27,27 @@ type
fFilename: String;
fFileReader: IutlFileReader;
fFileWriter: IutlFileWriter;
protected { virtual getter }
fClasses: TengShaderPartClassMap;
private
function GetGenerator(const aName: String): TengShaderCodeGenerator;
function GetGeneratorCount: Integer;
function GetGeneratorNames(const aIndex: Integer): String;
procedure UpdateClasses;
protected
function GetFilename: String; override;
function GetFileReader: IengShaderFileReader; override;
function GetFileWriter: IengShaderFileWriter; override;

{ General }
protected
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); override;
public
procedure LoadFromFile(const aFilename: String; const aFlags: TengShaderFileLoadFlags = []; const aFileReader: IengShaderFileReader = nil);
property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator;
property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames;
property GeneratorCount: Integer read GetGeneratorCount;

procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil);
procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil);
procedure Clear; override;
constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
end;

@@ -48,6 +58,54 @@ uses

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetGenerator(const aName: String): TengShaderCodeGenerator;
begin
result := fClasses[aName];
if not Assigned(result) then
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetGeneratorCount: Integer;
begin
result := fClasses.Count+1;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetGeneratorNames(const aIndex: Integer): String;
begin
if (aIndex < 0) or (aIndex >= Count) then
raise EengOutOfRange.Create(0, Count-1, aIndex, self);
if (aIndex = 0)
then result := ''
else result := fClasses.Keys[aIndex-1];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.UpdateClasses;
var
l: TengShaderPart.TSearchResults;
p: TengShaderPart;
new, old: TengShaderPartClass;

begin
l := TengShaderPart.TSearchResults.Create;
try
fClasses.Clear;
FindAll([sfSearchChildren], [TengShaderPartClass], l);
for p in l do begin
new := (p as TengShaderPartClass);
old := fClasses[new.Name];
if Assigned(old) then
raise EengDuplicateIdentifier.Create(new.Name, new, old, self);
fClasses.Add(new.Name, new);
end;
finally
FreeAndNil(l);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetFilename: String;
begin
@@ -71,16 +129,7 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList);
begin
if (sfCurrentFileOnly in aFlags) then
exclude(aFlags, sfSearchParents);
inherited FindIntern(aFlags, aDepth, aTypes, aList);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFlags: TengShaderFileLoadFlags;
const aFileReader: IengShaderFileReader);
procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader);
var
args: TengParseArgs;
token: String;
@@ -95,28 +144,28 @@ begin
try
Clear;
if not fFileReader.LoadStream(aFilename, ms) then
raise EengShaderPart.Create('unable to open file: ' + aFilename, Line, Col, Filename);
raise EengShaderPart.Create('unable to open file: ' + aFilename, Parent);
ms.Position := 0;
fFilename := aFilename;
args := TengParseArgs.Create(ms, Filename);
try
args.Flags := aFlags;
token := ParseText(args);
if (token <> '') then with args do
raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename);
raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self);
if (Root = self) then
UpdateClasses;
finally
FreeAndNil(args);
end;
finally
if not (lfLazyInclude in aFlags) then
fFileReader := nil;
fFileReader := nil;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter);
var
l: TengShaderPart.TSearchList;
l: TengShaderPart.TSearchResults;
i: Integer;
sl: TStringList;
ms: TMemoryStream;
@@ -127,7 +176,7 @@ begin
if not Assigned(fFileWriter) then
fFileWriter := TengShaderFileWriter.Create;

l := TengShaderPart.TSearchList.Create;
l := TengShaderPart.TSearchResults.Create;
sl := TStringList.Create;
ms := TMemoryStream.Create;
try
@@ -146,9 +195,26 @@ begin
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.Clear;
begin
inherited Clear;
fClasses.Clear;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderFile.Create(const aParent: TengShaderPart);
begin
inherited Create(aParent);
if not Assigned(fRoot) then
fRoot := self;
fClasses := TengShaderPartClassMap.Create(false);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengShaderFile.Destroy;
begin
FreeAndNil(fClasses);
fFileReader := nil;
fFileWriter := nil;
inherited Destroy;


+ 33
- 30
uengShaderFileExpression.pas Целия файл

@@ -13,17 +13,19 @@ type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengExpressionItem = class(TObject)
private
fOwner: TObject;
fLine: Integer;
fCol: Integer;
fFilename: String;
public
property Owner: TObject read fOwner;
property Line: Integer read fLine;
property Col: Integer read fCol;
property Filename: String read fFilename;

function GetText: String; virtual;
function GetValue: Variant; virtual;
constructor Create(const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -33,7 +35,7 @@ type
public
function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aValue: Variant; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -43,7 +45,7 @@ type
public
function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aName: String; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -54,7 +56,7 @@ type
property Child: TengExpressionItem read fChild write fChild;
function GetText: String; override;
function GetValue: Variant; override;
constructor Create(const aChild: TengExpressionItem; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
destructor Destroy; override;
end;

@@ -76,7 +78,7 @@ type
function GetText: String; override;
function GetValue: Variant; override;

constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
destructor Destroy; override;
end;

@@ -100,11 +102,11 @@ type
function GetText: String; override;
function GetValue: Variant; override;

constructor Create(const aOperator: TengExpressionBinaryOperator; const aLine, aCol: Integer; const aFilename: String);
constructor Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
destructor Destroy; override;
end;

function ParseExpression(const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;

implementation

@@ -162,9 +164,10 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionItem.Create(const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionItem.Create(const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create;
fOwner := aOwner;
fLine := aLine;
fCol := aCol;
fFilename := aFilename;
@@ -185,9 +188,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionValue.Create(const aValue: Variant; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionValue.Create(const aValue: Variant; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create(aLine, aCol, aFilename);
inherited Create(aOwner, aLine, aCol, aFilename);
fValue := aValue;
end;

@@ -206,9 +209,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionVariable.Create(const aName: String; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionVariable.Create(const aName: String; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create(aLine, aCol, aFilename);
inherited Create(aOwner, aLine, aCol, aFilename);
fName := aName;
end;

@@ -231,9 +234,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create(aLine, aCol, aFilename);
inherited Create(aOwner, aLine, aCol, aFilename);
fChild := aChild;
end;

@@ -250,7 +253,7 @@ end;
function TengExpressionUnaryOperation.GetText: String;
begin
if not Assigned(fChild) then
EengExpression.Create('no child assigned', Line, Col, Filename);
EengExpression.Create('no child assigned', self);
result :=
{$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
@@ -263,7 +266,7 @@ var
v: Variant;
begin
if not Assigned(fChild) then
raise EengExpression.Create('no child assigned', Line, Col, Filename);
raise EengExpression.Create('no child assigned', self);
try
case fUnaryOp of

@@ -293,14 +296,14 @@ begin
raise EengInvalidParamter.Create(
ex.Message + '("' + GetText + '" ==> ' +
EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")',
Line, Col, Filename);
Line, Col, Filename, Owner);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create(aLine, aCol, aFilename);
inherited Create(aOwner, aLine, aCol, aFilename);
fChild := nil;
fUnaryOp := aUnaryOp;
end;
@@ -364,14 +367,14 @@ begin
raise EengInvalidParamter.Create(
ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' +
EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")',
fLine, fCol, fFilename);
fLine, fCol, fFilename, fOwner);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator; const aLine, aCol: Integer; const aFilename: String);
constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator; const aOwner: TObject; const aLine, aCol: Integer; const aFilename: String);
begin
inherited Create(aLine, aCol, aFilename);
inherited Create(aOwner, aLine, aCol, aFilename);
fBinaryOp := aOperator;
fFirst := nil;
fSecond := nil;
@@ -401,13 +404,13 @@ type
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ParseExpression(const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
function ParseExpression(const aOwner: TObject; const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
var
p: TengTokenParameter;

procedure RaiseEx(const aMsg: String);
begin
raise EengExpression.Create(aMsg, p.Line, p.Col, aParam.Filename);
raise EengExpression.Create(aMsg, p.Line, p.Col, aParam.Filename, aOwner);
end;

function NextParam: Boolean;
@@ -531,7 +534,7 @@ var
if not NextParam then
RaiseEx('unexpected end');
tmp := BuildTree(aDepth + 1);
ei := TengExpressionGroup.Create(tmp, l, c, aParam.Filename);
ei := TengExpressionGroup.Create(tmp, aOwner, l, c, aParam.Filename);
try
MergeItems(stack, ei);
if (p.Name <> TOKEN_OP_GROUP_END) then
@@ -552,7 +555,7 @@ var
end else if IsUnaryOperation(p.Name, uOp) then begin
if not (exUnaryOperation in expected) then
RaiseEx('unexpected operator: ' + p.Name);
ei := TengExpressionUnaryOperation.Create(uOp, p.Line, p.Col, aParam.Filename);
ei := TengExpressionUnaryOperation.Create(uOp, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exVariable];
@@ -567,7 +570,7 @@ var
end else if IsBinaryOperation(p.Name, bOp) then begin
if not (exBinaryOperation in expected) then
RaiseEx('unexpected operator: ' + p.Name);
ei := TengExpressionBinaryOperation.Create(bOp, p.Line, p.Col, aParam.Filename);
ei := TengExpressionBinaryOperation.Create(bOp, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exVariable, exValue, exGroupBegin, exUnaryOperation];
@@ -580,7 +583,7 @@ var
end else if p.Quoted and IsValidIdentifier(p.Name) then begin
if not (exValue in expected) then
RaiseEx('unexpected value: ' + p.Name);
ei := TengExpressionValue.Create(p.Name, p.Line, p.Col, aParam.Filename);
ei := TengExpressionValue.Create(p.Name, aOwner,p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exGroupEnd, exBinaryOperation];
@@ -593,7 +596,7 @@ var
end else if IsValidIdentifier(p.Name) then begin
if not (exVariable in expected) then
RaiseEx('unexpected variable: ' + p.Name);
ei := TengExpressionVariable.Create(p.Name, p.Line, p.Col, aParam.Filename);
ei := TengExpressionVariable.Create(p.Name, aOwner, p.Line, p.Col, aParam.Filename);
try
MergeItems(stack, ei);
expected := [exGroupEnd, exBinaryOperation];
@@ -623,7 +626,7 @@ var
begin
dec(aIndex);
if not NextParam then with aParam[0] do
raise EengShaderPartInternal.Create('invalid parameter count in expression', Line, Col, aParam.Filename);
raise EengShaderPartInternal.Create('invalid parameter count in expression', Line, Col, aParam.Filename, aOwner);
result := BuildTree;
end;



+ 4
- 4
uengShaderFileHelper.pas Целия файл

@@ -40,12 +40,12 @@ begin
try
oldLine := aArgs.Line;
oldCol := aArgs.Col;
if not aArgs.ExtractToken(param) then
raise EengUnexpectedToken.Create(TOKEN_NONE, TOKEN_END, oldLine, oldCol, aShaderPart.Filename);
if not aArgs.ExtractToken(aShaderPart, param) then
EengUnexpectedToken.Create(TOKEN_NONE, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
if (param[0].Name <> TOKEN_END) then
raise EengUnexpectedToken.Create(param[0].Name, TOKEN_END, oldLine, oldCol, aShaderPart.Filename);
EengUnexpectedToken.Create(param[0].Name, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
if (param.Count <> 1) then
raise EengInvalidParamterCount.Create(TOKEN_END, 1, oldLine, oldCol, aShaderPart.Filename);
EengInvalidParamterCount.Create(TOKEN_END, 1, oldLine, oldCol, aShaderPart.Filename, aShaderPart);
result := '';
finally
FreeAndNil(param);


+ 10
- 13
uengShaderFileParser.pas Целия файл

@@ -37,7 +37,6 @@ type
private
fFilename: String;
fCode: TStringList;
fFlags: TengShaderFileLoadFlags;
fLineLength: Integer;
fLineCount: Integer;
fCurrentLine: String;
@@ -63,12 +62,10 @@ type
property Col: Integer read fCol write SetCol;
property Line: Integer read fLine write SetLine;

property Flags: TengShaderFileLoadFlags read fFlags write fFlags;

procedure NextCol;
procedure NextLine;
function ExtractToken(const aParameters: TengTokenParameterList): Boolean;
function GetTokenPreview(var aToken: String): Boolean;
function ExtractToken(const aSender: TObject; const aParameters: TengTokenParameterList): Boolean;
function GetTokenPreview(const aSender: TObject; var aToken: String): Boolean;

constructor Create(const aStream: TStream; const aFilename: String);
destructor Destroy; override;
@@ -138,7 +135,7 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengParseArgs.ExtractToken(const aParameters: TengTokenParameterList): Boolean;
function TengParseArgs.ExtractToken(const aSender: TObject; const aParameters: TengTokenParameterList): Boolean;
type
TCharType = (
ctUnknown,
@@ -173,9 +170,9 @@ var
(s[len] = TOKEN_CHAR_QUOTE)) then
begin
if not (s[1] = TOKEN_CHAR_QUOTE) then
raise EengShaderPart.Create('missing leading quote char', Line, Col, Filename);
raise EengShaderPart.Create('missing leading quote char', Line, Col, Filename, aSender);
if not (s[len] = TOKEN_CHAR_QUOTE) then
raise EengShaderPart.Create('missing trailing quote char', Line, Col, Filename);
raise EengShaderPart.Create('missing trailing quote char', Line, Col, Filename, aSender);
delete(s, len, 1);
delete(s, 1, 1);
p.Quoted := true;
@@ -221,7 +218,7 @@ begin
else if not (pfInToken in pf) then
Include(pf, pfInToken)
else
EengShaderPart.Create('invalid char in token', Line, Col, Filename);
EengShaderPart.Create('invalid char in token', Line, Col, Filename, aSender);
end;

TOKEN_CHAR_END: begin
@@ -229,7 +226,7 @@ begin
AddPart(not (pfIsComment in pf));
NextCol;
if (aParameters.Count <= 0) or (aParameters[0].Name = TOKEN_CHAR_IDENT) then
raise EengShaderPart.Create('empty token', Line, Col, Filename);
raise EengShaderPart.Create('empty token', Line, Col, Filename, aSender);
exit;
end else
s := s + CurrentChar;
@@ -274,7 +271,7 @@ begin
s := s + sLineBreak;
NextLine;
end;
raise EengShaderPart.Create('incomplete token', oldLine, oldCol, Filename);
raise EengShaderPart.Create('incomplete token', oldLine, oldCol, Filename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -284,7 +281,7 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengParseArgs.GetTokenPreview(var aToken: String): Boolean;
function TengParseArgs.GetTokenPreview(const aSender: TObject; var aToken: String): Boolean;
var
c: Integer;
begin
@@ -307,7 +304,7 @@ begin
until (c > LineLength) or not (CurrentLine[c] in VALID_TOKEN_CHARS);
aToken := Trim(aToken);
if (aToken = TOKEN_CHAR_IDENT) then
raise EengInvalidToken.Create('empty token', Line, Col, Filename);
raise EengInvalidToken.Create('empty token', Line, Col, Filename, aSender);
end;

TOKEN_CHAR_COMMENT:


+ 329
- 46
uengShaderFileTypes.pas Целия файл

@@ -24,130 +24,413 @@ type
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderFileLoadFlag = (
lfLazyInclude // include files will only be loaded when needed (this will store a reference to the passed IengShaderFileReader)
);
TengShaderFileLoadFlags = set of TengShaderFileLoadFlag;

//Exceptions////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengShaderPart = class(Exception)
protected
function GenerateMessage: String; virtual;
public
Sender: TObject;
Line: Integer;
Col: Integer;
Filename: String;

constructor Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String); overload;
procedure PrintTrace(const aLines: TStrings);
function PrintTrace: String;

constructor Create(const aSender: TObject); overload;
constructor Create(const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
constructor Create(const aMsg: String; const aSender: TObject); overload;
constructor Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;
EengShaderPartInternal = class(EengShaderPart);
EengExpression = class(EengShaderPart);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengInvalidToken = class(EengShaderPartInternal)
constructor Create(const aClassName: String; const aToken: String; const aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
SenderClassName: String;
Token: String;
constructor Create(const aSenderClassName: String; const aToken: String; const aSender: TObject); overload;
constructor Create(const aSenderClassName: String; const aToken: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengUnexpectedToken = class(EengShaderPart)
constructor Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
Token: String;
Expected: String;
constructor Create(const aToken, aExpected: String; const aSender: TObject); overload;
constructor Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengInvalidParamter = class(EengShaderPart)
constructor Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
Param: String;
Expected: String;
constructor Create(const aParam, aExpected: String; const aSender: TObject); overload;
constructor Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengInvalidParamterCount = class(EengShaderPart)
constructor Create(const aToken: String; const aExpected, aLine, aCol: Integer; const aFilename: String); overload;
constructor Create(const aToken: String; const aExpectedMin, aExpectedMax, aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
Token: String;
ExpectedMin: Integer;
ExpectedMax: Integer;
constructor Create(const aToken: String; const aExpected: Integer; const aSender: TObject); overload;
constructor Create(const aToken: String; const aExpectedMin, aExpectedMax: Integer; const aSender: TObject); overload;
constructor Create(const aToken: String; const aExpected, aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
constructor Create(const aToken: String; const aExpectedMin, aExpectedMax, aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengInvalidIdentifier = class(EengShaderPart)
constructor Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
Identifier: String;
constructor Create(const aIdentifier: String; const aSender: TObject); overload;
constructor Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengOutOfRange = class(EengShaderPartInternal)
constructor Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String); overload;
protected
function GenerateMessage: String; override;
public
Min: Integer;
Max: Integer;
Index: Integer;
constructor Create(const aMin, aMax, aIndex: Integer; const aSender: TObject); overload;
constructor Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EengDuplicateIdentifier = class(EengShaderPart)
protected
function GenerateMessage: String; override;
public
Name: String;
New: TObject;
Old: TObject;
constructor Create(const aName: String; const aNew, aOld, aSender: TObject); overload;
constructor Create(const aName: String; const aNew, aOld: TObject; aLine, aCol: Integer; const aFilename: String; const aSender: TObject); overload;
end;

implementation

uses
uengShaderPart;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengShaderPart.Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String);
function EengShaderPart.GenerateMessage: String;
begin
result := ''; // DUMMY
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure EengShaderPart.PrintTrace(const aLines: TStrings);

function GetName(const aPart: TengShaderPart): String;
begin
result := aPart.GetTokenName;
if (result = '')
then result := aPart.ClassName
else result := result + ' (' + aPart.ClassName + ')';
end;

var
p: TengShaderPart;
begin
if not Assigned(Sender) or not
(Sender is TengShaderPart) then
exit;
p := (Sender as TengShaderPart);
aLines.Text := Message;
while Assigned(p) do begin
aLines.Add(Format('%s (%d:%d): %s', [p.Filename, p.Line, p.Col, GetName(p)]));
p := p.Parent;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function EengShaderPart.PrintTrace: String;
var
sl: TStringList;
begin
sl := TStringList.Create;
try
PrintTrace(sl);
result := sl.Text;
finally
FreeAndNil(sl);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengShaderPart.Create(const aSender: TObject);
begin
Create(GenerateMessage, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengShaderPart.Create(const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Create(GenerateMessage, aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengShaderPart.Create(const aMsg: String; const aSender: TObject);
begin
Sender := nil;
if Assigned(aSender)
then Create(
aMsg,
(aSender as TengShaderPart).Line,
(aSender as TengShaderPart).Col,
(aSender as TengShaderPart).Filename,
aSender)
else inherited Create(Format('%s: %s', [
ClassName,
aMsg]));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengShaderPart.Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
inherited Create(Format('%s (file: %s; line: %d; col: %d): %s', [ClassName, ExtractFileName(aFilename), aLine+1, aCol, aMsg]));
Sender := aSender;
Line := aLine;
Col := aCol;
Filename := aFilename;
inherited Create(Format('%s (%s %d:%d): %s',[
ClassName,
ExtractFileName(Filename),
Line+1,
Col,
aMsg]))
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengInvalidToken//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidToken.Create(const aClassName: String; const aToken: String; const aLine, aCol: Integer; const aFilename: String);
function EengInvalidToken.GenerateMessage: String;
begin
inherited Create('invalid token: ' + aClassName + ' <> '+ aToken, aLine, aCol, aFilename);
result := 'invalid token: ' + SenderClassName + ' <> '+ Token;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidToken.Create(const aSenderClassName: String; const aToken: String; const aSender: TObject);
begin
SenderClassName := aSenderClassName;
Token := aToken;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidToken.Create(const aSenderClassName: String; const aToken: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
SenderClassName := aSenderClassName;
Token := aToken;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengUnexpectedToken///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengUnexpectedToken.Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String);
var
s: String;
function EengUnexpectedToken.GenerateMessage: String;
begin
s := 'unexpected token: ' + aToken;
if (aExpected <> '') then
s := s + '(expected ' + aExpected + ')';
inherited Create(s, aLine, aCol, aFilename);
result := 'unexpected token: ' + Token;
if (Expected <> '') then
result := result + '(expected ' + Expected + ')';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengUnexpectedToken.Create(const aToken, aExpected: String; const aSender: TObject);
begin
Token := aToken;
Expected := aExpected;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengUnexpectedToken.Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Token := aToken;
Expected := aExpected;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengInvalidParamter///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamter.Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String);
var
s: String;
function EengInvalidParamter.GenerateMessage: String;
begin
result := 'invalid parameter: ' + Param;
if (Expected <> '') then
result := result + '(expected ' + Expected + ')';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamter.Create(const aParam, aExpected: String; const aSender: TObject);
begin
Param := aParam;
Expected := aExpected;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamter.Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
s := 'invalid parameter: ' + aParam;
if (aExpected <> '') then
s := s + '(expected ' + aExpected + ')';
inherited Create(s, aLine, aCol, aFilename);
Param := aParam;
Expected := aExpected;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengInvalidParamterCount//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpected, aLine, aCol: Integer; const aFilename: String);
function EengInvalidParamterCount.GenerateMessage: String;
begin
inherited Create('invalid parameter count in ' + aToken + '(expected ' + IntToStr(aExpected) + ' parameter)', aLine, aCol, aFilename);
result := 'invalid parameter count in ' + Token + '(expected ';
if (ExpectedMin = ExpectedMax) then
result := result + IntToStr(ExpectedMin)
else if (ExpectedMax < 0) then
result := result + ' at least ' + IntToStr(ExpectedMin)
else
result := IntToStr(ExpectedMin) + ' to ' + IntToStr(ExpectedMax);
result := result + 'parameter)';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpectedMin, aExpectedMax, aLine, aCol: Integer; const aFilename: String);
var
s: String;
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpected: Integer; const aSender: TObject);
begin
Token := aToken;
ExpectedMin := aExpected;
ExpectedMax := aExpected;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpectedMin, aExpectedMax: Integer; const aSender: TObject);
begin
Token := aToken;
ExpectedMin := aExpectedMin;
ExpectedMax := aExpectedMax;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpected, aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Token := aToken;
ExpectedMin := aExpected;
ExpectedMax := aExpected;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpectedMin, aExpectedMax, aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
s := 'invalid parameter count in ' + aToken + '(expected ';
if (aExpectedMax < 0)
then s := s + ' at least '+ IntToStr(aExpectedMin)
else s := s + IntToStr(aExpectedMin) + ' to ' + IntToStr(aExpectedMax);
s := s + ' parameter)';
inherited Create(s, aLine, aCol, aFilename);
Token := aToken;
ExpectedMin := aExpectedMin;
ExpectedMax := aExpectedMax;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengInvalidIdentifier/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidIdentifier.Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String);
function EengInvalidIdentifier.GenerateMessage: String;
begin
inherited Create('invalid identifier: ' + aIdentifier, aLine, aCol, aFilename);
result := 'invalid identifier: ' + Identifier;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidIdentifier.Create(const aIdentifier: String; const aSender: TObject);
begin
Identifier := aIdentifier;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengInvalidIdentifier.Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Identifier := aIdentifier;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengOutOfRange////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengOutOfRange.Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String);
function EengOutOfRange.GenerateMessage: String;
begin
result := format('index (%d) out of range (%d:%d)', [Index, Min, Max])
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengOutOfRange.Create(const aMin, aMax, aIndex: Integer; const aSender: TObject);
begin
Min := aMin;
Max := aMax;
Index := aIndex;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengOutOfRange.Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
Min := aMin;
Max := aMax;
Index := aIndex;
inherited Create(aLine, aCol, aFilename, aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengDuplicateIdentifier///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function EengDuplicateIdentifier.GenerateMessage: String;
begin
result := 'duplicate identifier: ' + Name;
if (New is TengShaderPart) then
result := result + Format('(%s %d:%d)', [
(New as TengShaderPart).Filename,
(New as TengShaderPart).Line,
(New as TengShaderPart).Col]);
if (Old is TengShaderPart) then
result := result + Format('(previously declared here %s %d:%d)', [
(Old as TengShaderPart).Filename,
(Old as TengShaderPart).Line,
(Old as TengShaderPart).Col]);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengDuplicateIdentifier.Create(const aName: String; const aNew, aOld, aSender: TObject);
begin
Name := aName;
New := aNew;
Old := aOld;
inherited Create(aSender);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor EengDuplicateIdentifier.Create(const aName: String; const aNew, aOld: TObject; aLine, aCol: Integer; const aFilename: String; const aSender: TObject);
begin
inherited Create(format('index (%d) out of range (%d:%d)', [aIndex, aMin, aMax]), aLine, aCol, aFilename);
Name := aName;
New := aNew;
Old := aOld;
inherited Create(aLine, aCol, aFilename, aSender);
end;

end.


+ 69
- 39
uengShaderPart.pas Целия файл

@@ -11,19 +11,25 @@ uses
uengShaderFileParser, uengShaderFileTypes

{$IFDEF USE_BITSPACE_UTILS}
, uutlGenerics;
, uutlGenerics
{$ELSE}
, fgl;
, fgl
{$ENDIF}
;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderFileSearchFlag = (
sfFirstOnly, // search first match only
sfEvaluateIf, // evaluate if statements before search and process with suitable subtree
sfSearchChildren, // search in children
sfSearchParents, // search in parents
sfCurrentFileOnly // do not search in other files
sfFirstOnly, // search first match only
sfEvaluateIf, // evaluate if statements before search and process with suitable subtree

sfSearchChildren, // search in children
sfSearchParents, // search in parents
sfSearchInherited, // search in inherited

sfCurrentFileOnly, // do not leave current file
sfCurrentScopeOnly, // do not leave current scopes
sfCurrentGeneratorOnly // do not leave current generator
);
TengShaderFileSearchFlags = set of TengShaderFileSearchFlag;

@@ -44,17 +50,18 @@ type
constructor Create(const aOwner: TengShaderPart);
end;

TSearchList = class(TengShaderPartList)
TSearchResults = class(specialize TutlHashSet<TengShaderPart>)
public
constructor Create;
end;

{ Code Loading & Storage }
private { members }
fRoot: TengShaderPart;
fParent: TengShaderPart;
fLine: Integer;
fCol: Integer;
protected
fRoot: TengShaderPart;
protected { virtual getter }
function GetCount: Integer; virtual;
function GetChild(const aIndex: Integer): TengShaderPart; virtual;
@@ -68,8 +75,6 @@ type
function ParseText(const aArgs: TengParseArgs): String;

{ General }
protected
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); virtual;
public { general methods }
property Root: TengShaderPart read fRoot;
property Parent: TengShaderPart read fParent;
@@ -86,8 +91,12 @@ type

function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
function GetParent(const aType: CengShaderPart; out aPart): Boolean;
function GetParent(const aType: CengShaderPart): TengShaderPart;

function FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart;
procedure FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList);
procedure FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchResults);
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults); virtual;

function GetEnumerator: TEnumerator;

constructor Create(const aParent: TengShaderPart); virtual;
@@ -99,11 +108,16 @@ type
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
end;

function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;

implementation

uses
uengShaderFileConstants;
uengShaderPartScope, uengShaderCodeGenerator, uengShaderFile, uengShaderFileConstants;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
var
c: CengShaderPart;
@@ -141,9 +155,9 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TSearchList////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPart.TSearchResults////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderPart.TSearchList.Create;
constructor TengShaderPart.TSearchResults.Create;
begin
inherited Create(false);
end;
@@ -202,33 +216,13 @@ begin
fCol := aArgs.Col;
fLine := aArgs.Line;
if (GetTokenName <> '') then
aArgs.ExtractToken(params);
aArgs.ExtractToken(self, params);
result := ParseIntern(aArgs, params);
finally
FreeAndNil(params);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPart.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList);
var
c: TengShaderPart;
begin
if (sfFirstOnly in aFlags) and (aList.Count > 0) then
exit;

if CheckType(self, aTypes) then
aList.Add(self);

if (sfSearchChildren in aFlags) then begin
for c in self do
c.FindIntern(aFlags, aDepth+1, aTypes, aList);
end;

if (sfSearchParents in aFlags) and Assigned(Parent) then
Parent.FindIntern(aFlags, aDepth-1, aTypes, aList);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
@@ -255,12 +249,19 @@ begin
result := false;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
begin
if not GetParent(aType, result) then
raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.FindFirst(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart): TengShaderPart;
var
l: TSearchList;
l: TSearchResults;
begin
l := TSearchList.Create;
l := TSearchResults.Create;
try
FindIntern(aFlags + [sfFirstOnly], 0, aTypes, l);
if (l.Count > 0)
@@ -272,11 +273,40 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPart.FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchList);
procedure TengShaderPart.FindAll(const aFlags: TengShaderFileSearchFlags; const aTypes: array of CengShaderPart; const aList: TSearchResults);
begin
FindIntern(aFlags, 0, aTypes, aList);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPart.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults);
var
c: TengShaderPart;
begin
if (sfFirstOnly in aFlags) and (aList.Count > 0) then
exit;

if (sfSearchChildren in aFlags) then begin
for c in self do
if (not (sfCurrentScopeOnly in aFlags) or not (c is TengShaderPartScope)) and
(not (sfCurrentFileOnly in aFlags) or not (c is TengShaderFile)) and
(not (sfCurrentGeneratorOnly in aFlags) or not (c is TengShaderCodeGenerator))
then
c.FindIntern(aFlags, aDepth+1, aTypes, aList);
end;

if CheckType(self, aTypes) then
aList.Add(self);

if (sfSearchParents in aFlags) and
Assigned(Parent) and
(not (sfCurrentScopeOnly in aFlags) or not (self is TengShaderPartScope)) and
(not (sfCurrentFileOnly in aFlags) or not (self is TengShaderFile)) and
(not (sfCurrentGeneratorOnly in aFlags) or not (self is TengShaderCodeGenerator))
then
Parent.FindIntern(aFlags, aDepth-1, aTypes, aList);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPart.GetEnumerator: TEnumerator;
begin


+ 5
- 5
uengShaderPartCall.pas Целия файл

@@ -74,15 +74,15 @@ var
i: Integer;
begin
if (aParams[0].Name <> GetTokenName) then
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename, self);
if (aParams.Count < 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);

result := '';
fParameters.Clear;
with aParams[1] do begin
if not IsValidIdentifier(fName) then
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename);
raise EengInvalidIdentifier.Create(Name, self);
fName := Name;
end;
for i := 2 to aParams.Count-1 do
@@ -123,14 +123,14 @@ var
i: Integer;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);

fName := '';
fParameters.Clear;
if (aParams.Count >= 2) then begin
if not IsValidIdentifier(aParams[1].Name) and (aParams[1].Name <> TOKEN_MAIN) then
with aParams[1] do
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename);
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename, self);
fName := aParams[1].Name;
for i := 2 to aParams.Count-1 do
fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted)));


+ 36
- 11
uengShaderPartClass.pas Целия файл

@@ -7,7 +7,12 @@ interface

uses
Classes, SysUtils,
uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser;
uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser

{$IFDEF USE_BITSPACE_UTILS}
, uutlGenerics
{$ENDIF}
;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -32,12 +37,14 @@ type
{ Class Methods }
public
class function GetTokenName: String; override;
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
end;
TengShaderPartClassMap = specialize TutlMap<string, TengShaderPartClass>;

implementation

uses
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper;
uengShaderFile, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartIf;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartClass///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,27 +75,24 @@ function TengShaderPartClass.ParseIntern(const aArgs: TengParseArgs; const aPara
var
i: Integer;
begin
if (aParams[0].Name <> GetTokenName) then
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename);
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count < 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
with aParams[1] do begin
if not IsValidIdentifier(Name) then
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename);
raise EengInvalidIdentifier.Create(Name, self);
fName := Name;
end;
if (aParams.Count > 2) then begin
if (aParams.Count < 4) then
raise EengInvalidParamterCount.Create(GetTokenName, 4, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 4, -1, self);
if (aParams[2].Name <> TOKEN_EXTENDS) then with aParams[2] do
raise EengInvalidParamter.Create(aParams[2].Name, TOKEN_EXTENDS, Line, Col, Filename);
raise EengInvalidParamter.Create(aParams[2].Name, TOKEN_EXTENDS, Line, Col, Filename, self);
fExtends.Clear;
for i := 3 to aParams.Count-1 do
fExtends.Add(aParams[i].Name);
end;

// TODO fRoot.AddClass ?

result := inherited ParseIntern(aArgs, aParams);
result := CheckEndToken(aArgs, self);
end;
@@ -113,5 +117,26 @@ begin
result := TOKEN_CLASS;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class procedure TengShaderPartClass.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);

procedure RaiseEx(const aToken: String);
begin
with aArgs do
raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed in ' + aToken, Line, Col, Filename, aParent);
end;

begin
inherited Validate(aArgs, aParent);
if aParent.HasParent(TengShaderPartElIf, true) then
RaiseEx(TengShaderPartElIf.GetTokenName);
if aParent.HasParent(TengShaderPartElse, true) then
RaiseEx(TengShaderPartElse.GetTokenName);
if aParent.HasParent(TengShaderPartIf, true) then
RaiseEx(TengShaderPartIf.GetTokenName);
if aParent.HasParent(TengShaderPartClass, true) then
RaiseEx(TengShaderPartClass.GetTokenName);
end;

end.


+ 1
- 1
uengShaderPartCntr.pas Целия файл

@@ -23,7 +23,7 @@ type
function GetText: String; override;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
public { general methods }
procedure Clear;
procedure Clear; virtual;
constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
end;


+ 1
- 1
uengShaderPartComment.pas Целия файл

@@ -39,7 +39,7 @@ end;
function TengShaderPartComment.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count > 1) then
fText := aParams[1].Name;
result := '';


+ 3
- 3
uengShaderPartEcho.pas Целия файл

@@ -41,13 +41,13 @@ end;
function TengShaderPartEcho.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count <> 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, self);
result := '';
with aParams[1] do begin
if not IsValidIdentifier(Name) then
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename);
raise EengInvalidIdentifier.Create(Name, self);
fName := Name;
end;
end;


+ 23
- 5
uengShaderPartIf.pas Целия файл

@@ -27,6 +27,7 @@ type

{ General }
public
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults); override;
destructor Destroy; override;

{ Class Methods }
@@ -103,7 +104,7 @@ end;
function TengShaderPartIf.GetChild(const aIndex: Integer): TengShaderPart;
begin
if (aIndex < 0) or (aIndex >= Count) then
raise EengOutOfRange.Create(0, Count-1, aIndex, Line, Col, Filename);
raise EengOutOfRange.Create(0, Count-1, aIndex, self);
case aIndex of
0: result := fIfPart;
1: result := fElsePart;
@@ -123,17 +124,34 @@ end;
function TengShaderPartIf.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count < 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);

fExpression := ParseExpression(aParams, 1);
fExpression := ParseExpression(self, aParams, 1);

fIfPart := TengShaderPartCntr.Create(self);
result := fIfPart.ParseText(aArgs);
result := HandleToken(result, aArgs);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartIf.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchResults);
begin
if (sfEvaluateIf in aFlags) then begin
inherited FindIntern(aFlags - [sfSearchChildren], aDepth, aTypes, aList);
if (sfSearchChildren in aFlags) then begin
if fExpression.GetValue then begin
if Assigned(fIfPart) then
fIfPart.FindIntern(aFlags, aDepth, aTypes, aList);
end else begin
if Assigned(fElsePart) then
fElsePart.FindIntern(aFlags, aDepth, aTypes, aList);
end;
end;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengShaderPartIf.Destroy;
begin
@@ -156,7 +174,7 @@ function TengShaderPartElIf.HandeEndToken(const aToken: String; const aArgs: Ten
begin
result := aToken;
if (result <> TOKEN_END) then
raise EengInvalidToken.Create(ClassName, result, aArgs.Line, aArgs.Col, Filename);
raise EengInvalidToken.Create(ClassName, result, aArgs.Line, aArgs.Col, Filename, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 10
- 20
uengShaderPartInclude.pas Целия файл

@@ -17,7 +17,7 @@ type
fShaderFile: TengShaderFile;
fIncludeFile: String;
fAbsoluteFile: String;
procedure LoadShaderFile(const aFlags: TengShaderFileLoadFlags);
procedure LoadShaderFile;
protected
function GetCount: Integer; override;
function GetChild(const aIndex: Integer): TengShaderPart; override;
@@ -25,10 +25,9 @@ type
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ General }
protected
procedure FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList); override;
public
property IncludeFile: String read fIncludeFile;
property IncludeFile: String read fIncludeFile;
property ShaderFile: TengShaderFile read fShaderFile;
procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil);
constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
@@ -47,12 +46,12 @@ uses
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartInclude/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartInclude.LoadShaderFile(const aFlags: TengShaderFileLoadFlags);
procedure TengShaderPartInclude.LoadShaderFile;
begin
if not Assigned(fShaderFile) then
fShaderFile := TengShaderFile.Create(self);
if (fShaderFile.Filename <> fAbsoluteFile) then
fShaderFile.LoadFromFile(fAbsoluteFile, aFlags);
fShaderFile.LoadFromFile(fAbsoluteFile);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,7 +67,7 @@ function TengShaderPartInclude.GetChild(const aIndex: Integer): TengShaderPart;
begin
if Assigned(fShaderFile) and (aIndex = 0)
then result := fShaderFile
else raise EengOutOfRange.Create(0, Count-1, aIndex, Line, Col, Filename);
else raise EengOutOfRange.Create(0, Count-1, aIndex, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -81,28 +80,19 @@ end;
function TengShaderPartInclude.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count <> 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, self);
fIncludeFile := aParams[1].Name;
fAbsoluteFile := CreateAbsolutePath(fIncludeFile, ExtractFilePath(Filename));
result := '';
if not (lfLazyInclude in aArgs.Flags) then
LoadShaderFile(aArgs.Flags);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartInclude.FindIntern(aFlags: TengShaderFileSearchFlags; aDepth: Integer; aTypes: array of CengShaderPart; const aList: TSearchList);
begin
if (sfCurrentFileOnly in aFlags) then
exclude(aFlags, sfSearchChildren);
inherited FindIntern(aFlags, aDepth, aTypes, aList);
LoadShaderFile;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartInclude.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter);
begin
LoadShaderFile([]);
LoadShaderFile;
fIncludeFile := Format('%p_', [Pointer(fShaderFile)]) + ExtractFileName(fIncludeFile);
fAbsoluteFile := CreateAbsolutePath(fIncludeFile, ExtractFilePath(aFilename));
fShaderFile.SaveToFile(fAbsoluteFile, aFileWriter);


+ 32
- 5
uengShaderPartKeyValuePair.pas Целия файл

@@ -7,7 +7,12 @@ interface

uses
Classes, SysUtils, variants,
uengShaderPart, uengShaderFileParser;
uengShaderPart, uengShaderFileParser

{$IFDEF USE_BITSPACE_UTILS}
, uutlGenerics
{$ENDIF}
;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -33,7 +38,9 @@ type
{ Class Methods }
public
class function GetTokenName: String; override;
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
end;
TengShaderPartPropertyMap = specialize TutlMap<string, TengShaderPartProperty>;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartDefine = class(TengShaderPartKeyValuePair)
@@ -45,7 +52,7 @@ type
implementation

uses
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper;
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartIf;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartKeyValuePair////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -64,19 +71,20 @@ end;
function TengShaderPartKeyValuePair.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, GetTokenName, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, GetTokenName, Line, Col, Filename, self);
if (aParams.Count < 2) or (aParams.Count > 3) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, 3, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, 3, self);

result := '';
fName := aParams[1].Name;
if not IsValidIdentifier(fName) then with aParams[1] do
raise EengInvalidIdentifier.Create(fName, Line, Col, Filename);
raise EengInvalidIdentifier.Create(fName, Line, Col, Filename, self);
if (aParams.Count >= 3) then
if aParams[2].Quoted then begin
fValue := aParams[2].Name;
fValueName := '';
end else begin
// TODO resolve name and set value
fValue := Unassigned;
fValueName := aParams[2].Name;
end
@@ -94,6 +102,25 @@ begin
result := TOKEN_PROPERTY;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class procedure TengShaderPartProperty.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);

procedure RaiseEx(const aToken: String);
begin
with aArgs do
raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed in ' + aToken, Line, Col, Filename, aParent);
end;

begin
inherited Validate(aArgs, aParent);
if aParent.HasParent(TengShaderPartElIf, true) then
RaiseEx(TengShaderPartElIf.GetTokenName);
if aParent.HasParent(TengShaderPartElse, true) then
RaiseEx(TengShaderPartElse.GetTokenName);
if aParent.HasParent(TengShaderPartIf, true) then
RaiseEx(TengShaderPartIf.GetTokenName);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartDefine//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 8
- 8
uengShaderPartMeta.pas Целия файл

@@ -105,9 +105,9 @@ var
n: String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count < 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);

result := '';
n := aParams[1].Name;
@@ -117,26 +117,26 @@ begin
t := metaVersion;
if (aParams.Count = 3) then begin
if (aParams[2].Name <> VERSION_EXTRA_COMPAT) and not TryStrToInt(aParams[2].Name, i) then with aParams[2] do
raise EengInvalidParamter.Create('version must be an number or "' + VERSION_EXTRA_COMPAT + '"', Line, Col, Filename);
raise EengInvalidParamter.Create('version must be an number or "' + VERSION_EXTRA_COMPAT + '"', Line, Col, Filename, self);
end else if (aParams.Count = 4) then begin
if (aParams[2].Name <> VERSION_EXTRA_COMPAT) and not TryStrToInt(aParams[2].Name, i) then with aParams[2] do
raise EengInvalidParamter.Create('version must be an number or "' + VERSION_EXTRA_COMPAT + '"', Line, Col, Filename);
raise EengInvalidParamter.Create('version must be an number or "' + VERSION_EXTRA_COMPAT + '"', Line, Col, Filename, self);
if (aParams[3].Name <> VERSION_EXTRA_COMPAT) then with aParams[3] do
raise EengInvalidParamter.Create('only "' + VERSION_EXTRA_COMPAT + '" is alowed as second parameter', Line, Col, Filename);
raise EengInvalidParamter.Create('only "' + VERSION_EXTRA_COMPAT + '" is alowed as second parameter', Line, Col, Filename, self);
end else
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, self);

{.$EXTENSION}
end else if (n = TOKEN_EXTENSION) then begin
t := metaExtension;
if (aParams.Count <> 4) then
raise EengInvalidParamterCount.Create(GetTokenName, 4, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 4, self);

{.$LAYOUT}
end else if (n = TOKEN_LAYOUT) then begin
t := metaLayout;
if (aParams.Count <> 3) then
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 3, self);

{.VALUES}
end else


+ 4
- 4
uengShaderPartParameter.pas Целия файл

@@ -78,9 +78,9 @@ end;
function TengShaderPartParameter.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count <> 3) then
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 3, self);

result := '';
fType := aParams[1].Name;
@@ -104,9 +104,9 @@ end;
function TengShaderPartVar.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count < 3) or (aParams.Count > 4) then
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, self);

result := '';
fType := aParams[1].Name;


+ 9
- 9
uengShaderPartProc.pas Целия файл

@@ -113,9 +113,9 @@ var
param: TengShaderPartProcParam;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count < 2) then
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);

i := 2;
result := '';
@@ -135,7 +135,7 @@ begin
pasName: begin
if (aParams[i].Name = TOKEN_INLINE) then begin
with aParams[i] do
raise EengInvalidParamter.Create('expected parameter name (found ' + TOKEN_INLINE + ')', Line, Col, Filename);
raise EengInvalidParamter.Create('expected parameter name (found ' + TOKEN_INLINE + ')', Line, Col, Filename, self);
end else begin
param.Name := aParams[i].Name;
fParameters.Add(param);
@@ -146,7 +146,7 @@ begin
inc(i);
end;
if (state <> pasType) then
raise EengInvalidParamterCount.Create('invalid parameter count in ' + GetTokenName + '(expected multiple of 2)', Line, Col, Filename);
raise EengInvalidParamterCount.Create('invalid parameter count in ' + GetTokenName + '(expected multiple of 2)', self);
inherited ParseIntern(aArgs, aParams);
result := CheckEndToken(aArgs, self);
end;
@@ -176,7 +176,7 @@ class procedure TengShaderPartProc.Validate(const aArgs: TengParseArgs; const aP
begin
if (aParent.HasParent(TengShaderPartProc, true)) then with aArgs do
raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed inside ' +
TOKEN_PROC + ', ' + TOKEN_FUNC + ' or + ' + TOKEN_MAIN, Line, Col, aParent.Filename);
TOKEN_PROC + ', ' + TOKEN_FUNC + ' or + ' + TOKEN_MAIN, Line, Col, aParent.Filename, aParent);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -193,9 +193,9 @@ var
p: TengTokenParameter;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
if (aParams.Count <> 1) then
raise EengInvalidParamterCount.Create(GetTokenName, 1, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 1, self);

result := '';
p.Name := 'main';
@@ -232,9 +232,9 @@ end;
function TengShaderPartFunc.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if (aParams[0].Name <> GetTokenName) then with aParams[0] do
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename, self);
if (aParams.Count < 3) then
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename);
raise EengInvalidParamterCount.Create(GetTokenName, 3, self);

fReturnType := aParams[1].Name;
aParams.Delete(1);


+ 1
- 0
uengShaderPartScope.pas Целия файл

@@ -10,6 +10,7 @@ uses
uengShaderPartCntr;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartScope = class(TengShaderPartCntr)

end;


+ 2
- 2
uengShaderPartText.pas Целия файл

@@ -75,7 +75,7 @@ begin
fText := '';
result := '';
while not aArgs.EndOfLine do begin
if aArgs.GetTokenPreview(result) then begin
if aArgs.GetTokenPreview(self, result) then begin
exit;
end else if (aArgs.CurrentChar in COMMAND_END_TOKENS) then begin
result := aArgs.CurrentChar;
@@ -100,7 +100,7 @@ end;
function TengShaderPartLineBreak.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
if not aArgs.EndOfLine then
raise EengInvalidToken.Create(ClassName, '[LineBreak]', Line, Col, Filename);
raise EengInvalidToken.Create(ClassName, '[LineBreak]', self);
aArgs.NextLine;
result := '';
end;


Зареждане…
Отказ
Запис