base_parser.pas

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

PAS
2,625
字号
    begin
      if DuplicateVars then
      begin
        CurrToken.ID := LookUpID(CurrToken.Text);
      end
      else
        CurrToken.ID := 0;

      if CurrToken.ID = 0 then
      with SymbolTable do
      begin
        CurrToken.ID := AppVariant(Undefined);
        Name[CurrToken.ID] := CurrToken.Text;
        Level[CurrToken.ID] := CurrLevel;
        Module[CurrToken.ID] := ModuleID;
        Position[CurrToken.ID] := CurrToken.Position - 1;

        NewID := true;
      end;

    end
    else
    begin
      CurrToken.ID := LookUpID(CurrToken.Text);

      if CurrToken.ID = 0 then
      begin
        with SymbolTable do
        begin
          CurrToken.ID := AppVariant(Undefined);
          Name[CurrToken.ID] := CurrToken.Text;
          Level[CurrToken.ID] := CurrLevel;
          Module[CurrToken.ID] := ModuleID;
          Position[CurrToken.ID] := CurrToken.Position - 1;

          NewID := true;
        end;
      end;
    end;
  end;
end;

function TPAXParser.IsKeyword(const S: String): boolean;
begin
  if UpCase then
    result := Keywords.IndexOf(UpperCase(S)) <> - 1
  else
    result := Keywords.IndexOf(S) <> - 1;
end;

function TPAXParser.IsConstant: boolean;
begin
  result := (CurrToken.TokenClass in [tcIntegerConst, tcFloatConst, tcStringConst]);
end;

function TPAXParser.CurrLevel: Integer;
begin
  result := LevelStack.Top;
end;

function TPAXParser.LookUpID(const Name: String): Integer;
var
  L: Integer;
begin
  L := LevelStack.Card;
  while L > 1 do
  begin
    result := SymbolTable.LookUpID(Name, LevelStack[L], UpCase);
    if result <> 0 then
      Exit;
    Dec(L);
  end;

  result := InUsing(Name);
  if result <> 0 then
    Exit;
  result := SymbolTable.LookUpID(Name, 0, UpCase);
end;

function TPAXParser.LookUpLocalID(const Name: String): Integer;
begin
  result := SymbolTable.LookUpID(Name, CurrLevel, UpCase);
end;

function TPAXParser.Parse_Rank: Integer;
begin
  result := 1;
  Match('[');
  Call_SCANNER;
  repeat
    if IsCurrText(',') then
    begin
      Inc(result);
      Call_SCANNER;
    end
    else if IsCurrText(']') then
      break
    else
      Match(']');
  until false;
  Call_SCANNER;
end;

function TPAXParser.Parse_Ident: Integer;
begin
  if CurrToken.TokenClass <> tcId then
    raise TPAXScriptFailure.Create(errIdentifierExpected);

  result := CurrToken.ID;
  Call_SCANNER;
end;

function TPAXParser.Parse_OverloadableOperator: Integer;
begin
  if OverloadableOperators.IndexOf(CurrToken.Text) = -1 then
    raise TPaxScriptFailure.Create(errOverloadableOperatorExpected);

  result := NewVar();
  Name[result] := CurrToken.Text;
  Call_SCANNER;
end;

procedure TPAXParser.Parse_GoToStmt;
begin
  Call_SCANNER;
  Gen(OP_EXIT, Parse_UseLabel, 0, 0);
end;

function TPAXParser.IsLabelId: boolean;
begin
  result := (CurrToken.TokenClass = tcId) and IsNextText(':');
end;

function TPAXParser.Parse_SetLabel: Integer;
begin
  result := Parse_Ident;

  Gen(OP_SET_LABEL, 0, 0, 0);

  with SymbolTable do
  begin
    if not IsUndefined(GetVariant(result)) then
      raise TPAXScriptFailure.Create(errLabelAlreadyDefined);

    Kind[result] := KindLABEL;
    PutVariant(result, LastCodeLine);
  end;
end;

function TPAXParser.Parse_UseLabel: Integer;
begin
  result := Parse_Ident;
  SymbolTable.Kind[result] := KindLABEL;
end;

function TPAXParser.Parse_Constant: Integer;
begin
  result := CurrToken.ID;
  Call_SCANNER;
end;

function TPAXParser.LA(I: Integer): Char;
begin
  result := Scanner.LA(I);
end;

function TPAXParser.CurrClassID: Integer;
var
  I: Integer;
begin
  result := 0;

  for I:= LevelStack.Card downto 1 do
  if I > 1 then
    if Kind[LevelStack[I]] = kindTYPE then
    begin
      result := LevelStack[I];
      Exit;
    end;
end;

function TPAXParser.CurrMethodID: Integer;
var
  I, ID: Integer;
begin
  result := 0;

  for I:= LevelStack.Card downto 1 do
  if I > 1 then
    if SymbolTable.Kind[LevelStack[I]] = kindTYPE then
    if I <> LevelStack.Card then
    begin
      ID := LevelStack[I + 1];
      if SymbolTable.Kind[ID] = kindSUB then
        result := ID;
      Exit;
    end;
end;

function TPAXParser.CurrThisID: Integer;
var
  MemberRec: TPAXMemberRec;
  ID: Integer;
begin
  result := CurrMethodID;
  if result <> 0 then
  begin
    ID := CurrClassID;
    MemberRec := ClassList.FindMember(ID, SymbolTable.NameIndex[result], maMyClass);

    if MemberRec = nil then
      raise TPaxScriptFailure.Create(errPropertyIsNotFound);

    if MemberRec.IsStatic then
      result := 0
    else
      result := SymbolTable.GetThisID(result);
  end;
end;

function TPAXParser.GetOuterSubID(SubID: Integer): Integer;
var
  I, J, ID: Integer;
begin
  result := -1;
  for I:=2 to LevelStack.Card do
    if LevelStack[I] = SubID then
    begin
      J := I - 1;
      while J > 0 do
      begin
        ID := LevelStack[J];
        if ID <= 0 then
          Exit;
        if SymbolTable.Kind[ID] = KindSUB then
        begin
          result := ID;
          Exit;
        end;
        Dec(J);
      end;
    end;
end;

function TPAXParser.IsNestedSub(SubID: Integer): Boolean;
begin
  result := GetOuterSubID(SubID) > 0;
end;

function TPAXParser.CurrResultID: Integer;
var
  MemberRec: TPAXMemberRec;
  ID: Integer;
begin
  result := CurrSubID;
  if IsNestedSub(result) then
  begin
    result := SymbolTable.GetResultID(result);
    Exit;
  end;

  if result > 0 then
  begin
    ID := CurrClassID;
    MemberRec := ClassList.FindMember(ID, SymbolTable.NameIndex[result], maMyClass);
    if MemberRec = nil then
      result := 0
    else if MemberRec.ID = 0 then
      result := 0
    else
      result := SymbolTable.GetResultID(MemberRec.ID);
  end;
end;

function TPAXParser.CurrClassRec: TPAXClassRec;
begin
  result := ClassList.FindClass(CurrClassID);
end;

function TPAXParser.CurrSubID: Integer;
var
  I: Integer;
begin
  result := 0;

  for I:= LevelStack.Card downto 1 do
  if I > 1 then
    if SymbolTable.Kind[LevelStack[I]] = kindSUB then
    begin
      result := LevelStack[I];
      Exit;
    end;
end;

function TPAXParser.ToInteger(ID: Integer): Integer;
begin
  result := NewVar;
  Gen(OP_TO_INTEGER, ID, 0, result);
end;

function TPAXParser.ToBoolean(ID: Integer): Integer;
begin
  result := NewVar;
  Gen(OP_TO_BOOLEAN, ID, 0, result);
end;

function TPAXParser.ToString(ID: Integer): Integer;
begin
  result := NewVar;
  Gen(OP_TO_STRING, ID, 0, result);
end;

function TPAXParser.IsCallOperator(var Arg1, Arg2, Res: Integer): boolean;
var
  I: Integer;
begin
  I := LastCodeLine;
  if I <= 0 then
  begin
    result := false;
    Exit;
  end;
  with Code do
  begin
    result := (Prog[I].Op = OP_CALL);
    Arg1 := Prog[I].Arg1;
    Arg2 := Prog[I].Arg2;
    Res := Prog[I].Res;
  end;
end;

function TPAXParser.IsCallOperator: boolean;
var
  I: Integer;
begin
  I := LastCodeLine;
  if I <= 0 then
  begin
    result := false;
    Exit;
  end;
  with Code do
    result := Prog[I].Op = OP_CALL;
end;

procedure TPAXParser.RemoveLastOperator;
var
  I: Integer;
begin
  I := LastCodeLine;
  if I <= 0 then
    Exit;
  Code.Card := I - 1;
end;

function TPAXParser.LastCodeLine: Integer;
var
  I: Integer;
begin
  with Code do
  begin
    I := Card;
    while I > 1 do
      if Prog[I].Op = OP_SEPARATOR then
        Dec(I)
      else
      begin
        result := I;
        Exit;
      end;
    result := 0;
  end;
end;

procedure TPAXParser.InsertCode(L1, L2: Integer);
var
  I: Integer;
begin
  with Code do
    for I:=L1 to L2 do
      if Prog[I].Op <> OP_SEPARATOR then
      begin
        Inc(Card);
        Prog[Card] := Prog[I];
      end;
end;

function TPAXParser.Parse_ByRef: Integer;
begin
  Call_SCANNER;
  result := Parse_Ident;
  SymbolTable.ByRef[result] := 1;
end;

function ExtractModuleName(const S: String): String;
var
  P: Integer;
begin
  P := Pos('.', S);
  if P = 0 then
    result := S
  else
    result := Copy(S, 1, P - 1);
end;

procedure TPAXParser.Parse_ImportsStmt;
var
  I, ID, RefID: Integer;
  S, FullName, ModuleName: String;
  L: TStringList;
begin
  CurrClassRec.UsingInitList.Add(LastCodeLine);

  L := TStringList.Create;
  try

  // match "imports"
  repeat
    S := '';

    Gen(OP_SKIP, 0, 0, 0);
    if not UpCase then
      Gen(OP_UPCASE_ON, 0, 0, 0);

    Call_SCANNER;
    ModuleName := CurrToken.Text + FileExt;
    I := L.IndexOf(ModuleName);
    if I >= 0 then
      raise Exception.Create(Format(errIdentifierIsRedeclared, [ModuleName]));

    L.Add(ModuleName);
    ID := Parse_Ident;
    ID := GenEvalWith(ID);

    while IsCurrText('.') do
    begin
      FieldSwitch := true;
      Call_SCANNER;
      RefID := Parse_Ident;
      GenRef(ID, maAny, RefID);
      ID := RefID;
    end;

    Gen(OP_USE_NAMESPACE, UsingList.Push(ID), 0, 0);

    if IsCurrText('in') then
    begin
      Call_SCANNER;
      ModuleName := CurrToken.Text;
      FullName := TPaxBaseScripter(Scripter).FindFullName(ModuleName);
      if FullName = '' then
         FullName := ModuleName;

      Gen(OP_ON_USES, NewVar(ModuleName), NewVar(FullName), 0);

      with TPaxBaseScripter(Scripter) do
        if Assigned(OnUsedModule) then
        begin
          I := Modules.IndexOf(ModuleName);
          if I <> -1 then
            S := Modules.Items[I].Text;

          OnUsedModule(TPaxBaseScripter(scripter).Owner, ExtractModuleName(ModuleName), FullName, S);
        end
        else
          ModuleName := CurrToken.Text;

      Parse_Constant;

      TPaxBaseScripter(Scripter).AddExtraModule(ModuleName, S, SyntaxCheckOnly, LanguageName);
    end
    else if NamespaceAsModule then
    begin
      with TPaxBaseScripter(Scripter) do
        if Assigned(OnUsedModule) then
        begin
          I := Modules.IndexOf(ModuleName);
          if I <> -1 then
            S := Modules.Items[I].Text;

          OnUsedModule(TPaxBaseScripter(scripter).Owner, ExtractModuleName(ModuleName), FullName, S);
        end
        else
        begin
        end;

      TPaxBaseScripter(Scripter).AddExtraModule(ModuleName, S, SyntaxCheckOnly, LanguageName);
    end;

    if not IsCurrText(',') then
      Break;
  until false;

  if not UpCase then
    Gen(OP_UPCASE_OFF, 0, 0, 0);
  Gen(OP_HALT_OR_NOP, 0, 0, 0);

  finally
    L.Free;
  end;
end;

function TPAXParser.InUsing(const MemberName: String): Integer;
var
  I, ClassID: Integer;
  ClassRec: TPAXClassRec;
  MemberRec: TPAXMemberRec;
begin
  result := 0;

  ClassRec := CurrClassRec;
  MemberRec := ClassRec.MemberList.GetMemberRec(MemberName, UpCase);
  if MemberRec <> nil then
    if MemberRec.IsStatic then
    begin
      result := MemberRec.ID;
      Exit;
    end;

  for I:=UsingList.Card downto 1 do
  begin
    ClassID := UsingList[I];
    ClassRec := ClassList.FindClass(ClassID);
    if ClassRec <> nil then
    begin

⌨️ 快捷键说明

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