|
- unit uengShaderFileExpression;
-
- {$mode objfpc}{$H+}
- {$I uengShaderFile.inc}
-
- interface
-
- uses
- Classes, SysUtils, variants,
- uengShaderPart, uengShaderFileParser, uengShaderPartKeyValuePair;
-
- type
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionItem = class(TengShaderPart)
- public
- function GetValue: Variant; virtual;
- constructor Create(const aLine, aCol: Integer); reintroduce;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionValue = class(TengExpressionItem)
- private
- fValue: Variant;
- public
- property Value: Variant read fValue;
-
- function GetText: String; override;
- function GetValue: Variant; override;
-
- constructor Create(const aValue: Variant; const aLine, aCol: Integer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionVariable = class(TengExpressionItem)
- private
- fName: String;
- fPart: TengShaderPartKeyValuePair;
- public
- property Name: String read fName;
- property Part: TengShaderPartKeyValuePair read fPart;
-
- function GetText: String; override;
- function GetValue: Variant; override;
-
- constructor Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionGroup = class(TengExpressionItem)
- private
- fChild: TengExpressionItem;
- protected
- function GetCount: Integer; override;
- function GetChild(const aIndex: Integer): TengShaderPart; override;
- public
- property Child: TengExpressionItem read fChild;
-
- function GetText: String; override;
- function GetValue: Variant; override;
-
- constructor Create(const aChild: TengExpressionItem; const aLine, aCol: Integer);
- destructor Destroy; override;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionOperation = class(TengExpressionItem)
- protected
- function GetWeight: Integer; virtual;
- public
- property Weight: Integer read GetWeight;
- function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; virtual;
- function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; virtual;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TengExpressionUnaryOperator = (
- opBinaryNot,
- opLogicalNot
- );
- TengExpressionUnaryOperation = class(TengExpressionOperation)
- private
- fChild: TengExpressionItem;
- fUnaryOp: TengExpressionUnaryOperator;
- protected
- function GetWeight: Integer; override;
- function GetCount: Integer; override;
- function GetChild(const aIndex: Integer): TengShaderPart; override;
- public
- property Child: TengExpressionItem read fChild;
- property UnaryOp: TengExpressionUnaryOperator read fUnaryOp;
-
- function GetText: String; override;
- function GetValue: Variant; override;
- function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
- function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
-
- constructor Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
- 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(TengExpressionOperation)
- private
- fFirst: TengExpressionItem;
- fSecond: TengExpressionItem;
- fBinaryOp: TengExpressionBinaryOperator;
- protected
- function GetWeight: Integer; override;
- function GetCount: Integer; override;
- function GetChild(const aIndex: Integer): TengShaderPart; override;
- 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;
- function ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem; override;
- function ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem; override;
-
- constructor Create(const aOperator: TengExpressionBinaryOperator; const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
- destructor Destroy; override;
- end;
-
- function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
-
- implementation
-
- uses
- uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartScope, uengShaderFile;
-
- const
- EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = (
- TOKEN_OP_BINARY_NOT, //opBinaryNot
- TOKEN_OP_LOGICAL_NOT //opLogicalNot
- );
- 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
- );
-
- UNARY_OPERATION_WEIGHTS: array[TengExpressionUnaryOperator] of Integer = (
- 00, //opBinaryNot
- 00 //opLogicalNot
- );
- BINARY_OPERATION_WEIGHTS: array[TengExpressionBinaryOperator] of Integer = (
- 01, //opBinaryOr
- 02, //opBinaryAnd
- 03, //opBinaryXor
-
- 04, //opMultiply
- 05, //opDivide
- 06, //opAdd
- 07, //opSubtract
-
- 14, //opLogicalOr
- 15, //opLogicalAnd
- 16, //opLogicalXor
-
- 08, //opEquals
- 09, //opLesser
- 10, //opGreater
- 11, //opLEquals
- 12, //opGEquals
- 13 //opUnequals
- );
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionItem.GetValue: Variant;
- begin
- result := Unassigned; // DUMMY
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengExpressionItem.Create(const aLine, aCol: Integer);
- begin
- inherited Create(nil);
- fLine := aLine;
- fCol := aCol;
- 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);
- begin
- inherited Create(aLine, aCol);
- fValue := aValue;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionVariable////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionVariable.GetText: String;
- begin
- result := fName;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionVariable.GetValue: Variant;
- begin
- result := Unassigned;
- if Assigned(fPart) then
- result := fPart.Value;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengExpressionVariable.Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer);
- begin
- inherited Create(aLine, aCol);
- fName := aName;
- fPart := aPart;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionGroup///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionGroup.GetCount: Integer;
- begin
- result := 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionGroup.GetChild(const aIndex: Integer): TengShaderPart;
- begin
- if (aIndex >= 0) and (aIndex < 1)
- then result := fChild
- else raise EengOutOfRange.Create(0, 0, aIndex, self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- 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);
- begin
- inherited Create(aLine, aCol);
- fChild := aChild;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TengExpressionGroup.Destroy;
- begin
- FreeAndNil(fChild);
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionOperation///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionOperation.GetWeight: Integer;
- begin
- result := -1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionUnaryOperation//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.GetWeight: Integer;
- begin
- result := UNARY_OPERATION_WEIGHTS[fUnaryOp];
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.GetCount: Integer;
- begin
- result := 1;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
- begin
- if (aIndex >= 0) and (aIndex < 1)
- then result := fChild
- else raise EengOutOfRange.Create(0, 0, aIndex, self);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.GetText: String;
- begin
- if not Assigned(fChild) then
- EengExpression.Create('no child assigned', self);
- result :=
- {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF}
- EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText
- {$IFDEF SHADER_FILE_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', self);
- try
- case fUnaryOp of
-
- opBinaryNot: begin
- v := fChild.GetValue;
- result := not Integer(v);
- end;
-
- opLogicalNot: begin
- v := fChild.GetValue;
- result := not Boolean(v);
- 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, self);
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := fChild;
- fChild := aItem;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionUnaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := fChild;
- fChild := aItem;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengExpressionUnaryOperation.Create(const aUnaryOp: TengExpressionUnaryOperator; const aChild: TengExpressionItem; const aLine, aCol: Integer);
- begin
- inherited Create(aLine, aCol);
- fChild := aChild;
- fUnaryOp := aUnaryOp;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TengExpressionUnaryOperation.Destroy;
- begin
- FreeAndNil(fChild);
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TengExpressionBinaryOperation/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionBinaryOperation.GetWeight: Integer;
- begin
- result := BINARY_OPERATION_WEIGHTS[fBinaryOp];
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionBinaryOperation.GetCount: Integer;
- begin
- result := 2;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionBinaryOperation.GetChild(const aIndex: Integer): TengShaderPart;
- begin
- if (aIndex < 0) and (aIndex >= 2) then
- raise EengOutOfRange.Create(0, 1, aIndex, self);
- case aIndex of
- 0: result := fFirst;
- 1: result := fSecond;
- else
- result := nil;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- 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 SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF}
- fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText
- {$IFDEF SHADER_FILE_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 + '")',
- self);
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionBinaryOperation.ExchangeFirst(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := fFirst;
- fFirst := aItem;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TengExpressionBinaryOperation.ExchangeLast(const aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := fSecond;
- fSecond := aItem;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TengExpressionBinaryOperation.Create(const aOperator: TengExpressionBinaryOperator;
- const aFirst, aSecond: TengExpressionItem; const aLine, aCol: Integer);
- begin
- inherited Create(aLine, aCol);
- fBinaryOp := aOperator;
- fFirst := aFirst;
- fSecond := aSecond;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TengExpressionBinaryOperation.Destroy;
- begin
- FreeAndNil(fFirst);
- FreeAndNil(fSecond);
- inherited Destroy;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- type
- TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation);
- TExpectedParams = set of TExpectedParam;
- TExpressionParser = class(TObject)
- private
- fParent: TengShaderPart;
- fParamPos: Integer;
- fParams: TengTokenParameterList;
- private
- function NextParam(out aParam: TengTokenParameter): Boolean;
- function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean;
- function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean;
- procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
- function Move(var aItem: TengExpressionItem): TengExpressionItem;
- function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
- function GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
- public
- function GetGroup: TengExpressionItem;
- constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TExpressionParser/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean;
- begin
- inc(fParamPos);
- result := (fParamPos < fParams.Count);
- if result
- then aParam := fParams[fParamPos]
- else FillByte(aParam{%H-}, SizeOf(aParam), 0);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.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 TExpressionParser.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 TExpressionParser.RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = '');
- begin
- if (aName = '') then
- aName := aParam.Name;
- raise EengExpression.Create(aMsg + ' ' + aParam.Name, aParam.Line, aParam.Col, fParent.Filename, fParent);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.Move(var aItem: TengExpressionItem): TengExpressionItem;
- begin
- result := aItem;
- aItem := nil;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.Merge(aOld, aNew: TengExpressionItem): TengExpressionItem;
- var
- o, n: TengExpressionOperation;
- tmp: TengExpressionItem;
- begin
- result := nil;
- try
- if not Assigned(aOld) then begin
- result := aNew;
- exit;
- end else if not Assigned(aNew) then begin
- result := aOld;
- exit;
- end else if (aOld is TengExpressionOperation) and (aNew is TengExpressionOperation) then begin
- o := (aOld as TengExpressionOperation);
- n := (aNew as TengExpressionOperation);
- if (n.Weight < o.Weight) then begin
- tmp := n.ExchangeFirst(o.ExchangeLast(n));
- aNew := nil;
- result := aOld;
- end else begin
- tmp := n.ExchangeFirst(o);
- aOld := nil;
- result := aNew;
- end;
- if Assigned(tmp) then
- raise EengExpressionInternal.Create(1, fParent);
- end else if (aOld is TengExpressionOperation) then begin
- o := (aOld as TengExpressionOperation);
- o.ExchangeLast(aNew);
- aNew := nil;
- result := aOld;
- end else if (aNew is TengExpressionOperation) then begin
- n := (aNew as TengExpressionOperation);
- n.ExchangeFirst(aOld);
- aOld := nil;
- result := aNew;
- end;;
- except
- FreeAndNil(aOld);
- FreeAndNil(aNew);
- result := nil;
- raise;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.GetExpr(const aExpected: TExpectedParams): TengExpressionItem;
- var
- uOp: TengExpressionUnaryOperator;
- bOp: TengExpressionBinaryOperator;
- item: TengExpressionItem;
- param: TengTokenParameter;
- sr: TengSearchResults;
- walker: TengKeyValuePairSearchWalker;
- tmp: TengShaderPart;
- begin
- item := nil;
- result := nil;
- try
- if NextParam(param) then begin
- // GroupBegin
- if (param.Name = TOKEN_OP_GROUP_BEGIN) then begin
- if not (exGroupBegin in aExpected) then
- RaiseEx('unexpected', param);
- item := GetGroup;
- result := TengExpressionGroup.Create(Move(item), param.Col, param.Line);
-
- // GroupEnd
- end else if (param.Name = TOKEN_OP_GROUP_END) then begin
- if not (exGroupEnd in aExpected) then
- RaiseEx('unexpected', param);
-
- // UnaryOperation
- end else if IsUnaryOperation(param.Name, uOp) then begin
- if not (exUnaryOperation in aExpected) then
- RaiseEx('unexpected operation:', param);
- item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
- result := TengExpressionUnaryOperation.Create(uOp, Move(item), param.Line, param.Col);
-
- // BinaryOperation
- end else if IsBinaryOperation(param.Name, bOp) then begin
- if not (exBinaryOperation in aExpected) then
- RaiseEx('unexpected operation:', param);
- item := GetExpr([exVariable, exValue, exGroupBegin, exUnaryOperation]);
- item := TengExpressionBinaryOperation.Create(bOp, nil, Move(item), param.Line, param.Col);
- result := Merge(result, item);
-
- // Value
- end else if param.Quoted and IsValidIdentifier(param.Name) then begin
- if not (exValue in aExpected) then
- RaiseEx('unexpected value:', param);
- result := TengExpressionValue.Create(param.Name, param.Line, param.Col);
-
- // Variable
- end else if IsValidIdentifier(param.Name) then begin
- if not (exVariable in aExpected) then
- RaiseEx('unexpected variable:', param);
- sr := TengSearchResults.Create;
- walker := TengKeyValuePairSearchWalker.Create(sr);
- try
- walker.Name := param.Name;
- walker.SearchFlags := [sfSearchChildren, sfSearchParents, sfSearchInherited];
- walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic);
- walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
- walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
- walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
- walker.Run(fParent);
- tmp := ExtractSearchResult(fParent, param.Name, sr, [ifWarning, ifRaiseEx], param.Line, param.Col);
- result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
- finally
- FreeAndNil(walker);
- FreeAndNil(sr);
- end;
-
- // Unknown
- end else
- raise EengExpression.Create('invalid parameter: ' + param.Name, param.Line, param.Col, fParent.Filename, fParent);
- end;
-
- if not Assigned(result) and not (exGroupEnd in aExpected) then
- RaiseEx('unexpected', param, 'end');
- except
- FreeAndNil(item);
- FreeAndNil(result);
- raise;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TExpressionParser.GetGroup: TengExpressionItem;
- var
- ex: TExpectedParams;
- item: TengExpressionItem;
- b: Boolean;
- begin
- item := nil;
- result := nil;
- try
- ex := [exVariable, exValue, exGroupBegin, exUnaryOperation];
- repeat
- item := GetExpr(ex);
- b := Assigned(item);
- result := Merge(result, Move(item));
- ex := ex + [exBinaryOperation, exGroupEnd];
- until not b;
- except
- FreeAndNil(result);
- FreeAndNil(item);
- raise;
- end;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TExpressionParser.Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer);
- begin
- fParamPos := aIndex - 1;
- fParams := aParams;
- fParent := aParent;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function ParseExpression(const aParent: TengShaderPart; const aParams: TengTokenParameterList; aIndex: Integer): TengExpressionItem;
- var
- parser: TExpressionParser;
- begin
- parser := TExpressionParser.Create(aParent, aParams, aIndex);
- try
- result := parser.GetGroup;
- finally
- FreeAndNil(parser);
- end;
- end;
-
- end.
|