Files
bds.mr.jtg/src.jtag/svf/jtag.svfLex.pas
T
2026-01-08 19:12:06 +01:00

516 lines
14 KiB
ObjectPascal

unit jtag.svfLex;
interface
uses
System.Classes,
Generics.Collections;
type
TTokenType =
(
TT_EOF,
TT_SKIP,
TT_SEMI,
TT_COMMENT,
TT_ID,
TT_NUMBER,
TT_HEX,
TT_LPAREN,
TT_RPAREN,
TT_STRING,
// SVF commands
LT_ENDIR, LT_ENDDR,
LT_HIR, LT_HDR,
LT_TIR, LT_TDR,
LT_SIR, LT_SDR,
LT_FREQUENCY,
LT_HZ,
LT_PIO,
LT_PIOMAP,
LT_RUNTEST,
LT_TCK,
LT_SCK,
LT_SEC,
LT_MAXIMUM,
LT_ENDSTATE,
LT_TDI,
LT_TDO,
LT_MASK,
LT_SMASK,
// SVX commands
LT_PRINT,
// TAP States
LT_STATE,
LT_DRSELECT,
LT_DRCAPTURE,
LT_DRSHIFT,
LT_DRUPDATE,
LT_DREXIT1,
LT_DREXIT2,
LT_IRSELECT,
LT_IRCAPTURE,
LT_IRSHIFT,
LT_IRUPDATE,
LT_IREXIT1,
LT_IREXIT2,
LT_RESET,
LT_IDLE,
LT_IRPAUSE,
LT_DRPAUSE,
LT_IN,
LT_OUT,
LT_INOUT,
LT_TRST,
LT_ON,
LT_OFF,
LT_Z,
LT_ABSENT
);
TTokenTypes = set of TTokenType;
TsvfToken = class
TokenType : TTokenType;
TokenText : AnsiString;
end;
TTokenMap = TDictionary<AnsiString,TTokenType>;
TAnsiCharSet = set of AnsiChar;
TsvfMode = ( SVF, HEX);
TsvfLEX = class
private
fBuffer : PAnsiChar;
fStart : PAnsiChar;
fForward : PAnsiChar;
fToken : TsvfToken;
fMode : TsvfMode;
fLiterals: TTokenMap;
private
procedure InitLiterals;
function CheckLiteral( ttext: AnsiString; ttype: TTokenType): TTokenType;
function MakeToken( ttype : TTokenType;
ttext : AnsiString): TsvfToken;
public
function NextToken : TsvfToken;
public
constructor Create( Stream: TStream);
destructor Destroy; override;
end;
implementation
uses
WinAPI.Windows,
System.SysUtils;
{ TsvfLEX }
// ================================================================================================
// Constructor
// ================================================================================================
constructor TsvfLEX.Create(Stream: TStream);
var
size : Int64;
token : TsvfToken;
begin
InitLiterals;
if Assigned( Stream) then
begin
size := Stream.Size - Stream.Position;
fBuffer := GetMemory(size+1);
Stream.Read(fBuffer^, size);
fMode := SVF;
fStart := fBuffer;
fForward := fBuffer;
fBuffer[size] := #0;
end
end;
destructor TsvfLEX.Destroy;
begin
FreeAndNil(fLiterals);
inherited;
end;
// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Internals
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ================================================================================================
// MakeToken
// ================================================================================================
function TsvfLEX.MakeToken(ttype: TTokenType; ttext: AnsiString): TsvfToken;
begin
result := TsvfToken.Create;
with result do
begin
TokenType := ttype;
if TokenType in [TT_COMMENT,TT_STRING]
then TokenText := ttext
else TokenText := UpperCase(ttext);
end
end;
// ================================================================================================
// InitLiterals
// ================================================================================================
procedure TsvfLEX.InitLiterals;
begin
fLiterals := TTokenMap.Create;
fLiterals.Add('HIR', LT_HIR );
fLiterals.Add('HDR', LT_HDR );
fLiterals.Add('TIR', LT_TIR );
fLiterals.Add('TDR', LT_TDR );
fLiterals.Add('SIR', LT_SIR );
fLiterals.Add('SDR', LT_SDR );
fLiterals.Add('TDI', LT_TDI );
fLiterals.Add('TDO', LT_TDO );
fLiterals.Add('MASK', LT_MASK );
fLiterals.Add('SMASK', LT_SMASK );
fLiterals.Add('FREQUENCY', LT_FREQUENCY );
fLiterals.Add('HZ', LT_HZ );
fLiterals.Add('PIO', LT_PIO );
fLiterals.Add('PIOMAP', LT_PIOMAP );
fLiterals.Add('RUNTEST', LT_RUNTEST );
fLiterals.Add('TCK', LT_TCK );
fLiterals.Add('SCK', LT_SCK );
fLiterals.Add('SEC', LT_SEC );
fLiterals.Add('MAXIMUM', LT_MAXIMUM );
fLiterals.Add('ENDSTATE', LT_ENDSTATE );
fLiterals.Add('ENDIR', LT_ENDIR );
fLiterals.Add('ENDDR', LT_ENDDR );
fLiterals.Add('STATE', LT_STATE );
fLiterals.Add('RESET', LT_RESET );
fLiterals.Add('IDLE', LT_IDLE );
fLiterals.Add('DRSELECT', LT_DRSELECT );
fLiterals.Add('DRCAPTURE', LT_DRCAPTURE );
fLiterals.Add('DRSHIFT', LT_DRSHIFT );
fLiterals.Add('DRUPDATE', LT_DRUPDATE );
fLiterals.Add('DRPAUSE', LT_DRPAUSE );
fLiterals.Add('DREXIT1', LT_DREXIT1 );
fLiterals.Add('DREXIT2', LT_DREXIT2 );
fLiterals.Add('IRSELECT', LT_IRSELECT );
fLiterals.Add('IRCAPTURE', LT_DRCAPTURE );
fLiterals.Add('IRSHIFT', LT_IRSHIFT );
fLiterals.Add('IRUPDATE', LT_IRUPDATE );
fLiterals.Add('IRPAUSE', LT_IRPAUSE );
fLiterals.Add('IREXIT1', LT_IREXIT1 );
fLiterals.Add('IREXIT2', LT_IREXIT2 );
fLiterals.Add('IN', LT_IN );
fLiterals.Add('OUT', LT_OUT );
fLiterals.Add('INOUT', LT_INOUT );
fLiterals.Add('TRST', LT_TRST );
fLiterals.Add('ON', LT_ON );
fLiterals.Add('OFF', LT_OFF );
fLiterals.Add('Z', LT_Z );
fLiterals.Add('ABSENT', LT_ABSENT );
fLiterals.Add('PRINT', LT_PRINT );
end;
// ================================================================================================
// CheckLiteral
// ================================================================================================
function TsvfLEX.CheckLiteral(ttext: AnsiString; ttype: TTokenType): TTokenType;
begin
result := ttype;
fLiterals.TryGetValue(ttext, result);
end;
// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Interface
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ================================================================================================
// NextToken
// ================================================================================================
function TsvfLEX.NextToken: TsvfToken;
function GetTokenText: AnsiString;
begin
SetLength( result, fForward-fStart);
MoveMemory( @result[1], fStart, fForward-fStart);
end;
var
ttext : AnsiString;
ttype : TTokenType;
begin
while true do
begin
result := nil;
fForward := fStart;
if fMode = HEX then
case fForward^ of
// ----------------------------------------------------
// HEX digits
// ----------------------------------------------------
'0'..'9','a'..'f','A'..'F':
begin
INC(fForward);
while fForward^ in ['0'..'9','a'..'f','A'..'F'] do
INC(fForward);
result := MakeToken( TT_HEX, GetTokenText);
fStart := fForward;
end;
// ----------------------------------------------------
// HEX end
// ----------------------------------------------------
')':
begin
fMode := SVF;
INC(fForward);
result := MakeToken( TT_RPAREN, '');
fStart := fForward;
end;
// ----------------------------------------------------
// SPACE,TAB
// ----------------------------------------------------
#32, #9: INC(fStart);
// ----------------------------------------------------
// CR/LF
// ----------------------------------------------------
#13,#10:
begin
INC(fStart);
while fStart^ in [#13,#10] do
INC(fStart)
end;
// ----------------------------------------------------
// Invalid char
// ----------------------------------------------------
else
;
end
else
case fForward^ of
// ----------------------------------------------------
// String
// ----------------------------------------------------
'"':
begin
INC(fForward);
while not (fForward^ in ['"',#13,#10]) do
INC(fForward);
if fForward^ = '"' then
INC(fForward);
result := MakeToken( TT_STRING, GetTokenText);
fStart := fForward;
end;
// ----------------------------------------------------
// semicolon
// ----------------------------------------------------
';':
begin
INC(fForward);
result := MakeToken( TT_SEMI, ';');
fStart := fForward;
end;
// ----------------------------------------------------
// comment
// ----------------------------------------------------
'!','/':
begin
if fForward^ = '/' then
begin
INC(fForward);
if fForward^ <> '/' then
; //raise
end;
INC(fForward);
while not (fForward^ in [#13,#10]) do
INC(fForward);
result := MakeToken( TT_COMMENT, GetTokenText);
fStart := fForward;
end;
// ----------------------------------------------------
// id
// ----------------------------------------------------
'a'..'z','A'..'Z':
begin
INC(fForward);
while fForward^ in ['a'..'z','A'..'Z'] do
INC(fForward);
ttext := GetTokenText;
ttype := CheckLiteral( ttext, TT_ID);
result := MakeToken( ttype, ttext);
fStart := fForward;
end;
// ----------------------------------------------------
// number
// ----------------------------------------------------
'0'..'9':
begin
INC(fForward);
while fForward^ in ['0'..'9'] do
INC(fForward);
if fForward^ = '.' then
begin
INC(fForward);
while fForward^ in ['0'..'9'] do
INC(fForward)
end;
if fForward^ in ['e','E'] then
begin
INC(fForward);
if fForward^ in ['+','-'] then
begin
INC(fForward);
if fForward^ in ['0'..'9'] then
begin
INC(fForward);
while fForward^ in ['0'..'9'] do
INC(fForward);
end
else
// raise
end
else
; // raise
end;
result := MakeToken( TT_NUMBER, GetTokenText);
fStart := fForward;
end;
// ----------------------------------------------------
// HEX start
// ----------------------------------------------------
'(':
begin
fMode := HEX;
INC(fForward);
result := MakeToken( TT_LPAREN, '');
fStart := fForward;
end;
// ----------------------------------------------------
// WS,CR/LF
// ----------------------------------------------------
#32, #9: INC(fStart);
#13,#10:
begin
INC(fStart);
while fStart^ in [#13,#10] do
INC(fStart)
end;
// ----------------------------------------------------
// EOF
// ----------------------------------------------------
#0:
begin
result := MakeToken( TT_EOF, '');
fStart := fForward;
end;
// ----------------------------------------------------
// invalid
// ----------------------------------------------------
else
begin
fStart := 0;
break;
end;
end;
if Assigned(result) then
break;
end;
end;
end.