fpc/packages/fcl-js/tests/tcparser.pp
2022-02-01 14:22:22 +01:00

3474 lines
124 KiB
ObjectPascal

unit tcparser;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpcunit, testregistry, jstoken, jsParser, jstree, jsbase;
type
{ TTestJSParser }
{ TTestBaseJSParser }
TTestBaseJSParser = class(TTestCase)
Private
FSource : TStringStream;
FParser : TJSParser;
FSE : TJSSourceElements;
FToFree: TJSElement;
protected
procedure SetUp; override;
procedure TearDown; override;
Procedure CreateParser(Const ASource : string; aVersion : TECMAVersion = TECMAVersion.ecma5; aIsTypeScript : Boolean = False);
Function CheckClass(E : TJSElement; C : TJSElementClass; Const aMsg : String = '') : TJSElement;
Function CheckClass(Const aMsg : String; aExpectedClass : TJSElementClass; aActual : TJSElement) : TJSElement;
Procedure AssertEquals(Const AMessage : String; Expected, Actual : TJSToken); overload;
Procedure AssertEquals(Const AMessage : String; Expected, Actual : TJSType); overload;
Procedure AssertEquals(Const AMessage : String; Expected, Actual : TJSVarType); overload;
Procedure AssertEquals(Const AMessage : String; Expected, Actual : TKeyOptionality); overload;
Procedure AssertIdentifier(Msg : String; El : TJSElement; Const AName : TJSString);
procedure AssertEquals(Const AMessage : String; aExpected : AnsiString; aActual : TJSString); overload;
Function GetSourceElements : TJSSourceElements;
Function GetVars : TJSElementNodes;
Function GetStatements : TJSElementNodes;
Function GetFunctions : TJSElementNodes;
Function GetFirstFunction : TJSFunctionDeclarationStatement;
Function GetClasses : TJSElementNodes;
Function GetFirstClass(isAmbient : Boolean = false) : TJSClassDeclaration;
Function GetFirstStatement : TJSElement;
Function GetFirstVar : TJSElement;
Function GetModules : TJSElementNodes;
Function GetFirstModule : TJSModuleDeclaration;
Function GetNameSpaces : TJSElementNodes;
Function GetFirstNameSpace : TJSNamespaceDeclaration;
Function GetTypes : TJSElementNodes;
Function GetFirstType : TJSTypeDeclaration;
Function GetEnums : TJSElementNodes;
Function GetFirstEnum: TJSEnumDeclaration;
Function GetExpressionStatement : TJSExpressionStatement;
Function GetInterfaces : TJSElementNodes;
Function GetFirstInterface : TJSInterfaceDeclaration;
end;
TTestJSParser= class(TTestBaseJSParser)
private
published
procedure TestEmpty;
procedure TestSimple;
procedure TestSimpleExpressionNumericalLiteral;
procedure TestSimpleExpressionStringLiteral;
procedure TestSimpleExpressionBooleanLiteralFalse;
procedure TestSimpleExpressionBooleanLiteralTrue;
procedure TestSimpleExpressionIdentifier;
procedure TestSimpleExpressionNull;
procedure TestAssignExpressionNumerical;
procedure TestAssignExpressionNull;
procedure TestAssignExpressionString;
procedure TestAssignExpressionBooleanFalse;
procedure TestAssignExpressionBooleanTrue;
procedure TestAssignExpressionIdent;
procedure TestAssignExpressionPlus;
procedure TestAssignExpressionMinus;
procedure TestAssignExpressionDiv;
procedure TestAssignExpressionMul;
procedure TestAssignExpressionMod;
procedure TestAssignExpressionAnd;
procedure TestAssignExpressionOr;
procedure TestAssignExpressionXOr;
procedure TestAssignExpressionLShift;
procedure TestAssignExpressionRShift;
procedure TestAssignExpressionURShift;
procedure TestExpressionPlus;
procedure TestExpressionSub;
procedure TestExpressionMul;
procedure TestExpressionDiv;
procedure TestExpressionMod;
procedure TestExpressionLShift;
procedure TestExpressionRShift;
procedure TestExpressionURShift;
procedure TestExpressionPostPlusPlus;
procedure TestExpressionPostMinusMinus;
procedure TestExpressionPreMinusMinus;
procedure TestExpressionPrePlusPlus;
procedure TestExpressionPrecedenceMulPlus;
procedure TestExpressionPrecedencePlusMul;
procedure TestExpressionPrecedenceMulMinus;
procedure TestExpressionPrecedenceMinusMul;
procedure TestExpressionPrecedenceDivPlus;
procedure TestExpressionPrecedencePlusDiv;
procedure TestExpressionPrecedenceModPlus;
procedure TestExpressionPrecedencePlusMod;
procedure TestExpressionPrecedencePlusPostPlusPlus;
procedure TestExpressionPrecedencePlusPostMinusMinus;
procedure TestExpressionPrecedenceMulPostMinusMinus;
procedure TestExpressionPrecedenceMulPostPlusPlus;
procedure TestExpressionPrecedenceMulPreMinusMinus;
procedure TestExpressionPrecedenceMulPrePlusPlus;
procedure TestExpressionPrecedencePlusPreMinusMinus;
procedure TestExpressionPrecedencePlusPrePlusPlus;
procedure TestExpressionPrecedencePlusInv;
procedure TestExpressionPrecedenceMulInv;
procedure TestExpressionPrecedenceMulNot;
procedure TestExpressionPrecedencePlusNot;
procedure TestExpressionPrecedenceBraceMulPlus;
procedure TestExpressionPrecedenceBracePlusMul;
procedure TestExpressionFunction;
procedure TestFunctionCallNoArgs;
procedure TestAwaitFunctionCallNoArgs;
procedure TestFunctionCallOneArg;
procedure TestFunctionCallTwoArgs;
procedure TestObjectGeneratorFunction;
procedure TestArrayExpressionNumericalArgs;
procedure TestArrayExpressionStringArgs;
procedure TestArrayExpressionIdentArgs;
Procedure TestVarDeclarationSimple;
Procedure TestVarDeclarationInit;
Procedure TestLetDeclarationSimple;
procedure TestVarDeclarationDouble;
procedure TestVarDeclarationSimpleInit;
procedure TestConstDeclarationSimpleInit;
procedure TestVarDeclarationDoubleInit;
procedure TestDebuggerStatement;
procedure TestBlockEmpty;
procedure TestBlockEmptyStatement;
procedure TestBlockSimpleStatement;
procedure TestFunctionDeclarationEmpty;
procedure TestFunctionDeclarationAsync;
procedure TestFunctionDeclarationWithArgs;
procedure TestFunctionDeclarationWithSpreadArgs;
procedure TestFunctionDeclarationWithBody;
procedure TestIfSimple;
procedure TestIfElseSimple;
procedure TestIfEmptyBlock;
procedure TestIfEmptyBlockElse;
procedure TestWhileSimple;
procedure TestWhileBlock;
procedure TestDoWhileSimple;
procedure TestDoWhileBlock;
procedure TestForEmpty;
procedure TestForEmptyBody;
procedure TestForSimpleBody;
procedure TestTryCatch;
procedure TestTryCatchFinally;
procedure TestTryFinally;
procedure TestThrow;
procedure TestReturn;
procedure TestAssignment;
procedure TestNew;
procedure TestLabeledStatement;
procedure TestContinue;
procedure TestContinueTarget;
procedure TestBreak;
procedure TestBreakTarget;
procedure TestSwitchEmpty;
procedure TestSwitchOne;
procedure TestSwitchTwo;
procedure TestSwitchTwoDefault;
Procedure TestImportModule;
Procedure TestImportImportedDefault;
Procedure TestImportNamespaceImport;
Procedure TestImportImportedDefaultAndNamespaceImport;
Procedure TestImportNamedImport;
Procedure TestImportNamedImportAlias;
Procedure TestImport2NamedImports;
Procedure TestImport2NamedImportAlias;
Procedure TestImport2NamedImportsComma;
Procedure TestImportDefaultAndNamedImport;
Procedure TestExportAll;
Procedure TestExportAllFrom;
Procedure TestExportExportNameFrom;
Procedure TestExportExportName;
Procedure TestExportExportNameAlias;
Procedure TestExportVar;
Procedure TestExportLet;
Procedure TestExportConst;
Procedure TestExportFunction;
Procedure TestExportDefaultAssignment;
Procedure TestExportDefaultFunction;
Procedure TestExportDefaultAsyncFunction;
Procedure TestClass;
Procedure TestClassExtends;
Procedure TestClassWithMethod;
procedure TestClassExpression;
procedure TestLetClassExpression;
end;
implementation
uses typinfo;
{ ----------------------------------------------------------------------
TTestBaseJSParser
----------------------------------------------------------------------}
procedure TTestBaseJSParser.SetUp;
begin
FParser:=Nil;
FSource:=Nil;
end;
procedure TTestBaseJSParser.TearDown;
begin
FreeAndNil(FToFree);
FreeAndNil(FParser);
FReeAndNil(FSource);
end;
Procedure TTestBaseJSParser.CreateParser(Const ASource: string; aVersion : TECMAVersion = TECMAVersion.ecma5; aIsTypeScript : Boolean = False);
begin
FSource:=TStringStream.Create(ASource);
FParser:=TJSParser.Create(FSource,aVersion,aIsTypescript);
end;
function TTestBaseJSParser.CheckClass(E: TJSElement; C: TJSElementClass; const aMsg: String): TJSElement;
begin
AssertNotNull(aMsg+': Not null element',E);
AssertNotNull(aMsg+': Not null class',C);
AssertEquals(aMsg,C,E.ClassType);
Result:=E;
end;
function TTestBaseJSParser.CheckClass(const aMsg: String; aExpectedClass: TJSElementClass; aActual: TJSElement): TJSElement;
begin
Result:=CheckClass(aActual,aExpectedClass,aMsg);
end;
procedure TTestBaseJSParser.AssertEquals(const AMessage: String; Expected, Actual: TJSToken);
Var
NE,NA : String;
begin
NE:=GetEnumName(TypeInfo(TJSToken),Ord(Expected));
NA:=GetEnumName(TypeInfo(TJSToken),Ord(Actual));
AssertEquals(AMessage,NE,NA);
end;
Function TTestBaseJSParser.GetSourceElements: TJSSourceElements;
Var
E : TJSElement;
FB : TJSFunctionBody;
begin
If Not Assigned(FSE) then
begin
AssertNotNull('Parser assigned',FParser);
E:=FParser.Parse;
CheckClass(E,TJSFunctionBody);
FB:=TJSFunctionBody(E);
AssertNotNull(FB.A);
CheckClass(FB.A,TJSSourceElements);
FSE:=TJSSourceElements(FB.A);
FToFree:=E;
end;
Result:=FSE;
end;
Function TTestBaseJSParser.GetVars: TJSElementNodes;
begin
Result:=GetSourceElements.Vars;
end;
Function TTestBaseJSParser.GetStatements: TJSElementNodes;
begin
Result:=GetSourceElements.Statements;
end;
Function TTestBaseJSParser.GetFunctions: TJSElementNodes;
begin
Result:=GetSourceElements.Functions;
end;
function TTestBaseJSParser.GetFirstFunction: TJSFunctionDeclarationStatement;
Var
aFunctions : TJSElementNodes;
begin
aFunctions:=GetFunctions;
AssertTrue('Have functions ',aFunctions.Count>0);
AssertNotNull('have first function node',aFunctions.Nodes[0].Node);
AssertEquals('First function node is function declaration',TJSFunctionDeclarationStatement,aFunctions.Nodes[0].Node.ClassType);
Result:=TJSFunctionDeclarationStatement(aFunctions.Nodes[0].Node);
end;
function TTestBaseJSParser.GetClasses: TJSElementNodes;
begin
Result:=GetSourceElements.Classes;
end;
function TTestBaseJSParser.GetFirstClass(isAmbient : Boolean = false): TJSClassDeclaration;
Var
aClasses : TJSElementNodes;
begin
aClasses:=GetClasses;
AssertTrue('Have classes ',aClasses.Count>0);
AssertNotNull('have first class node',aClasses.Nodes[0].Node);
if IsAmbient then
AssertEquals('First class node is ambientclass declaration',TJSAmbientClassDeclaration,aClasses.Nodes[0].Node.ClassType)
else
AssertEquals('First class node is class declaration',TJSClassDeclaration,aClasses.Nodes[0].Node.ClassType);
Result:=TJSClassDeclaration(aClasses.Nodes[0].Node);
end;
Procedure TTestBaseJSParser.AssertEquals(Const AMessage: String; Expected,
Actual: TJSType);
Var
NE,NA : String;
begin
NE:=GetEnumName(TypeInfo(TJSType),Ord(Expected));
NA:=GetEnumName(TypeInfo(TJSType),Ord(Actual));
AssertEquals(AMessage,NE,NA);
end;
procedure TTestBaseJSParser.AssertEquals(const AMessage: String; Expected, Actual: TJSVarType);
Var
NE,NA : String;
begin
NE:=GetEnumName(TypeInfo(TJSVarType),Ord(Expected));
NA:=GetEnumName(TypeInfo(TJSVarType),Ord(Actual));
AssertEquals(AMessage,NE,NA);
end;
procedure TTestBaseJSParser.AssertEquals(const AMessage: String; Expected, Actual: TKeyOptionality);
Var
NE,NA : String;
begin
NE:=GetEnumName(TypeInfo(TKeyOptionality),Ord(Expected));
NA:=GetEnumName(TypeInfo(TKeyOptionality),Ord(Actual));
AssertEquals(AMessage,NE,NA);
end;
Procedure TTestBaseJSParser.AssertIdentifier(Msg: String; El: TJSElement;
Const AName: TJSString);
Var
L : TJSPrimaryExpressionIdent;
S1,S2 : TJSString;
begin
AssertNotNull(Msg+' have TJSPrimaryExpressionIdent element',El);
CheckClass(El,TJSPrimaryExpressionIdent);
L:=TJSPrimaryExpressionIdent(el);
S1:=L.Name;
S2:=Aname;
AssertEquals(Msg+'Identifier has correct name',S2,S1);
end;
procedure TTestBaseJSParser.AssertEquals(const AMessage: String; aExpected: AnsiString; aActual: TJSString);
begin
AssertEquals(AMessage,UTF8Decode(aExpected),aActual);
end;
Function TTestBaseJSParser.GetFirstStatement: TJSElement;
Var
E : TJSElementNodes;
begin
E:=GetStatements;
AssertNotNull('Have statements',E);
AssertTrue('1 statement',1<=E.Count);
Result:=E.Nodes[0].Node;
AssertNotNull('First statement assigned',Result);
end;
Function TTestBaseJSParser.GetFirstVar: TJSElement;
Var
E : TJSElementNodes;
begin
E:=GetVars;
AssertNotNull('Have statements',E);
// Writeln('Count : ',E.Count);
If (E.Count=0) then
Fail('Zero variables defined');
Result:=E.Nodes[0].Node;
AssertNotNull('First variable declaration',Result);
end;
function TTestBaseJSParser.GetModules: TJSElementNodes;
begin
Result:=GetSourceElements.Modules;
end;
function TTestBaseJSParser.GetFirstModule: TJSModuleDeclaration;
Var
E : TJSElementNodes;
begin
E:=GetModules;
AssertNotNull('Have modules',E);
AssertEquals('1 statement',1,E.Count);
AssertEquals('First module node is module declaration',TJSModuleDeclaration,E.Nodes[0].Node.ClassType);
Result:=E.Nodes[0].Node as TJSModuleDeclaration;
end;
function TTestBaseJSParser.GetNameSpaces: TJSElementNodes;
begin
Result:=GetSourceElements.NameSpaces;
end;
function TTestBaseJSParser.GetFirstNameSpace: TJSNamespaceDeclaration;
Var
E : TJSElementNodes;
begin
E:=GetNameSpaces;
AssertNotNull('Have namespaces',E);
AssertEquals('1 namespace',1,E.Count);
AssertEquals('First module node is namespace declaration',TJSNamespaceDeclaration,E.Nodes[0].Node.ClassType);
Result:=E.Nodes[0].Node as TJSNamespaceDeclaration;
end;
function TTestBaseJSParser.GetTypes: TJSElementNodes;
begin
Result:=GetSourceElements.Types;
end;
function TTestBaseJSParser.GetFirstType: TJSTypeDeclaration;
Var
E : TJSElementNodes;
begin
E:=GetTypes;
AssertNotNull('Have types',E);
AssertEquals('1 type',1,E.Count);
AssertEquals('First type node is type declaration',TJSTypeDeclaration,E.Nodes[0].Node.ClassType);
Result:=(E.Nodes[0].Node as TJSTypeDeclaration);
end;
function TTestBaseJSParser.GetEnums: TJSElementNodes;
begin
Result:=GetSourceElements.Enums;
end;
function TTestBaseJSParser.GetFirstEnum: TJSEnumDeclaration;
Var
E : TJSElementNodes;
begin
E:=GetEnums;
AssertNotNull('Have enums',E);
AssertEquals('1 type',1,E.Count);
AssertEquals('First type node is enum declaration',TJSEnumDeclaration,E.Nodes[0].Node.ClassType);
Result:=(E.Nodes[0].Node as TJSEnumDeclaration);
end;
Function TTestBaseJSParser.GetExpressionStatement: TJSExpressionStatement;
Var
N : TJSElement;
begin
N:=GetFirstStatement;
CheckClass(N,TJSExpressionStatement);
Result:=TJSExpressionStatement(N);
end;
function TTestBaseJSParser.GetInterfaces: TJSElementNodes;
begin
Result:=GetSourceElements.Interfaces;
end;
function TTestBaseJSParser.GetFirstInterface: TJSInterfaceDeclaration;
Var
E : TJSElementNodes;
begin
E:=GetInterfaces;
AssertNotNull('Have interfaces',E);
AssertEquals('1 interfaces',1,E.Count);
AssertEquals('First interface node is interface declaration',TJSInterfaceDeclaration,E.Nodes[0].Node.ClassType);
Result:=(E.Nodes[0].Node as TJSInterfaceDeclaration);
end;
{ ----------------------------------------------------------------------
TTestJSParser
----------------------------------------------------------------------}
procedure TTestJSParser.TestSimple;
Var
E : TJSElementNodes;
N : TJSElement;
X : TJSExpressionStatement;
begin
CreateParser('1;');
E:=GetStatements;
AssertNotNull('Have statements',E);
AssertEquals('1 statement',1,E.Count);
N:=E.Nodes[0].Node;
AssertNotNull('First statement assigned',N);
AssertNotNull('First statement assigned',N);
CheckClass(N,TJSExpressionStatement);
X:=TJSExpressionStatement(N);
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
end;
procedure TTestJSParser.TestSimpleExpressionNumericalLiteral;
Var
X : TJSExpressionStatement;
begin
CreateParser('1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(X.A).Value.ValueType);
AssertEquals('Expression value correct', 1.0,TJSLiteral(X.A).Value.AsNumber);
end;
procedure TTestJSParser.TestSimpleExpressionStringLiteral;
Var
X : TJSExpressionStatement;
begin
CreateParser('"string";');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value);
AssertEquals('Expression value type correct', jstString,TJSLiteral(X.A).Value.ValueType);
AssertEquals('Expression value correct', 'string',TJSLiteral(X.A).Value.AsString);
end;
procedure TTestJSParser.TestSimpleExpressionBooleanLiteralFalse;
Var
X : TJSExpressionStatement;
begin
CreateParser('false;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value);
AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(X.A).Value.ValueType);
AssertEquals('Expression value correct', False, TJSLiteral(X.A).Value.AsBoolean);
end;
procedure TTestJSParser.TestSimpleExpressionIdentifier;
Var
X : TJSExpressionStatement;
begin
CreateParser('Something;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSPrimaryExpressionIdent);
AssertEquals('Expression value assigned','Something',TJSPrimaryExpressionIdent(X.A).Name);
end;
procedure TTestJSParser.TestSimpleExpressionNull;
Var
X : TJSExpressionStatement;
begin
CreateParser('null;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value);
AssertEquals('Expression value type correct', jstNull,TJSLiteral(X.A).Value.ValueType);
AssertEquals('Expression value correct', True, TJSLiteral(X.A).Value.IsNull);
end;
procedure TTestJSParser.TestAssignExpressionNumerical;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionString;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a="string";');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstString,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 'string', TJSLiteral(SA.Expr).Value.AsString);
end;
procedure TTestJSParser.TestAssignExpressionBooleanFalse;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a=false;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', False, TJSLiteral(SA.Expr).Value.AsBoolean);
end;
procedure TTestJSParser.TestAssignExpressionBooleanTrue;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a=true;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', True, TJSLiteral(SA.Expr).Value.AsBoolean);
end;
procedure TTestJSParser.TestAssignExpressionNull;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a=null;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNull,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', True, TJSLiteral(SA.Expr).Value.IsNull);
end;
procedure TTestJSParser.TestAssignExpressionIdent;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
begin
CreateParser('a=b;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSPrimaryExpressionIdent);
AssertEquals('Expression value type correct', 'b',TJSPrimaryExpressionIdent(SA.Expr).Name);
end;
procedure TTestJSParser.TestAssignExpressionPlus;
Var
X : TJSExpressionStatement;
SA : TJSAddEqAssignStatement;
begin
CreateParser('a+=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAddEqAssignStatement);
SA:=TJSAddEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionMinus;
Var
X : TJSExpressionStatement;
SA : TJSSubEqAssignStatement;
begin
CreateParser('a-=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSubEqAssignStatement);
SA:=TJSSubEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionMul;
Var
X : TJSExpressionStatement;
SA : TJSMulEqAssignStatement;
begin
CreateParser('a*=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMulEqAssignStatement);
SA:=TJSMulEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionDiv;
Var
X : TJSExpressionStatement;
SA : TJSDivEqAssignStatement;
begin
CreateParser('a/=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSDivEqAssignStatement);
SA:=TJSDivEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionMod;
Var
X : TJSExpressionStatement;
SA : TJSModEqAssignStatement;
begin
CreateParser('a%=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSModEqAssignStatement);
SA:=TJSModEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionAnd;
Var
X : TJSExpressionStatement;
SA : TJSAndEqAssignStatement;
begin
CreateParser('a&=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAndEqAssignStatement);
SA:=TJSAndEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionOr;
Var
X : TJSExpressionStatement;
SA : TJSOrEqAssignStatement;
begin
CreateParser('a|=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSOrEqAssignStatement);
SA:=TJSOrEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionXOr;
Var
X : TJSExpressionStatement;
SA : TJSXOrEqAssignStatement;
begin
CreateParser('a^=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSXOrEqAssignStatement);
SA:=TJSXOrEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionLShift;
Var
X : TJSExpressionStatement;
SA : TJSLShiftEqAssignStatement;
begin
CreateParser('a<<=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLShiftEqAssignStatement);
SA:=TJSLShiftEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionRShift;
Var
X : TJSExpressionStatement;
SA : TJSRShiftEqAssignStatement;
begin
CreateParser('a>>=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSRShiftEqAssignStatement);
SA:=TJSRShiftEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestAssignExpressionURShift;
Var
X : TJSExpressionStatement;
SA : TJSURShiftEqAssignStatement;
begin
CreateParser('a>>>=1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSURShiftEqAssignStatement);
SA:=TJSURShiftEqAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
CheckClass(SA.EXPR,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(SA.Expr).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(SA.Expr).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPlus;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('1+2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionSub;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionMinus;
begin
CreateParser('1 - 2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionMinus);
E:=TJSAdditiveExpressionMinus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionMul;
Var
X : TJSExpressionStatement;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('1*2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionDiv;
Var
X : TJSExpressionStatement;
E : TJSMultiplicativeExpressionDiv;
begin
CreateParser('1/2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionDiv);
E:=TJSMultiplicativeExpressionDiv(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionMod;
Var
X : TJSExpressionStatement;
E : TJSMultiplicativeExpressionMod;
begin
CreateParser('1%2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMod);
E:=TJSMultiplicativeExpressionMod(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionLShift;
Var
X : TJSExpressionStatement;
E : TJSLShiftExpression;
begin
CreateParser('1 << 2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLShiftExpression);
E:=TJSLShiftExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionRShift;
Var
X : TJSExpressionStatement;
E : TJSRShiftExpression;
begin
CreateParser('1 >> 2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSRShiftExpression);
E:=TJSRShiftExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionURShift;
Var
X : TJSExpressionStatement;
E : TJSURShiftExpression;
begin
CreateParser('1 >>> 2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSURShiftExpression);
E:=TJSURShiftExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSLiteral);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Expression left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression left operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
AssertNotNull('Expression right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Expression left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 2.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPostPlusPlus;
Var
X : TJSExpressionStatement;
E : TJSUnaryPostPlusPlusExpression;
begin
CreateParser('1++;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSUnaryPostPlusPlusExpression);
E:=TJSUnaryPostPlusPlusExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPostMinusMinus;
Var
X : TJSExpressionStatement;
E : TJSUnaryPostMinusMinusExpression;
begin
CreateParser('1--;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSUnaryPostMinusMinusExpression);
E:=TJSUnaryPostMinusMinusExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrePlusPlus;
Var
X : TJSExpressionStatement;
E : TJSUnaryPrePlusPlusExpression;
begin
CreateParser('++1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSUnaryPrePlusPlusExpression);
E:=TJSUnaryPrePlusPlusExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPreMinusMinus;
Var
X : TJSExpressionStatement;
E : TJSUnaryPreMinusMinusExpression;
begin
CreateParser('--1;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSUnaryPreMinusMinusExpression);
E:=TJSUnaryPreMinusMinusExpression(X.A);
AssertNotNull('Expression left operand assigned',E.A);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Expression operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Expression operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression operand value correct', 1.0, TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulPlus;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionMul;
begin
CreateParser('2 * 3 + 4;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSMultiplicativeExpressionMul);
R:=TJSMultiplicativeExpressionMul(E.A);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceBraceMulPlus;
Var
X : TJSExpressionStatement;
E : TJSMultiplicativeExpressionMul;
R : TJSAdditiveExpressionPlus;
begin
CreateParser('2 * (3 + 4);');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSAdditiveExpressionPlus);
R:=TJSAdditiveExpressionPlus(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(E.A).Value.AsNumber);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(R.B).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(R.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceBracePlusMul;
Var
X : TJSExpressionStatement;
E : TJSMultiplicativeExpressionMul;
R : TJSAdditiveExpressionPlus;
begin
CreateParser('(3 + 4)*2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSAdditiveExpressionPlus);
R:=TJSAdditiveExpressionPlus(E.A);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(E.B).Value.AsNumber);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(R.B).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(R.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionFunction;
Var
X : TJSExpressionStatement;
A : TJSSimpleAssignStatement;
begin
CreateParser('a = function () {};');
X:=GetExpressionStatement;
CheckClass(X.A,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Have left operand',A.LHS);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Correct name for assignment LHS ','a',TJSPrimaryExpressionIdent(A.LHS).Name);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusMul;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 + 2 * 3;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSMultiplicativeExpressionMul);
R:=TJSMultiplicativeExpressionMul(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulMinus;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionMinus;
R : TJSMultiplicativeExpressionMul;
begin
CreateParser('2 * 3 - 4;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionMinus);
E:=TJSAdditiveExpressionMinus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSMultiplicativeExpressionMul);
R:=TJSMultiplicativeExpressionMul(E.A);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('subtraction right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('subtraction right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('subtraction right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMinusMul;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionMinus;
R : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 - 2 * 3;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionMinus);
E:=TJSAdditiveExpressionMinus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSMultiplicativeExpressionMul);
R:=TJSMultiplicativeExpressionMul(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
AssertNotNull('Multiplication right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Multiplication right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Multiplication right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Subtraction left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Subtraction left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Subtraction left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceDivPlus;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionDiv;
begin
CreateParser('2 / 3 + 4;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSMultiplicativeExpressionDiv);
R:=TJSMultiplicativeExpressionDiv(E.A);
CheckClass(E.B,TJSLiteral);
AssertNotNull('Div left operand assigned',R.A);
AssertNotNull('Div right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Div left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Div left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Div right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Div right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Addition right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusDiv;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionDiv;
begin
CreateParser('4 + 2 / 3;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSMultiplicativeExpressionDiv);
R:=TJSMultiplicativeExpressionDiv(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Div left operand assigned',R.A);
AssertNotNull('Div right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Div left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Div left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Div right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Div right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceModPlus;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionMod;
begin
CreateParser('2 % 3 + 4;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.A,TJSMultiplicativeExpressionMod);
R:=TJSMultiplicativeExpressionMod(E.A);
CheckClass(E.B,TJSLiteral);
AssertNotNull('mod left operand assigned',R.A);
AssertNotNull('mod right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('mod left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('mod left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('mod right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('mod right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.B).Value);
AssertEquals('Addition right operand type correct', jstNumber, TJSLiteral(E.B).Value.ValueType);
AssertEquals('Addition right operand value correct', 4.0,TJSLiteral(E.B).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusMod;
Var
X : TJSExpressionStatement;
E : TJSAdditiveExpressionPlus;
R : TJSMultiplicativeExpressionMod;
begin
CreateParser('4 + 2 % 3;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSMultiplicativeExpressionMod);
R:=TJSMultiplicativeExpressionMod(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Mod left operand assigned',R.A);
AssertNotNull('Mod right operand assigned',R.B);
CheckClass(R.A,TJSLiteral);
CheckClass(R.B,TJSLiteral);
AssertEquals('Mod left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Mod left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertEquals('Mod right operand type correct', jstNumber, TJSLiteral(R.B).Value.ValueType);
AssertEquals('Mod right operand value correct', 3.0, TJSLiteral(R.B).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusPostPlusPlus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPostPlusPlusExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + 2++;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPostPlusPlusExpression);
R:=TJSUnaryPostPlusPlusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('++ operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusPostMinusMinus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPostMinusMinusExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + 2--;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPostMinusMinusExpression);
R:=TJSUnaryPostMinusMinusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('-- operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('-- operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('-- operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulPostPlusPlus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPostPlusPlusExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * 2++;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPostPlusPlusExpression);
R:=TJSUnaryPostPlusPlusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('++operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulPostMinusMinus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPostMinusMinusExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * 2--;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPostMinusMinusExpression);
R:=TJSUnaryPostMinusMinusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('-- operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('-- operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('-- operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusPrePlusPlus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPrePlusPlusExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + ++2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPrePlusPlusExpression);
R:=TJSUnaryPrePlusPlusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('++ operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('++ operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusInv;
Var
X : TJSExpressionStatement;
R : TJSUnaryInvExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + ~2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryInvExpression);
R:=TJSUnaryInvExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('inv operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('inv operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulInv;
Var
X : TJSExpressionStatement;
R : TJSUnaryInvExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * ~2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryInvExpression);
R:=TJSUnaryInvExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Inv operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Inv operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusNot;
Var
X : TJSExpressionStatement;
R : TJSUnaryNotExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + !2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryNotExpression);
R:=TJSUnaryNotExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Not operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Not operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Addition left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestFunctionCallNoArgs;
Var
X : TJSExpressionStatement;
C : TJSCallExpression;
begin
CreateParser('abc();');
X:=GetExpressionStatement;
CheckClass(X.A,TJSCallExpression);
C:=TJSCallExpression(X.A);
AssertEquals('No arguments',0,C.Args.Elements.Count);
AssertNotNull('Call function expression',C.Expr);
CheckClass(C.Expr,TJSPrimaryExpressionIdent);
AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).Name);
end;
procedure TTestJSParser.TestAwaitFunctionCallNoArgs;
Var
X : TJSExpressionStatement;
W : TJSAwaitExpression;
C : TJSCallExpression;
begin
CreateParser('await abc();',MinAwaitVersion);
X:=GetExpressionStatement;
CheckClass(X.A,TJSAwaitExpression);
W:=TJSAwaitExpression(X.A);
CheckClass(W.A,TJSCallExpression);
C:=TJSCallExpression(W.A);
AssertEquals('No arguments',0,C.Args.Elements.Count);
AssertNotNull('Call function expression',C.Expr);
CheckClass(C.Expr,TJSPrimaryExpressionIdent);
AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).Name);
end;
procedure TTestJSParser.TestFunctionCallOneArg;
Var
X : TJSExpressionStatement;
C : TJSCallExpression;
E : TJSelement;
begin
CreateParser('abc(d);');
X:=GetExpressionStatement;
CheckClass(X.A,TJSCallExpression);
C:=TJSCallExpression(X.A);
AssertNotNull('Call function expression',C.Expr);
CheckClass(C.Expr,TJSPrimaryExpressionIdent);
AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).Name);
AssertEquals('1 argument',1,C.Args.Elements.Count);
E:=C.Args.Elements[0].Expr;
AssertNotNull('First argument expression',E);
CheckClass(E,TJSPrimaryExpressionIdent);
AssertEquals('First argument name correct','d',TJSPrimaryExpressionIdent(E).Name);
end;
procedure TTestJSParser.TestFunctionCallTwoArgs;
Var
X : TJSExpressionStatement;
C : TJSCallExpression;
E : TJSelement;
begin
CreateParser('abc(d,e);');
X:=GetExpressionStatement;
CheckClass(X.A,TJSCallExpression);
C:=TJSCallExpression(X.A);
AssertNotNull('Call function expression',C.Expr);
CheckClass(C.Expr,TJSPrimaryExpressionIdent);
AssertEquals('Function name correct','abc',TJSPrimaryExpressionIdent(C.Expr).Name);
AssertEquals('2 arguments',2,C.Args.Elements.Count);
E:=C.Args.Elements[0].Expr;
AssertNotNull('First argument expression',E);
CheckClass(E,TJSPrimaryExpressionIdent);
AssertEquals('First argument name correct','d',TJSPrimaryExpressionIdent(E).Name);
E:=C.Args.Elements[1].Expr;
AssertNotNull('Second argument expression',E);
CheckClass(E,TJSPrimaryExpressionIdent);
AssertEquals('Second argument name correct','e',TJSPrimaryExpressionIdent(E).Name);
end;
procedure TTestJSParser.TestObjectGeneratorFunction;
Var
X : TJSExpressionStatement;
SA : TJSSimpleAssignStatement;
Obj : TJSObjectLiteral;
begin
CreateParser('a = {* g() { } };',MinGeneratorVersion);
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSSimpleAssignStatement);
SA:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Assignment LHS assigned',SA.LHS);
CheckClass(SA.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Expression LHS name correct', 'a',TJSPrimaryExpressionIdent(SA.LHS).Name);
AssertNotNull('Assignment Expression assigned',SA.Expr);
AssertEquals('Assignment Expression assigned',TJSObjectLiteral,SA.Expr.ClassType);
Obj:=TJSObjectLiteral(SA.Expr);
AssertEquals('Object element count',1,Obj.Elements.Count);
AssertEquals('Object element name','g',Obj.Elements[0].Name);
AssertEquals('Object element expression',TJSFunctionDeclarationStatement,Obj.Elements[0].Expr.ClassType);
AssertTrue('Generator',TJSFunctionDeclarationStatement(Obj.Elements[0].Expr).IsGenerator);
end;
procedure TTestJSParser.TestArrayExpressionNumericalArgs;
Var
X : TJSExpressionStatement;
B : TJSBracketMemberExpression;
begin
CreateParser('A[1];');
X:=GetExpressionStatement;
CheckClass(X.A,TJSBracketMemberExpression);
B:=TJSBracketMemberExpression(X.A);
CheckClass(B.Name,TJSLiteral);
AssertEquals('Member name operand type correct', jstNumber, TJSLiteral(B.Name).Value.ValueType);
AssertEquals('Member name operand value correct', 1.0, TJSLiteral(B.Name).Value.AsNumber);
CheckClass(B.Mexpr,TJSPrimaryExpressionIdent);
AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).Name);
end;
procedure TTestJSParser.TestArrayExpressionStringArgs;
Var
X : TJSExpressionStatement;
B : TJSBracketMemberExpression;
begin
CreateParser('A["propname"];');
X:=GetExpressionStatement;
CheckClass(X.A,TJSBracketMemberExpression);
B:=TJSBracketMemberExpression(X.A);
CheckClass(B.Name,TJSLiteral);
AssertEquals('Member name operand type correct', jstString, TJSLiteral(B.Name).Value.ValueType);
AssertEquals('Member name operand value correct', 'propname', TJSLiteral(B.Name).Value.AsString);
CheckClass(B.Mexpr,TJSPrimaryExpressionIdent);
AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).Name);
end;
procedure TTestJSParser.TestArrayExpressionIdentArgs;
Var
X : TJSExpressionStatement;
B : TJSBracketMemberExpression;
begin
CreateParser('A[B];');
X:=GetExpressionStatement;
CheckClass(X.A,TJSBracketMemberExpression);
B:=TJSBracketMemberExpression(X.A);
CheckClass(B.Name,TJSPrimaryExpressionIdent);
AssertEquals('Member name identifier correct', 'B', TJSPrimaryExpressionIdent(B.Name).Name);
CheckClass(B.Mexpr,TJSPrimaryExpressionIdent);
AssertEquals('Array name correct','A',TJSPrimaryExpressionIdent(B.Mexpr).Name);
end;
Procedure TTestJSParser.TestVarDeclarationSimple;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('var a;');
X:=GetFirstVar;
AssertNotNull('Variable statement assigned',(X));
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('correct variable type', vtVar, V.VarType);
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNull('No initialization expression', V.Init);
end;
procedure TTestJSParser.TestVarDeclarationInit;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('var a = 0;');
X:=GetFirstVar;
AssertNotNull('Variable statement assigned',(X));
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('correct variable type', vtVar, V.VarType);
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNotNull('initialization expression', V.Init);
CheckClass(V.Init,TJSLiteral);
AssertEquals('Init value correct', 0, TJSLiteral(V.init).Value.AsNumber);
end;
procedure TTestJSParser.TestLetDeclarationSimple;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('let a;',minLetVersion);
X:=GetFirstVar;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('correct variable type', vtLet, V.VarType);
// AssertNotNull('Variable statement assigned',(X));
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNull('No initialization expression', V.Init);
end;
procedure TTestJSParser.TestVarDeclarationDouble;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('var a, b ;');
AssertEquals('2 variables declared',2,GetVars.Count);
X:=GetFirstVar;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('correct variable type', vtVar, V.VarType);
// AssertNotNull('Variable statement assigned',(X));
AssertEquals('variable name correct registered', 'a', V.name);
X:=GetVars.Nodes[1].Node;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('correct variable type', vtVar, V.VarType);
AssertEquals('variable name correct registered', 'b', V.Name);
AssertNull('No initialization expression', V.Init);
end;
procedure TTestJSParser.TestVarDeclarationSimpleInit;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('var a = b;');
X:=GetFirstVar;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
// AssertNotNull('Variable statement assigned',(X));
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNotNull('Initialization expression present', V.Init);
CheckClass(V.Init,TJSPrimaryExpressionIdent);
AssertEquals('Member name identifier correct', 'b', TJSPrimaryExpressionIdent(V.init).Name);
end;
procedure TTestJSParser.TestConstDeclarationSimpleInit;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('const a = 1;',MinLetVersion);
X:=GetFirstVar;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
// AssertNotNull('Variable statement assigned',(X));
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNotNull('Initialization expression present', V.Init);
CheckClass(V.Init,TJSLiteral);
AssertEquals('Expression value type correct', jstNumber,TJSLiteral(V.Init).Value.ValueType);
AssertEquals('Expression value correct', 1.0, TJSLiteral(V.Init).Value.AsNumber);
end;
procedure TTestJSParser.TestVarDeclarationDoubleInit;
Var
X : TJSELement;
V : TJSVarDeclaration;
begin
CreateParser('var a, c = b;');
AssertEquals('2 variables declared',2,GetVars.Count);
X:=GetFirstVar;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
// AssertNotNull('Variable statement assigned',(X));
AssertEquals('variable name correct registered', 'a', V.Name);
AssertNull('No initialization expression', V.Init);
X:=GetVars.Nodes[1].Node;
CheckClass(X,TJSVarDeclaration);
V:=TJSVarDeclaration(X);
AssertEquals('variable name correct registered', 'c', V.Name);
AssertNotNull('No initialization expression', V.Init);
CheckClass(V.Init,TJSPrimaryExpressionIdent);
AssertEquals('Member name identifier correct', 'b', TJSPrimaryExpressionIdent(V.init).Name);
end;
procedure TTestJSParser.TestDebuggerStatement;
Var
E : TJSSourceElements;
X : TJSElement;
begin
CreateParser('debugger',MinDebuggerVersion);
E:=GetSourceElements;
AssertEquals('1 statement in block',1,E.Statements.Count);
X:=E.Statements.Nodes[0].Node;
CheckClass(X,TJSDebuggerStatement);
end;
procedure TTestJSParser.TestBlockEmpty;
Var
E : TJSSourceElements;
X : TJSElement;
begin
CreateParser('{}');
E:=GetSourceElements;
AssertEquals('1 statement in block',1,E.Statements.Count);
X:=E.Statements.Nodes[0].Node;
CheckClass(X,TJSEmptyBlockStatement);
end;
procedure TTestJSParser.TestBlockEmptyStatement;
Var
E : TJSSourceElements;
X : TJSElement;
begin
CreateParser('{;}');
E:=GetSourceElements;
AssertEquals('1 statement in block',1,E.Statements.Count);
X:=E.Statements.Nodes[0].Node;
CheckClass(X,TJSEmptyStatement);
end;
procedure TTestJSParser.TestBlockSimpleStatement;
Var
E : TJSSourceElements;
X : TJSElement;
begin
CreateParser('{a;}');
E:=GetSourceElements;
AssertEquals('1 statement in block',1,E.Statements.Count);
X:=E.Statements.Nodes[0].Node;
CheckClass(X,TJSExpressionStatement);
CheckNotNull(TJSExpressionStatement(X).A);
CheckClass(TJSExpressionStatement(X).A,TJSPrimaryExpressionIdent);
AssertEquals('Name','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(X).A).Name)
end;
procedure TTestJSParser.TestFunctionDeclarationEmpty;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('function a () {}');
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertFalse('Async function ',FD.AFunction.IsAsync);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('No parameters',0,FD.AFunction.TypedParams.Count);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('0 statement in functionbody elements',0,E.Statements.Count);
// TJSEmptyBlockStatement
end;
procedure TTestJSParser.TestFunctionDeclarationAsync;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('async function a () {}',MinAsyncVersion);
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertTrue('Async function ',FD.AFunction.IsAsync);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('No parameters',0,FD.AFunction.TypedParams.Count);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('0 statement in functionbody elements',0,E.Statements.Count);
end;
procedure TTestJSParser.TestFunctionDeclarationWithArgs;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('function a (b,c) {}');
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('2 parameters',2,FD.AFunction.TypedParams.Count);
AssertEquals('1st parameter','b',FD.AFunction.TypedParams[0].Name);
AssertEquals('2nd parameter','c',FD.AFunction.TypedParams[1].Name);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('0 statement in functionbody elements',0,E.Statements.Count);
// TJSEmptyBlockStatement
end;
procedure TTestJSParser.TestFunctionDeclarationWithSpreadArgs;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('function a (...b,c) {}');
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('2 parameters',2,FD.AFunction.TypedParams.Count);
AssertEquals('1st parameter','b',FD.AFunction.TypedParams[0].Name);
AssertEquals('1st parameter','b',FD.AFunction.TypedParams.Names[0]);
AssertTrue('1st parameter spread',FD.AFunction.TypedParams.Params[0].IsSpread);
AssertEquals('2nd parameter','c',FD.AFunction.TypedParams[1].Name);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('0 statement in functionbody elements',0,E.Statements.Count);
// TJSEmptyBlockStatement
end;
procedure TTestJSParser.TestFunctionDeclarationWithBody;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('function a () { b; }');
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('2 parameters',0,FD.AFunction.TypedParams.Count);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('1 statement in functionbody elements',1,E.Statements.Count);
N:=E.Statements.Nodes[0].Node;
CheckClass(N,TJSExpressionStatement);
CheckNotNull(TJSExpressionStatement(N).A);
CheckClass(TJSExpressionStatement(N).A,TJSPrimaryExpressionIdent);
AssertEquals('Name','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(N).A).Name);
// TJSEmptyBlockStatement
end;
procedure TTestJSParser.TestIfSimple;
Var
E : TJSElement;
I : TJSIfStatement;
begin
CreateParser('if (a) b;');
E:=GetFirstStatement;
CheckClass(E,TJSIfStatement);
I:=TJSIfStatement(E);
AssertNotNull('Statement condition assigned',I.Cond);
CheckClass(I.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(I.Cond).Name);
AssertNull('Statement false branch assigned',I.BFalse);
AssertNotNull('Statement true branch assigned',I.Btrue);
CheckClass(I.Btrue,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(I.BTrue).A);
CheckClass(TJSExpressionStatement(I.BTrue).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 2','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.Btrue).A).Name);
end;
procedure TTestJSParser.TestIfEmptyBlock;
Var
E : TJSElement;
I : TJSIfStatement;
begin
CreateParser('if (a) {}');
E:=GetFirstStatement;
CheckClass(E,TJSIfStatement);
I:=TJSIfStatement(E);
AssertNotNull('Statement condition assigned',I.Cond);
CheckClass(I.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(I.Cond).Name);
AssertNull('Statement false branch assigned',I.BFalse);
AssertNotNull('Statement true branch assigned',I.Btrue);
CheckClass(I.Btrue,TJSEmptyBlockStatement);
end;
procedure TTestJSParser.TestIfEmptyBlockElse;
Var
E : TJSElement;
I : TJSIfStatement;
begin
CreateParser('if (a) {} else b;');
E:=GetFirstStatement;
CheckClass(E,TJSIfStatement);
I:=TJSIfStatement(E);
AssertNotNull('Statement condition assigned',I.Cond);
CheckClass(I.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(I.Cond).Name);
AssertNotNull('Statement false branch assigned',I.BFalse);
AssertNotNull('Statement true branch assigned',I.Btrue);
CheckClass(I.Btrue,TJSEmptyBlockStatement);
end;
procedure TTestJSParser.TestWhileSimple;
Var
E : TJSElement;
W : TJSWhileStatement;
begin
CreateParser('while (a) b;');
E:=GetFirstStatement;
CheckClass(E,TJSWhileStatement);
W:=TJSWhileStatement(E);
AssertNotNull('Statement condition assigned',W.Cond);
CheckClass(W.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(W.Cond).Name);
AssertNotNull('Statement condition assigned',W.body);
CheckClass(W.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A);
CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).Name);
end;
procedure TTestJSParser.TestWhileBlock;
Var
E : TJSElement;
W : TJSWhileStatement;
// B : TJSBlockStatement;
begin
CreateParser('while (a) {b;}');
E:=GetFirstStatement;
CheckClass(E,TJSWhileStatement);
W:=TJSWhileStatement(E);
AssertNotNull('Statement condition assigned',W.Cond);
CheckClass(W.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(W.Cond).Name);
AssertNotNull('Statement condition assigned',W.body);
CheckClass(W.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A);
CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).Name);
end;
procedure TTestJSParser.TestDoWhileSimple;
Var
E : TJSElement;
W : TJSDoWhileStatement;
// B : TJSBlockStatement;
begin
CreateParser('do b; while (a);');
E:=GetFirstStatement;
CheckClass(E,TJSDoWhileStatement);
W:=TJSDoWhileStatement(E);
AssertNotNull('Statement condition assigned',W.Cond);
CheckClass(W.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(W.Cond).Name);
AssertNotNull('Statement condition assigned',W.body);
CheckClass(W.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A);
CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).Name);
end;
procedure TTestJSParser.TestDoWhileBlock;
Var
E : TJSElement;
W : TJSDoWhileStatement;
// B : TJSBlockStatement;
begin
CreateParser('do {b;} while (a);');
E:=GetFirstStatement;
CheckClass(E,TJSDoWhileStatement);
W:=TJSDoWhileStatement(E);
AssertNotNull('Statement condition assigned',W.Cond);
CheckClass(W.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(W.Cond).Name);
AssertNotNull('Statement condition assigned',W.body);
CheckClass(W.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(W.Body).A);
CheckClass(TJSExpressionStatement(W.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(W.Body).A).Name);
end;
procedure TTestJSParser.TestForEmpty;
Var
E : TJSElement;
F : TJSForStatement;
begin
CreateParser('for (;;) a;');
E:=GetFirstStatement;
CheckClass(E,TJSForStatement);
F:=TJSForStatement(E);
AssertNull('Statement condition not assigned',F.Cond);
AssertNull('Statement init not assigned',F.Init);
AssertNull('Statement step not assigned',F.Incr);
CheckClass(F.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A);
CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).Name);
end;
procedure TTestJSParser.TestForEmptyBody;
Var
E : TJSElement;
F : TJSForStatement;
begin
CreateParser('for (;;) {a;}');
E:=GetFirstStatement;
CheckClass(E,TJSForStatement);
F:=TJSForStatement(E);
AssertNull('Statement condition not assigned',F.Cond);
AssertNull('Statement init not assigned',F.Init);
AssertNull('Statement step not assigned',F.Incr);
CheckClass(F.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A);
CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).Name);
end;
procedure TTestJSParser.TestForSimpleBody;
Var
E : TJSElement;
F : TJSForStatement;
begin
CreateParser('for (a;b;c) {d;}');
E:=GetFirstStatement;
CheckClass(E,TJSForStatement);
F:=TJSForStatement(E);
AssertNotNull('Statement condition not assigned',F.Cond);
AssertNotNull('Statement init not assigned',F.Init);
AssertNotNull('Statement step not assigned',F.Incr);
CheckClass(F.Init,TJSPrimaryExpressionIdent);
AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Init));
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(F.Init).Name);
CheckClass(F.Incr,TJSPrimaryExpressionIdent);
AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Incr));
AssertEquals('Name 2','c',TJSPrimaryExpressionIdent(F.Incr).Name);
CheckClass(F.Cond,TJSPrimaryExpressionIdent);
AssertNotNull('Expression statement expression',TJSPrimaryExpressionIdent(F.Cond));
AssertEquals('Name 3','b',TJSPrimaryExpressionIdent(F.cond).Name);
CheckClass(F.Body,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(F.Body).A);
CheckClass(TJSExpressionStatement(F.Body).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 4','d',TJSPrimaryExpressionIdent(TJSExpressionStatement(F.Body).A).Name);
end;
procedure TTestJSParser.TestTryCatch;
Var
E : TJSElement;
T : TJSTryCatchStatement;
begin
CreateParser('try {a;} catch (e) {b;}');
E:=GetFirstStatement;
CheckClass(E,TJSTryCatchStatement);
T:=TJSTryCatchStatement(E);
CheckClass(T.Block,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A);
CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).Name);
CheckClass(T.BCatch,TJSExpressionStatement);
AssertEquals('Except object identifier name','e',T.Ident);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BCatch).A);
CheckClass(TJSExpressionStatement(T.BCatch).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 2','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BCatch).A).Name);
AssertNull('No Finally expression',T.BFinally);
end;
procedure TTestJSParser.TestTryCatchFinally;
Var
E : TJSElement;
T : TJSTryCatchFinallyStatement;
begin
CreateParser('try {a;} catch (e) {b;} finally {c;}');
E:=GetFirstStatement;
CheckClass(E,TJSTryCatchFinallyStatement);
T:=TJSTryCatchFinallyStatement(E);
CheckClass(T.Block,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A);
CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).Name);
AssertEquals('Except object identifier name','e',T.Ident);
CheckClass(T.BCatch,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BCatch).A);
CheckClass(TJSExpressionStatement(T.BCatch).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 2','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BCatch).A).Name);
AssertNotNull('Finally expression',T.BFinally);
CheckClass(T.BFinally,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.BFinally).A);
CheckClass(TJSExpressionStatement(T.BFinally).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 3','c',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BFinally).A).Name);
end;
procedure TTestJSParser.TestTryFinally;
Var
E : TJSElement;
T : TJSTryFinallyStatement;
begin
CreateParser('try {a;} finally {c;}');
E:=GetFirstStatement;
CheckClass(E,TJSTryFinallyStatement);
T:=TJSTryFinallyStatement(E);
CheckClass(T.Block,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(T.Block).A);
CheckClass(TJSExpressionStatement(T.Block).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.Block).A).Name);
AssertNull('No catch',T.BCatch);
AssertNotNull('Finally expression',T.BFinally);
AssertNotNull('Finally expression',TJSExpressionStatement(T.BFinally).A);
CheckClass(TJSExpressionStatement(T.BFinally).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 2','c',TJSPrimaryExpressionIdent(TJSExpressionStatement(T.BFinally).A).Name);
end;
procedure TTestJSParser.TestThrow;
Var
E : TJSElement;
T : TJSThrowStatement;
begin
CreateParser('throw a;');
E:=GetFirstStatement;
CheckClass(E,TJSThrowStatement);
T:=TJSThrowStatement(E);
AssertNotNull('Have throw object',T.A);
CheckClass(T.A,TJSPrimaryExpressionIdent);
AssertEquals('Correct identifier','a',TJSPrimaryExpressionIdent(T.A).Name);
end;
procedure TTestJSParser.TestReturn;
Var
E : TJSSourceElements;
N : TJSElement;
FD : TJSFunctionDeclarationStatement;
begin
CreateParser('function a () { return b; }');
E:=GetSourceElements;
AssertEquals('1 function defined',1,E.functions.Count);
N:=E.Functions.Nodes[0].Node;
AssertNotNull('Function element defined ',N);
CheckClass(N,TJSFunctionDeclarationStatement);
FD:=TJSFunctionDeclarationStatement(N);
AssertNotNull('Function definition assigned',FD.AFunction);
AssertEquals('Function name OK','a',FD.AFunction.Name);
AssertNotNull('Function body assigned', FD.AFunction.Body);
AssertEquals('No parameters',0,FD.AFunction.TypedParams.Count);
N:=FD.AFunction.Body;
CheckClass(N,TJSFunctionBody);
AssertNotNull('Function body has element',TJSFunctionBody(N).A);
CheckClass(TJSFunctionBody(N).A, TJSSourceElements);
E:=TJSSourceElements(TJSFunctionBody(N).A);
AssertEquals('1 statement in functionbody elements',1,E.Statements.Count);
end;
procedure TTestJSParser.TestAssignment;
Var
E : TJSElement;
ES : TJSExpressionStatement;
A : TJSSimpleAssignStatement;
begin
CreateParser('a=b;');
E:=GetFirstStatement;
CheckClass(E,TJSExpressionStatement);
ES:=TJSExpressionStatement(E);
CheckClass(ES.A,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(ES.A);
AssertNotNull('Have LHS',A.LHS);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Have LHS name','a',TJSPrimaryExpressionIdent(A.LHS).Name);
CheckClass(A.Expr,TJSPrimaryExpressionIdent);
AssertEquals('Have RHS name','b',TJSPrimaryExpressionIdent(A.Expr).Name);
end;
procedure TTestJSParser.TestNew;
Var
E : TJSElement;
ES : TJSExpressionStatement;
A : TJSSimpleAssignStatement;
N : TJSNewMemberExpression;
L : TJSLiteral;
begin
CreateParser('a = new b(123)');
E:=GetFirstStatement;
CheckClass(E,TJSExpressionStatement);
ES:=TJSExpressionStatement(E);
CheckClass(ES.A,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(ES.A);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Have LHS name','a',TJSPrimaryExpressionIdent(A.LHS).Name);
CheckClass(A.Expr,TJSNewMemberExpression);
N:=TJSNewMemberExpression(A.Expr);
AssertNotNull('Have LHS name',N.Mexpr);
CheckClass(N.Mexpr,TJSPrimaryExpressionIdent);
AssertEquals('Have LHS name','b',TJSPrimaryExpressionIdent(N.Mexpr).Name);
AssertNotNull('Have arguments',N.Args);
AssertEquals('One argument',1,N.Args.Elements.Count);
AssertNotNull('Have argument 0',N.Args.Elements[0].Expr);
CheckClass(N.Args.Elements[0].Expr,TJSLiteral);
L:=TJSLiteral(N.Args.Elements[0].Expr);
AssertNotNull('Expression value assigned',L.Value);
AssertEquals('Expression value type correct', jstNumber,L.Value.ValueType);
AssertEquals('Expression value correct', 123,L.Value.AsNumber);
end;
procedure TTestJSParser.TestLabeledStatement;
Var
E : TJSElement;
ES : TJSExpressionStatement;
A : TJSSimpleAssignStatement;
N : TJSNewMemberExpression;
L : TJSLiteral;
LS : TJSLabeledStatement;
begin
CreateParser('loc: a = new b(123)');
E:=GetFirstStatement;
CheckClass(E,TJSLabeledStatement);
LS:=TJSLabeledStatement(E);
AssertNotNull('Have label',LS.TheLabel);
AssertEquals('Have correct label','loc',LS.TheLabel.Name);
CheckClass(LS.A,TJSExpressionStatement);
ES:=TJSExpressionStatement(LS.A);
CheckClass(ES.A,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(ES.A);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Have LHS name','a',TJSPrimaryExpressionIdent(A.LHS).Name);
CheckClass(A.Expr,TJSNewMemberExpression);
N:=TJSNewMemberExpression(A.Expr);
AssertNotNull('Have LHS name',N.Mexpr);
CheckClass(N.Mexpr,TJSPrimaryExpressionIdent);
AssertEquals('Have LHS name','b',TJSPrimaryExpressionIdent(N.Mexpr).Name);
AssertNotNull('Have arguments',N.Args);
AssertEquals('One argument',1,N.Args.Elements.Count);
AssertNotNull('Have argument 0',N.Args.Elements[0].Expr);
CheckClass(N.Args.Elements[0].Expr,TJSLiteral);
L:=TJSLiteral(N.Args.Elements[0].Expr);
AssertNotNull('Expression value assigned',L.Value);
AssertEquals('Expression value type correct', jstNumber,L.Value.ValueType);
AssertEquals('Expression value correct', 123,L.Value.AsNumber);
end;
procedure TTestJSParser.TestContinue;
Var
E : TJSElement;
C : TJSContinueStatement;
begin
CreateParser('while (true) continue;');
E:=GetFirstStatement;
CheckClass(E,TJSWhileStatement);
E:=TJSWhileStatement(E).Body;
CheckClass(E,TJSContinueStatement);
C:=TJSContinueStatement(E);
AssertEquals('Have correct (empty) label','',C.TargetName);
end;
procedure TTestJSParser.TestContinueTarget;
Var
E : TJSElement;
C : TJSContinueStatement;
begin
CreateParser('a: while (true) continue a;');
E:=GetFirstStatement;
CheckClass(E,TJSLabeledStatement);
E:=TJSLabeledStatement(E).A;
CheckClass(E,TJSWhileStatement);
E:=TJSWhileStatement(E).Body;
CheckClass(E,TJSContinueStatement);
C:=TJSContinueStatement(E);
AssertEquals('Have correct label','a',C.TargetName);
end;
procedure TTestJSParser.TestBreakTarget;
Var
E : TJSElement;
C : TJSBreakStatement;
begin
CreateParser('a: while (true) break a;');
E:=GetFirstStatement;
CheckClass(E,TJSLabeledStatement);
E:=TJSLabeledStatement(E).A;
CheckClass(E,TJSWhileStatement);
E:=TJSWhileStatement(E).Body;
CheckClass(E,TJSBreakStatement);
C:=TJSBreakStatement(E);
AssertEquals('Have correct label','a',C.TargetName);
end;
procedure TTestJSParser.TestSwitchEmpty;
Var
E : TJSElement;
S : TJSSwitchStatement;
begin
CreateParser('switch (a) {}');
E:=GetFirstStatement;
CheckClass(E,TJSSwitchStatement);
S:=TJSSwitchStatement(E);
AssertNotNull('Have condition',S.Cond);
AssertNull('Have no default',S.TheDefault);
AssertIdentifier('Case condition',S.Cond,'a');
S:=TJSSwitchStatement(E);
AssertEquals('No cases',0,S.Cases.Count)
end;
procedure TTestJSParser.TestSwitchOne;
Var
E : TJSElement;
S : TJSSwitchStatement;
C : TJSCaseElement;
begin
CreateParser('switch (a) { case c : {}}');
E:=GetFirstStatement;
CheckClass(E,TJSSwitchStatement);
S:=TJSSwitchStatement(E);
AssertNotNull('Have condition',S.Cond);
AssertNull('Have no default',S.TheDefault);
AssertIdentifier('Case condition',S.Cond,'a');
S:=TJSSwitchStatement(E);
AssertEquals('1 case',1,S.Cases.Count);
C:=TJSCaseElement(S.Cases[0]);
AssertIdentifier('Case expression',C.Expr,'c');
CheckClass(C.Body,TJSEmptyBlockStatement);
end;
procedure TTestJSParser.TestSwitchTwo;
Var
E : TJSElement;
S : TJSSwitchStatement;
C : TJSCaseElement;
begin
CreateParser('switch (a) { case c: {}'+sLineBreak+' case d: {}}');
E:=GetFirstStatement;
CheckClass(E,TJSSwitchStatement);
S:=TJSSwitchStatement(E);
AssertNotNull('Have condition',S.Cond);
AssertNull('Have no default',S.TheDefault);
AssertIdentifier('Case condition',S.Cond,'a');
S:=TJSSwitchStatement(E);
AssertEquals('2 cases',2,S.Cases.Count);
C:=TJSCaseElement(S.Cases[0]);
AssertIdentifier('Case expression',C.Expr,'c');
CheckClass(C.Body,TJSEmptyBlockStatement);
C:=TJSCaseElement(S.Cases[1]);
AssertIdentifier('Case expression',C.Expr,'d');
CheckClass(C.Body,TJSEmptyBlockStatement);
end;
procedure TTestJSParser.TestSwitchTwoDefault;
Var
E : TJSElement;
S : TJSSwitchStatement;
C : TJSCaseElement;
begin
CreateParser('switch (a) { case c: {} case d: {} default: {}}');
E:=GetFirstStatement;
CheckClass(E,TJSSwitchStatement);
S:=TJSSwitchStatement(E);
AssertNotNull('Have condition',S.Cond);
AssertNotNull('Have default',S.TheDefault);
AssertIdentifier('Case condition',S.Cond,'a');
S:=TJSSwitchStatement(E);
AssertEquals('2 cases',3,S.Cases.Count);
C:=TJSCaseElement(S.Cases[0]);
AssertIdentifier('Case expression',C.Expr,'c');
CheckClass(C.Body,TJSEmptyBlockStatement);
C:=TJSCaseElement(S.Cases[1]);
AssertIdentifier('Case expression',C.Expr,'d');
CheckClass(C.Body,TJSEmptyBlockStatement);
C:=TJSCaseElement(S.Cases[2]);
CheckClass(C.Body,TJSEmptyBlockStatement);
AssertSame('Default',C,S.TheDefault);
end;
procedure TTestJSParser.TestImportModule;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
begin
CreateParser('import "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertFalse('Named imports',Imp.HaveNamedImports);
end;
procedure TTestJSParser.TestImportImportedDefault;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
begin
CreateParser('import A from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','A',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertFalse('Named imports',Imp.HaveNamedImports);
end;
procedure TTestJSParser.TestImportNamespaceImport;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
begin
CreateParser('import * as A from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','A',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertFalse('Named imports',Imp.HaveNamedImports);
end;
procedure TTestJSParser.TestImportImportedDefaultAndNamespaceImport;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
begin
CreateParser('import A, * as B from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','A',Imp.DefaultBinding);
AssertEquals('NamespaceImport','B',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertFalse('Named imports',Imp.HaveNamedImports);
end;
procedure TTestJSParser.TestImportNamedImport;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import {A} from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',1,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name','A',NamedImp.Name);
AssertEquals('Named import alias','',NamedImp.Alias);
end;
procedure TTestJSParser.TestImportNamedImportAlias;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import {A as C} from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',1,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name','A',NamedImp.Name);
AssertEquals('Named import alias','C',NamedImp.Alias);
end;
procedure TTestJSParser.TestImport2NamedImports;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import {A, B} from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',2,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name 1','A',NamedImp.Name);
AssertEquals('Named import alias 1','',NamedImp.Alias);
NamedImp:=Imp.NamedImports[1];
AssertEquals('Named import name 2','B',NamedImp.Name);
AssertEquals('Named import alias 2','',NamedImp.Alias);
end;
procedure TTestJSParser.TestImport2NamedImportAlias;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import {A as C, B as D} from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',2,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name 1','A',NamedImp.Name);
AssertEquals('Named import alias 1','C',NamedImp.Alias);
NamedImp:=Imp.NamedImports[1];
AssertEquals('Named import name 2','B',NamedImp.Name);
AssertEquals('Named import alias 2','D',NamedImp.Alias);
end;
procedure TTestJSParser.TestImport2NamedImportsComma;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import {A, B, } from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',2,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name 1','A',NamedImp.Name);
AssertEquals('Named import alias 1','',NamedImp.Alias);
NamedImp:=Imp.NamedImports[1];
AssertEquals('Named import name 2','B',NamedImp.Name);
AssertEquals('Named import alias 2','',NamedImp.Alias);
end;
procedure TTestJSParser.TestImportDefaultAndNamedImport;
Var
E : TJSElement;
Imp : TJSImportStatement absolute E;
NamedImp : TJSNamedImportElement;
begin
CreateParser('import D, {A} from "a.js"',MinImportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSImportStatement);
AssertEquals('DefaultImportedName','D',Imp.DefaultBinding);
AssertEquals('NamespaceImport','',Imp.NameSpaceImport);
AssertEquals('Modulename','a.js',Imp.ModuleName);
AssertTrue('Named imports',Imp.HaveNamedImports);
AssertEquals('Named import count',1,Imp.NamedImports.Count);
NamedImp:=Imp.NamedImports[0];
AssertEquals('Named import name','A',NamedImp.Name);
AssertEquals('Named import alias','',NamedImp.Alias);
end;
procedure TTestJSParser.TestExportAll;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
begin
CreateParser('export *',MinExportVersion);
E:=GetFirstStatement;
AssertFalse('Default',Exp.IsDefault);
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','*',Exp.NameSpaceExport);
AssertNull('Declaration',Exp.Declaration);
AssertEquals('ModuleName','',Exp.ModuleName);
AssertFalse('ExportNames',Exp.HaveExportNames);
end;
procedure TTestJSParser.TestExportAllFrom;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
begin
CreateParser('export * from "a.js"',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','*',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNull('Declaration',Exp.Declaration);
AssertEquals('ModuleName','a.js',Exp.ModuleName);
AssertFalse('ExportNames',Exp.HaveExportNames);
end;
procedure TTestJSParser.TestExportExportName;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
El : TJSExportNameElement;
begin
CreateParser('export { a }',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNull('Declaration',Exp.Declaration);
AssertEquals('ModuleName','',Exp.ModuleName);
AssertTrue('ExportNames',Exp.HaveExportNames);
AssertEquals('ExportNames count',1,Exp.ExportNames.Count);
El:=Exp.ExportNames[0];
AssertEquals('ExportNames[0].Name','a',El.Name);
AssertEquals('ExportNames[0].Name','',El.Alias);
end;
procedure TTestJSParser.TestExportExportNameAlias;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
El : TJSExportNameElement;
begin
CreateParser('export { a as b }',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNull('Declaration',Exp.Declaration);
AssertEquals('ModuleName','',Exp.ModuleName);
AssertTrue('ExportNames',Exp.HaveExportNames);
AssertEquals('ExportNames count',1,Exp.ExportNames.Count);
El:=Exp.ExportNames[0];
AssertEquals('ExportNames[0].Name','a',El.Name);
AssertEquals('ExportNames[0].Name','b',El.Alias);
end;
procedure TTestJSParser.TestExportVar;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
V : TJSVariableStatement;
begin
CreateParser('export var a = 1',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSVariableStatement);
V:=TJSVariableStatement(Exp.Declaration);
AssertEquals('var type',vtVar,V.varType);
CheckClass(V.VarDecl,TJSVarDeclaration);
AssertEquals('Variable name','a',TJSVarDeclaration(V.VarDecl).Name);
end;
procedure TTestJSParser.TestExportLet;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
V : TJSVariableStatement;
begin
CreateParser('export let a = 1',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSVariableStatement);
V:=TJSVariableStatement(Exp.Declaration);
AssertEquals('var type',vtLet,V.varType);
CheckClass(V.VarDecl,TJSVarDeclaration);
AssertEquals('Variable name','a',TJSVarDeclaration(V.VarDecl).Name);
end;
procedure TTestJSParser.TestExportConst;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
V : TJSVariableStatement;
begin
CreateParser('export const a = 1',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSVariableStatement);
V:=TJSVariableStatement(Exp.Declaration);
AssertEquals('var type',vtConst,V.varType);
CheckClass(V.VarDecl,TJSVarDeclaration);
AssertEquals('Variable name','a',TJSVarDeclaration(V.VarDecl).Name);
end;
procedure TTestJSParser.TestExportFunction;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
F : TJSFunctionDeclarationStatement;
begin
CreateParser('export function a () { return 1; } ',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertFalse('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSFunctionDeclarationStatement);
F:=TJSFunctionDeclarationStatement(Exp.Declaration);
AssertNotNull('Have function', F.AFunction);
AssertEquals('Variable name','a',F.AFunction.Name);
end;
procedure TTestJSParser.TestExportDefaultAssignment;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
A : TJSAssignStatement;
begin
CreateParser('export default a = 1',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertTrue('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(Exp.Declaration);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Operator token',jstoken.tjsASSIGN,A.OperatorToken);
AssertEquals('Variable name','a',TJSPrimaryExpressionIdent(A.LHS).Name);
end;
procedure TTestJSParser.TestExportDefaultFunction;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
F : TJSFunctionDeclarationStatement;
begin
CreateParser('export default function a () { return 1; } ',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertTrue('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSFunctionDeclarationStatement);
F:=TJSFunctionDeclarationStatement(Exp.Declaration);
AssertNotNull('Have function', F.AFunction);
AssertEquals('Variable name','a',F.AFunction.Name);
AssertFalse('Async',F.AFunction.IsAsync);
end;
procedure TTestJSParser.TestExportDefaultAsyncFunction;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
F : TJSFunctionDeclarationStatement;
begin
CreateParser('export default async function a () { return 1; } ',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertTrue('Default',Exp.IsDefault);
AssertNotNull('Declaration',Exp.Declaration);
CheckClass(Exp.Declaration,TJSFunctionDeclarationStatement);
F:=TJSFunctionDeclarationStatement(Exp.Declaration);
AssertNotNull('Have function', F.AFunction);
AssertEquals('Variable name','a',F.AFunction.Name);
AssertTrue('Async',F.AFunction.IsAsync);
end;
procedure TTestJSParser.TestClass;
begin
CreateParser('class Rectangle { } ',MinClassVersion);
AssertEquals('class name correct','Rectangle',GetFirstClass.Name);
AssertNull('class extends name correct',GetFirstClass.Extends);
end;
procedure TTestJSParser.TestClassExtends;
Var
Ext: TJSTypeReference;
begin
CreateParser('class Rectangle extends Shape { function myMethod () { return null; } } ',MinClassVersion);
AssertEquals('class name correct','Rectangle',GetFirstClass.Name);
Ext:=TJSTypeReference(CheckClass('Extends is type ref',TJSTypeReference,GetFirstClass.Extends));
AssertEquals('class extends name correct','Shape',Ext.Name);
end;
procedure TTestJSParser.TestClassWithMethod;
begin
CreateParser('class Rectangle { function myMethod () { return null; } } ',MinClassVersion);
AssertEquals('class name correct','Rectangle',GetFirstClass.Name);
AssertNull('class extends name correct',GetFirstClass.Extends);
AssertNotNull('Have members',GetFirstClass.Members);
AssertEquals('Have functions',1,GetFirstClass.Members.Functions.Count);
end;
procedure TTestJSParser.TestClassExpression;
Var
X : TJSExpressionStatement;
A : TJSSimpleAssignStatement;
begin
CreateParser('a = class Rectangle { } ',MinClassVersion);
X:=GetExpressionStatement;
CheckClass(X.A,TJSSimpleAssignStatement);
A:=TJSSimpleAssignStatement(X.A);
AssertNotNull('Have left operand',A.LHS);
CheckClass(A.LHS,TJSPrimaryExpressionIdent);
AssertEquals('Correct name for assignment LHS ','a',TJSPrimaryExpressionIdent(A.LHS).Name);
end;
procedure TTestJSParser.TestLetClassExpression;
Var
aVars : TJSVariableStatement;
aVarDecl : TJSVarDeclaration;
aClass : TJSClassDeclaration;
begin
CreateParser('let a = class Rectangle { } ',MinClassVersion);
AssertEquals('class name correct',TJSVariableStatement, GetFirstStatement.ClassType);
aVars:=TJSVariableStatement(GetFirstStatement);
AssertEquals('First class node is var declaration',TJSVarDeclaration,aVars.VarDecl.ClassType);
aVarDecl:=TJSVarDeclaration(aVars.VarDecl);
AssertNotNull('Var declaration has init',aVarDecl.Init);
AssertEquals('Init is class declaration',TJSClassDeclaration,aVarDecl.Init.ClassType);
aClass:=TJSClassDeclaration(aVarDecl.Init);
AssertEquals('class name correct','Rectangle',aClass.Name);
end;
procedure TTestJSParser.TestExportExportNameFrom;
Var
E : TJSElement;
Exp : TJSExportStatement absolute E;
El : TJSExportNameElement;
begin
CreateParser('export { a } from "a.js"',MinExportVersion);
E:=GetFirstStatement;
CheckClass(E,TJSExportStatement);
AssertEquals('NameSpaceExport','',Exp.NameSpaceExport);
AssertNull('Declaration',Exp.Declaration);
AssertEquals('ModuleName','a.js',Exp.ModuleName);
AssertTrue('ExportNames',Exp.HaveExportNames);
AssertEquals('ExportNames count',1,Exp.ExportNames.Count);
El:=Exp.ExportNames[0];
AssertEquals('ExportNames[0].Name','a',El.Name);
AssertEquals('ExportNames[0].Name','',El.Alias);
end;
procedure TTestJSParser.TestBreak;
Var
E : TJSElement;
C : TJSBreakStatement;
begin
CreateParser('while (true) break;');
E:=GetFirstStatement;
CheckClass(E,TJSWhileStatement);
E:=TJSWhileStatement(E).Body;
CheckClass(E,TJSBreakStatement);
C:=TJSBreakStatement(E);
AssertEquals('Have correct (empty) label','',C.TargetName);
end;
procedure TTestJSParser.TestIfElseSimple;
Var
E : TJSElement;
I : TJSIfStatement;
begin
CreateParser('if (a) b; else c;');
E:=GetFirstStatement;
CheckClass(E,TJSIfStatement);
I:=TJSIfStatement(E);
AssertNotNull('Statement condition assigned',I.Cond);
CheckClass(I.Cond,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','a',TJSPrimaryExpressionIdent(I.Cond).Name);
AssertNotNull('Statement condition assigned',I.Btrue);
CheckClass(I.Btrue,TJSExpressionStatement);
AssertNotNull('Expression statement expression',TJSExpressionStatement(I.BTrue).A);
CheckClass(TJSExpressionStatement(I.BTrue).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','b',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.Btrue).A).Name);
AssertNotNull('Else Statement condition assigned',I.BFalse);
CheckClass(I.BFalse,TJSExpressionStatement);
AssertNotNull('Else statement expression',TJSExpressionStatement(I.BFalse).A);
CheckClass(TJSExpressionStatement(I.BFalse).A,TJSPrimaryExpressionIdent);
AssertEquals('Name 1','c',TJSPrimaryExpressionIdent(TJSExpressionStatement(I.BFalse).A).Name);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulNot;
Var
X : TJSExpressionStatement;
R : TJSUnaryNotExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * !2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryNotExpression);
R:=TJSUnaryNotExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Not operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Not operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Multiplication left operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedencePlusPreMinusMinus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPreMinusMinusExpression;
E : TJSAdditiveExpressionPlus;
begin
CreateParser('4 + --2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSAdditiveExpressionPlus);
E:=TJSAdditiveExpressionPlus(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPreMinusMinusExpression);
R:=TJSUnaryPreMinusMinusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulPrePlusPlus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPrePlusPlusExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * ++2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPrePlusPlusExpression);
R:=TJSUnaryPrePlusPlusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestExpressionPrecedenceMulPreMinusMinus;
Var
X : TJSExpressionStatement;
R : TJSUnaryPreMinusMinusExpression;
E : TJSMultiplicativeExpressionMul;
begin
CreateParser('4 * --2;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSMultiplicativeExpressionMul);
E:=TJSMultiplicativeExpressionMul(X.A);
AssertNotNull('Expression left operand assigned',E.A);
AssertNotNull('Expression right operand assigned',E.B);
CheckClass(E.B,TJSUnaryPreMinusMinusExpression);
R:=TJSUnaryPreMinusMinusExpression(E.B);
CheckClass(E.A,TJSLiteral);
AssertNotNull('Multiplication left operand assigned',R.A);
CheckClass(R.A,TJSLiteral);
AssertEquals('Multiplication left operand type correct', jstNumber, TJSLiteral(R.A).Value.ValueType);
AssertEquals('Multiplication left operand value correct', 2.0, TJSLiteral(R.A).Value.AsNumber);
AssertNotNull('Addition right operand value assigned',TJSLiteral(E.A).Value);
AssertEquals('Addition left operand type correct', jstNumber, TJSLiteral(E.A).Value.ValueType);
AssertEquals('Expression right operand value correct', 4.0,TJSLiteral(E.A).Value.AsNumber);
end;
procedure TTestJSParser.TestSimpleExpressionBooleanLiteralTrue;
Var
X : TJSExpressionStatement;
begin
CreateParser('true;');
X:=GetExpressionStatement;
AssertNotNull('Expression statement assigned',X.A);
CheckClass(X.A,TJSLiteral);
AssertNotNull('Expression value assigned',TJSLiteral(X.A).Value);
AssertEquals('Expression value type correct', jstBoolean,TJSLiteral(X.A).Value.ValueType);
AssertEquals('Expression value correct', True, TJSLiteral(X.A).Value.AsBoolean);
end;
procedure TTestJSParser.TestEmpty;
Var
E : TJSElement;
FB : TJSFunctionBody;
SE : TJSSourceElements;
begin
CreateParser('var a;');
E:=FParser.Parse;
try
CheckClass(E,TJSFunctionBody);
FB:=TJSFunctionBody(E);
AssertNotNull(FB.A);
CheckClass(FB.A,TJSSourceElements);
SE:=TJSSourceElements(FB.A);
AssertEquals('1 variable declaration ',1,SE.Vars.Count);
CheckClass(FB.A,TJSSourceElements);
finally
E.Free;
end;
end;
initialization
RegisterTest(TTestJSParser);
end.