unit uengShaderPartProc; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses Classes, SysUtils, uengShaderPart, uengShaderPartScope, uengShaderFileParser {$IFDEF USE_BITSPACE_UTILS} , uutlGenerics; {$ELSE} , fgl; {$ENDIF} type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartProcParam = packed record Typ: String; Name: String; end; TengShaderPartProcParamList = specialize TutlSimpleList; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartProc = class(TengShaderPartScope) { Code Loading & Storage } private fName: String; fIsInline: Boolean; fParameters: TengShaderPartProcParamList; protected function GetHeaderText: String; virtual; function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { General } public property Name: String read fName; property IsInline: Boolean read fIsInline; constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; { Class Members } public class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartMain = class(TengShaderPartProc) { Code Loading & Storage } protected function GetHeaderText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { General } public class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartFunc = class(TengShaderPartProc) { Code Loading & Storage } private fReturnType: String; protected function GetHeaderText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { Class Methods } public class function GetTokenName: String; override; end; implementation uses uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartProc//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartProc.GetHeaderText: String; var p: TengShaderPartProcParam; begin result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + TOKEN_CHAR_QUOTE + fName + TOKEN_CHAR_QUOTE; for p in fParameters do begin result := result + ' ' + TOKEN_CHAR_QUOTE + p.Typ + TOKEN_CHAR_QUOTE + ' ' + TOKEN_CHAR_QUOTE + p.Name + TOKEN_CHAR_QUOTE; end; result := result + TOKEN_CHAR_END; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartProc.GetText: String; begin result := GetHeaderText + inherited GetText + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartProc.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; type TParseArgsState = (pasType, pasName); var i: Integer; state: TParseArgsState; param: TengShaderPartProcParam; begin 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, self); i := 2; result := ''; fName := aParams[1].Name; state := pasType; fParameters.Clear; while (i < aParams.Count) do begin case state of pasType: begin if (aParams[i].Name <> TOKEN_INLINE) then begin param.Typ := aParams[i].Name; state := pasName; end else fIsInline := true; end; 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, self); end else begin param.Name := aParams[i].Name; fParameters.Add(param); state := pasType; end; end; end; inc(i); end; if (state <> pasType) then raise EengInvalidParamterCount.Create('invalid parameter count in ' + GetTokenName + '(expected multiple of 2)', self); inherited ParseIntern(aArgs, aParams); result := CheckEndToken(aArgs, self); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPartProc.Create(const aParent: TengShaderPart); begin inherited Create(aParent); fParameters := TengShaderPartProcParamList.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderPartProc.Destroy; begin FreeAndNil(fParameters); inherited Destroy; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartProc.GetTokenName: String; begin result := TOKEN_PROC; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartMain//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartMain.GetHeaderText: String; begin result := TOKEN_CHAR_BEGIN + GetTokenName + TOKEN_CHAR_END; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartMain.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; var p: TengTokenParameter; begin if (aParams[0].Name <> GetTokenName) then with aParams[0] do raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); if (aParams.Count <> 1) then raise EengInvalidParamterCount.Create(GetTokenName, 1, self); result := ''; p.Name := 'main'; p.Quoted := false; p.Line := Line; p.Col := Col + Length(GetTokenName); aParams.Add(p); inherited ParseIntern(aArgs, aParams); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartMain.GetTokenName: String; begin result := TOKEN_MAIN; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartFunc//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartFunc.GetHeaderText: String; var p: TengShaderPartProcParam; begin result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + TOKEN_CHAR_QUOTE + fReturnType + TOKEN_CHAR_QUOTE + ' ' + TOKEN_CHAR_QUOTE + fName + TOKEN_CHAR_QUOTE; for p in fParameters do result := result + ' ' + TOKEN_CHAR_QUOTE + p.Typ + TOKEN_CHAR_QUOTE + ' ' + TOKEN_CHAR_QUOTE + p.Name + TOKEN_CHAR_QUOTE; result := result + TOKEN_CHAR_END; 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, self); if (aParams.Count < 3) then raise EengInvalidParamterCount.Create(GetTokenName, 3, self); fReturnType := aParams[1].Name; aParams.Delete(1); result := inherited ParseIntern(aArgs, aParams); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartFunc.GetTokenName: String; begin result := TOKEN_FUNC; end; end.