pax_basic.pas

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

PAS
2,916
字号

function TPAXBasicParser.Parse_ArgumentExpression: Integer;
begin
  result := Parse_Expression;
end;

procedure TPAXBasicParser.SkipColons;
begin
  while IsCurrText(':') do
    Parse_Statement;
end;

procedure TPAXBasicParser.Call_SCANNER;
var
  S: String;
  TempID: Integer;
begin
  _Call_SCANNER;
  if IsCurrText('NULL') then
  begin
    CurrToken.ID := UndefinedID
  end
  else if CurrToken.TokenClass in [tcId, tcKeyword] then
  begin
    S := FindTypeAlias(CurrToken.Text, UpCase);
    if S <> '' then
    begin
      CurrToken.Text := S;
      TempID := SymbolTable.LookUpID(S, 0, UpCase);
      if TempID > 0 then
        CurrToken.ID := TempID
      else
        Name[CurrToken.ID] := S;
    end;
  end;
end;

procedure TPAXBasicParser._Call_SCANNER;
begin
  NewID := false;

  Scanner.ReadToken;
  CurrToken := Scanner.Token;

  if CurrToken.TokenClass = tcHtmlStringConst then
  begin
    GenHtml;
    Call_SCANNER;
    Exit;
  end;

  if CurrToken.TokenClass = tcId then
    if IsKeyword(CurrToken.Text) then
    begin
      CurrToken.TokenClass := tcKeyword;
      CurrToken.ID := 0;

      if IsCurrText('New') and IsNextText('(') then
        CurrToken.TokenClass := tcID;

      if IsCurrText('Long') then
      begin
        CurrToken.ID := typeINT64;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('byte') then
      begin
        CurrToken.ID := typeBYTE;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('sbyte') then
      begin
        CurrToken.ID := typeSHORTINT;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('short') then
      begin
        CurrToken.ID := typeSMALLINT;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('ushort') then
      begin
        CurrToken.ID := typeWORD;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('uint') then
      begin
        CurrToken.ID := typeCARDINAL;
        CurrToken.TokenClass := tcId;
        Exit;
      end
      else if IsCurrText('set') then
      begin
        CurrToken.ID := typeSET;
        CurrToken.TokenClass := tcId;
      end;
    end;

  if CurrToken.TokenClass = tcSeparator then
    if CurrToken.ID <> SP_EOF then
    begin
      SeparatorIds.Add(Pointer(CurrToken.ID));

      CurrToken.ID := SP_COLON;
      CurrToken.Text := ':';
      CurrToken.TokenClass := tcSPECIAL;
      Exit;
    end;

  if FieldSwitch then
  begin
    CurrToken.ID := NewField(CurrToken.Text);
    FieldSwitch := false;
    Exit;
  end;

  case CurrToken.TokenClass of
    tcIntegerConst, tcFloatConst:
    begin
      CurrToken.ID := SymbolTable.CodeNumberConst(CurrToken.Value);
      if CurrToken.TokenClass = tcFloatConst then
        TypeID[CurrToken.ID] := typeDOUBLE;
      if JavaScriptOperators then
        TypeID[CurrToken.ID] := typeVARIANT;
      Exit;
    end;
    tcStringConst:
    begin
      CurrToken.ID := SymbolTable.CodeStringConst(CurrToken.Text);
      if JavaScriptOperators then
        TypeID[CurrToken.ID] := typeVARIANT;
      Exit;
    end;
    tcId:
    if DeclareSwitch 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
    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 TPAXBasicParser.IsBaseType(const S: String): Boolean;
begin
  result := inherited IsBaseType(S);
  if result then
    Exit;
  result := StrEql(S, 'int') or
            StrEql(S, 'uint') or
            StrEql(S, 'sbyte') or
            StrEql(S, 'short') or
            StrEql(S, 'ushort') or
            StrEql(S, 'long') or
            StrEql(S, 'bool') or
            StrEql(S, 'void') or
            StrEql(S, 'set');
end;

procedure TPAXBasicParser.Match(const S: String);
var
  I: Integer;
begin
  if S = ':' then
  begin
    for I:=0 to SeparatorIds.Count - 1 do
      Gen(OP_SEPARATOR, ModuleID, Integer(SeparatorIds[I]), CurrLevel);
    SeparatorIDs.Clear;
  end;
  inherited;
end;

function TPAXBasicParser.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;

///////  EXPRESSIONS /////////////////////////////////////////////////////////

function TPAXBasicParser.Parse_PrimaryExpression: Integer;
var
  ma: TPAXMemberAccess;
  ID, SubID: Integer;
  IsArrayItem: Boolean;
begin
  if IsCurrText('(') then // (Expression)
  begin
    Call_SCANNER;
    result := Parse_Expression;
    Match(')');
    Call_SCANNER;
  end
  else if IsCurrText('MyBase') or IsCurrText('MyClass') then
  begin
    if CurrClassID = 0 then
      raise TPAXScriptFailure.Create(errStatementIsNotAllowedHere);
    if CurrSubID <> CurrMethodID then
      raise TPAXScriptFailure.Create(errStatementIsNotAllowedHere);

    if IsCurrText('MyBase') then
      ma := maMyBase
    else
      ma := maMyClass;

    Call_SCANNER;
    Match('.');
    FieldSwitch := true;
    Call_SCANNER;
    result := Parse_Ident;
    GenRef(CurrThisID, ma, result);
  end
  else if IsCurrText('[') then // (array literal)
    result := Parse_ArrayLiteral
  else if IsCurrText('{') then // (object literal)
    result := Parse_ObjectLiteral
  else if IsCurrText('/') then // (regexp literal)
    result := Parse_RegExpr('New')
  else if IsCurrText('AddressOf') then
  begin
    result := NewVar;
    Call_SCANNER;
    if IsCallOperator then
      RemoveLastOperator;

    IsArrayItem := IsNextText('(') or IsNextText('[');

    SubID := Parse_MemberExpression(0);
    if IsCallOperator and (not IsArrayItem) then
      RemoveLastOperator;
    Gen(OP_ASSIGN_ADDRESS, result, SubID, result);
  end
  else if IsCurrText('TerminalOf') then
  begin
    Call_SCANNER;
    ID := Parse_MemberExpression(0);
    result := NewVar;
    Gen(OP_GET_TERMINAL, ID, 0, result);
  end
  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
    FieldSwitch := true;
    Call_SCANNER;
    result := Parse_Ident;
    GenRef(WithStack.Top, maAny, result);

    if not (CurrToken.Text[1] in ['(', '[']) then
      Gen(OP_CALL, result, 0, result);
  end
  else
  begin
    result := Parse_Ident;
    result := GenEvalWith(result);
  end;
end;

function TPAXBasicParser.Parse_ObjectLiteral: Integer;
begin
  result := 0; // not implemented yet
end;

function TPAXBasicParser.Parse_MemberExpression(ID: Integer): Integer;
var
  SubID, RefID, NP, Vars: Integer;
  S: String;
  CallRec: TPaxCallRec;
  Rank: Integer;
label
  Again;
begin
  if ID = 0 then
    result := Parse_PrimaryExpression
  else
    result := ID;

  Rank := SymbolTable.Rank[result];
  while CurrToken.Text[1] in ['(','[','.'] do
    case CurrToken.Text[1] of
      '.':
      begin
        FieldSwitch := true;
        Call_SCANNER;

        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;

        if not (CurrToken.Text[1] in ['(', '[']) then
          Gen(OP_CALL, result, 0, result);
      end;
      '(', '[':
      begin
        if Rank = -1 then
          raise TPaxScriptFailure.Create(errCannotApplyToScalar);

        if CurrToken.Text = '(' then
          S := ')'
        else
          S := ']';

        SubID := result;

        Call_SCANNER;
        if IsCurrText(S) then
        begin
          NP := 0;
          Vars := 0;

          CallRec := TPaxCallRec.Create;
          CallRec.CallP := Scanner.PosNumber;
          CallRec.CallN := Code.Card + 1;
          TPaxBaseScripter(Scripter).CallRecList.AddObject(CallRec.CallN, CallRec);
        end
        else
          NP := Parse_ArgumentList(SubID, Vars);
        Match(S);

        if (Rank > 0) and (NP <> Rank) then
           raise TPaxScriptFailure.Create(errRankMismatch);

        result := NewVar;
        Gen(OP_CALL, SubID, NP, result);
        SetVars(Vars);

        Call_SCANNER;
      end;
    end;
end;

function TPAXBasicParser.Parse_NewExpression: Integer;
var
  ClassID, ObjectID, RefID: Integer;
begin
  if IsCurrText('new') then
  begin
    Call_SCANNER;
    ClassID := Parse_Ident;
    ClassID := GenEvalWith(ClassID);

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

    ObjectID := NewVar;
    Gen(OP_CREATE_OBJECT, ClassID, 0, ObjectID);

    TypeID[ObjectID] := ClassID;

    if IsCurrText('(') then
    begin
      result := NewRef;
      Name[result] := 'New';
      GenRef(ObjectID, maMyClass, result);
      result := Parse_MemberExpression(result);
    end
    else
      result := ObjectID;
  end
  else
    result := Parse_MemberExpression(0);
end;

function TPAXBasicParser.Parse_PowerExpression: Integer;
var
  ResID: Integer;
begin
  ResID := 0;
  result := Parse_NewExpression;

  while CurrToken.ID = OP_POWER do
  begin
    if ResID = 0 then
      ResID := NewVar;

    Call_SCANNER;
    Gen(OP_POWER, result, Parse_NewExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_UnaryMinusExpression: Integer;
begin
  if CurrToken.ID = OP_MINUS then
  begin
    result := NewVar;
    Call_SCANNER;
    Gen(OP_UNARY_MINUS, Parse_UnaryMinusExpression, 0, result);
  end
  else if CurrToken.ID = OP_PLUS then
  begin
    result := NewVar;
    Call_SCANNER;
    Gen(OP_UNARY_PLUS, Parse_UnaryMinusExpression, 0, result);
  end
  else
    result := Parse_PowerExpression;
end;

function TPAXBasicParser.Parse_MultiplicativeExpression: Integer;
var
  OP, ResID: Integer;
begin
  ResID := 0;
  result := Parse_UnaryMinusExpression;

  while
    (CurrToken.ID = OP_MULT) or
    (CurrToken.ID = OP_DIV) or
    (CurrToken.ID = OP_INT_DIV)
  do
  begin
    OP := CurrToken.ID;
    if ResID = 0 then
      ResID := NewVar;

    Call_SCANNER;
    Gen(OP, result, Parse_UnaryMinusExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_ModExpression: Integer;
var
  ResID: Integer;
begin
  ResID := 0;
  result := Parse_MultiplicativeExpression;

  while CurrToken.ID = OP_MOD do
  begin
    if ResID = 0 then
      ResID := NewVar;

    Call_SCANNER;
    Gen(OP_MOD, result, Parse_MultiplicativeExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_AdditiveExpression: Integer;
var
  OP, ResID: Integer;
begin
  ResID := 0;
  result := Parse_ModExpression;

  while
    (CurrToken.ID = OP_PLUS) or
    (CurrToken.ID = OP_MINUS)
  do
  begin
    OP := CurrToken.ID;
    if ResID = 0 then
      ResID := NewVar;

    Call_SCANNER;
    Gen(OP, result, Parse_ModExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_ConcatenationExpression: Integer;
var
  ResID: Integer;
begin
  ResID := 0;
  result := Parse_AdditiveExpression;

  while CurrToken.ID = SP_CONCAT do
  begin
    Call_SCANNER;
    if ResID = 0 then
    begin
      ResID := NewVar;
      Gen(OP_PLUS, result, Parse_AdditiveExpression, ResID);
    end
    else
      Gen(OP_PLUS, result, Parse_AdditiveExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_EqualityExpression: Integer;
var
  OP, ResID: Integer;
begin
  ResID := 0;
  result := Parse_ConcatenationExpression;

  while
    (CurrToken.ID = OP_EQ) or
    (CurrToken.ID = OP_NE) or
    (CurrToken.ID = OP_GT) or
    (CurrToken.ID = OP_LT) or
    (CurrToken.ID = OP_GE) or
    (CurrToken.ID = OP_LE) or
    (CurrToken.ID = OP_IN_SET)
  do
  begin
    OP := CurrToken.ID;
    if ResID = 0 then
      ResID := NewVar;

    Call_SCANNER;
    Gen(OP, result, Parse_ConcatenationExpression, ResID);

    result := ResID;
  end;
end;

function TPAXBasicParser.Parse_Expression: Integer;
var
  OP, ResID, A: Integer;

⌨️ 快捷键说明

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