| @@ -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. | |||