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