unit uengShaderFileHelper; {$mode objfpc}{$H+} {$I uengShaderFile.inc} interface uses uengShaderPart, uengShaderFileParser; function IsValidIdentifier(const aIdent: String): Boolean; function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer = -1; aCol: Integer = -1; aFilename: String = ''): TengShaderPart; type TkvpSearchResults = class(TengSearchResults) private fName: String; protected function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override; public constructor Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); end; implementation uses sysutils, uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function IsValidIdentifier(const aIdent: String): Boolean; var i, len: Integer; begin len := Length(aIdent); result := false; for i := 1 to len do if not (aIdent[i] in VALID_IDENT_CHARS) then exit; result := true; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; var oldLine, oldCol: Integer; param: TengTokenParameterList; begin param := TengTokenParameterList.Create(''); try oldLine := aArgs.Line; oldCol := aArgs.Col; 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 EengUnexpectedToken.Create(param[0].Name, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart); if (param.Count <> 1) then EengInvalidParamterCount.Create(TOKEN_END, 1, oldLine, oldCol, aShaderPart.Filename, aShaderPart); result := ''; finally FreeAndNil(param); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart; var s: String; i: Integer; begin result := nil; if Assigned(aSender) then begin if (aLine < 0) then aLine := aSender.Line; if (aCol < 0) then aCol := aSender.Col; if (aFilename = '') then aFilename := aSender.Filename; end; if (aList.Count <= 0) then raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender); result := aList[0]; if (aList.Count > 1) and Assigned(aSender) then begin s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, aList[0].Filename, aList[0].Line + 1, aList[0].Col]) + sLineBreak + 'previously declared here:' + sLineBreak; i := 1; while (i < aList.Count) do begin s := s + Format(' %s %d:%d', [aList[i].Filename, aList[i].Line + 1, aList[i].Col]) + sLineBreak; inc(i); end; aSender.LogMsg(llWarning, s); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TkvpSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; begin result := inherited CheckObj(aPart, aContinue); if result then result := ((aPart as TengShaderPartKeyValuePair).Name = fName); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TkvpSearchResults.Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); begin if aSearchDefines and aSearchProperties then inherited Create([TengShaderPartStatic, TengShaderPartProperty]) else if aSearchDefines then inherited Create([TengShaderPartStatic]) else if aSearchProperties then inherited Create([TengShaderPartProperty]) else inherited Create([]); fName := aName; end; end.