📄 rm_jvhlparser.pas
字号:
while (P[0] in IdentifierSymbols) do
Inc(P);
SetString(Result, F, P - F);
end
else
if P[0] = '''' then
{ pascal string constant }
begin
Inc(P);
while P[0] <> #0 do
begin
if P[0] = '''' then
if P[1] = '''' then
Inc(P)
else
Break;
Inc(P);
end;
if P[0] <> #0 then
Inc(P);
SetString(Result, F, P - F);
I := 2;
while I < Length(Result) - 1 do
begin
if Result[I] = '''' then
Delete(Result, I, 1);
Inc(I);
end;
end
else
if (FStyle in [psCpp, psCocoR]) and (P[0] = '"') then
{ C++ string constant }
begin
Inc(P);
while P[0] <> #0 do
begin
if (P[0] = '"') and (P[-1] <> '\') then
Break;
if (P[0] = '"') and (P[-1] = '\') then
begin
// count the backslashes, on even backslahses it is a string end
I := 1;
while (P - 1 - I > F) and (P[-1 - I] = '\') do
Inc(I);
if I and $01 = 0 then
Break; { same but faster than: if I mod 2 = 0 then Break; }
end;
Inc(P);
end;
if P[0] <> #0 then
Inc(P);
SetString(Result, F, P - F);
end
else
if ((FStyle in [psPython, psVB, psHtml]) and (P[0] = '"')) or
((FStyle in [psPerl, psPhp]) and (P[0] = '"') and ((P = FpcPos) or (P[-1] <> '/'))) then
{ Python, VB, Html, Perl string constant }
begin
Inc(P);
while P[0] <> #0 do
begin
if P[0] = '"' then
Break;
Inc(P);
end;
if P[0] <> #0 then
Inc(P);
SetString(Result, F, P - F);
end
else
if P[0] = #0 then
Result := ''
else
begin
Result := P[0];
Inc(P);
end;
end
else { html }
begin
if (P[0] in ['=', '<', '>']) or
((P <> pcProgram) and (P[0] = '/') and (P[-1] = '<')) then
begin
Result := P[0];
Inc(P);
end
else
if P[0] = '"' then
{ Html string constant }
begin
Inc(P);
while P[0] <> #0 do
begin
if P[0] = '"' then
Break;
Inc(P);
end;
if P[0] <> #0 then
Inc(P);
SetString(Result, F, P - F);
end
else
begin
while not (P[0] in [#0, ' ', '=', '<', '>']) do
Inc(P);
SetString(Result, F, P - F);
end;
end;
Return;
end;
function TJvIParser.HistoryInd(Index: Integer): Integer;
begin
Result := FHistoryPtr - 1 - Index;
if Result < 0 then
Result := Result + FHistorySize;
end;
function TJvIParser.GetHistory(Index: Integer): string;
begin
Result := FHistory[HistoryInd(Index)];
end;
function TJvIParser.GetPosEnd(Index: Integer): Integer;
begin
Result := Integer(FHistory.Objects[HistoryInd(Index)]) + 1;
end;
function TJvIParser.GetPosBeg(Index: Integer): Integer;
var
I: Integer;
S: string;
begin
I := HistoryInd(Index);
S := FHistory[I];
Result := Integer(FHistory.Objects[I]) - Length(S) + 1;
case FStyle of
psPascal:
if S[1] = '''' then
for I := 2 to Length(S) - 1 do
if S[I] = '''' then
Dec(Result);
end;
end;
procedure TJvIParser.SetHistorySize(Size: Integer);
begin
while Size > FHistorySize do
begin
FHistory.Add('');
Inc(FHistorySize);
end;
while Size < FHistorySize do
begin
FHistory.Delete(0);
Dec(FHistorySize);
end;
FHistoryPtr := 0;
end;
function TJvIParser.GetPos: Integer;
begin
Result := pcPos - FpcProgram;
end;
procedure TJvIParser.RollBack(Index: Integer);
begin
FpcPos := PosEnd[Index] + FpcProgram;
Dec(FHistoryPtr, Index);
if FHistoryPtr < 0 then
FHistoryPtr := FHistorySize + FHistoryPtr;
end;
//=== { TJvIParserW } ========================================================
constructor TJvIParserW.Create;
begin
inherited Create;
FHistory := TWStringList.Create;
HistorySize := 10;
Style := psPascal;
end;
destructor TJvIParserW.Destroy;
begin
FHistory.Free;
inherited Destroy;
end;
function TJvIParserW.Token: WideString;
const
StSkip = [' ', Lf, Cr];
var
P, F: PWideChar;
F1: PWideChar;
I: Integer;
function SkipComments: Boolean;
begin
SkipComments := True;
case P[0] of
'{':
if FStyle = psPascal then
begin
F := StrScanW(P + 1, WideChar('}'));
if F = nil then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
P := F + 1;
end;
'}':
if FStyle = psPascal then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
'(':
if (FStyle in [psPascal, psCocoR]) and (P[1] = '*') then
begin
if P[2] = #0 then
Exit; // line end
F := P + 2;
while True do
begin
F := StrScanW(F, WideChar('*'));
if F = nil then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
if F[1] = ')' then
begin
Inc(F);
Break;
end;
Inc(F);
end;
P := F + 1;
end;
'*':
if FStyle in [psPascal, psCocoR] then
begin
if (P[1] = ')') then
//IParserError(ieBadRemark, P - FpcProgram)
Exit;
end
else
if FStyle in [psCpp, psPhp] then
if P[1] = '/' then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
'/':
if (FStyle in [psPascal, psCpp, psCocoR, psPhp]) and (P[1] = '/') then
begin
F := StrScanW(P + 1, WideChar(Cr));
if F = nil then
F := StrEndW(P + 1);
P := F;
end
else
if (FStyle in [psCpp, psCocoR, psPhp, psSQL]) and (P[1] = '*') then
begin
if P[2] = #0 then
Exit; // line end
F := P + 2;
while True do
begin
F := StrScanW(F, WideChar('*'));
if F = nil then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
if F[1] = '/' then
begin
Inc(F);
Break;
end;
Inc(F);
end;
P := F + 1;
end;
'#':
if (FStyle in [psPython, psPerl]) { and
((P = FpcProgram) or (P[-1] in [Lf, Cr])) }then
begin
F := StrScanW(P + 1, WideChar(Cr));
if F = nil then
F := StrEndW(P + 1);
P := F;
end;
'''':
if FStyle = psVB then
begin
F := StrScanW(P + 1, WideChar(Cr));
if F = nil then
F := StrEndW(P + 1);
P := F;
end;
// Support for the SQL -- comments
'-':
if (FStyle = psSql) and (P[1] = '-') then
begin
F := StrScanW(P + 1, WideChar(Cr));
if F = nil then
F := StrEndW(P + 1);
P := F;
end;
// Support for multiline comments for HTML
'<':
if (FStyle = psHtml) and (P[1] = '!') then
begin
// we need the next 2 chars to be --
if (P[2] = #0) or (P[3] = #0) then
Exit; // line end
if (P[2] <> '-') and (P[3] <> '-') then
Exit;
F := P + 3;
while True do
begin
F := StrScanW(F, WideChar('-'));
if F = nil then //IParserError(ieBadRemark, P - FpcProgram);
Exit;
if (F[1] = '-') and (F[2] = '>') then
begin
Inc(F, 2);
Break;
end;
Inc(F);
end;
P := F + 1;
end;
end;
SkipComments := False;
end;
procedure Return;
begin
FpcPos := P;
FHistory.PStrings[FHistoryPtr]^ := Result;
FHistory.Objects[FHistoryPtr] := TObject(Pos - 1);
Inc(FHistoryPtr);
if FHistoryPtr > FHistorySize - 1 then
FHistoryPtr := 0;
end;
begin
{ New Token - To begin reading a new token [translated] }
F := FpcPos;
P := FpcPos;
{ Firstly skip spaces and remarks }
repeat
while CharInSetW(P[0], StSkip) do
Inc(P);
F1 := P;
try
if SkipComments then
P := StrEndW(F1);
except
on E: EJvIParserError do
if (E.ErrCode = ieBadRemark) and ReturnComments then
P := StrEndW(F1)
else
raise;
end;
if ReturnComments and (P > F1) then
begin
SetString(Result, F1, P - F1);
Return;
Exit;
end;
while CharInSetW(P[0], StSkip) do
Inc(P);
until F1 = P;
F := P;
if FStyle <> psHtml then
begin
if CharInSetW(P[0], IdentifierFirstSymbols) then
{ token }
begin
while CharInSetW(P[0], IdentifierSymbols) do
Inc(P);
SetString(Result, F, P - F);
end
else
if CharInSetW(P[0], DigitSymbols) then
{ number }
begin
while CharInSetW(P[0], DigitSymbols) or (P[0] = '.') do
Inc(P);
SetString(Result, F, P - F);
end
else
if (Style = psPascal) and (P[0] = '$') and
CharInSetW(P[1], HexadecimalSymbols) then
{ pascal hex number }
begin
Inc(P);
while CharInSetW(P[0], HexadecimalSymbols) do
Inc(P);
SetString(Result, F, P - F);
end
else
if (Style = psPerl) and CharInSetW(P[0], ['$', '@', '%', '&']) then
{ perl identifier }
begin
Inc(P);
while CharInSetW(P[0], IdentifierSymbols) do
Inc(P);
SetString(Result, F, P - F);
end
else
if P[0] = '''' then
{ pascal string constant }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -