unit Myc.Ast.Identities; interface uses System.SysUtils, Myc.Data.Value, Myc.Data.Keyword; type // Forward declarations INamedIdentity = interface; IConstantIdentity = interface; IKeywordIdentity = interface; IDefinitionIdentity = interface; IListIdentity = interface; // Represents a position in the source code. ISourceLocation = interface function GetLine: Integer; function GetCol: Integer; function ToString: string; property Line: Integer read GetLine; property Col: Integer read GetCol; end; // Discriminator enum for identity types. TAstIdentityKind = ( ikStructural, // Pure location, no extra data (e.g. If, Block) ikNamed, // Identifier, MacroDef (Name + Location) ikConstant, // Literals (Value + Location) ikKeyword, // Keywords (Keyword + Location) ikDefinition, // Complex definitions (DefString + Location) ikList // Lists (Open/Close Tokens + Separator + Location) ); // Base interface for the "Green Tree" nodes. // Holds the raw syntax data and optional source location. IAstIdentity = interface {$region 'private'} function GetKind: TAstIdentityKind; function GetLocation: ISourceLocation; {$endregion} function ToString: string; // Explicit casting methods (Fail-Fast) function AsNamed: INamedIdentity; function AsConstant: IConstantIdentity; function AsKeyword: IKeywordIdentity; function AsDefinition: IDefinitionIdentity; function AsList: IListIdentity; property Kind: TAstIdentityKind read GetKind; // Optional: Returns nil if the node has no source mapping (e.g. generated code) property Location: ISourceLocation read GetLocation; end; INamedIdentity = interface(IAstIdentity) {$region 'private'} function GetName: string; {$endregion} property Name: string read GetName; end; IConstantIdentity = interface(IAstIdentity) {$region 'private'} function GetValue: TDataValue; {$endregion} property Value: TDataValue read GetValue; end; IKeywordIdentity = interface(IAstIdentity) {$region 'private'} function GetValue: IKeyword; {$endregion} property Value: IKeyword read GetValue; end; IDefinitionIdentity = interface(IAstIdentity) {$region 'private'} function GetDefinition: string; {$endregion} property Definition: string read GetDefinition; end; // Spezifische Identität für Listen IListIdentity = interface(IAstIdentity) {$region 'private'} function GetOpenToken: string; function GetCloseToken: string; function GetSeparator: string; {$endregion} property OpenToken: string read GetOpenToken; property CloseToken: string read GetCloseToken; property Separator: string read GetSeparator; end; // Factory and static access. TIdentities = record public class function Location(ALine, ACol: Integer): ISourceLocation; static; class function Structural(const ALoc: ISourceLocation = nil): IAstIdentity; static; class function Identifier(const AName: string; const ALoc: ISourceLocation = nil): INamedIdentity; static; class function Constant(const AValue: TDataValue; const ALoc: ISourceLocation = nil): IConstantIdentity; static; class function Keyword(const AValue: IKeyword; const ALoc: ISourceLocation = nil): IKeywordIdentity; static; class function Definition(const ADef: string; const ALoc: ISourceLocation = nil): IDefinitionIdentity; static; class function List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation = nil): IListIdentity; static; end; implementation type TSourceLocation = class(TInterfacedObject, ISourceLocation) private FLine, FCol: Integer; function GetLine: Integer; function GetCol: Integer; public constructor Create(ALine, ACol: Integer); function ToString: string; override; end; // Abstract base implementation providing the casting logic TAbstractIdentity = class(TInterfacedObject, IAstIdentity) private FLocation: ISourceLocation; function GetKind: TAstIdentityKind; virtual; abstract; function GetLocation: ISourceLocation; public constructor Create(const ALoc: ISourceLocation); function ToString: string; override; function AsNamed: INamedIdentity; virtual; function AsConstant: IConstantIdentity; virtual; function AsKeyword: IKeywordIdentity; virtual; function AsDefinition: IDefinitionIdentity; virtual; function AsList: IListIdentity; virtual; end; TStructuralIdentity = class(TAbstractIdentity) protected function GetKind: TAstIdentityKind; override; end; TNamedIdentity = class(TAbstractIdentity, INamedIdentity) private FName: string; function GetName: string; protected function GetKind: TAstIdentityKind; override; public constructor Create(const AName: string; const ALoc: ISourceLocation); function ToString: string; override; function AsNamed: INamedIdentity; override; end; TConstantIdentity = class(TAbstractIdentity, IConstantIdentity) private FValue: TDataValue; function GetValue: TDataValue; protected function GetKind: TAstIdentityKind; override; public constructor Create(const AValue: TDataValue; const ALoc: ISourceLocation); function ToString: string; override; function AsConstant: IConstantIdentity; override; end; TKeywordIdentity = class(TAbstractIdentity, IKeywordIdentity) private FValue: IKeyword; function GetValue: IKeyword; protected function GetKind: TAstIdentityKind; override; public constructor Create(const AValue: IKeyword; const ALoc: ISourceLocation); function ToString: string; override; function AsKeyword: IKeywordIdentity; override; end; TDefinitionIdentity = class(TAbstractIdentity, IDefinitionIdentity) private FDefinition: string; function GetDefinition: string; protected function GetKind: TAstIdentityKind; override; public constructor Create(const ADef: string; const ALoc: ISourceLocation); function ToString: string; override; function AsDefinition: IDefinitionIdentity; override; end; TListIdentity = class(TAbstractIdentity, IListIdentity) private FOpen, FClose, FSeparator: string; function GetOpenToken: string; function GetCloseToken: string; function GetSeparator: string; protected function GetKind: TAstIdentityKind; override; public constructor Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation); function ToString: string; override; function AsList: IListIdentity; override; end; { TSourceLocation } constructor TSourceLocation.Create(ALine, ACol: Integer); begin inherited Create; FLine := ALine; FCol := ACol; end; function TSourceLocation.GetCol: Integer; begin Result := FCol; end; function TSourceLocation.GetLine: Integer; begin Result := FLine; end; function TSourceLocation.ToString: string; begin Result := Format('Line %d, Col %d', [FLine, FCol]); end; { TAbstractIdentity } constructor TAbstractIdentity.Create(const ALoc: ISourceLocation); begin inherited Create; FLocation := ALoc; end; function TAbstractIdentity.GetLocation: ISourceLocation; begin Result := FLocation; end; function TAbstractIdentity.ToString: string; begin if Assigned(FLocation) then Result := FLocation.ToString else Result := ''; end; function TAbstractIdentity.AsNamed: INamedIdentity; begin raise EInvalidCast.Create('Identity is not a Named Identity'); end; function TAbstractIdentity.AsConstant: IConstantIdentity; begin raise EInvalidCast.Create('Identity is not a Constant Identity'); end; function TAbstractIdentity.AsKeyword: IKeywordIdentity; begin raise EInvalidCast.Create('Identity is not a Keyword Identity'); end; function TAbstractIdentity.AsDefinition: IDefinitionIdentity; begin raise EInvalidCast.Create('Identity is not a Definition Identity'); end; function TAbstractIdentity.AsList: IListIdentity; begin raise EInvalidCast.Create('Identity is not a List Identity'); end; { TStructuralIdentity } function TStructuralIdentity.GetKind: TAstIdentityKind; begin Result := ikStructural; end; { TNamedIdentity } constructor TNamedIdentity.Create(const AName: string; const ALoc: ISourceLocation); begin inherited Create(ALoc); FName := AName; end; function TNamedIdentity.GetKind: TAstIdentityKind; begin Result := ikNamed; end; function TNamedIdentity.GetName: string; begin Result := FName; end; function TNamedIdentity.AsNamed: INamedIdentity; begin Result := Self; end; function TNamedIdentity.ToString: string; begin Result := Format('Name: "%s" (%s)', [FName, inherited ToString]); end; { TConstantIdentity } constructor TConstantIdentity.Create(const AValue: TDataValue; const ALoc: ISourceLocation); begin inherited Create(ALoc); FValue := AValue; end; function TConstantIdentity.GetKind: TAstIdentityKind; begin Result := ikConstant; end; function TConstantIdentity.GetValue: TDataValue; begin Result := FValue; end; function TConstantIdentity.AsConstant: IConstantIdentity; begin Result := Self; end; function TConstantIdentity.ToString: string; begin Result := Format('Const: %s (%s)', [FValue.ToString, inherited ToString]); end; { TKeywordIdentity } constructor TKeywordIdentity.Create(const AValue: IKeyword; const ALoc: ISourceLocation); begin inherited Create(ALoc); FValue := AValue; end; function TKeywordIdentity.GetKind: TAstIdentityKind; begin Result := ikKeyword; end; function TKeywordIdentity.GetValue: IKeyword; begin Result := FValue; end; function TKeywordIdentity.AsKeyword: IKeywordIdentity; begin Result := Self; end; function TKeywordIdentity.ToString: string; begin Result := Format('Keyword: :%s (%s)', [FValue.Name, inherited ToString]); end; { TDefinitionIdentity } constructor TDefinitionIdentity.Create(const ADef: string; const ALoc: ISourceLocation); begin inherited Create(ALoc); FDefinition := ADef; end; function TDefinitionIdentity.GetKind: TAstIdentityKind; begin Result := ikDefinition; end; function TDefinitionIdentity.GetDefinition: string; begin Result := FDefinition; end; function TDefinitionIdentity.AsDefinition: IDefinitionIdentity; begin Result := Self; end; function TDefinitionIdentity.ToString: string; begin Result := Format('Def: "%s" (%s)', [FDefinition, inherited ToString]); end; { TListIdentity } constructor TListIdentity.Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation); begin inherited Create(ALoc); FOpen := AOpen; FClose := AClose; FSeparator := ASeparator; end; function TListIdentity.GetKind: TAstIdentityKind; begin Result := ikList; end; function TListIdentity.GetOpenToken: string; begin Result := FOpen; end; function TListIdentity.GetCloseToken: string; begin Result := FClose; end; function TListIdentity.GetSeparator: string; begin Result := FSeparator; end; function TListIdentity.AsList: IListIdentity; begin Result := Self; end; function TListIdentity.ToString: string; begin Result := Format('List: "%s...%s" (Sep: "%s") (%s)', [FOpen, FClose, FSeparator, inherited ToString]); end; { TIdentities } class function TIdentities.Location(ALine, ACol: Integer): ISourceLocation; begin Result := TSourceLocation.Create(ALine, ACol); end; class function TIdentities.Structural(const ALoc: ISourceLocation): IAstIdentity; begin Result := TStructuralIdentity.Create(ALoc); end; class function TIdentities.Identifier(const AName: string; const ALoc: ISourceLocation): INamedIdentity; begin Result := TNamedIdentity.Create(AName, ALoc); end; class function TIdentities.Constant(const AValue: TDataValue; const ALoc: ISourceLocation): IConstantIdentity; begin Result := TConstantIdentity.Create(AValue, ALoc); end; class function TIdentities.Keyword(const AValue: IKeyword; const ALoc: ISourceLocation): IKeywordIdentity; begin Result := TKeywordIdentity.Create(AValue, ALoc); end; class function TIdentities.Definition(const ADef: string; const ALoc: ISourceLocation): IDefinitionIdentity; begin Result := TDefinitionIdentity.Create(ADef, ALoc); end; class function TIdentities.List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation): IListIdentity; begin Result := TListIdentity.Create(AOpen, AClose, ASeparator, ALoc); end; end.