* started implementation of code generationmaster
| @@ -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. | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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); | |||
| @@ -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: | |||
| @@ -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. | |||
| @@ -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 | |||
| @@ -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))); | |||
| @@ -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. | |||
| @@ -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; | |||
| @@ -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 := ''; | |||
| @@ -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; | |||
| @@ -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; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -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); | |||
| @@ -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////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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); | |||
| @@ -10,6 +10,7 @@ uses | |||
| uengShaderPartCntr; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderPartScope = class(TengShaderPartCntr) | |||
| end; | |||
| @@ -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; | |||