base_scanner.pas
来自「Delphi脚本控件」· PAS 代码 · 共 1,577 行 · 第 1/3 页
PAS
1,577 行
////////////////////////////////////////////////////////////////////////////
// PAXScript Interpreter
// Author: Alexander Baranovsky (ab@cable.netlux.org)
// ========================================================================
// Copyright (c) Alexander Baranovsky, 2003-2005. All rights reserved.
// Code Version: 3.0
// ========================================================================
// Unit: BASE_SCANNER.pas
// ========================================================================
////////////////////////////////////////////////////////////////////////////
{$I PaxScript.def}
unit BASE_SCANNER;
interface
uses
Classes,
SysUtils,
// QStrings,
BASE_CONSTS,
BASE_SYS;
type
TScannerState = (scanText, scanProg);
TPAXScanner = class;
TDefRec = class
public
Word: Integer;
What: String;
Vis: boolean;
end;
TDefStack = class
private
fItems: TList;
function GetItem(I: Integer): TDefRec;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
function Count: Integer;
procedure Push(Word: Integer; What: String; Vis: Boolean);
procedure Pop;
property Items[I: Integer]: TDefRec read GetItem; default;
end;
TScannerRec = class
public
LineNumber, PosNumber: Integer;
c: Char;
P: Integer;
Buff: String;
end;
TScannerStack = class
private
fItems: TList;
function GetItem(I: Integer): TScannerRec;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
function Count: Integer;
procedure Push(Scanner: TPaxScanner);
procedure Pop(Scanner: TPaxScanner);
property Items[I: Integer]: TScannerRec read GetItem; default;
end;
TPAXScanner = class
private
Scripter: Pointer;
fScannerState: TScannerState;
Parser: Pointer;
procedure SetSourceCode(const Value: String);
function GetSourceCode: String;
procedure SetScannerState(Value: TScannerState);
public
LineNumber, PosNumber: Integer;
Token, BuffToken: TPAXToken;
c: Char;
P: Integer;
Buff: String;
VarNameList: TStringList;
DefStack: TDefStack;
ScannerStack: TScannerStack;
LookForward: Boolean;
constructor Create(Parser: Pointer);
destructor Destroy; override;
procedure SetScripter(AScripter: Pointer);
procedure Reset;
function EndOfTagExpected: Boolean;
function GetText(P1, P2: Integer): String;
function GetNextChar: Char;
function LA(N: Integer ): Char;
procedure ReadToken; virtual;
function NextToken: TPAXToken;
function Next2Token: TPAXToken;
procedure ScanIdentifier;
procedure ScanIdentifierEx(ExtraChars: TCharSet);
procedure ScanChars(CSet: TCharSet);
procedure ScanString(ch: Char);
procedure ScanHtmlString(const Ch: String);
procedure ScanFormatString;
procedure ScanDigits;
procedure ScanHexDigits;
procedure ScanWhiteSpace;
procedure ScanEOF;
procedure ScanPlus;
procedure ScanMinus;
procedure ScanMult;
procedure ScanDiv;
procedure ScanMod;
procedure ScanGT;
procedure ScanLT;
procedure ScanEQ;
procedure ScanLeftRoundBracket;
procedure ScanRightRoundBracket;
procedure ScanLeftBracket;
procedure ScanRightBracket;
procedure ScanLeftBrace;
procedure ScanRightBrace;
procedure ScanColon;
procedure ScanSemiColon;
procedure ScanComma;
procedure ScanPoint;
procedure ScanBackslash;
function GetRegExpr: String;
procedure ScanCondDir(Start1: Char;
Start2: TCharSet);
function IsEOF: Boolean;
procedure IncLineNumber;
property SourceCode: String read GetSourceCode write SetSourceCode;
property ScannerState: TScannerState read fScannerState write SetScannerState;
end;
implementation
uses
BASE_SCRIPTER, BASE_PARSER;
const
_IFDEF = 1;
_IFNDEF = 2;
_ELSE = 3;
_ENDIF = 4;
constructor TDefStack.Create;
begin
fItems := TList.Create;
end;
destructor TDefStack.Destroy;
begin
Clear;
fItems.Free;
inherited;
end;
procedure TDefStack.Clear;
begin
while Count > 0 do
Pop;
end;
function TDefStack.Count: Integer;
begin
result := fItems.Count;
end;
function TDefStack.GetItem(I: Integer): TDefRec;
begin
result := TDefRec(fItems[I - 1]);
end;
procedure TDefStack.Push(Word: Integer; What: String; Vis: Boolean);
var
R: TDefRec;
begin
R := TDefRec.Create;
R.Word := Word;
R.What := What;
R.Vis := Vis;
fItems.Add(R);
end;
procedure TDefStack.Pop;
var
R: TDefRec;
begin
R := fItems[Count - 1];
fItems.Delete(Count - 1);
R.Free;
end;
constructor TScannerStack.Create;
begin
fItems := TList.Create;
end;
destructor TScannerStack.Destroy;
begin
Clear;
fItems.Free;
inherited;
end;
procedure TScannerStack.Clear;
begin
while Count > 0 do
Pop(nil);
end;
function TScannerStack.GetItem(I: Integer): TScannerRec;
begin
result := TScannerRec(fItems[I - 1]);
end;
function TScannerStack.Count: Integer;
begin
result := fItems.Count;
end;
procedure TScannerStack.Push(Scanner: TPaxScanner);
var
R: TScannerRec;
begin
R := TScannerRec.Create;
R.LineNumber := Scanner.LineNumber;
R.PosNumber := Scanner.PosNumber;
R.c := Scanner.c;
R.P := Scanner.P;
R.Buff := Scanner.Buff;
fItems.Add(R);
end;
procedure TScannerStack.Pop(Scanner: TPaxScanner);
var
R: TScannerRec;
begin
R := fItems[Count - 1];
fItems.Delete(Count - 1);
if Scanner <> nil then
begin
Scanner.LineNumber := R.LineNumber;
Scanner.PosNumber := R.PosNumber;
Scanner.c := R.c;
Scanner.P := R.P;
Scanner.Buff := R.Buff;
end;
R.Free;
end;
constructor TPAXScanner.Create(Parser: Pointer);
begin
VarNameList := TStringList.Create;
DefStack := TDefStack.Create;
ScannerStack := TScannerStack.Create;
Self.Parser := Parser;
scripter := nil;
Reset;
end;
destructor TPAXScanner.Destroy;
begin
VarNameList.Free;
DefStack.Free;
ScannerStack.Free;
inherited;
end;
procedure TPAXScanner.SetScripter(AScripter: Pointer);
begin
Scripter := AScripter;
end;
function TPAXScanner.GetText(P1, P2: Integer): String;
var
S: ShortString;
L: Integer;
begin
L := P2 - P1 + 1;
Move(Buff[P1], S[1], L);
S[0] := Chr(L);
result := S;
end;
procedure TPAXScanner.ReadToken;
begin
if scripter <> nil then
with TPAXBaseScripter(Scripter) do
begin
if CancelMessage <> '' then
raise TPaxScriptFailure.Create(CancelMessage);
Code.N := Code.Card;
if Assigned(OnCompilerProgress) then
OnCompilerProgress(Owner, CurrModule);
Code.N := 0;
end;
Token.Position := P + 1;
end;
procedure TPAXScanner.Reset;
begin
P := 0;
LineNumber := 0;
PosNumber := -1;
Buff := '';
BuffToken.Text := '';
fScannerState := scanText;
VarNameList.Clear;
DefStack.Clear;
ScannerStack.Clear;
LookForward := false;
end;
procedure TPAXScanner.SetSourceCode(const Value: String);
begin
Reset;
Buff := Value + #255#255#255;
end;
function TPAXScanner.GetSourceCode: String;
begin
result := Buff;
end;
function TPAXScanner.GetNextChar: Char;
begin
Inc(P);
result := Buff[P];
Inc(PosNumber);
c := result;
end;
function TPAXScanner.LA(N: Integer ): Char;
begin
if BuffToken.Text <> '' then
begin
result := BuffToken.Text[P + N];
Exit;
end;
result := Buff[P + N];
end;
function TPAXScanner.EndOfTagExpected: Boolean;
var
I: Integer;
ch: Char;
begin
result := false;
I := 1;
repeat
Ch := LA(I);
case Ch of
'?','%':
begin
result := true;
Exit;
end;
#8, #9, #10, #13, #32: begin end;
else
Exit;
end;
Inc(I);
until false;
end;
function TPAXScanner.NextToken: TPAXToken;
var
SaveP, SaveLineNumber, SavePosNumber, SaveTotal: Integer;
SaveToken: TPAXToken;
SaveC: Char;
SaveState: TScannerState;
begin
LookForward := true;
if ScannerStack.Count > 0 then
begin
Token.Text := '';
Token.TokenClass := tcSeparator;
Exit;
end;
SaveTotal := TPAXBaseScripter(Scripter).fTotalLineCount;
SaveP := P;
SaveLineNumber := LineNumber;
SavePosNumber := PosNumber;
SaveToken := Token;
SaveC := c;
SaveState := fScannerState;
ReadToken;
while Token.TokenClass = tcSeparator do
begin
if Token.ID = SP_EOF then
Break;
ReadToken;
end;
result := Token;
P := SaveP;
LineNumber := SaveLineNumber;
PosNumber := SavePosNumber;
Token := SaveToken;
c := SaveC;
TPAXBaseScripter(Scripter).fTotalLineCount := SaveTotal;
fScannerState := SaveState;
VarNameList.Clear;
LookForward := false;
end;
function TPAXScanner.Next2Token: TPAXToken;
label Fin;
var
SaveP, SaveLineNumber, SavePosNumber, SaveTotal: Integer;
SaveToken: TPAXToken;
SaveC: Char;
SaveState: TScannerState;
begin
LookForward := true;
if ScannerStack.Count > 0 then
begin
Token.Text := '';
Token.TokenClass := tcSeparator;
Exit;
end;
SaveTotal := TPAXBaseScripter(Scripter).fTotalLineCount;
SaveP := P;
SaveLineNumber := LineNumber;
SavePosNumber := PosNumber;
SaveToken := Token;
SaveC := c;
SaveState := fScannerState;
ReadToken;
while Token.TokenClass = tcSeparator do
begin
if Token.ID = SP_EOF then
goto Fin;
ReadToken;
end;
ReadToken;
while Token.TokenClass = tcSeparator do
begin
if Token.ID = SP_EOF then
goto Fin;
ReadToken;
end;
Fin:
result := Token;
P := SaveP;
LineNumber := SaveLineNumber;
PosNumber := SavePosNumber;
Token := SaveToken;
c := SaveC;
TPAXBaseScripter(Scripter).fTotalLineCount := SaveTotal;
fScannerState := SaveState;
VarNameList.Clear;
LookForward := false;
end;
{
procedure TPAXScanner.ScanIdentifier;
var
S: String;
begin
Token.Position := P;
S := c;
while LA(1) in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do
S := S + GetNextChar;
Token.TokenClass := tcId;
Token.Text := S;
SetScannerState(scanProg);
end;
}
procedure TPAXScanner.ScanIdentifier;
begin
Token.Position := P;
repeat
case LA(1) of
'A'..'Z', 'a'..'z', '0'..'9', '_':
begin
Inc(P);
Inc(PosNumber);
end;
else
break;
end;
until false;
Token.TokenClass := tcId;
Token.Text := Copy(Buff, Token.Position, P - Token.Position + 1);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?