base_parser.pas

来自「Delphi脚本控件」· PAS 代码 · 共 2,625 行 · 第 1/5 页

PAS
2,625
字号
      result := ClassRec.MemberList.GetMemberID(MemberName, UpCase);
      if result <> 0 then
        Exit;
    end;
  end;
end;

function TPAXParser.GenEvalWith(ID: Integer): Integer;

function IsScriptDefinedSubID(ID: Integer): Boolean;
var
  K: Integer;
begin
  result := false;
  if ID <= 0 then
    Exit;

  K := Kind[ID];
  if K = KindSUB then
    result := true;
end;

function IsParameterID(ID: Integer): Boolean;
var
  I, SubID, ParamID: Integer;
  Success: Boolean;
label Again;
begin
  result := false;
  SubID := LevelStack.Top;

Again:

  if SymbolTable.Kind[SubID] <> KindSUB then
    Exit;

  Success := false;
  with SymbolTable do
    for I:=1 to Count[SubID] do
    begin
      ParamID := GetParamID(SubID, I);

      if UpCase then
        Success := StrEql(Name[ParamID], Name[ID])
      else
        Success := Name[ParamID] = Name[ID];

      if Success then
      begin
        result := true;
        Exit;
      end;
   end;

  if not Success then
  begin
    SubID := GetOuterSubID(SubID);
    if SubID <= 0 then
      Exit;
    goto Again;
  end;
end;

function IsLocalVar(ID: Integer): Boolean;
var
  SubID: Integer;
begin
  result := false;
  SubID := CurrSubID;

  repeat
    if SubID <= 0 then
      Exit;
    result := (SymbolTable.Level[ID] = SubID) and SymbolTable.IsLocal(ID);

    if not result then
      SubID := GetOuterSubID(SubID)
    else
      Exit;
  until false;
end;

var
  K, MemberID: Integer;
  C: TPaxClassRec;
  nonstat: Boolean;
  neg: Boolean;
begin
  result := ID;

  K := Kind[ID];

  neg := ID < 0;

  if WithCount > 0 then
    neg := false;

  if not neg then
  if SymbolTable.Level[ID] <> 0 then
//  if (K <> KindCONST) and (K <> KindSUB) then
    if not IsParameterID(ID) then
    if not IsScriptDefinedSubID(ID) then
     if not IsLocalVar(ID) then
       if CurrThisID <> ID then
         if CurrResultID <> ID then
         begin
           MemberID := InUsing(Name[ID]);

           if MemberID <> 0 then
           begin
             if Kind[MemberID] = KindSUB then
               if Count[MemberID] = 0 then
               if not IsCurrText('(') then
               begin
                 result := NewVar;
                 Gen(OP_CALL, MemberID, 0, result);
                 Exit;
               end;
             if MemberID > 0 then
               Exit
             else
             begin
               result := NewVar;
               with SymbolTable do
               begin
                 Name[result] := Name[ID];
                 Level[result] := -1;
                 Module[result] := -1;
               end;
               Gen(OP_EVAL_WITH, 0, 0, result);
               Exit;
             end;
           end;

           Gen(OP_EVAL_WITH, 0, 0, ID);
           Exit;
         end;

  if K = KindSUB then
  if Count[ID] = 0 then if not IsCurrText('(') then if not IsCurrText(':=') then
  begin
    nonstat := false;
    for K:=2 to LevelStack.Card do
      if SymbolTable.Kind[LevelStack[K]] = KindTYPE then
      begin
        C := ClassList.FindClass(LevelStack[K]);
        if C <> nil then
          if not (modSTATIC in C.ml) then
            nonstat := true;
      end;

    if (SymbolTable.Kind[LevelStack.Top] = KindSUB) and nonstat then
    begin
      K := NewVar;
      with SymbolTable do
      begin
        Name[K] := Name[ID];
        Level[K] := -1;
        Module[K] := -1;
      end;
      Gen(OP_CREATE_REF, CurrThisId, 0, K);
      result := NewVar;
      Gen(OP_CALL, K, 0, result);
    end
    else
    begin
      result := NewVar;
      Gen(OP_CALL, ID, 0, result);
    end;
  end;
end;

function TPAXParser.GenBeginWith(ID: Integer): Integer;
var
  I, TempID: Integer;
begin
  result := 0;
  for I:=2 to LevelStack.Card do
  begin
    TempID := LevelStack[I];
    if TempID <> ID then
    if SymbolTable.Kind[TempID] = KindTYPE then
    begin
      Inc(result);
      Gen(OP_BEGIN_WITH, WithStack.Push(TempID), 0, 0);
    end;
  end;

  Gen(OP_BEGIN_WITH, WithStack.Push(ID), 0, 0);
  Inc(result);
end;

procedure TPAXParser.GenEndWith(WithCount: Integer);
var
  I: Integer;
begin
  for I:=1 to WithCount do
  begin
    Gen(OP_END_WITH, 0, 0, 0);
    WithStack.Pop;
  end;
end;

procedure TPAXParser.SetVars(Vars: Integer);
begin
  Code.Prog[Code.Card].Vars := Vars;
end;

procedure TPAXParser.AddExtraCode(const Key, StrCode: String);
begin
  if Scripter <> nil then
    TPAXBaseScripter(Scripter).ExtraCodeList.AddCode(Key, LanguageName, StrCode)
  else
    raise Exception.Create(errInternalError);
end;

procedure TPAXParser.LinkVariables(SubID: Integer; HasResult: Boolean);
begin
  SymbolTable.LinkVariables(SubID, HasResult);
end;

{
procedure TPAXParser.MatchTypes;
var
  T1, T2, ResType: Integer;
label
  Fin;
begin
  ResType := typeVARIANT;
  T1 := TypeID[Code.CurrArg1ID];
  T2 := TypeID[Code.CurrArg2ID];
  if T1 = T2 then
  begin
    ResType := T1;
    goto Fin;
  end;
  if T1 = typeVARIANT then
    goto Fin;
  if T2 = typeVARIANT then
    goto Fin;

  if OpResultType(T1, T2) > 0 then
  begin
    ResType := OpResultType(T1, T2);
    goto Fin;
  end;

  raise TPAXScriptFailure.Create(strIncompatibleTypes(T1, T2));
Fin:
  TypeID[Code.CurrResID] := ResType;
end;

procedure TPAXParser.CompareTypes;
var
  T1, T2: Integer;
begin
  TypeID[Code.CurrResID] := typeBOOLEAN;
  T1 := TypeID[Code.CurrArg1ID];
  T2 := TypeID[Code.CurrArg2ID];
  if T1 = T2 then
    Exit;
  if T1 = typeVARIANT then
    Exit;
  if T2 = typeVARIANT then
    Exit;
  if Abs(T1) > PaxTypes.Count then
    Exit;
  if Abs(T2) > PaxTypes.Count then
    Exit;
  if OpResultType(T1, T2) > 0 then
    Exit;
  raise TPAXScriptFailure.Create(strIncompatibleTypes(T1, T2));
end;

function TPAXParser.MatchAssignment(ID1, ID2, ResID: Integer;
                                    RaiseException: Boolean = true;
                                    InitT1: Integer = 0;
                                    InitT2: Integer = 0): Integer;
var
  T1, T2, ResType: Integer;
label
  Fin;
begin
  ResType := typeVARIANT;
  result := ID2;

  if InitT1 = 0 then
    T1 := TypeID[ID1]
  else
    T1 := InitT1;

  if InitT2 = 0 then
    T2 := TypeID[ID2]
  else
    T2 := InitT2;

  if T1 = T2 then
  begin
    ResType := T1;
    goto Fin;
  end;

  if T1 = typeVARIANT then
  begin
    ResType := T2;
    goto Fin;
  end;

  if T2 = typeVARIANT then
    goto Fin;

  if T1 > PAXTypes.Count then
    goto Fin;

  if T2 > PAXTypes.Count then
    goto Fin;

  if T1 < 0 then
    goto Fin;

  if T2 < 0 then
    goto Fin;

  if AssResultTypes[T1, T2] then
  begin
    ResType := T1;
    goto Fin;
  end;

  TPaxBaseScripter(Scripter).Dump;

  if RaiseException then
    raise TPAXScriptFailure.Create(strIncompatibleTypes(T1, T2))
  else
  begin
    result := 0;
    Exit;
  end;
Fin:
  if ResID > 0 then
    if ResTYPE <> typeVARIANT then
      TypeID[ResID] := ResType;
end;


procedure TPAXParser.MatchTheseTypes(S: TIntegerSet);
var
  T1: Integer;
begin
  T1 := TypeID[Code.CurrArg1ID];
  if T1 <= PAXTypes.Count then
    if T1 in (S + [typeVARIANT]) then
    begin
      TypeID[Code.CurrResID] := T1;
      Exit;
    end;
  raise TPAXScriptFailure.Create(errOperatorNotApplicable);
end;

function TPAXParser.strIncompatibleTypes(T1, T2: Integer): String;
begin
  result := Format(errIncompatibleTypesExt, [Name[T1], Name[T2]]);
end;
}

function TPAXParser.Parse_ArgumentList(SubID: Integer; var Vars: Integer;
                                       CheckCall: Boolean = true;
                                       Erase: Boolean = true): Integer;
var
  CallRec: TPaxCallRec;

procedure _ParseExpr;
var
  ID, ExprID: Integer;
begin
  Inc(result);

  ExprID := Parse_ArgumentExpression;

  if Kind[ExprID] = KindCONST then
  begin
    ID := NewVar;
    Gen(OP_ASSIGN, ID, ExprID, ID);
    TypeID[ID] := TypeID[ExprID];
  end
  else
  begin
    ID := ExprID;
    SetBit(Vars, result);
  end;

  Gen(OP_PUSH, ID, result, SubID);

  if CheckCall then
  begin
    CallRec.ArgsN.Add(Code.Card);
    CallRec.ArgsP.Add(Scanner.PosNumber);
  end;
end;

var
  I: Integer;
  S: String;
begin
  Vars := 0;
  result := 0;

  ArgumentListSwitch := true;

  if CheckCall then
  begin
    CallRec := TPaxCallRec.Create;
    CallRec.CallP := Scanner.PosNumber;
  end;

  _ParseExpr;
  while IsCurrText(',') do
  begin
    Call_SCANNER;
    _ParseExpr;
  end;

  if CheckCall then
  begin
    CallRec.CallN := Code.Card + 1;
    TPaxBaseScripter(Scripter).CallRecList.AddObject(CallRec.CallN, CallRec);
  end;

  ArgumentListSwitch := false;
  if Erase then
  begin
    S := Name[SubId];
    I := ArrayParamMethods.IndexOf(S);
    if I = -1 then
      ArrayArgumentList.Clear;
  end;
end;

procedure TPAXParser.GenDestroyTempObjects;
var
  I, ID: Integer;
begin
  for I := TempObjectList.Count - 1 downto 0 do
  begin
    ID := TempObjectList[I];
    Gen(OP_DESTROY_OBJECT, ID, 0, 0);
  end;
  TempObjectList.Clear;
end;

procedure TPAXParser.GenDestroyArrayArgumentList;
var
  I, ID: Integer;
begin
  for I := ArrayArgumentList.Count - 1 downto 0 do
  begin
    ID := ArrayArgumentList[I];
    Gen(OP_DESTROY_OBJECT, ID, 0, 0);
  end;
  ArrayArgumentList.Clear;
end;

procedure TPAXParser.GenDestroyLocalVars;
var
  I, ID, SubID: Integer;
begin
  SubID := LevelStack.Top;
  for I := LocalVars.Count - 1 downto 0 do
  begin
    ID := LocalVars[I];
    if SymbolTable.Level[ID] = SubID then
    begin
      Gen(OP_DESTROY_LOCAL_VAR, ID, 0, 0);
      LocalVars.Delete(I);
    end;
  end;
end;

function TPAXParser.OpResultType(T1, T2: Integer): Integer;
begin
  result := 0;
  if T1 > PAXTypes.Count then
    Exit;
  if T2 > PAXTypes.Count then
    Exit;
  result := OpResultTypes[T1, T2];
  if result = 0 then
    result := OpResultTypes[T2, T1];
end;

function TPAXParser.Parse_RegExpr(const ConstructorName: String): Integer;
var
  S: String;
  I, RegExpID, CreateID, SourceID, ExprID, ID: Integer;
begin
  S := Scanner.GetRegExpr;

  RegExpID := NewVar;
  Name[RegExpID] := 'RegExp';

  CreateID := NewVar;
  Name[CreateID] := ConstructorName;

  SourceID := NewVar;
  Name[SourceID] := 'source';

  ExprID := NewConst(S);

  result := NewVar;

  Gen(OP_EVAL_WITH, 0, 0, RegExpID);
  Gen(OP_CREATE_OBJECT, RegExpID, Integer(maAny), result);
  GenRef(result,  maAny, CreateID);
  Gen(OP_CALL, CreateID, 0, result);

  GenRef(result, MaAny, SourceID);
  Gen(OP_PUSH, ExprID, 0, 0);
  Gen(OP_PUT_PROPERTY, SourceID, 1, 0);

  Call_SCANNER;
  Match('/');

  if LA(1) in ['i', 'I', 'g', 'G', 'm', 'M'] then
  begin
    Call_SCANNER;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?