pax_pascal.pas
来自「Delphi脚本控件」· PAS 代码 · 共 2,877 行 · 第 1/5 页
PAS
2,877 行
Name[CurrToken.ID] := S;
end;
end;
end;
end;
function TPAXPascalParser.Parse_OverloadableOperator: Integer;
begin
if IsCurrText('=') then
CurrToken.Text := '=='
else if IsCurrText('<>') then
CurrToken.Text := '!='
else if IsCurrText('mod') then
CurrToken.Text := '%'
else if IsCurrText('shl') then
CurrToken.Text := '<<'
else if IsCurrText('shr') then
CurrToken.Text := '>>';
result := NewVar();
Name[result] := CurrToken.Text;
if OverloadableOperators.IndexOf(CurrToken.Text) = -1 then
raise TPaxScriptFailure.Create(errOverloadableOperatorExpected);
Call_SCANNER;
end;
function TPAXPascalParser.IsBaseType(const S: String): Boolean;
begin
result := inherited IsBaseType(S);
if result then
Exit;
result := (StrEql(S, 'TDateTime') or StrEql(S, 'Real'));
end;
destructor TPAXPascalParser.Destroy;
begin
ForwardIds.Free;
ForwardPos.Free;
EnumIds.Free;
OperCompare.Free;
OperAdditive.Free;
OperMult.Free;
ConstIds.Free;
inherited;
end;
procedure TPAXPascalParser.Reset;
begin
inherited;
if Assigned(ForwardIds) then
ForwardIds.Clear;
if Assigned(ForwardPos) then
ForwardPos.Clear;
if Assigned(EnumIds) then
EnumIds.Clear;
ConstIds.Clear;
end;
function TPAXPascalParser.Parse_EvalExpression: Integer;
begin
result := Parse_Expression;
end;
function TPAXPascalParser.Parse_ArgumentExpression: Integer;
begin
result := Parse_Expression;
end;
/////// EXPRESSIONS /////////////////////////////////////////////////////////
function TPAXPascalParser.Parse_ConstExpr: Integer;
begin
result := Parse_Expression;
end;
function TPAXPascalParser.Parse_Expression: Integer;
var
OP, TypeID: Integer;
CallRec: TPaxCallRec;
begin
result := Parse_SimpleExpression;
if IsOperator(OperCompare, OP) then
begin
if OP = OP_TYPE_CAST then
begin
Gen(OP_PUSH, result, 0, 0);
TypeID := Parse_Ident;
result := NewVar;
Gen(OP_CALL, TypeID, 1, result);
CallRec := TPaxCallRec.Create;
CallRec.CallP := Scanner.PosNumber;
CallRec.CallN := Code.Card;
TPaxBaseScripter(Scripter).CallRecList.AddObject(CallRec.CallN, CallRec);
end
else
begin
result := BinOp(OP, result, Parse_SimpleExpression);
symboltable.PType[result] := typeBOOLEAN;
end;
end;
end;
function TPAXPascalParser.Parse_SimpleExpression: Integer;
var
OP: Integer;
begin
result := Parse_Term;
while IsOperator(OperAdditive, OP) do
begin
if (OP = OP_OR) and ShortEvalSwitch and (TypeID[result] = typeBOOLEAN) then
begin
result := Parse_ShortEvalOR(result, Parse_Term, nil);
end
else
begin
result := BinOp(OP, result, Parse_Term);
end;
end;
end;
function TPAXPascalParser.Parse_Term: Integer;
var
OP: Integer;
begin
result := Parse_Factor;
while IsOperator(OperMult, OP) do
begin
if (OP = OP_AND) and ShortEvalSwitch and (TypeID[result] = typeBOOLEAN) then
begin
result := Parse_ShortEvalAND(result, Parse_Factor, nil);
end
else
begin
result := BinOp(OP, result, Parse_Factor);
end;
end;
end;
function TPAXPascalParser.Parse_Factor: Integer;
var
SubID, Vars: Integer;
IsArrayItem: Boolean;
CallRec: TPaxCallRec;
begin
if IsTypeID then
begin
result := Parse_Ident;
Match('(');
Call_SCANNER;
Parse_Expression;
Match(')');
Call_SCANNER;
end
else if IsCurrText('not') then
begin
Call_SCANNER;
result := NewVar;
Gen(OP_NOT, Parse_Factor, 0, result);
end
else if IsCurrText('-') then
begin
Call_SCANNER;
result := NewVar;
Gen(OP_UNARY_MINUS, Parse_Factor, 0, result);
end
else if IsCurrText('+') then
begin
Call_SCANNER;
result := NewVar;
Gen(OP_UNARY_PLUS, Parse_Factor, 0, result);
end
else if IsCurrText('/') then
result := Parse_RegExpr('Create')
else if IsConstant then
begin
result := CurrToken.ID;
if TypeID[result] = typeSTRING then
begin
result := Parse_StringLiteral;
end
else
Call_SCANNER;
end
else if IsCurrText('(') then
begin
Call_SCANNER;
result := Parse_Expression;
Match(')');
Call_SCANNER;
end
else if IsCurrText('[') then
result := Parse_SetConstructor
else if IsCurrText('@') then
begin
result := NewVar;
Call_SCANNER;
if IsCallOperator then
RemoveLastOperator;
IsArrayItem := IsNextText('[') or IsNextText('(');;
SubID := Parse_Designator;
if IsCallOperator and (not IsArrayItem) then
RemoveLastOperator;
Gen(OP_ASSIGN_ADDRESS, result, SubID, result);
end
else if IsCurrText('inherited') then
begin
if CurrClassID = 0 then
raise TPAXScriptFailure.Create(errStatementIsNotAllowedHere);
if CurrSubID <> CurrMethodID then
raise TPAXScriptFailure.Create(errStatementIsNotAllowedHere);
FieldSwitch := true;
Call_SCANNER;
result := Parse_Ident;
GenRef(CurrThisID, maMyBase, result);
SubID := result;
if IsCurrText('(') then
begin
Call_SCANNER;
result := NewVar;
Gen(OP_CALL, SubID, Parse_ArgumentList(SubID, Vars), result);
SetVars(Vars);
Match(')');
Call_SCANNER;
end
else
begin
Gen(OP_CALL, SubID, 0, result);
CallRec := TPaxCallRec.Create;
CallRec.CallP := Scanner.PosNumber;
CallRec.CallN := Code.Card;
TPaxBaseScripter(Scripter).CallRecList.AddObject(CallRec.CallN, CallRec);
end;
end
else
begin // designator
{ if IsCurrText('new') then
begin
Call_SCANNER;
ClassName := CurrToken.Text;
ClassID := Parse_Ident;
ObjectID := NewVar;
Gen(OP_CREATE_OBJECT, ClassID, 0, ObjectID);
result := NewRef;
Gen(OP_CREATE_REF, ObjectID, NewConst(ClassName), result);
end
else }
result := Parse_Designator;
end;
end;
function TPAXPascalParser.Parse_Designator(ResID: Integer = 0): Integer;
var
RefID, ID, Vars: Integer;
ObjectID: Integer;
CallRec: TPaxCallRec;
K, Rank: Integer;
begin
Vars := 0;
if ResID = 0 then
begin
result := Parse_QualID;
result := GenEvalWith(result);
end
else
result := ResID;
ID := result;
Rank := SymbolTable.Rank[result];
while True do
case CurrToken.Text[1] of
'.':
begin
FieldSwitch := true;
Call_SCANNER;
if IsCurrText('Create') or IsCurrText('CreateNew') then
begin
ObjectID := NewVar;
Gen(OP_CREATE_OBJECT, result, 0, ObjectID);
result := Parse_Ident;
GenRef(ObjectID, maAny, result);
SymbolTable.PType[result] := ObjectID;
end
else
begin
if IsCurrText('free') then
begin
CurrToken.Text := 'Free';
Name[CurrToken.ID] := 'Destroy';
end;
if IsKeyword(CurrToken.Text) then
begin
RefID := NewVar;
Name[RefID] := CurrToken.Text;
Call_SCANNER;
end
else
RefID := Parse_Ident;
GenRef(result, maAny, RefID);
result := RefID;
end;
if not (CurrToken.Text[1] in ['(', '[']) then
begin
if Kind[ID] = KindVIRTUALOBJECT then
begin
ID := result;
result := NewVar;
Gen(OP_CALL, ID, 0, result);
end
else
Gen(OP_CALL, result, 0, result);
end;
{ if IsDestructor then
begin
Gen(OP_DESTROY_OBJECT, ObjectID, 0, 0);
Gen(OP_CALL, 0, 0, 0);
end; }
end;
'[':
begin
// if Rank = -1 then
// raise TPaxScriptFailure.Create(errCannotApplyToScalar);
ID := result;
result := NewVar;
Call_SCANNER;
K := Parse_ArgumentList(ID, Vars);
Gen(OP_CALL, ID, K, result);
SetVars(Vars);
Match(']');
if (Rank > 0) and (K <> Rank) then
raise TPaxScriptFailure.Create(errRankMismatch);
Call_SCANNER;
end;
'(':
begin
ID := result;
result := NewVar;
Call_SCANNER;
if IsCurrText(')') then
begin
Gen(OP_CALL, ID, 0, result);
CallRec := TPaxCallRec.Create;
CallRec.CallP := Scanner.PosNumber;
CallRec.CallN := Code.Card;
TPaxBaseScripter(Scripter).CallRecList.AddObject(CallRec.CallN, CallRec);
end
else
begin
Gen(OP_CALL, ID, Parse_ArgumentList(ID, Vars), result);
end;
SetVars(Vars);
Match(')');
Call_SCANNER;
end;
'^':
begin
Call_SCANNER;
ID := result;
result := NewVar;
Gen(OP_GET_TERMINAL, ID, 0, result);
end;
else
Exit;
end;
end;
function TPAXPascalParser.Parse_QualID: Integer;
begin
if IsUnitID then
begin
Parse_Ident;
Match('.');
Call_SCANNER;
end;
result := Parse_Ident;
end;
function TPAXPascalParser.Parse_SetConstructor: Integer;
begin
result := Parse_ArrayLiteral;
end;
function TPAXPascalParser.Parse_SetElement: Integer;
begin
result := Parse_Expression;
if IsCurrText('..') then
begin
Call_SCANNER;
result := Parse_Expression;
end;
end;
function TPAXPascalParser.Parse_UnitID: Integer;
begin
result := Parse_Ident;
end;
function TPAXPascalParser.Parse_TypeID: Integer;
var
S: String;
begin
if IsCurrText('record') then
begin
result := NewVar;
Kind[result] := KindTYPE;
Parse_ClassStmt([], ckStructure, result);
Exit;
end;
if IsCurrText('array') then
begin
result := NewVar;
Name[result] := '__'+IntToStr(result);
Kind[result] := KindTYPE;
Parse_ArrayStmt(result);
Exit;
end;
if IsCurrText('set') then
begin
result := typeSET;
Call_SCANNER;
if IsCurrText('of') then
begin
Call_SCANNER;
Call_SCANNER;
end;
Exit;
end;
if IsCurrText('String') and IsNextText('[') then
result := Parse_Ident
else
result := Parse_Designator;
S := Name[result];
if (result > PAXTypes.Count) or (result < 0) then
begin
// if Kind[result] <> KindTYPE then
// raise TPAXScriptFailure.Create(Format(errTypeNotFound, [S]));
end
else
if not (result in SupportedPaxTypes) then
begin
if StrEql(S, 'TextFile') or StrEql(S, 'File') then
begin
// ok
end
else
raise TPAXScriptFailure.Create(Format(errTypeNotFound, [S]));
end;
end;
function TPAXPascalParser.IsTypeID: boolean;
begin
result := false;
end;
function TPAXPascalParser.IsConstant: boolean;
begin
result := inherited IsConstant or IsCurrText('nil');
end;
function TPAXPascalParser.IsUnitId: boolean;
begin
result := false;
end;
/////// STATEMENTS /////////////////////////////////////////////////////////
procedure TPAXPascalParser.Parse_Statement;
var
ml: TPAXModifierList;
begin
ml := [modPUBLIC];
if IsLabelID then if Kind[CurrToken.ID] = KindLABEL then
begin
StatementLabel := CurrToken.Text;
Parse_SetLabel;
Match(':');
Call_SCANNER;
end;
if IsCurrText('begin') then
begin
Parse_CompoundStmt;
Call_SCANNER;
if IsCurrText('.') then
CurrToken.Text := ';';
end
else if IsCurrText('if') then
begin
IsExecutable := true;
Parse_IfStmt;
IsExecutable := false;
end
else if IsCurrText('namespace') then
Parse_NamespaceStmt(ml)
else if IsCurrText('function') then
begin
if LevelStack.KindTop <> KindSUB then
ml := ml + [modSTATIC];
Parse_FunctionStmt(tsGlobal, ml);
end
else if IsCurrText('procedure') then
begin
if LevelStack.KindTop <> KindSUB then
ml := ml + [modSTATIC];
Parse_FunctionStmt(tsGlobal, ml);
end
else if IsCurrText('constructor') then
Parse_FunctionStmt(tsConstructor, ml)
else if IsCurrText('destructor') then
Parse_FunctionStmt(tsDestructor, ml)
else if IsCurrText('var') then
begin
DeclareSwitch := true;
Call_SCANNER;
Parse_VarStmt(false, ml, false);
end
else if IsCurrText('const') then
begin
DeclareSwitch := true;
Call_SCANNER;
Parse_VarStmt(false, ml, true);
end
else if IsCurrText('class') then
Parse_ClassStmt(ml, ckClass)
else if IsCurrText('type') then
Parse_TypeStmt
else if IsCurrText('enum') then
Parse_EnumStmt
else if IsCurrText('record') then
Parse_ClassStmt(ml, ckStructure)
else if IsCurrText('case') then
Parse_CaseStmt
else if IsCurrText('repeat') then
begin
IsExecutable := true;
Parse_RepeatStmt;
IsExecutable := false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?