Files
bds.mr.dpg/src.rtl/dpgrtl.inputbuffer.pas
T
2026-01-03 18:32:50 +01:00

124 lines
4.4 KiB
ObjectPascal

unit dpgrtl.inputbuffer;
interface
uses
dpgrtl.types;
type
TInputBuffer = class( TInterfacedObject, IInputBuffer)
protected
fMarkerCount : integer;
fMarkerOffset : integer;
fNumToConsume : integer;
protected
procedure Remove( Num: integer); virtual; abstract;
procedure SyncConsume; inline;
protected
function GetMarked: boolean; inline;
procedure Consume; inline;
procedure Commit; inline;
function Mark: integer;
procedure Rewind( Value: integer);
end;
implementation
{ TInputBuffer }
// @@@: IInputBuffer implementation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// IInputBuffer implementation
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ================================================================================================
// Mark
//
// Returns an integer marker theh can be used to rewind the buffer to its current state.
// ================================================================================================
function TInputBuffer.Mark: integer;
begin
SyncConsume;
INC( fMarkerCount);
result := fMarkerOffset
end;
// ================================================================================================
// Consume
//
// Mark another input item for deferred consumption.
// ================================================================================================
procedure TInputBuffer.Consume;
begin
INC( fNumToConsume);
end;
// ================================================================================================
// Commit
//
// This method updates the state of the input buffer so that the text matched since the most
// recent Mark() is no longer held by the buffer. So, you either do a mark/rewind for failed
// predicate or mark/commit to keep on parsing without rewinding the input.
// ================================================================================================
procedure TInputBuffer.Commit;
begin
if fMarkerCount > 0 then
DEC( fMarkerCount)
end;
// ================================================================================================
// Rewind
//
// Rewind the character buffer to a marker. 'Value' marker returned previously from mark.
// ================================================================================================
procedure TInputBuffer.Rewind(Value: integer);
begin
SyncConsume;
fMarkerOffset := Value;
DEC( fMarkerCount)
end;
// ================================================================================================
// GetMarked
// ================================================================================================
function TInputBuffer.GetMarked: boolean;
begin
result := fMarkerCount <> 0
end;
// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Internals
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ================================================================================================
// Sync Consume
// ================================================================================================
procedure TInputBuffer.SyncConsume;
begin
if fNumToConsume > 0 then
begin
if fMarkerCount > 0
then INC( fMarkerOffset, fNumToConsume)
else Remove( fNumToConsume);
fNumToConsume := 0
end
end;
end.