@@ -0,0 +1,5 @@ | |||
*/lib/ | |||
*.lps | |||
*.exe | |||
*.res | |||
*.ico |
@@ -0,0 +1,210 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<CONFIG> | |||
<ProjectOptions> | |||
<Version Value="9"/> | |||
<PathDelim Value="\"/> | |||
<General> | |||
<SessionStorage Value="InProjectDir"/> | |||
<MainUnit Value="0"/> | |||
<Title Value="ShaderFileTests"/> | |||
<ResourceType Value="res"/> | |||
<UseXPManifest Value="True"/> | |||
<Icon Value="0"/> | |||
</General> | |||
<i18n> | |||
<EnableI18N LFM="False"/> | |||
</i18n> | |||
<VersionInfo> | |||
<StringTable ProductVersion=""/> | |||
</VersionInfo> | |||
<BuildModes Count="1"> | |||
<Item1 Name="Default" Default="True"/> | |||
</BuildModes> | |||
<PublishOptions> | |||
<Version Value="2"/> | |||
</PublishOptions> | |||
<RunParams> | |||
<local> | |||
<FormatVersion Value="1"/> | |||
</local> | |||
</RunParams> | |||
<RequiredPackages Count="3"> | |||
<Item1> | |||
<PackageName Value="FPCUnitTestRunner"/> | |||
</Item1> | |||
<Item2> | |||
<PackageName Value="LCL"/> | |||
</Item2> | |||
<Item3> | |||
<PackageName Value="FCL"/> | |||
</Item3> | |||
</RequiredPackages> | |||
<Units Count="27"> | |||
<Unit0> | |||
<Filename Value="ShaderFileTests.lpr"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="ShaderFileTests"/> | |||
</Unit0> | |||
<Unit1> | |||
<Filename Value="uShaderFileTestCase.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uShaderFileTestCase"/> | |||
</Unit1> | |||
<Unit2> | |||
<Filename Value="..\uengShaderPart.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPart"/> | |||
</Unit2> | |||
<Unit3> | |||
<Filename Value="..\uengShaderFileTypes.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileTypes"/> | |||
</Unit3> | |||
<Unit4> | |||
<Filename Value="..\uengShaderFile.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFile"/> | |||
</Unit4> | |||
<Unit5> | |||
<Filename Value="..\uengShaderGenerator.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderGenerator"/> | |||
</Unit5> | |||
<Unit6> | |||
<Filename Value="..\uengShaderFileConstants.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileConstants"/> | |||
</Unit6> | |||
<Unit7> | |||
<Filename Value="..\uengShaderFileExpression.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileExpression"/> | |||
</Unit7> | |||
<Unit8> | |||
<Filename Value="..\uengShaderFileHelper.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileHelper"/> | |||
</Unit8> | |||
<Unit9> | |||
<Filename Value="..\uengShaderFileParser.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileParser"/> | |||
</Unit9> | |||
<Unit10> | |||
<Filename Value="..\uengShaderFileScope.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderFileScope"/> | |||
</Unit10> | |||
<Unit11> | |||
<Filename Value="..\uengShaderGeneratorArgs.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderGeneratorArgs"/> | |||
</Unit11> | |||
<Unit12> | |||
<Filename Value="..\uengShaderPartCall.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartCall"/> | |||
</Unit12> | |||
<Unit13> | |||
<Filename Value="..\uengShaderPartClass.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartClass"/> | |||
</Unit13> | |||
<Unit14> | |||
<Filename Value="..\uengShaderPartCntr.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartCntr"/> | |||
</Unit14> | |||
<Unit15> | |||
<Filename Value="..\uengShaderPartComment.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartComment"/> | |||
</Unit15> | |||
<Unit16> | |||
<Filename Value="..\uengShaderPartEcho.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartEcho"/> | |||
</Unit16> | |||
<Unit17> | |||
<Filename Value="..\uengShaderPartIf.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartIf"/> | |||
</Unit17> | |||
<Unit18> | |||
<Filename Value="..\uengShaderPartInclude.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartInclude"/> | |||
</Unit18> | |||
<Unit19> | |||
<Filename Value="..\uengShaderPartKeyValuePair.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartKeyValuePair"/> | |||
</Unit19> | |||
<Unit20> | |||
<Filename Value="..\uengShaderPartMessage.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartMessage"/> | |||
</Unit20> | |||
<Unit21> | |||
<Filename Value="..\uengShaderPartMeta.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartMeta"/> | |||
</Unit21> | |||
<Unit22> | |||
<Filename Value="..\uengShaderPartParameter.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartParameter"/> | |||
</Unit22> | |||
<Unit23> | |||
<Filename Value="..\uengShaderPartProc.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartProc"/> | |||
</Unit23> | |||
<Unit24> | |||
<Filename Value="..\uengShaderPartScope.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartScope"/> | |||
</Unit24> | |||
<Unit25> | |||
<Filename Value="..\uengShaderPartText.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderPartText"/> | |||
</Unit25> | |||
<Unit26> | |||
<Filename Value="..\uengShaderCodePart.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<UnitName Value="uengShaderCodePart"/> | |||
</Unit26> | |||
</Units> | |||
</ProjectOptions> | |||
<CompilerOptions> | |||
<Version Value="11"/> | |||
<PathDelim Value="\"/> | |||
<Target> | |||
<Filename Value="ShaderFileTests"/> | |||
</Target> | |||
<SearchPaths> | |||
<IncludeFiles Value="$(ProjOutDir);.."/> | |||
<OtherUnitFiles Value="..;..\..\Utils"/> | |||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> | |||
</SearchPaths> | |||
<Other> | |||
<CompilerMessages> | |||
<IgnoredMessages idx5024="True"/> | |||
</CompilerMessages> | |||
</Other> | |||
</CompilerOptions> | |||
<Debugging> | |||
<Exceptions Count="3"> | |||
<Item1> | |||
<Name Value="EAbort"/> | |||
</Item1> | |||
<Item2> | |||
<Name Value="ECodetoolError"/> | |||
</Item2> | |||
<Item3> | |||
<Name Value="EFOpenError"/> | |||
</Item3> | |||
</Exceptions> | |||
</Debugging> | |||
</CONFIG> |
@@ -0,0 +1,15 @@ | |||
program ShaderFileTests; | |||
{$mode objfpc}{$H+} | |||
uses | |||
Interfaces, Forms, GuiTestRunner, uShaderFileTestCase; | |||
{$R *.res} | |||
begin | |||
Application.Initialize; | |||
Application.CreateForm(TGuiTestRunner, TestRunner); | |||
Application.Run; | |||
end. | |||
@@ -0,0 +1,8 @@ | |||
{$PROPERTY TestProp '0'} | |||
{$IF TestProp = '0'} | |||
int i = 0; | |||
{$ELIF TestProp = '1'} | |||
int i = 1; | |||
{$ELSE} | |||
int i = 2; | |||
{$END} |
@@ -0,0 +1,9 @@ | |||
{$PROPERTY TestProp '0'} | |||
some code here = {$IF TestProp = '0'}this code{$ELSE}that code{$END}; | |||
some code here = {$IF TestProp = '0'} | |||
this code * | |||
more code | |||
{$ELSE} | |||
that code * | |||
more code | |||
{$END}; |
@@ -0,0 +1 @@ | |||
int i = 0; |
@@ -0,0 +1 @@ | |||
int i = 1; |
@@ -0,0 +1 @@ | |||
int i = 2; |
@@ -0,0 +1,4 @@ | |||
some code here = this code; | |||
some code here = | |||
this code * | |||
more code; |
@@ -0,0 +1,4 @@ | |||
some code here = that code; | |||
some code here = | |||
that code * | |||
more code; |
@@ -0,0 +1,72 @@ | |||
unit uShaderFileTestCase; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, fpcunit, testregistry, | |||
uengShaderFile, uengShaderGenerator, uengShaderFileTypes; | |||
type | |||
TShaderFileTestCase = class(TTestCase) | |||
private | |||
procedure DoTest(const aCode: String; const aValue: Integer; const aResult: String); | |||
published | |||
procedure IfElseElifEnd; | |||
procedure InlineIf; | |||
end; | |||
implementation | |||
uses | |||
Forms; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TShaderFileTestCase/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TShaderFileTestCase.DoTest(const aCode: String; const aValue: Integer; const aResult: String); | |||
var | |||
shdr: TengShaderFile; | |||
gen: TengShaderGenerator; | |||
code: TengShaderCode; | |||
sl: TStringList; | |||
begin | |||
shdr := TengShaderFile.Create; | |||
code := TengShaderCode.Create; | |||
sl := TStringList.Create; | |||
try | |||
shdr.LoadFromFile(ExpandFileName(aCode)); | |||
gen := shdr.Generator['']; | |||
if (gen.PropertyCount > 0) then | |||
gen.PropertyByIndex[0] := aValue; | |||
gen.GenerateCode(code); | |||
sl.LoadFromFile(ExpandFileName(aResult)); | |||
AssertEquals(sl.Text, code.Text); | |||
finally | |||
FreeAndNil(sl); | |||
FreeAndNil(code); | |||
FreeAndNil(shdr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TShaderFileTestCase.IfElseElifEnd; | |||
begin | |||
DoTest('code_IfElseElifEnd.shdr', 0, 'result_IfElseElifEnd_0.shdr'); | |||
DoTest('code_IfElseElifEnd.shdr', 1, 'result_IfElseElifEnd_1.shdr'); | |||
DoTest('code_IfElseElifEnd.shdr', 2, 'result_IfElseElifEnd_2.shdr'); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TShaderFileTestCase.InlineIf; | |||
begin | |||
DoTest('code_InlineIf.shdr', 0, 'result_InlineIf_0.shdr'); | |||
DoTest('code_InlineIf.shdr', 1, 'result_InlineIf_1.shdr'); | |||
end; | |||
initialization | |||
RegisterTest(TShaderFileTestCase); | |||
end. | |||
@@ -60,7 +60,8 @@ type | |||
property OnLog: TengShaderFileLogEvent read fOnLog write fOnLog; | |||
procedure Clear; override; | |||
constructor Create(const aParent: TengShaderPart); override; | |||
constructor Create; overload; | |||
constructor Create(const aParent: TengShaderPart); override; overload; | |||
destructor Destroy; override; | |||
end; | |||
@@ -309,6 +310,12 @@ begin | |||
fClasses.Clear; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TengShaderFile.Create; | |||
begin | |||
Create(nil); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TengShaderFile.Create(const aParent: TengShaderPart); | |||
begin | |||
@@ -16,7 +16,7 @@ type | |||
TInfoFlags = set of TInfoFlag; | |||
function IsValidIdentifier(const aIdent: String): Boolean; | |||
function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; | |||
function CheckEndToken(const aToken: String; const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; | |||
function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; | |||
function ExtractSearchResult( | |||
const aSender: TengShaderPart; | |||
@@ -97,7 +97,8 @@ implementation | |||
uses | |||
sysutils, | |||
uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, uengShaderPartIf; | |||
uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, | |||
uengShaderPartIf, uengShaderPartClass; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function IsValidIdentifier(const aIdent: String): Boolean; | |||
@@ -113,15 +114,17 @@ begin | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; | |||
function CheckEndToken(const aToken: String; const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; | |||
var | |||
oldLine, oldCol: Integer; | |||
param: TengTokenParameterList; | |||
begin | |||
oldLine := aArgs.Line; | |||
oldCol := aArgs.Col; | |||
if (aToken <> TOKEN_END) then | |||
raise EengUnexpectedToken.Create(aToken, TOKEN_END, oldLine, oldCol, aShaderPart.Filename, aShaderPart); | |||
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 | |||
@@ -227,6 +230,7 @@ var | |||
var | |||
p: TengShaderPart; | |||
c: TengShaderPartClass; | |||
nextArgs: TArgs; | |||
begin | |||
if not Assigned(aPart) then | |||
@@ -245,6 +249,12 @@ begin | |||
if VisitParent then | |||
Visit(aPart.Parent, aPart, @nextArgs); | |||
// visit inherited | |||
if (sfSearchInherited in args.Flags) and (aPart is TengShaderPartClass) then begin | |||
for c in (aPart as TengShaderPartClass).InheritedClasses do | |||
Visit(c, aPart, @nextArgs); | |||
end; | |||
// visit children | |||
if (sfSearchChildren in args.Flags) then begin | |||
if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin | |||
@@ -253,7 +263,7 @@ begin | |||
then p := IfPart | |||
else p := ElsePart; | |||
if Assigned(p) then | |||
Visit(p, aPart, @args); | |||
Visit(p, aPart, @nextArgs); | |||
exit; | |||
end else if (sfIgnoreIf in args.Flags) then | |||
exit; | |||
@@ -263,7 +273,7 @@ begin | |||
if Check(p) then | |||
fResults.Add(p); | |||
if VisitChild(p) then | |||
Visit(p, aPart, @args); | |||
Visit(p, aPart, @nextArgs); | |||
end; | |||
end; | |||
end; | |||
@@ -9,7 +9,7 @@ interface | |||
uses | |||
Classes, SysUtils, | |||
uengShaderFilePart; | |||
uengShaderPart; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -201,7 +201,8 @@ type | |||
gfToken, // current line has a token in it | |||
gfTokenOnly, // current line has only a token (or whitespaces) in it | |||
gfPrevIsEmpty, // previouse line was empty (or whitespaces only) | |||
gfCodeIsEmpty // nothing has added to code | |||
gfCodeIsEmpty, // nothing has added to code | |||
gfAddToPrev // add current line to previouse line | |||
); | |||
TGenFlags = set of TGenFlag; | |||
@@ -291,12 +292,15 @@ var | |||
Include(f, gfPrevIsEmpty); | |||
end; | |||
end else begin | |||
aCode.Add(line); | |||
if (gfAddToPrev in f) and not (gfCodeIsEmpty in f) | |||
then aCode[aCode.Count-1] := aCode[aCode.Count-1] + TrimLeft(line) | |||
else aCode.Add(line); | |||
Exclude(f, gfPrevIsEmpty); | |||
Exclude(f, gfCodeIsEmpty); | |||
end; | |||
Exclude(f, gfToken); | |||
Exclude(f, gfTokenOnly); | |||
Exclude(f, gfAddToPrev); | |||
line := ''; | |||
end; | |||
@@ -313,6 +317,8 @@ var | |||
gtBlockEnd: begin | |||
IndentBlock(FirstLineIndex, aIndent); | |||
if (Trim(line) = '') and not (gfPrevIsEmpty in f) then | |||
include(f, gfAddToPrev); | |||
exit; | |||
end; | |||
@@ -198,7 +198,7 @@ procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGene | |||
if (walker.Name = '') then | |||
walker.Name := ParentProc.Name; | |||
walker.Owner := ParentProc; | |||
walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited, sfSearchParents]; | |||
walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited]; | |||
walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | |||
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | |||
walker.Run(ParentProc); | |||
@@ -38,8 +38,9 @@ type | |||
{ General } | |||
public | |||
property Name: String read fName; | |||
property Extends: TStrings read GetExtends; | |||
property Name: String read fName; | |||
property Extends: TStrings read GetExtends; | |||
property InheritedClasses: TengShaderPartClassList read fInherited; | |||
constructor Create(const aParent: TengShaderPart); override; | |||
destructor Destroy; override; | |||
@@ -154,7 +155,7 @@ begin | |||
end; | |||
UpdateInherited; | |||
result := inherited ParseIntern(aArgs, aParams); | |||
result := CheckEndToken(aArgs, self); | |||
result := CheckEndToken(result, aArgs, self); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -101,6 +101,7 @@ begin | |||
break; | |||
end; | |||
end; | |||
result := aToken; | |||
if Assigned(fElsePart) then | |||
result := fElsePart.ParseText(aArgs); | |||
result := HandeEndToken(result, aArgs); | |||
@@ -109,7 +110,7 @@ end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TengShaderPartIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; | |||
begin | |||
result := CheckEndToken(aArgs, self); | |||
result := CheckEndToken(aToken, aArgs, self); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -185,7 +186,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, self); | |||
raise EengUnexpectedToken.Create(aToken, TOKEN_END, aArgs.Col, aArgs.Line, Filename, self); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -179,8 +179,8 @@ begin | |||
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); | |||
result := inherited ParseIntern(aArgs, aParams); | |||
result := CheckEndToken(result, aArgs, self); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||