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