@@ -0,0 +1,21 @@ | |||||
unit uengShaderCodeGenerator; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPartCntr; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderCodeGenerator = class(TengShaderPartCntr) | |||||
end; | |||||
implementation | |||||
end. | |||||
@@ -0,0 +1,3 @@ | |||||
{$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions | |||||
{$DEFINE USE_BITSPACE_UTILS} // use bitSpace Utils | |||||
{$DEFINE DEBUG} // enable debug output |
@@ -0,0 +1,96 @@ | |||||
unit uengShaderFile; | |||||
{ Package: SpaceEngine | |||||
Prefix: eng - ENGine | |||||
Beschreibung: stellt Klassen zum laden von Shader-Datein zur Verfügung | |||||
beim laden des Codes wird gleichzeitig die Präprozessor-Sprache ausgewertet } | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, sysutils, | |||||
uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
, uutlSerialization | |||||
{$ENDIF} | |||||
; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderFile = class(TengShaderCodeGenerator) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fFilename: String; | |||||
fFileReader: IutlFileReader; | |||||
fFileWriter: IutlFileWriter; | |||||
protected { virtual getter } | |||||
function GetFilename: String; override; | |||||
function GetFileReader: IengShaderFileReader; override; | |||||
function GetFileWriter: IengShaderFileWriter; override; | |||||
public { general methods } | |||||
procedure LoadCode(const aFilename: String; const aFileReader: IengShaderFileReader = nil); | |||||
end; | |||||
implementation | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderFile.GetFilename: String; | |||||
begin | |||||
result := fFilename; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderFile.GetFileReader: IengShaderFileReader; | |||||
begin | |||||
result := fFileReader; | |||||
if not Assigned(result) and Assigned(Parent) then | |||||
result := Parent.FileReader; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderFile.GetFileWriter: IengShaderFileWriter; | |||||
begin | |||||
result := fFileWriter; | |||||
if not Assigned(result) and Assigned(Parent) then | |||||
result := Parent.FileWriter; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengShaderFile.LoadCode(const aFilename: String; const aFileReader: IengShaderFileReader); | |||||
var | |||||
args: TengParseArgs; | |||||
token: String; | |||||
ms: TMemoryStream; | |||||
begin | |||||
fFileReader := aFileReader; | |||||
if not Assigned(fFileReader) then | |||||
fFileReader := GetFileReader; | |||||
if not Assigned(fFileReader) then | |||||
fFileReader := TengShaderFileReader.Create; | |||||
ms := TMemoryStream.Create; | |||||
try | |||||
Clear; | |||||
if not fFileReader.LoadStream(aFilename, ms) then | |||||
raise EengShaderPart.Create('unable to open file: ' + aFilename, Line, Col, Filename); | |||||
ms.Position := 0; | |||||
args := TengParseArgs.Create(ms, Filename); | |||||
try | |||||
token := ParseText(args); | |||||
if (token <> '') then with args do | |||||
raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename); | |||||
finally | |||||
FreeAndNil(args); | |||||
end; | |||||
finally | |||||
fFileReader := nil; | |||||
end; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,93 @@ | |||||
unit uengShaderFileConstants; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
const | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
PRECOMPILER_STATEMENT_BEGIN = '{'; | |||||
PRECOMPILER_STATEMENT_END = '}'; | |||||
TOKEN_CHAR_BEGIN = '{'; | |||||
TOKEN_CHAR_END = '}'; | |||||
TOKEN_CHAR_QUOTE = ''''; | |||||
TOKEN_CHAR_IDENT = '$'; | |||||
TOKEN_CHAR_COMMENT = '.'; | |||||
TOKEN_CHAR_COMMANT_END = ';'; | |||||
TOKEN_CHAR_SCOPE_BEGIN = '{'; | |||||
TOKEN_CHAR_SCOPE_END = '}'; | |||||
UNKNOWN_FILENAME = 'unknown file'; | |||||
TOKEN_LINE_BREAK = sLineBreak; | |||||
TOKEN_NONE = '[none]'; | |||||
TOKEN_CLASS = TOKEN_CHAR_IDENT + 'CLASS'; //{$CLASS PhongLight $EXTENDS Normal Glow} | |||||
TOKEN_EXTENDS = TOKEN_CHAR_IDENT + 'EXTENDS'; | |||||
TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED} {$INHERITED BaseClass} | |||||
TOKEN_INCLUDE = TOKEN_CHAR_IDENT + 'INCLUDE'; //{$INCLUDE 'Normal.frag'} | |||||
TOKEN_META = TOKEN_CHAR_IDENT + 'META'; //{$META 'Fuu' 'Bar'} | |||||
TOKEN_VERSION = TOKEN_CHAR_IDENT + 'VERSION'; //{$META $VERSION 'version'} | |||||
TOKEN_EXTENSION = TOKEN_CHAR_IDENT + 'EXTENSION'; //{$META $EXTENSION 'GL_ARB_geometry_shader4' 'enable'} | |||||
TOKEN_LAYOUT = TOKEN_CHAR_IDENT + 'LAYOUT'; //{$META $LAYOUT '(line_strip, max_vertices = 6) out'} | |||||
TOKEN_PROPERTY = TOKEN_CHAR_IDENT + 'PROPERTY'; //{$PROPERTY InvertRoughmap 'false'} | |||||
TOKEN_DEFINE = TOKEN_CHAR_IDENT + 'DEFINE'; //{$DEFINE RENDER_FACE_FRONT '0'} | |||||
TOKEN_ECHO = TOKEN_CHAR_IDENT + 'ECHO'; //{$ECHO InvertRoughmap} | |||||
TOKEN_VAR = TOKEN_CHAR_IDENT + 'VAR'; //{$VAR 'float' 'refractivity' '0.0'} | |||||
TOKEN_VARYING = TOKEN_CHAR_IDENT + 'VARYING'; //{$VARYING 'vec3' 'vVertex'} | |||||
TOKEN_UNIFORM = TOKEN_CHAR_IDENT + 'UNIFORM'; //{$UNIFORM 'sampler2D' 'uShadowMap'} | |||||
TOKEN_CALL = TOKEN_CHAR_IDENT + 'CALL'; //{$CALL CalcLight} | |||||
TOKEN_PROC = TOKEN_CHAR_IDENT + 'PROC'; //{$PROC CalcLight} Code... {$END} | |||||
TOKEN_FUNC = TOKEN_CHAR_IDENT + 'FUNC'; //{$FUND 'float' 'ShadowPoisson' 'vec2' 'shadowMapST' 'float' 'receiver'} Code... {$END} | |||||
TOKEN_MAIN = TOKEN_CHAR_IDENT + 'MAIN'; | |||||
TOKEN_INLINE = TOKEN_CHAR_IDENT + 'INLINE'; //{$PROC CalcLight $INLINE} Code... {$END} | |||||
TOKEN_IF = TOKEN_CHAR_IDENT + 'IF'; //{$IF PhongLight = '0'} Code ... {$END} | |||||
TOKEN_ELIF = TOKEN_CHAR_IDENT + 'ELIF'; | |||||
TOKEN_ELSE = TOKEN_CHAR_IDENT + 'ELSE'; | |||||
TOKEN_END = TOKEN_CHAR_IDENT + 'END'; | |||||
TOKEN_MESSAGE = TOKEN_CHAR_IDENT + 'MESSAGE'; //{$MESSAGE 'message'} | |||||
TOKEN_WARNING = TOKEN_CHAR_IDENT + 'WARNING'; //{$WARNING 'message'} | |||||
TOKEN_ERROR = TOKEN_CHAR_IDENT + 'ERROR'; //{$ERROR 'message'} | |||||
TOKEN_OP_LOGICAL_NOT = TOKEN_CHAR_IDENT + 'NOT'; //{$IF $NOT test} | |||||
TOKEN_OP_LOGICAL_OR = TOKEN_CHAR_IDENT + 'OR'; //{$IF test1 $OR test2} | |||||
TOKEN_OP_LOGICAL_AND = TOKEN_CHAR_IDENT + 'AND'; //{$IF test1 $AND test2} | |||||
TOKEN_OP_LOGICAL_XOR = TOKEN_CHAR_IDENT + 'XOR'; //{$IF test1 $XOR test2} | |||||
TOKEN_OP_DEFINED = TOKEN_CHAR_IDENT + 'DEFINED'; //{$IF $DEFINED test2} | |||||
TOKEN_OP_SET = TOKEN_CHAR_IDENT + 'SET'; //{$IF $SET vVertex} | |||||
TOKEN_OP_ADD = '+'; //{$IF test1 + test2} | |||||
TOKEN_OP_SUBTRACT = '-'; //{$IF test1 - test2} | |||||
TOKEN_OP_MULTIPLY = '*'; //{$IF test1 * test2} | |||||
TOKEN_OP_DIVIDE = '/'; //{$IF test1 / test2} | |||||
TOKEN_OP_EQUALS = '='; //{$IF test1 = test2} | |||||
TOKEN_OP_LESSER = '<'; //{$IF test1 < test2} | |||||
TOKEN_OP_GREATER = '>'; //{$IF test1 > test2} | |||||
TOKEN_OP_LEQUALS = '<='; //{$IF test1 <= test2} | |||||
TOKEN_OP_GEQUALS = '>='; //{$IF test1 >= test2} | |||||
TOKEN_OP_UNEQUALS = '<>'; //{$IF test1 <> test2} | |||||
TOKEN_OP_BINARY_OR = '|'; //{$IF test1 | test2} | |||||
TOKEN_OP_BINARY_AND = '&'; //{$IF test1 & test2} | |||||
TOKEN_OP_BINARY_XOR = '^'; //{$IF test1 ^ test2} | |||||
TOKEN_OP_BINARY_NOT = '!'; //{$IF !test1} | |||||
TOKEN_OP_GROUP_BEGIN = '('; //{$IF (test1 $OR test2) >= '0'} | |||||
TOKEN_OP_GROUP_END = ')'; | |||||
VALID_IDENT_CHARS = ['A'..'Z', 'a'..'z', '0'..'9', '_']; | |||||
VALID_TOKEN_CHARS = ['$'] + VALID_IDENT_CHARS; | |||||
TOKEN_SPLIT_CHARS = [' ', #9, TOKEN_OP_GROUP_BEGIN, TOKEN_OP_GROUP_END]; | |||||
COMMAND_END_TOKENS = [TOKEN_CHAR_COMMANT_END, TOKEN_CHAR_SCOPE_BEGIN, TOKEN_CHAR_SCOPE_END]; | |||||
VERSION_EXTRA_COMPAT = 'compatibility'; //{$META $VERSION 'compatibility'} | |||||
implementation | |||||
end. | |||||
@@ -0,0 +1,630 @@ | |||||
unit uengShaderFileExpression; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, variants, | |||||
uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionItem = class(TObject) | |||||
private | |||||
fLine: Integer; | |||||
fCol: Integer; | |||||
fFilename: String; | |||||
public | |||||
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); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionValue = class(TengExpressionItem) | |||||
private | |||||
fValue: Variant; | |||||
public | |||||
function GetText: String; override; | |||||
function GetValue: Variant; override; | |||||
constructor Create(const aValue: Variant; const aLine, aCol: Integer; const aFilename: String); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionVariable = class(TengExpressionItem) | |||||
private | |||||
fName: String; | |||||
public | |||||
function GetText: String; override; | |||||
function GetValue: Variant; override; | |||||
constructor Create(const aName: String; const aLine, aCol: Integer; const aFilename: String); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionGroup = class(TengExpressionItem) | |||||
private | |||||
fChild: TengExpressionItem; | |||||
public | |||||
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); | |||||
destructor Destroy; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionUnaryOperator = ( | |||||
opBinaryNot, | |||||
opLogicalNot, | |||||
opDefined, | |||||
opSet | |||||
); | |||||
TengExpressionUnaryOperation = class(TengExpressionItem) | |||||
private | |||||
fChild: TengExpressionItem; | |||||
fUnaryOp: TengExpressionUnaryOperator; | |||||
public | |||||
property Child: TengExpressionItem read fChild write fChild; | |||||
property UnaryOp: TengExpressionUnaryOperator read fUnaryOp; | |||||
function GetText: String; override; | |||||
function GetValue: Variant; override; | |||||
constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aLine, aCol: Integer; const aFilename: String); | |||||
destructor Destroy; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengExpressionBinaryOperator = ( //order of elements in this enum is also the weight of the operators | |||||
opBinaryOr, opBinaryAnd, opBinaryXor, // binary | |||||
opMultiply, opDivide, opAdd, opSubtract, // arithmetic | |||||
opLogicalOr, opLogicalAnd, opLogicalXor, // logical | |||||
opEquals, opLesser, opGreater, opLEquals, opGEquals, opUnequals // comparison | |||||
); | |||||
TengExpressionBinaryOperation = class(TengExpressionItem) | |||||
private | |||||
fFirst: TengExpressionItem; | |||||
fSecond: TengExpressionItem; | |||||
fBinaryOp: TengExpressionBinaryOperator; | |||||
public | |||||
property First: TengExpressionItem read fFirst write fFirst; | |||||
property Second: TengExpressionItem read fSecond write fSecond; | |||||
property BinaryOp: TengExpressionBinaryOperator read fBinaryOp; | |||||
function GetText: String; override; | |||||
function GetValue: Variant; override; | |||||
constructor Create(const aOperator: TengExpressionBinaryOperator; const aLine, aCol: Integer; const aFilename: String); | |||||
destructor Destroy; override; | |||||
end; | |||||
function ParseExpression(const aParam: TengTokenParameterList; aIndex: Integer): TengExpressionItem; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
, uutlGenerics | |||||
{$ELSE} | |||||
, fgl | |||||
{$ENDIF} | |||||
; | |||||
const | |||||
EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = ( | |||||
TOKEN_OP_BINARY_NOT, //opBinaryNot | |||||
TOKEN_OP_LOGICAL_NOT, //opLogicalNot | |||||
TOKEN_OP_DEFINED, //opDefined | |||||
TOKEN_OP_SET //opSet | |||||
); | |||||
EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = ( | |||||
TOKEN_OP_BINARY_OR, //opBinaryOr | |||||
TOKEN_OP_BINARY_AND, //opBinaryAnd | |||||
TOKEN_OP_BINARY_XOR, //opBinaryXor | |||||
TOKEN_OP_MULTIPLY, //opMultiply | |||||
TOKEN_OP_DIVIDE, //opDivide | |||||
TOKEN_OP_ADD, //opAdd | |||||
TOKEN_OP_SUBTRACT, //opSubtract | |||||
TOKEN_OP_LOGICAL_OR, //opLogicalOr | |||||
TOKEN_OP_LOGICAL_AND, //opLogicalAnd | |||||
TOKEN_OP_LOGICAL_XOR, //opLogicalXor | |||||
TOKEN_OP_EQUALS, //opEquals | |||||
TOKEN_OP_LESSER, //opLesser | |||||
TOKEN_OP_GREATER, //opGreater | |||||
TOKEN_OP_LEQUALS, //opLEquals | |||||
TOKEN_OP_GEQUALS, //opGEquals | |||||
TOKEN_OP_UNEQUALS //opUnequals, | |||||
); | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengExpressionItem//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionItem.GetText: String; | |||||
begin | |||||
result := ''; // DUMMY | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionItem.GetValue: Variant; | |||||
begin | |||||
result := Unassigned; // DUMMY | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionItem.Create(const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create; | |||||
fLine := aLine; | |||||
fCol := aCol; | |||||
fFilename := aFilename; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengExpressionValue/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionValue.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_QUOTE + fValue + TOKEN_CHAR_QUOTE; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionValue.GetValue: Variant; | |||||
begin | |||||
result := fValue; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionValue.Create(const aValue: Variant; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(aLine, aCol, aFilename); | |||||
fValue := aValue; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengExpressionVariable//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionVariable.GetText: String; | |||||
begin | |||||
result := fName; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionVariable.GetValue: Variant; | |||||
begin | |||||
result := Unassigned; // TODO | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionVariable.Create(const aName: String; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(aLine, aCol, aFilename); | |||||
fName := aName; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
///TengExpressionGroup////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionGroup.GetText: String; | |||||
begin | |||||
if Assigned(fChild) | |||||
then result := TOKEN_OP_GROUP_BEGIN + fChild.GetText + TOKEN_OP_GROUP_END | |||||
else result := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionGroup.GetValue: Variant; | |||||
begin | |||||
if Assigned(fChild) | |||||
then result := fChild.GetValue | |||||
else result := Unassigned; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionGroup.Create(const aChild: TengExpressionItem; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(aLine, aCol, aFilename); | |||||
fChild := aChild; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengExpressionGroup.Destroy; | |||||
begin | |||||
FreeAndNil(fChild); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengExpressionUnaryOperation////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionUnaryOperation.GetText: String; | |||||
begin | |||||
if not Assigned(fChild) then | |||||
EengExpression.Create('no child assigned', Line, Col, Filename); | |||||
result := | |||||
{$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF} | |||||
EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText | |||||
{$IFDEF EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF}; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionUnaryOperation.GetValue: Variant; | |||||
var | |||||
v: Variant; | |||||
begin | |||||
if not Assigned(fChild) then | |||||
raise EengExpression.Create('no child assigned', Line, Col, Filename); | |||||
try | |||||
case fUnaryOp of | |||||
opBinaryNot: begin | |||||
v := fChild.GetValue; | |||||
result := not Integer(v); | |||||
end; | |||||
opLogicalNot: begin | |||||
v := fChild.GetValue; | |||||
result := not Boolean(v); | |||||
end; | |||||
opDefined: begin | |||||
// TODO | |||||
end; | |||||
opSet: begin | |||||
// TODO | |||||
end; | |||||
else | |||||
result := inherited GetValue; | |||||
end; | |||||
except | |||||
on ex: Exception do | |||||
raise EengInvalidParamter.Create( | |||||
ex.Message + '("' + GetText + '" ==> ' + | |||||
EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + v + '")', | |||||
Line, Col, Filename); | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(aLine, aCol, aFilename); | |||||
fChild := nil; | |||||
fUnaryOp := aUnaryOp; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengExpressionUnaryOperation.Destroy; | |||||
begin | |||||
FreeAndNil(fChild); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengExpressionBinaryOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionBinaryOperation.GetText: String; | |||||
begin | |||||
if not Assigned(fFirst) or not Assigned(fSecond) then | |||||
raise EengExpression.Create('first or second item not assigned'); | |||||
result := | |||||
{$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF} | |||||
fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText | |||||
{$IFDEF EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF}; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengExpressionBinaryOperation.GetValue: Variant; | |||||
var | |||||
v1: Variant; | |||||
v2: Variant; | |||||
begin | |||||
if not Assigned(fFirst) or not Assigned(fSecond) then | |||||
raise EengExpression.Create('first or second item not assigned'); | |||||
v1 := fFirst.GetValue; | |||||
v2 := fSecond.GetValue; | |||||
try | |||||
case fBinaryOp of | |||||
opBinaryOr: result := (Integer(v1) or Integer(v2)); | |||||
opBinaryAnd: result := (Integer(v1) and Integer(v2)); | |||||
opBinaryXor: result := (Integer(v1) xor Integer(v2)); | |||||
opMultiply: result := (v1 * v2); | |||||
opDivide: result := (v1 / v2); | |||||
opAdd: result := (v1 + v2); | |||||
opSubtract: result := (v1 - v2); | |||||
opLogicalOr: result := (Boolean(v1) or Boolean(v2)); | |||||
opLogicalAnd: result := (Boolean(v1) and Boolean(v2)); | |||||
opLogicalXor: result := (Boolean(v1) xor Boolean(v2)); | |||||
opEquals: result := (v1 = v2); | |||||
opLesser: result := (v1 < v2); | |||||
opGreater: result := (v1 > v2); | |||||
opLEquals: result := (v1 <= v2); | |||||
opGEquals: result := (v1 >= v2); | |||||
opUnequals: result := (v1 <> v2); | |||||
else | |||||
result := inherited GetValue; | |||||
end; | |||||
except | |||||
on ex: Exception do | |||||
raise EengInvalidParamter.Create( | |||||
ex.Message + ' ("' + GetText + '" ==> "' + v1 + ' ' + | |||||
EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + v2 + '")', | |||||
fLine, fCol, fFilename); | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(aLine, aCol, aFilename); | |||||
fBinaryOp := aOperator; | |||||
fFirst := nil; | |||||
fSecond := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengExpressionBinaryOperation.Destroy; | |||||
begin | |||||
FreeAndNil(fFirst); | |||||
FreeAndNil(fSecond); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
type | |||||
TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation); | |||||
TExpectedParams = set of TExpectedParam; | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
TExpressionItemStack = specialize TutlSimpleList<TengExpressionItem>; | |||||
{$ELSE} | |||||
TExpressionItemStack = class(specialize TFPList<TengExpressionItem>) | |||||
public | |||||
end; | |||||
{$ENDIF} | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function ParseExpression(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); | |||||
end; | |||||
function NextParam: Boolean; | |||||
begin | |||||
inc(aIndex); | |||||
result := (aIndex < aParam.Count); | |||||
if result then | |||||
p := aParam[aIndex]; | |||||
end; | |||||
function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean; | |||||
begin | |||||
result := true; | |||||
for aOperator in TengExpressionUnaryOperator do | |||||
if (aParam = EXPRESSION_UNARY_OPERATIONS[aOperator]) then | |||||
exit; | |||||
result := false; | |||||
end; | |||||
function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean; | |||||
begin | |||||
result := true; | |||||
for aOperator in TengExpressionBinaryOperator do | |||||
if (aParam = EXPRESSION_BINARY_OPERATIONS[aOperator]) then | |||||
exit; | |||||
result := false; | |||||
end; | |||||
procedure MergeItems(const aStack: TExpressionItemStack; var aNew: TengExpressionItem); | |||||
var | |||||
item: TengExpressionItem; | |||||
begin | |||||
try | |||||
if (aStack.Count = 0) then begin | |||||
aStack.PushLast(aNew); | |||||
aNew := nil; | |||||
exit; | |||||
end; | |||||
item := aStack.Last; | |||||
if (item is TengExpressionBinaryOperation) then begin | |||||
if (aNew is TengExpressionBinaryOperation) then begin | |||||
//both are binary operators, new is weaker then existing | |||||
if ((aNew as TengExpressionBinaryOperation).BinaryOp < | |||||
(item as TengExpressionBinaryOperation).BinaryOp) then | |||||
begin | |||||
(aNew as TengExpressionBinaryOperation).First := item; | |||||
aStack.PopLast; | |||||
aStack.PushLast(aNew); | |||||
aNew := nil; | |||||
//both are binary operators, new is stronger than existing | |||||
end else begin | |||||
if not Assigned((item as TengExpressionBinaryOperation).Second) then | |||||
RaiseEx('inconsistent state'); | |||||
(aNew as TengExpressionBinaryOperation).First := (item as TengExpressionBinaryOperation).Second; | |||||
(item as TengExpressionBinaryOperation).Second := aNew; | |||||
aStack.PushLast(aNew); | |||||
aNew := nil; | |||||
end; | |||||
//existing is binary operator, new is normal | |||||
end else begin | |||||
if Assigned((item as TengExpressionBinaryOperation).Second) then | |||||
RaiseEx('inconsistent state'); | |||||
(item as TengExpressionBinaryOperation).Second := aNew; | |||||
aNew := nil; | |||||
while (aStack.Count > 1) do | |||||
aStack.PopLast; //remove all but first | |||||
end; | |||||
end else begin | |||||
//existing is normal item, new is binary operation | |||||
if (aNew is TengExpressionBinaryOperation) then begin | |||||
aStack.PopLast; | |||||
(aNew as TengExpressionBinaryOperation).First := item; | |||||
aStack.PushLast(aNew); | |||||
aNew := nil; | |||||
//existing is unary operation, new is normal item or unary operation | |||||
end else if (item is TengExpressionUnaryOperation) then begin | |||||
if Assigned((item as TengExpressionUnaryOperation).Child) then | |||||
RaiseEx('inconsistent state'); | |||||
(item as TengExpressionUnaryOperation).Child := aNew; | |||||
if not (aNew is TengExpressionUnaryOperation) then begin | |||||
while (aStack.Count > 1) do | |||||
aStack.PopLast; //remove all but first | |||||
end else | |||||
aStack.PushLast(aNew); | |||||
aNew := nil; | |||||
//existing and new are both normal items | |||||
end else | |||||
RaiseEx('inconsistent state'); | |||||
end; | |||||
except | |||||
FreeAndNil(aNew); | |||||
raise; | |||||
end; | |||||
end; | |||||
function BuildTree(const aDepth: Integer = 0): TengExpressionItem; | |||||
var | |||||
uOp: TengExpressionUnaryOperator; | |||||
bOp: TengExpressionBinaryOperator; | |||||
expected: TExpectedParams; | |||||
stack: TExpressionItemStack; | |||||
l, c: Integer; | |||||
ei, tmp: TengExpressionItem; | |||||
begin | |||||
expected := [exVariable, exValue, exGroupBegin, exUnaryOperation]; | |||||
result := nil; | |||||
stack := TExpressionItemStack.Create(false); | |||||
try try | |||||
repeat | |||||
// GroupBegin | |||||
if (p.Name = TOKEN_OP_GROUP_BEGIN) then begin | |||||
if not (exGroupBegin in expected) then | |||||
RaiseEx('unexpected ''' + p.Name + ''''); | |||||
l := p.Line; | |||||
c := p.Col; | |||||
if not NextParam then | |||||
RaiseEx('unexpected end'); | |||||
tmp := BuildTree(aDepth + 1); | |||||
ei := TengExpressionGroup.Create(tmp, l, c, aParam.Filename); | |||||
try | |||||
MergeItems(stack, ei); | |||||
if (p.Name <> TOKEN_OP_GROUP_END) then | |||||
RaiseEx('missing ''' + TOKEN_OP_GROUP_END + ''''); | |||||
expected := [exBinaryOperation, exGroupEnd]; | |||||
except | |||||
FreeAndNil(ei); | |||||
raise; | |||||
end; | |||||
// GroupEnd | |||||
end else if (p.Name = TOKEN_OP_GROUP_END) then begin | |||||
if not (exGroupEnd in expected) or (aDepth = 0) then | |||||
RaiseEx('unexpected ''' + TOKEN_OP_GROUP_END + ''''); | |||||
exit; | |||||
// UnaryOperation | |||||
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); | |||||
try | |||||
MergeItems(stack, ei); | |||||
expected := [exVariable]; | |||||
if (uOp <> opDefined) then | |||||
expected := expected + [exValue, exGroupBegin, exUnaryOperation] | |||||
except | |||||
FreeAndNil(ei); | |||||
raise; | |||||
end; | |||||
// BinaryOperation | |||||
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); | |||||
try | |||||
MergeItems(stack, ei); | |||||
expected := [exVariable, exValue, exGroupBegin, exUnaryOperation]; | |||||
except | |||||
FreeAndNil(ei); | |||||
raise; | |||||
end; | |||||
// Value | |||||
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); | |||||
try | |||||
MergeItems(stack, ei); | |||||
expected := [exGroupEnd, exBinaryOperation]; | |||||
except | |||||
FreeAndNil(ei); | |||||
raise; | |||||
end; | |||||
// Variable | |||||
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); | |||||
try | |||||
MergeItems(stack, ei); | |||||
expected := [exGroupEnd, exBinaryOperation]; | |||||
except | |||||
FreeAndNil(ei); | |||||
raise | |||||
end; | |||||
// Unknown | |||||
end else | |||||
RaiseEx('invalid parameter: ' + p.Name); | |||||
until not NextParam; | |||||
except | |||||
if (stack.Count > 0) then begin | |||||
stack[0].Free; | |||||
stack[0] := nil; | |||||
end; | |||||
raise; | |||||
end; | |||||
finally | |||||
if (stack.Count > 0) then | |||||
result := stack[0]; | |||||
FreeAndNil(stack); | |||||
end; | |||||
end; | |||||
begin | |||||
dec(aIndex); | |||||
if not NextParam then with aParam[0] do | |||||
raise EengShaderPartInternal.Create('invalid parameter count in expression', Line, Col, aParam.Filename); | |||||
result := BuildTree; | |||||
end; | |||||
end. |
@@ -0,0 +1,56 @@ | |||||
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; | |||||
implementation | |||||
uses | |||||
sysutils, | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
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(param) then | |||||
raise EengUnexpectedToken.Create(TOKEN_NONE, TOKEN_END, oldLine, oldCol, aShaderPart.Filename); | |||||
if (param[0].Name <> TOKEN_END) then | |||||
raise EengUnexpectedToken.Create(param[0].Name, TOKEN_END, oldLine, oldCol, aShaderPart.Filename); | |||||
if (param.Count <> 1) then | |||||
raise EengInvalidParamterCount.Create(TOKEN_END, 1, oldLine, oldCol, aShaderPart.Filename); | |||||
result := ''; | |||||
finally | |||||
FreeAndNil(param); | |||||
end; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,333 @@ | |||||
unit uengShaderFileParser; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
, uutlGenerics | |||||
{$ELSE} | |||||
, fgl | |||||
{$ENDIF} | |||||
; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengTokenParameter = packed record | |||||
Name: String; | |||||
Quoted: Boolean; | |||||
Line: Integer; | |||||
Col: Integer; | |||||
end; | |||||
TengTokenParameterList = class(specialize TutlSimpleList<TengTokenParameter>) | |||||
private | |||||
fFilename: String; | |||||
public | |||||
property Filename: String read fFilename; | |||||
constructor Create(const aFilename: String); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengParseArgs = class | |||||
private | |||||
fFilename: String; | |||||
fCode: TStringList; | |||||
fLineLength: Integer; | |||||
fLineCount: Integer; | |||||
fCurrentLine: String; | |||||
fCurrentChar: Char; | |||||
fCol: Integer; | |||||
fLine: Integer; | |||||
procedure SetCol(const aValue: Integer); | |||||
procedure SetLine(const aValue: Integer); | |||||
function GetEndOfLine: Boolean; | |||||
function GetEndOfFile: Boolean; | |||||
function GetCode: TStrings; | |||||
public | |||||
property Code: TStrings read GetCode; | |||||
property LineLength: Integer read fLineLength; | |||||
property LineCount: Integer read fLineCount; | |||||
property CurrentLine: String read fCurrentLine; | |||||
property CurrentChar: Char read fCurrentChar; | |||||
property EndOfLine: Boolean read GetEndOfLine; | |||||
property EndOfFile: Boolean read GetEndOfFile; | |||||
property Filename: String read fFilename; | |||||
property Col: Integer read fCol write SetCol; | |||||
property Line: Integer read fLine write SetLine; | |||||
procedure NextCol; | |||||
procedure NextLine; | |||||
function ExtractToken(const aParameters: TengTokenParameterList): Boolean; | |||||
function GetTokenPreview(var aToken: String): Boolean; | |||||
constructor Create(const aStream: TStream; const aFilename: String); | |||||
destructor Destroy; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengTokenParameterList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengTokenParameterList.Create(const aFilename: String); | |||||
begin | |||||
inherited Create(true); | |||||
fFilename := aFilename; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengParseArgs///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengParseArgs.SetCol(const aValue: Integer); | |||||
begin | |||||
fCol := aValue; | |||||
if not EndOfLine | |||||
then fCurrentChar := fCurrentLine[fCol] | |||||
else fCurrentChar := #0; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengParseArgs.SetLine(const aValue: Integer); | |||||
begin | |||||
fLine := aValue; | |||||
if not EndOfFile then begin | |||||
fCurrentLine := fCode[fLine]; | |||||
fLineLength := Length(fCurrentLine); | |||||
end else begin | |||||
fCurrentLine := ''; | |||||
fLineLength := 0; | |||||
end; | |||||
Col := 1; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengParseArgs.GetEndOfLine: Boolean; | |||||
begin | |||||
result := (fCol > fLineLength) | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengParseArgs.GetEndOfFile: Boolean; | |||||
begin | |||||
result := (fLine >= fLineCount); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengParseArgs.NextCol; | |||||
begin | |||||
Col := Col + 1; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengParseArgs.NextLine; | |||||
begin | |||||
Line := Line + 1; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengParseArgs.ExtractToken(const aParameters: TengTokenParameterList): Boolean; | |||||
type | |||||
TCharType = ( | |||||
ctUnknown, | |||||
ctValidTokenChar, | |||||
ctInvalidTokenChar | |||||
); | |||||
TParseFlag = ( | |||||
pfQuote, | |||||
pfInToken, | |||||
pfIsComment, | |||||
pfCommentTokenAdded | |||||
); | |||||
TParseFlags = set of TParseFlag; | |||||
var | |||||
flags: TParseFlags; | |||||
ct: TCharType; | |||||
s: String; | |||||
pLine, pCol, oldLine, oldCol: Integer; | |||||
procedure AddPart(const aTrimAndCheck: Boolean = true); | |||||
var | |||||
len: Integer; | |||||
p: TengTokenParameter; | |||||
begin | |||||
if aTrimAndCheck then | |||||
s := Trim(s); | |||||
if not aTrimAndCheck or (s <> '') then begin | |||||
len := Length(s); | |||||
if aTrimAndCheck and | |||||
( (s[1] = TOKEN_CHAR_QUOTE) and | |||||
(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); | |||||
if not (s[len] = TOKEN_CHAR_QUOTE) then | |||||
raise EengShaderPart.Create('missing trailing quote char', Line, Col, Filename); | |||||
delete(s, len, 1); | |||||
delete(s, 1, 1); | |||||
p.Quoted := true; | |||||
end else | |||||
p.Quoted := false; | |||||
p.Name := s; | |||||
p.Line := pLine; | |||||
p.Col := pCol; | |||||
aParameters.Add(p); | |||||
end; | |||||
s := ''; | |||||
pLine := Line; | |||||
pCol := Col; | |||||
ct := ctUnknown; | |||||
end; | |||||
begin | |||||
result := false; | |||||
aParameters.Clear; | |||||
if (CurrentChar <> TOKEN_CHAR_BEGIN) or | |||||
(Col + 1 > LineLength) or | |||||
( (CurrentLine[Col+1] <> TOKEN_CHAR_IDENT) and | |||||
(CurrentLine[Col+1] <> TOKEN_CHAR_COMMENT)) | |||||
then | |||||
exit; | |||||
result := true; | |||||
s := ''; | |||||
ct := ctUnknown; | |||||
oldLine := Line; | |||||
oldCol := Col; | |||||
flags := []; | |||||
if (CurrentLine[Col+1] = TOKEN_CHAR_COMMENT) then | |||||
Include(flags, pfIsComment); | |||||
AddPart; // initialize | |||||
while not EndOfFile do begin | |||||
while not EndOfLine do begin | |||||
case CurrentChar of | |||||
TOKEN_CHAR_BEGIN: begin | |||||
if (pfQuote in flags) then | |||||
s := s + CurrentChar | |||||
else if not (pfInToken in flags) then | |||||
Include(flags, pfInToken) | |||||
else | |||||
EengShaderPart.Create('invalid char in token', Line, Col, Filename); | |||||
end; | |||||
TOKEN_CHAR_END: begin | |||||
if not (pfQuote in flags) then begin | |||||
AddPart(not (pfIsComment in flags)); | |||||
NextCol; | |||||
if (aParameters.Count <= 0) or (aParameters[0].Name = TOKEN_CHAR_IDENT) then | |||||
raise EengShaderPart.Create('empty token', Line, Col, Filename); | |||||
exit; | |||||
end else | |||||
s := s + CurrentChar; | |||||
end; | |||||
TOKEN_CHAR_QUOTE: begin | |||||
if not (pfQuote in flags) and not (pfIsComment in flags) then | |||||
AddPart; | |||||
s := s + CurrentChar; | |||||
if (pfQuote in flags) | |||||
then exclude(flags, pfQuote) | |||||
else include(flags, pfQuote); | |||||
if not (pfQuote in flags) and not (pfIsComment in flags) then | |||||
AddPart; | |||||
end; | |||||
TOKEN_CHAR_COMMENT: begin | |||||
s := s + CurrentChar; | |||||
if (pfIsComment in flags) and not (pfCommentTokenAdded in flags) then begin | |||||
include(flags, pfCommentTokenAdded); | |||||
AddPart(false); | |||||
end; | |||||
end; | |||||
else | |||||
if not (pfQuote in flags) and not (pfIsComment in flags) then begin | |||||
if (CurrentChar in TOKEN_SPLIT_CHARS) then begin | |||||
AddPart; | |||||
end else if (CurrentChar in VALID_TOKEN_CHARS) then begin | |||||
if (ct <> ctValidTokenChar) then | |||||
AddPart; | |||||
ct := ctValidTokenChar; | |||||
end else begin | |||||
if (ct <> ctInvalidTokenChar) then | |||||
AddPart; | |||||
ct := ctInvalidTokenChar; | |||||
end; | |||||
end; | |||||
s := s + CurrentChar; | |||||
end; | |||||
NextCol; | |||||
end; | |||||
s := s + sLineBreak; | |||||
NextLine; | |||||
end; | |||||
raise EengShaderPart.Create('incomplete token', oldLine, oldCol, Filename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengParseArgs.GetCode: TStrings; | |||||
begin | |||||
result := fCode; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengParseArgs.GetTokenPreview(var aToken: String): Boolean; | |||||
var | |||||
c: Integer; | |||||
begin | |||||
result := false; | |||||
if (CurrentChar <> TOKEN_CHAR_BEGIN) or | |||||
(Col >= LineLength) or | |||||
not (CurrentLine[Col + 1] in [TOKEN_CHAR_IDENT, TOKEN_CHAR_COMMENT]) | |||||
then exit; | |||||
result := true; | |||||
aToken := CurrentChar; | |||||
if (aToken = TOKEN_CHAR_COMMANT_END) then | |||||
exit; | |||||
c := Col + 1; | |||||
case CurrentLine[c] of | |||||
TOKEN_CHAR_IDENT: begin | |||||
aToken := ''; | |||||
repeat | |||||
aToken := aToken + CurrentLine[c]; | |||||
inc(c); | |||||
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); | |||||
end; | |||||
TOKEN_CHAR_COMMENT: | |||||
aToken := TOKEN_CHAR_COMMENT; | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengParseArgs.Create(const aStream: TStream; const aFilename: String); | |||||
begin | |||||
inherited Create; | |||||
fFilename := aFilename; | |||||
fCode := TStringList.Create; | |||||
fCode.LoadFromStream(aStream); | |||||
fLineCount := fCode.Count; | |||||
Line := 0; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengParseArgs.Destroy; | |||||
begin | |||||
FreeAndNil(fCode); | |||||
inherited Destroy; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,23 @@ | |||||
unit uengShaderFileScope; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderFilePart; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderFileScope = class(TengShaderPart) | |||||
end; | |||||
implementation | |||||
end. | |||||
@@ -0,0 +1,148 @@ | |||||
unit uengShaderFileTypes; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
, uutlSerialization, uutlCommon | |||||
{$ENDIF} | |||||
; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
IengShaderFileWriter = uutlSerialization.IutlFileWriter; | |||||
IengShaderFileReader = uutlSerialization.IutlFileReader; | |||||
TengShaderFileReader = uutlSerialization.TutlSimpleFileReader; | |||||
TengShaderFileWriter = uutlSerialization.TutlSimpleFileWriter; | |||||
TIntfObjNoRefCount = uutlCommon.TutlInterfaceNoRefCount; | |||||
{$ENDIF} | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
EengShaderPart = class(Exception) | |||||
public | |||||
Line: Integer; | |||||
Col: Integer; | |||||
Filename: String; | |||||
constructor Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String); 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; | |||||
end; | |||||
EengUnexpectedToken = class(EengShaderPart) | |||||
constructor Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String); overload; | |||||
end; | |||||
EengInvalidParamter = class(EengShaderPart) | |||||
constructor Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String); 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; | |||||
end; | |||||
EengInvalidIdentifier = class(EengShaderPart) | |||||
constructor Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String); overload; | |||||
end; | |||||
EengOutOfRange = class(EengShaderPartInternal) | |||||
constructor Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String); overload; | |||||
end; | |||||
implementation | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengShaderPart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengShaderPart.Create(const aMsg: String; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(Format('%s (file: %s; line: %d; col: %d): %s', [ClassName, ExtractFileName(aFilename), aLine+1, aCol, aMsg])); | |||||
Line := aLine; | |||||
Col := aCol; | |||||
Filename := aFilename; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengInvalidToken////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengInvalidToken.Create(const aClassName: String; const aToken: String; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create('invalid token: ' + aClassName + ' <> '+ aToken, aLine, aCol, aFilename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengUnexpectedToken/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengUnexpectedToken.Create(const aToken, aExpected: String; const aLine, aCol: Integer; const aFilename: String); | |||||
var | |||||
s: String; | |||||
begin | |||||
s := 'unexpected token: ' + aToken; | |||||
if (aExpected <> '') then | |||||
s := s + '(expected ' + aExpected + ')'; | |||||
inherited Create(s, aLine, aCol, aFilename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengInvalidParamter/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengInvalidParamter.Create(const aParam, aExpected: String; const aLine, aCol: Integer; const aFilename: String); | |||||
var | |||||
s: String; | |||||
begin | |||||
s := 'invalid parameter: ' + aParam; | |||||
if (aExpected <> '') then | |||||
s := s + '(expected ' + aExpected + ')'; | |||||
inherited Create(s, aLine, aCol, aFilename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengInvalidParamterCount////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpected, aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create('invalid parameter count in ' + aToken + '(expected ' + IntToStr(aExpected) + ' parameter)', aLine, aCol, aFilename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengInvalidParamterCount.Create(const aToken: String; const aExpectedMin, aExpectedMax, aLine, aCol: Integer; const aFilename: String); | |||||
var | |||||
s: String; | |||||
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); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengInvalidIdentifier///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengInvalidIdentifier.Create(const aIdentifier: String; const aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create('invalid identifier: ' + aIdentifier, aLine, aCol, aFilename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//EengOutOfRange//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor EengOutOfRange.Create(const aMin, aMax, aIndex, aLine, aCol: Integer; const aFilename: String); | |||||
begin | |||||
inherited Create(format('index (%d) out of range (%d:%d)', [aIndex, aMin, aMax]), aLine, aCol, aFilename); | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,233 @@ | |||||
unit uengShaderPart; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderFileParser, uengShaderFileTypes | |||||
{$IFDEF USE_BITSPACE_UTILS} | |||||
, uutlGenerics; | |||||
{$ELSE} | |||||
, fgl; | |||||
{$ENDIF} | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
CengShaderPart = class of TengShaderPart; | |||||
TengShaderPart = class(TIntfObjNoRefCount) | |||||
{ Nested Types } | |||||
public type | |||||
TEnumerator = class(TObject) | |||||
private | |||||
fOwner: TengShaderPart; | |||||
fPosition: Integer; | |||||
function GetCurrent: TengShaderPart; | |||||
public | |||||
property Current: TengShaderPart read GetCurrent; | |||||
function MoveNext: Boolean; | |||||
constructor Create(const aOwner: TengShaderPart); | |||||
end; | |||||
{ Code Loading & Storage } | |||||
private { members } | |||||
fRoot: TengShaderPart; | |||||
fParent: TengShaderPart; | |||||
fLine: Integer; | |||||
fCol: Integer; | |||||
protected { virtual getter } | |||||
function GetCount: Integer; virtual; | |||||
function GetChild(const aIndex: Integer): TengShaderPart; virtual; | |||||
function GetText: String; virtual; | |||||
function GetFilename: String; virtual; | |||||
function GetFileReader: IengShaderFileReader; virtual; | |||||
function GetFileWriter: IengShaderFileWriter; virtual; | |||||
protected { parse methodes } | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual; | |||||
public | |||||
function ParseText(const aArgs: TengParseArgs): String; | |||||
{ General } | |||||
public { general methods } | |||||
property Root: TengShaderPart read fRoot; | |||||
property Parent: TengShaderPart read fParent; | |||||
property Line: Integer read fLine; | |||||
property Col: Integer read fCol; | |||||
property Filename: String read GetFilename; | |||||
property Text: String read GetText; | |||||
property Count: Integer read GetCount; | |||||
property FileReader: IengShaderFileReader read GetFileReader; | |||||
property FileWriter: IengShaderFileWriter read GetFileWriter; | |||||
property Children[const aIndex: Integer]: TengShaderPart read GetChild; default; | |||||
function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean; | |||||
function GetParent(const aType: CengShaderPart; out aPart): Boolean; | |||||
function GetEnumerator: TEnumerator; | |||||
constructor Create(const aParent: TengShaderPart); virtual; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; virtual; | |||||
class function CheckToken(const aToken: String): Boolean; virtual; | |||||
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual; | |||||
end; | |||||
TengShaderPartList = specialize TutlSimpleList<TengShaderPart>; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart; | |||||
begin | |||||
result := fOwner[fPosition]; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.TEnumerator.MoveNext: Boolean; | |||||
begin | |||||
inc(fPosition); | |||||
result := (fPosition < fOwner.Count); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart); | |||||
begin | |||||
inherited Create; | |||||
fOwner := aOwner; | |||||
fPosition := -1; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetCount: Integer; | |||||
begin | |||||
result := 0; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart; | |||||
begin | |||||
EengShaderPartInternal.Create('this part does not have any children'); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetText: String; | |||||
begin | |||||
result := ''; //DUMMY | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetFilename: String; | |||||
begin | |||||
if Assigned(fParent) | |||||
then result := fParent.Filename | |||||
else result := UNKNOWN_FILENAME; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetFileReader: IengShaderFileReader; | |||||
begin | |||||
if Assigned(fParent) | |||||
then result := fParent.GetFileReader | |||||
else result := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetFileWriter: IengShaderFileWriter; | |||||
begin | |||||
if Assigned(fParent) | |||||
then result := fParent.GetFileWriter | |||||
else result := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.ParseText(const aArgs: TengParseArgs): String; | |||||
var | |||||
params: TengTokenParameterList; | |||||
begin | |||||
params := TengTokenParameterList.Create(Filename); | |||||
try | |||||
fCol := aArgs.Col; | |||||
fLine := aArgs.Line; | |||||
if (GetTokenName <> '') then | |||||
aArgs.ExtractToken(params); | |||||
result := ParseIntern(aArgs, params); | |||||
finally | |||||
FreeAndNil(params); | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
begin | |||||
result := ''; // DUMMY | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean; | |||||
var | |||||
p: TengShaderPart; | |||||
begin | |||||
result := (aIncludeSelf and (self is aType)) or GetParent(aType, p); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean; | |||||
begin | |||||
result := true; | |||||
if (fParent is aType) then | |||||
TengShaderPart(aPart) := fParent | |||||
else if Assigned(fParent) then | |||||
result := fParent.GetParent(aType, aPart) | |||||
else | |||||
result := false; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPart.GetEnumerator: TEnumerator; | |||||
begin | |||||
result := TEnumerator.Create(self); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPart.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create; | |||||
fParent := aParent; | |||||
if Assigned(fParent) | |||||
then fRoot := fParent.Root | |||||
else fRoot := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPart.GetTokenName: String; | |||||
begin | |||||
result := ''; // DUMMY | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPart.CheckToken(const aToken: String): Boolean; | |||||
begin | |||||
result := (aToken = GetTokenName); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); | |||||
begin | |||||
// DUMMY | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,158 @@ | |||||
unit uengShaderPartCall; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartCall = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private { member } | |||||
fName: String; | |||||
fParameters: TStringList; | |||||
protected { virtual getter } | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
private | |||||
function GetParameters: TStrings; | |||||
public | |||||
property Name: String read fName; | |||||
property Parameters: TStrings read GetParameters; | |||||
constructor Create(const aParent: TengShaderPart); override; | |||||
destructor Destroy; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartInherited = class(TengShaderPartCall) | |||||
{ Class Methods } | |||||
protected | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
public | |||||
class function GetTokenName: String; override; | |||||
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartCall//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCall.GetText: String; | |||||
var | |||||
i: Integer; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName; | |||||
if (fName <> '') then | |||||
result := result + ' ' + fName; | |||||
for i := 0 to fParameters.Count-1 do begin | |||||
if (PtrInt(fParameters.Objects[i]) <> 0) | |||||
then result := result + ' ' + TOKEN_CHAR_QUOTE + fParameters[i] + TOKEN_CHAR_QUOTE | |||||
else result := result + ' ' + fParameters[i]; | |||||
end; | |||||
result := result + TOKEN_CHAR_END; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCall.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
var | |||||
i: Integer; | |||||
begin | |||||
if (aParams[0].Name <> GetTokenName) then | |||||
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename); | |||||
if (aParams.Count < 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename); | |||||
result := ''; | |||||
fParameters.Clear; | |||||
with aParams[1] do begin | |||||
if not IsValidIdentifier(fName) then | |||||
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename); | |||||
fName := Name; | |||||
end; | |||||
for i := 2 to aParams.Count-1 do | |||||
fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCall.GetParameters: TStrings; | |||||
begin | |||||
result := fParameters; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPartCall.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create(aParent); | |||||
fParameters := TStringList.Create; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartCall.Destroy; | |||||
begin | |||||
FreeAndNil(fParameters); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartCall.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_CALL; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartInherited/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartInherited.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
var | |||||
i: Integer; | |||||
begin | |||||
if (aParams[0].Name <> GetTokenName) then with aParams[0] do | |||||
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename); | |||||
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); | |||||
fName := aParams[1].Name; | |||||
for i := 2 to aParams.Count-1 do | |||||
fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); | |||||
end; | |||||
result := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartInherited.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_INHERITED; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class procedure TengShaderPartInherited.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); | |||||
begin | |||||
inherited Validate(aArgs, aParent); | |||||
if not aParent.HasParent(TengShaderPartProc, true) or | |||||
not aParent.HasParent(TengShaderPartClass, true) then | |||||
raise EengShaderPart.Create(GetTokenName + ' is not allowed outside of ' + | |||||
TOKEN_PROC + ', ' + TOKEN_FUNC + ', ' + TOKEN_MAIN + ' or ' + TOKEN_CLASS); | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,117 @@ | |||||
unit uengShaderPartClass; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartClass = class(TengShaderCodeGenerator) | |||||
{ Code Loading & Storage } | |||||
private { member } | |||||
fName: String; | |||||
fExtends: TStringList; | |||||
private { getter } | |||||
function GetExtends: TStrings; | |||||
protected { virtual getter } | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property Name: String read fName; | |||||
property Extends: TStrings read GetExtends; | |||||
constructor Create(const aParent: TengShaderPart); override; | |||||
destructor Destroy; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartClass.GetExtends: TStrings; | |||||
begin | |||||
result := fExtends; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartClass.GetText: String; | |||||
var | |||||
s: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName; | |||||
if (fExtends.Count > 0) then begin | |||||
result := result + ' ' + TOKEN_EXTENDS; | |||||
for s in fExtends do | |||||
result := result + ' ' + s; | |||||
end; | |||||
result := result + TOKEN_CHAR_END + | |||||
inherited GetText + | |||||
TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartClass.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
var | |||||
i: Integer; | |||||
begin | |||||
if (aParams[0].Name <> GetTokenName) then | |||||
raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename); | |||||
if (aParams.Count < 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename); | |||||
with aParams[1] do begin | |||||
if not IsValidIdentifier(Name) then | |||||
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename); | |||||
fName := Name; | |||||
end; | |||||
if (aParams.Count > 2) then begin | |||||
if (aParams.Count < 4) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 4, -1, Line, Col, Filename); | |||||
if (aParams[2].Name <> TOKEN_EXTENDS) then with aParams[2] do | |||||
raise EengInvalidParamter.Create(aParams[2].Name, TOKEN_EXTENDS, Line, Col, Filename); | |||||
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; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPartClass.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create(aParent); | |||||
fExtends := TStringList.Create; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartClass.Destroy; | |||||
begin | |||||
FreeAndNil(fExtends); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartClass.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_CLASS; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,159 @@ | |||||
unit uengShaderPartCntr; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartCntr = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fChildren: TengShaderPartList; | |||||
procedure AddChild(const aChild: TengShaderPart; const aPrepend: Boolean = false); | |||||
function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
protected { virtual getter } | |||||
function GetCount: Integer; override; | |||||
function GetChild(const aIndex: Integer): TengShaderPart; override; | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
public { general methods } | |||||
procedure Clear; | |||||
constructor Create(const aParent: TengShaderPart); override; | |||||
destructor Destroy; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderPartKeyValuePair, uengShaderPartClass, uengShaderPartMessage, uengShaderPartMeta, | |||||
uengShaderPartCall, uengShaderPartProc, uengShaderPartText, uengShaderPartEcho, uengShaderPartIf, | |||||
uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment; | |||||
const | |||||
TOKEN_CLASSES: array[0..20] of CengShaderPart = ( | |||||
TengShaderPartCall, | |||||
TengShaderPartClass, | |||||
TengShaderPartDefine, | |||||
TengShaderPartLineBreak, | |||||
TengShaderPartCommandEnd, | |||||
TengShaderPartComment, | |||||
TengShaderPartEcho, | |||||
TengShaderPartError, | |||||
TengShaderPartMain, | |||||
TengShaderPartIf, | |||||
TengShaderPartInclude, | |||||
TengShaderPartInherited, | |||||
TengShaderPartFunc, | |||||
TengShaderPartMessage, | |||||
TengShaderPartMeta, | |||||
TengShaderPartProc, | |||||
TengShaderPartProperty, | |||||
TengShaderPartUniform, | |||||
TengShaderPartVar, | |||||
TengShaderPartVarying, | |||||
TengShaderPartWarning | |||||
); | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartCntr//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengShaderPartCntr.AddChild(const aChild: TengShaderPart; const aPrepend: Boolean); | |||||
begin | |||||
if aPrepend | |||||
then fChildren.PushFirst(aChild) | |||||
else fChildren.PushLast(aChild); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCntr.HandleToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
var | |||||
p: TengShaderPart; | |||||
c: CengShaderPart; | |||||
begin | |||||
p := nil; | |||||
for c in TOKEN_CLASSES do begin | |||||
if c.CheckToken(aToken) then begin | |||||
c.Validate(aArgs, self); | |||||
p := c.Create(self); | |||||
AddChild(p); | |||||
break; | |||||
end; | |||||
end; | |||||
if Assigned(p) | |||||
then result := p.ParseText(aArgs) | |||||
else result := aToken; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCntr.GetCount: Integer; | |||||
begin | |||||
result := fChildren.Count; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCntr.GetChild(const aIndex: Integer): TengShaderPart; | |||||
begin | |||||
result := fChildren[aIndex]; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCntr.GetText: String; | |||||
var | |||||
p: TengShaderPart; | |||||
begin | |||||
result := ''; | |||||
for p in self do | |||||
result := result + p.Text; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCntr.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
var | |||||
TextObj: TengShaderPartText; | |||||
begin | |||||
result := ''; | |||||
fChildren.Clear; | |||||
while not aArgs.EndOfFile and (result = '') do begin | |||||
TextObj := TengShaderPartText.Create(self); | |||||
try | |||||
result := TextObj.ParseText(aArgs); | |||||
if not TextObj.IsEmpty | |||||
then AddChild(TextObj) | |||||
else FreeAndNil(TextObj); | |||||
except | |||||
FreeAndNil(TextObj); | |||||
raise; | |||||
end; | |||||
if (result <> '') then | |||||
result := HandleToken(result, aArgs); | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
procedure TengShaderPartCntr.Clear; | |||||
begin | |||||
fChildren.Clear; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPartCntr.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create(aParent); | |||||
fChildren := TengShaderPartList.Create(true); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartCntr.Destroy; | |||||
begin | |||||
FreeAndNil(fChildren); | |||||
inherited Destroy; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,55 @@ | |||||
unit uengShaderPartComment; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartComment = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fText: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartComment///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartComment.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + fText + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count > 1) then | |||||
fText := aParams[1].Name; | |||||
result := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartComment.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_CHAR_COMMENT; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,62 @@ | |||||
unit uengShaderPartEcho; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartEcho = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fName: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartEcho//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartEcho.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count <> 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, Line, Col, Filename); | |||||
result := ''; | |||||
with aParams[1] do begin | |||||
if not IsValidIdentifier(Name) then | |||||
raise EengInvalidIdentifier.Create(Name, Line, Col, Filename); | |||||
fName := Name; | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartEcho.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_ECHO; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,183 @@ | |||||
unit uengShaderPartIf; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderPartCntr, uengShaderFileExpression, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartIf = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fExpression: TengExpressionItem; | |||||
fIfPart: TengShaderPart; | |||||
fElsePart: TengShaderPart; | |||||
function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
protected | |||||
function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual; | |||||
function GetCount: Integer; override; | |||||
function GetChild(const aIndex: Integer): TengShaderPart; override; | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
destructor Destroy; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartElIf = class(TengShaderPartIf) | |||||
{ Code Loading & Storage } | |||||
protected | |||||
function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartElse = class(TengShaderPartCntr) | |||||
{ Code Loading & Storage } | |||||
protected | |||||
function GetText: String; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileTypes, uengShaderFileConstants, uengShaderFileHelper; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartIf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
const | |||||
TOKEN_CLASSES: array[0..1] of CengShaderPart = ( | |||||
TengShaderPartElse, | |||||
TengShaderPartElIf | |||||
); | |||||
var | |||||
c: CengShaderPart; | |||||
begin | |||||
for c in TOKEN_CLASSES do begin | |||||
if c.CheckToken(aToken) then begin | |||||
c.Validate(aArgs, self); | |||||
fElsePart := c.Create(self); | |||||
break; | |||||
end; | |||||
end; | |||||
if Assigned(fElsePart) then | |||||
result := fElsePart.ParseText(aArgs); | |||||
result := HandeEndToken(result, aArgs); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
begin | |||||
result := CheckEndToken(aArgs, self); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartIf.GetCount: Integer; | |||||
begin | |||||
result := 1; | |||||
if Assigned(fElsePart) then | |||||
inc(result, 1); | |||||
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); | |||||
case aIndex of | |||||
0: result := fIfPart; | |||||
1: result := fElsePart; | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartIf.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fExpression.GetText + TOKEN_CHAR_END + fIfPart.Text; | |||||
if Assigned(fElsePart) then | |||||
result := result + fElsePart.Text; | |||||
result := result + TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count < 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename); | |||||
fExpression := ParseExpression(aParams, 1); | |||||
fIfPart := TengShaderPartCntr.Create(self); | |||||
result := fIfPart.ParseText(aArgs); | |||||
result := HandleToken(result, aArgs); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartIf.Destroy; | |||||
begin | |||||
FreeAndNil(fExpression); | |||||
FreeAndNil(fIfPart); | |||||
FreeAndNil(fElsePart); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartIf.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_IF; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartElIf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartElIf.HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; | |||||
begin | |||||
result := aToken; | |||||
if (result <> TOKEN_END) then | |||||
raise EengInvalidToken.Create(ClassName, result, aArgs.Line, aArgs.Col, Filename); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartElIf.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_ELIF; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartElse//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartElse.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + TOKEN_CHAR_END + inherited GetText; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartElse.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_ELSE; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,100 @@ | |||||
unit uengShaderPartInclude; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFile, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartInclude = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fShaderFile: TengShaderFile; | |||||
fIncludeFile: String; | |||||
fAbsoluteFile: String; | |||||
protected | |||||
function GetCount: Integer; override; | |||||
function GetChild(const aIndex: Integer): TengShaderPart; override; | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property IncludeFile: String read fIncludeFile; | |||||
constructor Create(const aParent: TengShaderPart); override; | |||||
destructor Destroy; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
FileUtil, | |||||
uengShaderFileTypes, uengShaderFileConstants; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartInclude///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartInclude.GetCount: Integer; | |||||
begin | |||||
if Assigned(fShaderFile) | |||||
then result := 1 | |||||
else result := 0; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
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); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartInclude.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ''' + fIncludeFile + '''' + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count <> 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, Line, Col, Filename); | |||||
fIncludeFile := aParams[1].Name; | |||||
fAbsoluteFile := CreateAbsolutePath(fIncludeFile, ExtractFilePath(Filename)); | |||||
result := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPartInclude.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create(aParent); | |||||
fShaderFile := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartInclude.Destroy; | |||||
begin | |||||
FreeAndNil(fShaderFile); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartInclude.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_INCLUDE; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,106 @@ | |||||
unit uengShaderPartKeyValuePair; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, variants, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartKeyValuePair = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fName: String; | |||||
fValue: Variant; | |||||
fValueName: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property Name: String read fName; | |||||
property Value: Variant read fValue; | |||||
property ValueName: String read fValueName; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartProperty = class(TengShaderPartKeyValuePair) | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartDefine = class(TengShaderPartKeyValuePair) | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartKeyValuePair//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartKeyValuePair.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName; | |||||
if (fValueName <> '') then | |||||
result := result + ' ' + fValueName | |||||
else if (fValue <> Unassigned) then | |||||
result := result + TOKEN_CHAR_QUOTE + String(fValue) + TOKEN_CHAR_QUOTE; | |||||
result := result + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count < 2) or (aParams.Count > 3) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, 3, Line, Col, Filename); | |||||
result := ''; | |||||
fName := aParams[1].Name; | |||||
if not IsValidIdentifier(fName) then with aParams[1] do | |||||
raise EengInvalidIdentifier.Create(fName, Line, Col, Filename); | |||||
if (aParams.Count >= 3) then | |||||
if aParams[2].Quoted then begin | |||||
fValue := aParams[2].Name; | |||||
fValueName := ''; | |||||
end else begin | |||||
fValue := Unassigned; | |||||
fValueName := aParams[2].Name; | |||||
end | |||||
else begin | |||||
fValue := Unassigned; | |||||
fValueName := ''; | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartProperty//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartProperty.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_PROPERTY; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartDefine////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartDefine.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_DEFINE; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,31 @@ | |||||
unit uengShaderPartMessage; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartMessage = class(TengShaderPart) | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartWarning = class(TengShaderPartMessage) | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartError = class(TengShaderPartMessage) | |||||
end; | |||||
implementation | |||||
end. | |||||
@@ -0,0 +1,175 @@ | |||||
unit uengShaderPartMeta; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengMetaType = ( | |||||
metaUnknown, | |||||
metaNormal, | |||||
metaVersion, | |||||
metaExtension, | |||||
metaLayout); | |||||
TengMetaData = class(TObject) | |||||
private | |||||
fMetaType: TengMetaType; | |||||
fName: String; | |||||
fValues: TStringList; | |||||
function GetValues: TStrings; | |||||
public | |||||
property MetaType: TengMetaType read fMetaType; | |||||
property Name: String read fName; | |||||
property Values: TStrings read GetValues; | |||||
constructor Create(const aName: String; const aType: TengMetaType); | |||||
destructor Destroy; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartMeta = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fData: TengMetaData; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property Data: TengMetaData read fData; | |||||
constructor Create(const aParent: TengShaderPart); override; | |||||
destructor Destroy; override; | |||||
{ Classs Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengMetaData////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengMetaData.GetValues: TStrings; | |||||
begin | |||||
result := fValues; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengMetaData.Create(const aName: String; const aType: TengMetaType); | |||||
begin | |||||
inherited Create; | |||||
fName := aName; | |||||
fMetaType := aType; | |||||
fValues := TStringList.Create; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengMetaData.Destroy; | |||||
begin | |||||
FreeAndNil(fValues); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartMeta//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartMeta.GetText: String; | |||||
var | |||||
i: Integer; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fData.Name; | |||||
for i := 0 to fData.Values.Count-1 do begin | |||||
if (PtrInt(fData.Values.Objects[i]) <> 0) | |||||
then result := result + ' ' + TOKEN_CHAR_QUOTE + fData.Values[i] + TOKEN_CHAR_QUOTE | |||||
else result := result + ' ' + fData.Values[i]; | |||||
end; | |||||
result := result + TOKEN_CHAR_END; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartMeta.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
var | |||||
i: Integer; | |||||
t: TengMetaType; | |||||
n: String; | |||||
begin | |||||
if (aParams[0].Name <> GetTokenName) then with aParams[0] do | |||||
raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename); | |||||
if (aParams.Count < 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename); | |||||
result := ''; | |||||
n := aParams[1].Name; | |||||
{.$VERSION} | |||||
if (n = TOKEN_VERSION) then 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); | |||||
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); | |||||
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); | |||||
end else | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, Line, Col, Filename); | |||||
{.$EXTENSION} | |||||
end else if (n = TOKEN_EXTENSION) then begin | |||||
t := metaExtension; | |||||
if (aParams.Count <> 4) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 4, Line, Col, Filename); | |||||
{.$LAYOUT} | |||||
end else if (n = TOKEN_LAYOUT) then begin | |||||
t := metaLayout; | |||||
if (aParams.Count <> 3) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename); | |||||
{.VALUES} | |||||
end else | |||||
t := metaNormal; | |||||
fData := TengMetaData.Create(n, t); | |||||
try | |||||
for i := 2 to aParams.Count-1 do | |||||
fData.Values.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); | |||||
except | |||||
FreeAndNil(fData); | |||||
end; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
constructor TengShaderPartMeta.Create(const aParent: TengShaderPart); | |||||
begin | |||||
inherited Create(aParent); | |||||
fData := nil; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
destructor TengShaderPartMeta.Destroy; | |||||
begin | |||||
FreeAndNil(fData); | |||||
inherited Destroy; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartMeta.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_META; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,143 @@ | |||||
unit uengShaderPartParameter; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartParameter = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fName: String; | |||||
fType: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property Name: String read fName; | |||||
property Typ: String read fType; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartVar = class(TengShaderPartParameter) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fDefaultValue: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ General } | |||||
public | |||||
property DefaultValue: String read fDefaultValue; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartVarying = class(TengShaderPartParameter) | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartUniform = class(TengShaderPartParameter) | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartParameter.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + | |||||
TOKEN_CHAR_QUOTE + fType + TOKEN_CHAR_QUOTE + ' ' + | |||||
TOKEN_CHAR_QUOTE + fName + TOKEN_CHAR_QUOTE + | |||||
TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count <> 3) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename); | |||||
result := ''; | |||||
fType := aParams[1].Name; | |||||
fName := aParams[2].Name; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartVar///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartVar.GetText: String; | |||||
begin | |||||
result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + | |||||
TOKEN_CHAR_QUOTE + fType + TOKEN_CHAR_QUOTE + ' ' + | |||||
TOKEN_CHAR_QUOTE + fName + TOKEN_CHAR_QUOTE; | |||||
if (fDefaultValue <> '') then | |||||
result := result + ' ' + TOKEN_CHAR_QUOTE + fDefaultValue + TOKEN_CHAR_QUOTE; | |||||
result := result + TOKEN_CHAR_END; | |||||
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); | |||||
if (aParams.Count < 3) or (aParams.Count > 4) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 3, 4, Line, Col, Filename); | |||||
result := ''; | |||||
fType := aParams[1].Name; | |||||
fName := aParams[2].Name; | |||||
if (aParams.Count >= 4) then | |||||
fDefaultValue := aParams[3].Name | |||||
else | |||||
fDefaultValue := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartVar.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_VAR; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartVarying///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartVarying.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_VARYING; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartUniform///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartUniform.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_UNIFORM; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,251 @@ | |||||
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<TengShaderPartProcParam>; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
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; | |||||
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); 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); | |||||
if (aParams.Count < 2) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, Line, Col, Filename); | |||||
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); | |||||
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)', Line, Col, Filename); | |||||
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; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class procedure TengShaderPartProc.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); | |||||
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); | |||||
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); | |||||
if (aParams.Count <> 1) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 1, Line, Col, Filename); | |||||
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); | |||||
if (aParams.Count < 3) then | |||||
raise EengInvalidParamterCount.Create(GetTokenName, 3, Line, Col, Filename); | |||||
fReturnType := aParams[1].Name; | |||||
aParams.Delete(1); | |||||
result := inherited ParseIntern(aArgs, aParams); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartFunc.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_FUNC; | |||||
end; | |||||
end. | |||||
@@ -0,0 +1,20 @@ | |||||
unit uengShaderPartScope; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPartCntr; | |||||
type | |||||
TengShaderPartScope = class(TengShaderPartCntr) | |||||
end; | |||||
implementation | |||||
end. | |||||
@@ -0,0 +1,143 @@ | |||||
unit uengShaderPartText; | |||||
{$mode objfpc}{$H+} | |||||
{$I uengShaderFile.inc} | |||||
interface | |||||
uses | |||||
Classes, SysUtils, | |||||
uengShaderPart, uengShaderFileParser; | |||||
type | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartText = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fText: String; | |||||
function GetIsEmpty: Boolean; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
public | |||||
property Text: String read fText; | |||||
property IsEmpty: Boolean read GetIsEmpty; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartLineBreak = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ Class Methods } | |||||
public | |||||
class function GetTokenName: String; override; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
TengShaderPartCommandEnd = class(TengShaderPart) | |||||
{ Code Loading & Storage } | |||||
private | |||||
fToken: String; | |||||
protected | |||||
function GetText: String; override; | |||||
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||||
{ Class Methods } | |||||
public | |||||
class function CheckToken(const aToken: String): Boolean; override; | |||||
end; | |||||
implementation | |||||
uses | |||||
uengShaderFileConstants, uengShaderFileTypes; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartText//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartText.GetIsEmpty: Boolean; | |||||
begin | |||||
result := (fText = ''); | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartText.GetText: String; | |||||
begin | |||||
result := fText; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartText.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
begin | |||||
fText := ''; | |||||
result := ''; | |||||
while not aArgs.EndOfLine do begin | |||||
if aArgs.GetTokenPreview(result) then begin | |||||
exit; | |||||
end else if (aArgs.CurrentChar in COMMAND_END_TOKENS) then begin | |||||
result := aArgs.CurrentChar; | |||||
exit; | |||||
end else begin | |||||
fText := fText + aArgs.CurrentChar; | |||||
aArgs.NextCol; | |||||
end; | |||||
end; | |||||
result := TOKEN_LINE_BREAK; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartLineBreak/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartLineBreak.GetText: String; | |||||
begin | |||||
result := TOKEN_LINE_BREAK; | |||||
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); | |||||
aArgs.NextLine; | |||||
result := ''; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartLineBreak.GetTokenName: String; | |||||
begin | |||||
result := TOKEN_LINE_BREAK; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//TengShaderPartCommandEnd////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCommandEnd.GetText: String; | |||||
begin | |||||
result := fToken; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
function TengShaderPartCommandEnd.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||||
begin | |||||
result := ''; | |||||
fToken := aArgs.CurrentChar; | |||||
aArgs.NextCol; | |||||
end; | |||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
class function TengShaderPartCommandEnd.CheckToken(const aToken: String): Boolean; | |||||
var | |||||
s: String; | |||||
begin | |||||
result := true; | |||||
for s in COMMAND_END_TOKENS do | |||||
if (s = aToken) then | |||||
exit; | |||||
result := false; | |||||
end; | |||||
end. | |||||