pax_javascript.pas
来自「Delphi脚本控件」· PAS 代码 · 共 2,775 行 · 第 1/5 页
PAS
2,775 行
SymbolTable.Position[SubID] := SymbolTable.Position[LeftSideID]
else
SymbolTable.Position[SubID] := SymbolTable.Position[ClassID];
result := SubID;
Name[SubID] := Name[ClassID];
LevelStack.PushSub(SubID, CurrClassID, ml);
ResID := NewVar;
NewVar;
Match('(');
DeclareSwitch := true;
Call_SCANNER;
ParamCount := 0;
if not IsCurrText(')') then
repeat
Inc(ParamCount);
ParamID := Parse_Ident;
if IsCurrText('=') then
begin
TempCard := SymbolTable.Card;
Call_SCANNER;
ValID := Parse_AssignmentExpression;
with TPaxBaseScripter(Scripter) do
DefaultParameterList.AddParameter(SubID, ParamID,
SymbolTable.VariantValue[ValID]);
SymbolTable.EraseTail(TempCard);
end;
if IsCurrText(',') then
Call_SCANNER
else
Break;
until false;
DeclareSwitch := false;
Match(')');
Kind[SubID] := KindSUB;
Count[SubID] := ParamCount;
Next[SubID] := ResID;
TypeSub[SubID] := tsConstructor;
if Code.Prog[Code.Card].OP = OP_SEPARATOR then
Value[SubID] := Code.Card
else
Value[SubID] := Code.Card + 1;
Name[CurrThisID] := 'this';
if LeftSideClassID > 0 then
TypeID[CurrThisID] := LeftSideClassID
else
TypeID[CurrThisID] := ClassID;
if TPAXJavaScriptScanner(Scanner).UsesIdent('arguments') then
begin
for I:=ParamCount + 1 to MaxArg do
begin
ID1 := NewVar;
Name[ID1] := '_' + IntToStr(I);
end;
ArgumentsID := NewVar;
Name[ArgumentsID] := 'arguments';
CreateArguments;
end;
{
if TPAXJavaScriptScanner(Scanner).UsesIdent('this') then
begin
// 29 Line 5 this = base.Function(); :20009
// 32 CREATE REF this[20011] 1 Function[20013]
// 33 CALL Function[20013] 0 $$20014
// 34 := this[20011] $$20014 this[20011]
ID1 := NewVar;
ID2 := NewVar;
Name[ID1] := 'Function';
GenRef(CurrThisID, maMyBase, ID1);
Gen(OP_CALL, ID1, 0, ID2);
Gen(OP_ASSIGN, CurrThisID, ID2, CurrThisID);
end;
}
Call_SCANNER;
Match('{');
Gen(OP_DECLARE_OFF, 0, 0, 0);
Parse_Block;
GenDestroyLocalVars;
Gen(OP_RET, 0, 0, 0);
SetLabelHere(L);
Gen(OP_SAVE_RESULT, ClassID, 0, 0);
if TPaxBaseScripter(Scripter).EvalCount > 0 then
Gen(OP_ASSIGN, PrototypeID, FunctionObjectID, PrototypeID)
else
begin
ID1 := NewVar;
Name[ID1] := 'Function';
SymbolTable.Level[ID1] := -1;
Gen(OP_EVAL_WITH, 0, 0, ID1);
ID2 := NewVar;
Gen(OP_CREATE_OBJECT, ID1, 0, ID2);
Gen(OP_CREATE_REF, ID2, 0, ID1);
Gen(OP_CALL, ID1, 0, ID1);
Gen(OP_ASSIGN, PrototypeID, ID1, PrototypeID);
end;
ID1 := NewField('constructor');
Gen(OP_CREATE_REF, PrototypeID, 0, ID1);
Gen(OP_ASSIGN, ID1, ClassID, ID1);
LevelStack.Pop;
LevelStack.Pop;
LinkVariables(SubID, false);
Call_SCANNER;
end;
procedure TPaxJavaScriptParser.Parse_ReturnStmt;
var
ResID: Integer;
begin
// match "return"
ResID := SymbolTable.GetResultID(CurrLevel);
Call_SCANNER;
if not IsCurrText(';') then
Gen(OP_ASSIGN_RESULT, ResID, Parse_Expression, ResID);
Gen(OP_RETURN, 0, 0, 0);
end;
procedure TPaxJavaScriptParser.Parse_HaltStmt;
begin
// match "halt"
Call_SCANNER;
if not IsCurrText(';') then
Call_SCANNER;
Gen(OP_HALT_GLOBAL, 0, 0, 0);
end;
procedure TPaxJavaScriptParser.Parse_SwitchStmt;
procedure Match(const S: String);
begin
Self.Match(S);
Call_SCANNER;
end;
var
lg, l_default, bool_id, expr_id, case_expr_id, lf, l_skip, I, N1, N2: Integer;
lt: TPaxStack;
n_skips: TPaxIds;
begin
lg := NewLabel();
l_default := NewLabel();
lt := TPaxStack.Create;
n_skips := TPaxIds.Create(true);
bool_id := NewVar();
Gen(OP_ASSIGN, bool_id, symboltable.IDTRUE, bool_id);
EntryStack.Push(lg, 0, StatementLabel);
Match('switch');
Match('(');
expr_id := Parse_Expression();
Match(')');
Match('{'); // parse switch block
repeat // parse switch sections
repeat // parse switch labels
if (IsCurrText('case')) then
begin
Match('case');
lt.Push(NewLabel());
case_expr_id := Parse_Expression();
Gen(OP_EQ, expr_id, case_expr_id, bool_id);
Gen(OP_GO_TRUE, lt.Top(), bool_id, 0);
end
else if (IsCurrText('default')) then
begin
Match('default');
SetLabelHere(l_default);
Gen(OP_ASSIGN, bool_id, symboltable.IDTRUE, bool_id);
end
else
break; //switch labels
Match(':');
until false;
while (lt.Card > 0) do
SetLabelHere(lt.Pop());
lf := NewLabel();
Gen(OP_GO_FALSE, lf, bool_id, 0);
// parse statement list
repeat
if (IsCurrText('case')) then
break;
if (IsCurrText('default')) then
break;
if (IsCurrText('}')) then
break;
l_skip := NewLabel();
SetLabelHere(l_skip);
Parse_Statement;
Gen(OP_GO, l_skip, 0, 0);
n_skips.Add(Code.Card);
until false;
SetLabelHere(lf);
if (IsCurrText('}')) then
break;
until false;
EntryStack.Pop();
SetLabelHere(lg);
Match('}');
if n_skips.Count >= 2 then
for I:=0 to n_skips.Count - 2 do
begin
N1 := n_skips[I];
N2 := n_skips[I+1];
Code.Prog[N1].Arg1 := Code.Prog[N2].Arg1;
end;
N1 := n_skips[n_skips.Count - 1];
Code.Prog[N1].Op := OP_NOP;
lt.Free;
n_skips.Free;
end;
procedure TPaxJavaScriptParser.Parse_WithStmt;
var
ID, ID2: Integer;
begin
// match "with"
Call_SCANNER;
Match('(');
Call_SCANNER;
ID := Parse_Expression;
if IsCallOperator then
begin
ID2 := NewVar;
Gen(OP_ASSIGN, ID2, ID, ID2);
Gen(OP_BEGIN_WITH, WithStack.Push(ID2), 0, 0);
end
else
Gen(OP_BEGIN_WITH, WithStack.Push(ID), 0, 0);
Match(')');
Call_SCANNER;
Parse_Statement;
Gen(OP_END_WITH, 0, 0, 0);
WithStack.Pop;
end;
procedure TPaxJavaScriptParser.Parse_ThrowStmt;
var
ID: Integer;
begin
// match "throw"
Call_SCANNER;
if IsCurrText(';') then
begin
ID := 0;
Call_SCANNER;
end
else
begin
ID := Parse_Expression;
end;
Gen(OP_THROW, ID, 0, 0);
end;
procedure TPaxJavaScriptParser.Parse_TryStmt;
var
L, LTRY, ID: Integer;
begin
// match "try"
LTRY := NewLabel;
Gen(OP_TRY_ON, LTRY, 0, 0);
Call_SCANNER;
Parse_Block;
Call_SCANNER;
L := NewLabel;
Gen(OP_GO, L, 0, 0);
if not IsCurrText('catch') or IsCurrText('finally') then
Match('catch');
while IsCurrText('catch') do
begin
Call_SCANNER;
Match('(');
DeclareSwitch := true;
Call_SCANNER;
ID := Parse_Ident;
Gen(OP_CATCH, ID, 0, 0);
DeclareSwitch := false;
Match(')');
CurrClassRec.AddField(ID, [modSTATIC]);
Call_SCANNER;
Parse_Block;
Call_SCANNER;
Gen(OP_DISCARD_ERROR, 0, 0, 0);
end;
SetLabelHere(L);
if IsCurrText('finally') then
begin
Gen(OP_FINALLY, 0, 0, 0);
Call_SCANNER;
Parse_Block;
Call_SCANNER;
Gen(OP_EXIT_ON_ERROR, 0, 0, 0);
end;
SetLabelHere(LTRY);
Gen(OP_TRY_OFF, 0, 0, 0);
end;
function TPaxJavaScriptParser.Parse_VarStmt(IsField: Boolean;
ml: TPAXModifierList;
IsLoopVar: Boolean = false): Integer;
begin
DeclareSwitch := true;
DuplicateVars := true;
Call_SCANNER;
DuplicateVars := false;
result := Parse_VariableDeclaration(IsField, ml, IsLoopVar);
while IsCurrText(',') do
begin
DeclareSwitch := true;
Call_SCANNER;
result := Parse_VariableDeclaration(IsField, ml, IsLoopVar);
end;
DeclareSwitch := false;
end;
function TPaxJavaScriptParser.Parse_VariableDeclaration(IsField: Boolean;
ml: TPAXModifierList;
IsLoopVar: Boolean = false): Integer;
var
ID, ArrID, Vars: Integer;
MemberRec: TPAXMemberRec;
S: String;
begin
MemberRec := nil;
result := Parse_Ident;
if IsField then
MemberRec := CurrClassRec.AddField(result, ml)
else if (CurrClassID > 0) and (CurrSubID = 0) then
CurrClassRec.AddField(result, ml + [modSTATIC])
else if CurrSubID > 0 then
begin
S := SymbolTable.Name[result];
SymbolTable.DecCard;
ID := SymbolTable.LookUpID(S, CurrSubId);
SymbolTable.IncCard;
if ID > 0 then
begin
if ID <> result then
SymbolTable.Name[result] := '';
result := ID;
end
else
SymbolTable.SetLocal(result);
LocalVars.Add(result);
end;
if IsCurrText('[') then
begin
if MemberRec <> nil then
MemberRec.InitN := LastCodeLine;
DeclareSwitch := false;
Call_SCANNER;
ArrID := 0;
Gen(OP_CREATE_ARRAY, result, Parse_ArgumentList(ArrID, Vars), 0);
if MemberRec <> nil then
Gen(OP_HALT, 0, 0, 0);
Match(']');
Call_SCANNER;
end
else if IsCurrText('=') then
begin
Gen(OP_NOP, 0, 0, 0);
if (MemberRec <> nil) and (not IsLoopVar) then
MemberRec.InitN := LastCodeLine;
DeclareSwitch := false;
Call_SCANNER;
LeftSideID := result;
ID := Parse_AssignmentExpression;
if ID = UndefinedID then
Gen(OP_DESTROY_INTF, result, 0, 0);
Gen(OP_ASSIGN, result, ID, result);
if (MemberRec <> nil) and (not IsLoopVar) then
Gen(OP_HALT, 0, 0, 0);
TempObjectList.Clear;
end;
end;
procedure TPaxJavaScriptParser.Parse_ExpressionStmt;
begin
Gen(OP_SAVE_RESULT, Parse_Expression, 0, 0);
end;
procedure TPaxJavaScriptParser.Parse_StmtList;
begin
repeat
if CurrToken.ID = SP_POINT then
Exit
else if CurrToken.ID = SP_EOF then
Exit
else
Parse_Statement;
until false;
IsExecutable := true;
Gen(OP_SKIP, 0, 0, 0);
IsExecutable := false;
end;
procedure TPaxJavaScriptParser.Parse_SourceElements;
begin
repeat
if CurrToken.ID = SP_POINT then
Exit
else if CurrToken.ID = SP_EOF then
Exit
else
Parse_Statement;
until false;
end;
procedure TPaxJavaScriptParser.CreateGlobalObjects;
var
ID: Integer;
begin
ID := NewVar;
Name[ID] := 'Function';
SymbolTable.Level[ID] := -1;
Gen(OP_EVAL_WITH, 0, 0, ID);
FunctionObjectID := NewVar;
Gen(OP_CREATE_OBJECT, ID, 0, FunctionObjectID);
Gen(OP_CREATE_REF, FunctionObjectID, 0, ID);
Gen(OP_CALL, ID, 0, ID);
Gen(OP_ASSIGN, FunctionObjectID, ID, FunctionObjectID);
end;
procedure TPaxJavaScriptParser.GenDestroyLocalVars;
var
I, J, ID, SubID: Integer;
// ok: Boolean;
begin
SubID := LevelStack.Top;
for I := LocalVars.Count - 1 downto 0 do
begin
ID := LocalVars[I];
if SymbolTable.Level[ID] = SubID then
if SymbolTable.GetResultID(SubId) <> ID then
begin
// ok := false;
for J:=1 to Code.Card do
if (Code.Prog[J].Op = OP_ASSIGN_RESULT) and (Code.Prog[J].Arg2 = ID) then
begin
// ok := true;
break;
end;
// if not ok then
// Gen(OP_DESTROY_OBJECT, ID, 0, 0);
LocalVars.Delete(I);
end;
end;
end;
procedure TPaxJavaScriptParser.Parse_Program;
begin
if CurrToken.ID = SP_EOF then
Exit;
if DeclareVariables then
Gen(OP_DECLARE_ON, 0, 0, 0)
else
Gen(OP_DECLARE_OFF, 0, 0, 0);
if VBArrays then
Gen(OP_VBARRAYS_ON, 0, 0, 0)
else
Gen(OP_VBARRAYS_OFF, 0, 0, 0);
Gen(OP_UPCASE_OFF, 0, 0, 0);
Gen(OP_JS_OPERS_ON, 0, 0, 0);
if ZeroBasedStrings then
Gen(OP_ZERO_BASED_STRINGS_ON, 0, 0, 0)
else
Gen(OP_ZERO_BASED_STRINGS_OFF, 0, 0, 0);
CreateGlobalObjects;
Parse_SourceElements;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?