base_parser.pas
来自「Delphi脚本控件」· PAS 代码 · 共 2,625 行 · 第 1/5 页
PAS
2,625 行
for I:=1 to Length(CurrToken.Text) do
case CurrToken.Text[I] of
'g','G':
begin
ID := NewVar;
Name[ID] := 'global';
GenRef(result, MaAny, ID);
Gen(OP_PUSH, NewConst('true'), 0, 0);
Gen(OP_PUT_PROPERTY, ID, 1, 0);
end;
'i','I':
begin
ID := NewVar;
Name[ID] := 'ignoreCase';
GenRef(result, MaAny, ID);
Gen(OP_PUSH, NewConst('true'), 0, 0);
Gen(OP_PUT_PROPERTY, ID, 1, 0);
end;
'm','M':
begin
ID := NewVar;
Name[ID] := 'multiline';
GenRef(result, MaAny, ID);
Gen(OP_PUSH, NewConst('true'), 0, 0);
Gen(OP_PUT_PROPERTY, ID, 1, 0);
end;
end;
end;
Call_SCANNER;
end;
procedure TPAXParser.Parse_PrintList;
begin
// print
Call_SCANNER;
repeat
Gen(OP_PRINT, Parse_ArgumentExpression, 0, 0);
if IsCurrText(',') then
Call_SCANNER
else
Break;
until false;
end;
procedure TPAXParser.Parse_PrintlnList;
begin
// print
Call_SCANNER;
repeat
Gen(OP_PRINT, Parse_ArgumentExpression, 0, 0);
if IsCurrText(',') then
Call_SCANNER
else
Break;
until false;
Gen(OP_PRINT, NewConst('\r\n'), 0, 0);
end;
function TPAXParser.BinOp(OP, Arg1, Arg2: Integer): Integer;
begin
result := NewVar;
Gen(OP, Arg1, Arg2, result);
end;
function TPAXParser.IsOperator(OperList: TPAXIds; var OP: Integer): Boolean;
var
I: Integer;
begin
if CurrToken.TokenClass <> tcSpecial then
begin
result := false;
Exit;
end;
I := OperList.IndexOf(CurrToken.ID);
if I >= 0 then
begin
result := true;
OP := OperList[I];
Call_SCANNER;
end
else
result := false;
end;
function TPAXParser.Parse_StringLiteral: Integer;
var
K, ID, Count, FormatID, ArrayID, SubID: Integer;
S: String;
begin
Count := Scanner.VarNameList.Count;
if Count = 0 then
result := CurrToken.ID
else
begin
FormatID := LookupID('Format');
ArrayID := NewVar;
Result := NewVar;
Gen(OP_PUSH, NewConst(Count - 1), 0, 0);
Gen(OP_CREATE_ARRAY, ArrayID, 1, 0);
for K:=0 to Count - 1 do
begin
Gen(OP_PUSH, NewConst(K), 0, 0);
S := Scanner.VarNameList[K];
ID := NewVar;
Name[ID] := S;
Gen(OP_EVAL_WITH, 0, 0, ID);
Gen(OP_PUSH, ID, 0, 0);
Gen(OP_PUT_PROPERTY, ArrayID, 2, 0);
end;
Gen(OP_PUSH, CurrToken.ID, 0, 0);
Gen(OP_PUSH, ArrayID, 0, 0);
Gen(OP_CALL, FormatID, 2, Result);
Gen(OP_DESTROY_OBJECT, ArrayID, 0, 0);
end;
Scanner.VarNameList.Clear;
Call_SCANNER;
if IsCurrText('with') then
begin
Call_SCANNER;
Gen(OP_PUSH, result, 0, 0);
Gen(OP_PUSH, Parse_ArrayLiteral, 0, 0);
SubID := LookUpID('Format');
result := NewVar;
Gen(OP_CALL, SubID, 2, result);
end;
end;
procedure TPAXParser.GenHtml;
var
K, ID, Count, FormatID, ArrayID, ResultID, N: Integer;
S: String;
begin
CurrToken.ID := SymbolTable.CodeStringConst(CurrToken.Text);
N := Code.Card + 1;
Count := Scanner.VarNameList.Count;
if Count = 0 then
Gen(OP_PRINT_HTML, CurrToken.ID, 0, N)
else
begin
FormatID := LookupID('Format');
ArrayID := NewVar;
ResultID := NewVar;
Gen(OP_PUSH, NewConst(Count - 1), 0, 0);
Gen(OP_CREATE_ARRAY, ArrayID, 1, 0);
for K:=0 to Count - 1 do
begin
Gen(OP_PUSH, NewConst(K), 0, 0);
S := Scanner.VarNameList[K];
ID := NewVar;
Name[ID] := S;
Gen(OP_EVAL_WITH, 0, 0, ID);
Gen(OP_PUSH, ID, 0, 0);
Gen(OP_PUT_PROPERTY, ArrayID, 2, 0);
end;
Gen(OP_PUSH, CurrToken.ID, 0, 0);
Gen(OP_PUSH, ArrayID, 0, 0);
Gen(OP_CALL, FormatID, 2, ResultID);
Gen(OP_DESTROY_OBJECT, ArrayID, 0, 0);
Gen(OP_PRINT_HTML, ResultID, 0, N);
end;
Scanner.VarNameList.Clear;
end;
function TPAXParser.Parse_ArrayLiteral: Integer;
var
L, K, ArgID: Integer;
procedure Parse_Element;
var
S: String;
c, c1, c2: Char;
I, I1, I2: Integer;
begin
if IsNextText('..') then
begin
S := CurrToken.Text;
if CurrToken.TokenClass = tcIntegerConst then
begin
I1 := StrToInt(S);
Call_SCANNER;
Call_SCANNER;
S := CurrToken.Text;
I2 := StrToInt(S);
Call_SCANNER;
for I := I1 to I2 do
begin
ArgID := NewConst(I);
Inc(K);
Gen(OP_PUSH, NewConst(K), 0, 0);
Gen(OP_PUSH, ArgID, 0, 0);
Gen(OP_PUT_PROPERTY, result, 2, 0);
end;
end
else if CurrToken.TokenClass = tcStringConst then
begin
c1 := S[1];
Call_SCANNER;
Call_SCANNER;
S := CurrToken.Text;
Call_SCANNER;
c2 := S[1];
for c := c1 to c2 do
begin
S := c;
ArgID := NewConst(S);
Inc(K);
Gen(OP_PUSH, NewConst(K), 0, 0);
Gen(OP_PUSH, ArgID, 0, 0);
Gen(OP_PUT_PROPERTY, result, 2, 0);
end;
end
else
raise TPaxScriptFailure.Create(errConstantExpected);
end
else
begin
Inc(K);
Gen(OP_PUSH, NewConst(K), 0, 0);
ArgID := Parse_ArgumentExpression;
Gen(OP_PUSH, ArgID, 0, 0);
Gen(OP_PUT_PROPERTY, result, 2, 0);
end;
end;
begin
Match('[');
Call_SCANNER;
K := -1;
result := NewVar;
if ArgumentListSwitch then
ArrayArgumentList.Add(result);
// TempObjectList.Add(result);
Gen(OP_PUSH, 0, 0, 0);
L := LastCodeLine;
Gen(OP_CREATE_ARRAY, result, 1, 0);
if not IsCurrText(']') then
begin
Parse_Element;
while IsCurrText(',') do
begin
Call_SCANNER;
Parse_Element;
end;
end
else
K := -1;
with Code do
Prog[L].Arg1 := NewConst(K);
Match(']');
Call_SCANNER;
end;
procedure TPAXParser.Parse_ObjectInitializer(ObjectID: Integer);
var
FieldID, K: Integer;
begin
K := -1;
// match "("
Call_SCANNER;
if IsCurrText(')') then
Call_SCANNER
else
repeat
FieldID := NewVar;
Inc(K);
Gen(OP_GET_FIELD, ObjectID, K, FieldID);
if IsCurrText('(') then
begin
Parse_ObjectInitializer(FieldID);
end
else
begin
Gen(OP_ASSIGN, FieldID, Parse_ArgumentExpression(), FieldID);
end;
if IsCurrText(',') then
Call_SCANNER
else
break;
until false;
Match(')');
Call_SCANNER;
end;
function TPAXParser.Parse_CallConv: Integer;
var
S: String;
Temp: Integer;
begin
S := NextToken.Text;
result := -1;
if StrEql(S, 'register') then
result := _ccRegister
else if StrEql(S, 'stdcall') then
result := _ccStdCall
else if StrEql(S, 'safecall') then
result := _ccSafeCall
else if StrEql(S, 'cdecl') then
result := _ccCDecl
else if StrEql(S, 'pascal') then
result := _ccPascal;
if result >= 0 then
begin
Temp := SymbolTable.Card;
Call_SCANNER; // call conv
Call_SCANNER;
SymbolTable.Card := Temp;
end;
end;
procedure TPAXParser.Parse_ReducedAssignment(LeftID: Integer);
var
Card1, Card2, NP, RightID, TempVar, I: Integer;
SaveProg: TPAXCodeRec;
IsCall: Boolean;
begin
Card1 := Code.Card;
RightID := Parse_EvalExpression;
Card2 := Code.Card;
IsCall := IsCallOperator;
if Code.Prog[Card2].OP = OP_SEPARATOR then
with Code do
begin
SaveProg := Prog[Card];
Dec(Card);
Dec(Card2);
end
else
SaveProg.Op := OP_NOP;
NP := Code.Prog[Card2].Arg2;
TempVar := 0;
if IsCall then
begin
TempVar := NewVar;
Gen(OP_ASSIGN, TempVar, Code.Prog[Card2].Res, TempVar);
end;
with Code do
if IsCall then
for I:=Card1 to Card2 - 1 do
begin
Inc(Card);
if Prog[I].Op = OP_SEPARATOR then
begin
SaveProg := Prog[I];
Prog[Card].Op := OP_NOP;
Prog[Card].Arg1 := 0;
Prog[Card].Arg2 := 0;
Prog[Card].Res := 0;
end
else
begin
Prog[Card].Op := Prog[I].Op;
Prog[Card].Arg1 := Prog[I].Arg1;
Prog[Card].Arg2 := Prog[I].Arg2;
Prog[Card].Res := Prog[I].Res;
end;
end;
if IsCall then
begin
Gen(OP_PUSH, SymbolTable.IDundefined, 0, 0);
Gen(OP_PUT_PROPERTY, LeftID, NP + 1, 0);
Gen(OP_DESTROY_OBJECT, LeftID, 0, 0);
Gen(OP_ASSIGN, LeftID, TempVar, LeftID);
// Gen(OP_ASSIGN, TempVar, SymbolTable.IDundefined, TempVar);
end
else
begin
Gen(OP_DESTROY_OBJECT, LeftID, 0, 0);
Gen(OP_ASSIGN, LeftID, RightID, LeftID);
end;
if SaveProg.Op <> OP_NOP then
with Code do
begin
Inc(Card);
Prog[Card].Op := SaveProg.Op;
Prog[Card].Arg1 := SaveProg.Arg1;
Prog[Card].Arg2 := SaveProg.Arg2;
Prog[Card].Res := SaveProg.Res;
end;
end;
procedure TPaxParser.MoveUpSourceLine;
var
I: Integer;
begin
with Code do
begin
I := Card;
while Prog[I].Op <> OP_SEPARATOR do
Dec(I);
Inc(Card);
Prog[Card] := Prog[I];
Prog[I].Op := OP_NOP;
end;
end;
function TPaxParser.Parse_ShortEvalAND(ID: Integer;
Method0: TIntegerMethodNoParam;
Method1: TIntegerMethodOneParam): Integer;
var
LF: Integer;
begin
if Assigned(Method0) and Assigned (Method1) then
raise Exception.Create(errInternalError);
if (not Assigned(Method0)) and (not Assigned (Method1)) then
raise Exception.Create(errInternalError);
LF := NewLabel;
result := NewVar;
Gen(OP_ASSIGN, result, ID, result);
Gen(OP_GO_FALSE, LF, result, 0);
if Assigned(Method0) then
Gen(OP_ASSIGN, result, Method0(), result)
else
Gen(OP_ASSIGN, result, Method1(0), result);
SetLabelHere(LF);
end;
function TPaxParser.Parse_ShortEvalOR(ID: Integer;
Method0: TIntegerMethodNoParam;
Method1: TIntegerMethodOneParam): Integer;
var
LT: Integer;
begin
if Assigned(Method0) and Assigned (Method1) then
raise Exception.Create(errInternalError);
if (not Assigned(Method0)) and (not Assigned (Method1)) then
raise Exception.Create(errInternalError);
LT := NewLabel;
result := NewVar;
Gen(OP_ASSIGN, result, ID, result);
Gen(OP_GO_TRUE, LT, result, 0);
if Assigned(Method0) then
Gen(OP_ASSIGN, result, Method0(), result)
else
Gen(OP_ASSIGN, result, Method1(0), result);
SetLabelHere(LT);
end;
function TPaxParser.IsBaseType(const S: String): Boolean;
var
I: Integer;
begin
result := false;
for I:=0 to PaxTypes.Count - 1 do
if StrEql(PaxTypes[I], S) then
begin
result := true;
Exit;
end;
end;
function TPaxParser.UndefinedID: Integer;
begin
result := SymbolTable.IDundefined;
end;
procedure TPaxParser.TestDupLocalVars(NewVarID: Integer);
var
S: String;
I, tempID, L, tempL: Integer;
b: Boolean;
begin
S := Name[NewVarID];
L := SymbolTable.Level[NewVarID];
for I:=0 to LocalVars.Count - 1 do
begin
tempID := LocalVars[I];
if UpCase then
b := StrEql(Name[tempID], S)
else
b := Name[tempID] = S;
if b then
begin
TempL := SymbolTable.Level[tempID];
if tempL = L then
raise TPAXScriptFailure.Create(Format(errIdentifierIsRedeclared, [Name[tempID]]));
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?