base_scanner.pas

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

PAS
1,577
字号
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanIdentifierEx(ExtraChars: TCharSet);
begin
  Token.Position := P;

  repeat
    case LA(1) of
      'A'..'Z', 'a'..'z', '0'..'9', '_':
      begin
        Inc(P);
        Inc(PosNumber);
      end;
      else
      begin
        if LA(1) in ExtraChars then
        begin
          Inc(P);
          Inc(PosNumber);
        end
        else
          break;
      end;
    end;
  until false;

  Token.TokenClass := tcId;

  Token.Text := Copy(Buff, Token.Position, P - Token.Position + 1);

  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanChars(CSet: TCharSet);
var
  S: String;
begin
  Token.Position := P;

  S := c;
  while LA(1) in CSet do
    S := S + GetNextChar;
  Token.TokenClass := tcId;
  Token.Text := S;

  SetScannerState(scanProg);
end;

function GetVal(const StrVal: String): Variant;
var
  I, J, K: Integer;
  ch: Char;
  S: String;
begin
  I := Length(StrVal);
  ch := StrVal[I];
  case ch of
    'B', 'b':
    begin
      J := 0;
      K := 1;
      Dec(I);
      repeat
        ch := StrVal[I];

        if not (ch in ['0'..'1']) then
          raise TPaxScriptFailure.Create(errSyntaxError);

        if ch = '1' then
          Inc(J, K);

        K := K * 2;
        Dec(I);
      until I = 0;
      result := J;
    end;
    'D', 'd':
    begin
      result :=  SysUtils.StrToInt(Copy(StrVal, 1, I - 1));
    end;
    'H', 'h':
    begin
      S := '$' + Copy(StrVal, 1, I - 1);
      result := StrToInt(S);
    end;
    else
    begin
      S := Copy(StrVal, 1, 2);
      if (S = '0x') or (S = '0X') then
      begin
        S := '$' + Copy(StrVal, 3, Length(StrVal) - 2);
        result := StrToInt(S);
      end
      else if (S = '0b') or (S = '0B') then
      begin
        S := Copy(StrVal, 3, Length(StrVal) - 2);
        I := Length(S);
        J := 0;
        K := 1;
        repeat
          ch := S[I];

          if not (ch in ['0'..'1']) then
           raise TPaxScriptFailure.Create(errSyntaxError);

          if ch = '1' then
            Inc(J, K);
          K := K * 2;
          Dec(I);
        until I = 0;
        result := J;
      end
      else
        result := SysUtils.StrToFloat(StrVal);
    end;
  end;
end;

procedure TPAXScanner.ScanDigits;
var
  S: String;
  I64: Int64;
{$IFNDEF VARIANTS}
  D: Double;
{$ENDIF}
begin
  S := c;

  if c = '0' then
  begin
    case LA(1) of
      'x','X':
      begin
        GetNextChar;
        c := '$';
        ScanHexDigits;
        Exit;
      end;
      'b','B':
      begin
        GetNextChar;
        S := '';
        while LA(1) in ['0'..'1'] do
          S := S + GetNextChar;
        Token.TokenClass := tcIntegerConst;
        Token.Text := '0b' + S;
        Token.Value := StringToBinary(S);
        Exit;
      end;
      else
      begin
        while LA(1) in ['0'..'9', 'A'..'F'] do
          S := S + GetNextChar;
        Token.TokenClass := tcIntegerConst;
        if LA(1) in ['b','B','d','D','h','H'] then
        begin
          S := S + GetNextChar;
          Token.Value := GetVal(S);
          Exit;
        end;
      end;
    end;
  end;

  while LA(1) in ['0'..'9'] do
    S := S + GetNextChar;
  Token.TokenClass := tcIntegerConst;

  if ((LA(1) = '.') and (LA(2) <> '.')) or (LA(1) in ['e', 'E']) then
  begin
    S := S + GetNextChar;
    if LA(1) = '-' then
      S := S + GetNextChar;
    while LA(1) in ['0'..'9', 'e', 'E'] do
    begin
      S := S + GetNextChar;
      Token.TokenClass := tcFloatConst;
    end;
  end;

  if S[Length(S)] = '.' then
  begin
    Delete(S, Length(S), 1);
    Dec(P);
  end;

  Token.Text := S;

  if Token.TokenClass = tcIntegerConst then
  begin
    I64 := StrToInt64(S);

    if Abs(I64) > MaxInt then
    begin
{$IFDEF VARIANTS}
      Token.Value := i64;  //
{$ELSE}
      D := I64;
      Token.Value := D;
{$ENDIF}
    end
    else
      Token.Value := integer(I64);
  end
  else
  begin
    Token.Value := StrToFloat(StringReplace(S, '.', DecimalSeparator, []));
  end;

  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanHexDigits;
var
  S: String;
  I64: Int64;
  D: Double;
begin
  S := c;
  while LA(1) in ['0'..'9', 'A'..'F', 'a'..'f'] do
    S := S + GetNextChar;

  Token.TokenClass := tcIntegerConst;
  Token.Text := S;

  I64 := StrToInt64(S);
  if I64 > MaxInt then
  begin
    D := I64;
    Token.Value := D;
  end
  else
    Token.Value := StrToInt(S);
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanWhiteSpace;
begin
  if c in [#10,#13] then
  begin
    IncLineNumber;
    PosNumber := -1;

    if c = #13 then
      GetNextChar;
    Token.ID := LineNumber;
    Token.TokenClass := tcSeparator;
  end;
end;

procedure TPAXScanner.ScanEOF;
begin
  if ScannerStack.Count > 0 then
  begin
    ScannerStack.Pop(Self);
    Exit;
  end;

  Token.Text := 'EOF';
  Token.TokenClass := tcSeparator;
  Token.ID := SP_EOF;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanPlus;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_PLUS;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanMinus;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_MINUS;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanMult;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_MULT;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanDiv;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_DIV;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanGT;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_GT;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanLT;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_LT;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanEQ;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_EQ;

  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanMod;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := OP_MOD;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanLeftRoundBracket;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_ROUND_BRACKET_L;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanRightRoundBracket;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_ROUND_BRACKET_R;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanLeftBracket;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_BRACKET_L;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanRightBracket;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_BRACKET_R;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanLeftBrace;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_BRACE_L;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanRightBrace;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_BRACE_R;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanColon;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_COLON;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanSemiColon;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_SEMICOLON;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanComma;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_COMMA;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanBackslash;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_BACKSLASH;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.ScanPoint;
begin
  Token.Text := c;
  Token.TokenClass := tcSpecial;
  Token.ID := SP_POINT;
  SetScannerState(scanProg);
end;

function TPAXScanner.GetRegExpr: String;
begin
  result := '';
  while not ((LA(1) = '/') and (LA(0) <> '\')) do
  begin
    GetNextChar;
    if c = #255 then Exit;
    result := result + c;
  end;
  SetScannerState(scanProg);
end;

procedure TPAXScanner.SetScannerState(Value: TScannerState);
begin
  fScannerState := Value;
end;

procedure TPAXScanner.ScanFormatString;
var
  P1, P2: Integer;
  StrFormat, VarName: String;
begin
//  "%" [index ":"] ["-"] [width] ["." prec] type
  GetNextChar;
  P1 := P;
  if LA(1) in ['0'..'9'] then // Index
  begin
    while (LA(1) in ['0'..'9']) do
      GetNextChar;
    if LA(1) <> ':' then
      raise TPAXScriptFailure.Create(':' + errExpected);
    GetNextChar;
  end;
  if LA(1) = '-' then
    GetNextChar;
  if LA(1) in ['0'..'9'] then // width
    while (LA(1) in ['0'..'9']) do
      GetNextChar;
  if LA(1) = '.' then
    GetNextChar;
  if LA(1) in ['0'..'9'] then // prec
    while (LA(1) in ['0'..'9']) do
      GetNextChar;
  GetNextChar; // type

  P2 := P;

  StrFormat := Copy(Buff, P1, P2 - P1 + 1);
  Token.Text := Token.Text + StrFormat;

  if LA(1) <> '=' then
    raise TPAXScriptFailure.Create('=' + errExpected);
  GetNextChar;

  if not (LA(1) in ['a'..'z','A'..'Z','_']) then
    raise TPAXScriptFailure.Create(errIdentifierExpected);
  VarName := GetNextChar;
  while (LA(1) in ['a'..'z','A'..'Z','_','0'..'9']) do
    VarName := VarName + GetNextChar;

  VarNameList.Add(VarName);
end;

procedure TPAXScanner.ScanHtmlString(const Ch: String);
var
  K1, K2: Integer;
  Backslash: Boolean;
begin
  Backslash := TPAXParser(Parser).Backslash;
  K1 := 0;
  K2 := 0;
  with Token do
  begin
    TokenClass := tcHtmlStringConst;
    Text := Ch;
    repeat
      c := GetNextChar;

      case c of
        #0,#13,#10:
        begin
          Text := Text + c;
          if c = #13 then
          begin
            c := GetNextChar;
            Text := Text + c;
          end;

          IncLineNumber;
          PosNumber := -1;

          with TPAXBaseScripter(Scripter).Code do
            Add(OP_SEPARATOR, ModuleID, LineNumber, 0);
        end;
        '\':
        if (K1 mod 2 = 0) and (K2 mod 2 = 0) then
        begin

          if not Backslash then
          Text := Text + c
          else

          case LA(1) of
          '%': ScanFormatString;
          'b':
          begin
            GetNextChar;
            Text := Text + #$08;

⌨️ 快捷键说明

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