Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
352c20a
Merge pull request #1 from RomanYankovsky/master
JBontes Oct 3, 2017
0df834c
#220, #181
Oct 3, 2017
2400ab9
#221, record type params in the name
Oct 3, 2017
c26af5a
#222, use the anName attribute to store names exclusively
Oct 3, 2017
12ca887
#223 Except else <> if else
Oct 3, 2017
6f33800
#226 Add support for forwarded `object` types
Oct 3, 2017
8a9b20c
#227 Labeled statement does not register
Oct 3, 2017
b7ec406
#228 differentiate between const and resourcestring section
Oct 3, 2017
496edbb
#229 Parse object type correctly
Oct 3, 2017
0425ee9
#225, optimization: use a set to keep track of attributes in use by a…
Oct 3, 2017
76e4e81
#224 Optimization fetch correct operator record in O(1) time
Oct 3, 2017
8ad0174
#166 Forward declaration fixes
Oct 3, 2017
09b4d92
#232 SyntaxNodeNames should be automatically derived from SyntaxNodeT…
Oct 3, 2017
8fb608d
The remainder of the fixes, issue to follow
Oct 3, 2017
f416308
#216 reference to anonymoustype fixed. #237 resident external keywo…
Oct 5, 2017
9226c1f
#230 Variant records are now supported
Oct 6, 2017
c78a6d5
#239 Nil literal should be a ValuesSyntaxNode
Oct 6, 2017
02195f1
#242 subrange and enum should use anType attributes
Oct 12, 2017
45c50a0
#242 and #243
Oct 12, 2017
0160fc3
#243 retracted, uses in not allowed outside program or library
Oct 13, 2017
cfa5cc3
Fix for #246 varargs, #245 proc of object, #244 automated section
Oct 13, 2017
21d2872
Fix for #62, #247 hinting directives
Oct 13, 2017
5e64775
#248 static methodbinding
Oct 13, 2017
5c34b3d
#249 `assembler` inline directive
Oct 13, 2017
8ae51f0
#248 static + 249 assembler inline directive
Oct 14, 2017
6d60707
#250 record constants are not recorded correctly
Oct 15, 2017
7ef300f
#251 Also parse programs, libs and packages
Oct 16, 2017
468a2be
#252 record compiler directive
Oct 16, 2017
602e980
#35 More capable {$IF ... } handling
Oct 16, 2017
e89593a
#252 do not register compiler directives, unless the compiler can see…
Oct 17, 2017
23637da
#253 support `absolute` and #252 part2
Oct 17, 2017
0f89a62
#252 always put compiler directive underneigh the root
Oct 17, 2017
5fcd93f
#254 Error in parsing anonymous methods
Oct 17, 2017
bbbe2e2
#255 Treat `array of const` correctly
Oct 17, 2017
793b098
#35 add processing for isdeclared and fix endless loop
Oct 18, 2017
1a15887
#217 Record const [ref] atrtribute
Oct 18, 2017
a8ad741
#256 Record `@@` casting (for procedural variables)
Oct 18, 2017
0679a5f
#257 inline asm statements are not recorded
Oct 18, 2017
644161a
#257 small refinements.
Oct 18, 2017
1e3101d
#258 type safe `TOperators`. #217 fix corruption of childnode list.
Oct 19, 2017
3f8415e
#258 minor tweak
Oct 19, 2017
959fe23
#227 correct label processing, #217 Fix bug in parameter processing i…
Oct 20, 2017
c888a89
minor optimizations
Oct 20, 2017
84a28d4
Merge branch 'master' into master
JBontes Nov 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 142 additions & 61 deletions Source/DelphiAST.Classes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,62 @@ EParserException = class(Exception)
property Line: Integer read FLine;
property Col: Integer read FCol;
end;

TAttributeEntry = TPair<TAttributeName, string>;
PAttributeEntry = ^TAttributeEntry;

TSyntaxNodeClass = class of TSyntaxNode;
TSyntaxNode = class
public
function HasAttribute(const Key: TAttributeName): Boolean; inline;
private
FCol: Integer;
FLine: Integer;
FFileName: string;
function GetHasChildren: Boolean;
function GetHasAttributes: Boolean;
function TryGetAttributeEntry(const Key: TAttributeName; var AttributeEntry: PAttributeEntry): boolean;
function GetHasChildren: Boolean; inline;
function TryGetAttributeEntry(const Key: TAttributeName; out AttributeEntry: PAttributeEntry): boolean;
function GetChildCount: cardinal; inline;
function GetChildNode(index: cardinal): TSyntaxNode; inline;
procedure RemoveAttribute(const Key: TAttributeName);
protected
FAttributes: TArray<TAttributeEntry>;
FChildNodes: TArray<TSyntaxNode>;
FTyp: TSyntaxNodeType;
FParentNode: TSyntaxNode;
FAttributesInUse: TAttributeNames;
public
constructor Create(Typ: TSyntaxNodeType);
destructor Destroy; override;

function Clone: TSyntaxNode; virtual;
procedure AssignPositionFrom(const Node: TSyntaxNode);

function GetAttribute(const Key: TAttributeName): string;
function HasAttribute(const Key: TAttributeName): Boolean;
procedure SetAttribute(const Key: TAttributeName; const Value: string);
procedure ClearAttributes;

function AddChild(Typ: TSyntaxNodeType): TSyntaxNode; overload; inline;
procedure AddChildren(Nodes: TArray<TSyntaxNode>);
function AddChild(Node: TSyntaxNode): TSyntaxNode; overload;
function AddChild(Typ: TSyntaxNodeType): TSyntaxNode; overload;
procedure DeleteChild(Node: TSyntaxNode);
procedure ExtractChild(Node: TSyntaxNode);
procedure DeleteChild(Node: TSyntaxNode); inline;
function ExtractChild(Node: TSyntaxNode): TSyntaxNode; overload;
function ExtractChild(Typ: TSyntaxNodeType): TSyntaxNode; overload;

function FindNode(Typ: TSyntaxNodeType): TSyntaxNode;
function FindNode(Typ: TSyntaxNodeType): TSyntaxNode; overload;
function FindNode(const Types: TSyntaxNodeTypes): TSyntaxNode; overload;

property Attributes: TArray<TAttributeEntry> read FAttributes;
property ChildNodes: TArray<TSyntaxNode> read FChildNodes;
property HasAttributes: Boolean read GetHasAttributes;
property HasChildren: Boolean read GetHasChildren;
property Typ: TSyntaxNodeType read FTyp;
property ParentNode: TSyntaxNode read FParentNode;

property Col: Integer read FCol write FCol;
property Line: Integer read FLine write FLine;
property FileName: string read FFileName write FFileName;
property ChildNode[index: cardinal]:TSyntaxNode read GetChildNode;
property ChildCount: cardinal read GetChildCount;
property Attribute[const Key: TAttributeName]: string read GetAttribute write SetAttribute;
end;

TCompoundSyntaxNode = class(TSyntaxNode)
Expand Down Expand Up @@ -122,15 +131,16 @@ TOperatorInfo = record

TOperators = class
strict private
class function GetItem(Typ: TSyntaxNodeType): TOperatorInfo; static;
class function GetItem(Typ: TSyntaxNodeType): TOperatorInfo; inline; static;
public
class function IsOpName(Typ: TSyntaxNodeType): Boolean;
class property Items[Typ: TSyntaxNodeType]: TOperatorInfo read GetItem; default;
end;

const
OperatorsInfo: array [0..27] of TOperatorInfo =
OperatorsInfo: array [ntAddr..ntIs] of TOperatorInfo =
((Typ: ntAddr; Priority: 1; Kind: okUnary; AssocType: atRight),
(Typ: ntDoubleAddr; Priority: 1; Kind: okUnary; AssocType: atRight),
(Typ: ntDeref; Priority: 1; Kind: okUnary; AssocType: atLeft),
(Typ: ntGeneric; Priority: 1; Kind: okBinary; AssocType: atRight),
(Typ: ntIndexed; Priority: 1; Kind: okUnary; AssocType: atLeft),
Expand Down Expand Up @@ -162,22 +172,15 @@ TOperators = class
{ TOperators }

class function TOperators.GetItem(Typ: TSyntaxNodeType): TOperatorInfo;
var
i: Integer;
begin
for i := 0 to High(OperatorsInfo) do
if OperatorsInfo[i].Typ = Typ then
Exit(OperatorsInfo[i]);
Assert(Typ = OperatorsInfo[Typ].Typ);
Assert(Typ in [ntAddr..ntIs]);
Result:= OperatorsInfo[Typ]; //don't use exit in inline routines.
end;

class function TOperators.IsOpName(Typ: TSyntaxNodeType): Boolean;
var
i: Integer;
begin
for i := 0 to High(OperatorsInfo) do
if OperatorsInfo[i].Typ = Typ then
Exit(True);
Result := False;
Result:= (Typ in [ntAddr..ntIs]);
end;

function IsRoundClose(Typ: TSyntaxNodeType): Boolean; inline;
Expand Down Expand Up @@ -349,39 +352,108 @@ class procedure TExpressionTools.RawNodeListToTree(RawParentNode: TSyntaxNode; R

{ TSyntaxNode }


function TSyntaxNode.HasAttribute(const Key: TAttributeName): Boolean;
begin
Result := Key in FAttributesInUse;
end;

procedure TSyntaxNode.ClearAttributes;
begin
SetLength(FAttributes, 0);
FAttributesInUse:= [];
end;

function TSyntaxNode.GetHasChildren: Boolean;
begin
Result := Length(FChildNodes) > 0;
end;

function TSyntaxNode.GetChildCount: cardinal;
begin
Result:= Length(FChildNodes);
end;

function TSyntaxNode.AddChild(Typ: TSyntaxNodeType): TSyntaxNode;
begin
Result := AddChild(TSyntaxNode.Create(Typ));
end;

function TSyntaxNode.GetChildNode(index: cardinal): TSyntaxNode;
begin
Assert(index < ChildCount);
Result:= FChildNodes[index];
end;

procedure TSyntaxNode.DeleteChild(Node: TSyntaxNode);
begin
ExtractChild(Node);
Node.Free;
end;

procedure TSyntaxNode.SetAttribute(const Key: TAttributeName; const Value: string);
var
AttributeEntry: PAttributeEntry;
len: Integer;
begin
if not TryGetAttributeEntry(Key, AttributeEntry) then
if not HasAttribute(Key) then
begin
if (Value = '') then Exit; //no action needed
len := Length(FAttributes);
SetLength(FAttributes, len + 1);
AttributeEntry := @FAttributes[len];
AttributeEntry^.Key := Key;
Include(FAttributesInUse, Key);
end;
if (Value = '') then RemoveAttribute(Key);
AttributeEntry^.Value := Value;
end;

function TSyntaxNode.TryGetAttributeEntry(const Key: TAttributeName; var AttributeEntry: PAttributeEntry): boolean;
procedure TSyntaxNode.RemoveAttribute(const Key: TAttributeName);
const
Size = SizeOf(TAttributeEntry);
var
Entry: PAttributeEntry;
Index: integer;
begin
if HasAttribute(Key) then begin
TryGetAttributeEntry(Key, Entry);
Index:= (NativeUInt(Entry) - NativeUInt(@FAttributes[0])) + Size;
Move(Entry^, Pointer(NativeUInt(Entry)+Size)^, (High(FAttributes) * Size) - Index);
Exclude(FAttributesInUse, Key);
end;
end;

function SameText(const Needle: string; const HayStack: array of string): boolean; overload;
var
S: string;
begin
for S in HayStack do begin
if (SameText(Needle, S)) then exit(true);
end;
Result:= false;
end;

function TSyntaxNode.TryGetAttributeEntry(const Key: TAttributeName; out AttributeEntry: PAttributeEntry): boolean;
var
i: integer;
begin
for i := 0 to High(FAttributes) do
Result:= false;
if not(Key in FAttributesInUse) then begin
//Do not allow the AttributeEntry to be undefined.
AttributeEntry:= nil;
end else for i := 0 to High(FAttributes) do begin
if FAttributes[i].Key = Key then
begin
AttributeEntry := @FAttributes[i];
Exit(True);
end;

Result := False;
end;
end;

function TSyntaxNode.AddChild(Node: TSyntaxNode): TSyntaxNode;
begin
Assert(Assigned(Node));

SetLength(FChildNodes, Length(FChildNodes) + 1);
FChildNodes[Length(FChildNodes) - 1] := Node;

Expand All @@ -390,9 +462,18 @@ function TSyntaxNode.AddChild(Node: TSyntaxNode): TSyntaxNode;
Result := Node;
end;

function TSyntaxNode.AddChild(Typ: TSyntaxNodeType): TSyntaxNode;
procedure TSyntaxNode.AddChildren(Nodes: TArray<TSyntaxNode>);
var
Node: TSyntaxNode;
OldLength: integer;
begin
Result := AddChild(TSyntaxNode.Create(Typ));
OldLength:= Length(FChildNodes);
SetLength(FChildNodes, OldLength + Length(Nodes));
for Node in Nodes do begin
FChildNodes[OldLength]:= Node;
Inc(OldLength);
Node.FParentNode:= Self;
end;
end;

function TSyntaxNode.Clone: TSyntaxNode;
Expand All @@ -409,6 +490,7 @@ function TSyntaxNode.Clone: TSyntaxNode;
end;

Result.FAttributes := Copy(FAttributes);
Result.FAttributesInUse:= FAttributesInUse;
Result.AssignPositionFrom(Self);
end;

Expand All @@ -418,26 +500,23 @@ constructor TSyntaxNode.Create(Typ: TSyntaxNodeType);
FTyp := Typ;
end;

procedure TSyntaxNode.ExtractChild(Node: TSyntaxNode);

function TSyntaxNode.ExtractChild(Node: TSyntaxNode): TSyntaxNode;
var
i: integer;
begin
Result:= nil; //do not allow undefined result
for i := 0 to High(FChildNodes) do
if FChildNodes[i] = Node then
begin
Result:= Node;
if i < High(FChildNodes) then
Move(FChildNodes[i + 1], FChildNodes[i], SizeOf(TSyntaxNode) * (Length(FChildNodes) - i - 1));
SetLength(FChildNodes, High(FChildNodes));
Break;
end;
end;

procedure TSyntaxNode.DeleteChild(Node: TSyntaxNode);
begin
ExtractChild(Node);
Node.Free;
end;

destructor TSyntaxNode.Destroy;
var
i: integer;
Expand All @@ -447,6 +526,19 @@ destructor TSyntaxNode.Destroy;
inherited;
end;

function TSyntaxNode.ExtractChild(Typ: TSyntaxNodeType): TSyntaxNode;
var
Child: TSyntaxNode;
begin
for Child in FChildNodes do begin
if (Child.Typ = Typ) then begin
ExtractChild(Child);
Exit(Child);
end;
end;
Result:= nil;
end;

function TSyntaxNode.FindNode(Typ: TSyntaxNodeType): TSyntaxNode;
var
i: Integer;
Expand All @@ -457,6 +549,16 @@ function TSyntaxNode.FindNode(Typ: TSyntaxNodeType): TSyntaxNode;
Result := nil;
end;

function TSyntaxNode.FindNode(const Types: TSyntaxNodeTypes): TSyntaxNode;
var
i: integer;
begin
for i:= 0 to High(FChildNodes) do begin
if (FChildNodes[i].Typ in Types) then Exit(FChildNodes[i]);
end;
Result:= nil;
end;

function TSyntaxNode.GetAttribute(const Key: TAttributeName): string;
var
AttributeEntry: PAttributeEntry;
Expand All @@ -467,28 +569,6 @@ function TSyntaxNode.GetAttribute(const Key: TAttributeName): string;
Result := '';
end;

function TSyntaxNode.GetHasAttributes: Boolean;
begin
Result := Length(FAttributes) > 0;
end;

function TSyntaxNode.GetHasChildren: Boolean;
begin
Result := Length(FChildNodes) > 0;
end;

function TSyntaxNode.HasAttribute(const Key: TAttributeName): Boolean;
var
AttributeEntry: PAttributeEntry;
begin
Result := TryGetAttributeEntry(Key, AttributeEntry);
end;

procedure TSyntaxNode.ClearAttributes;
begin
SetLength(FAttributes, 0);
end;

procedure TSyntaxNode.AssignPositionFrom(const Node: TSyntaxNode);
begin
FCol := Node.Col;
Expand Down Expand Up @@ -534,4 +614,5 @@ constructor EParserException.Create(Line, Col: Integer; const FileName, Msg: str
FCol := Col;
end;


end.
Loading