Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 29 additions & 15 deletions Source/DelphiAST.Classes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
interface

uses
SysUtils, Generics.Collections, SimpleParser.Lexer.Types, DelphiAST.Consts;
SysUtils, {$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF}, SimpleParser.Lexer.Types, DelphiAST.Consts;

type
EParserException = class(Exception)
Expand Down Expand Up @@ -104,6 +104,8 @@ TCompoundSyntaxNode = class(TSyntaxNode)
FEndLine: Integer;
public
function Clone: TSyntaxNode; override;
//counterpart to AssignPositionFrom, for a node rebuilt from a parsed one
procedure AssignEndPositionFrom(const Node: TCompoundSyntaxNode);

property EndCol: Integer read FEndCol write FEndCol;
property EndLine: Integer read FEndLine write FEndLine;
Expand Down Expand Up @@ -419,32 +421,38 @@ procedure TSyntaxNode.SetAttribute(const Key: TAttributeName; const Value: strin
AttributeEntry: PAttributeEntry;
len: Integer;
begin
if not HasAttribute(Key) then
if (Value = '') then
begin
RemoveAttribute(Key);
Exit;
end;
if not TryGetAttributeEntry(Key, AttributeEntry) 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;

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;
i, Kept: Integer;
begin
if not HasAttribute(Key) then
Exit;
Kept := 0;
for i := 0 to High(FAttributes) do
if FAttributes[i].Key <> Key then
begin
if Kept <> i then
FAttributes[Kept] := FAttributes[i];
Inc(Kept);
end;
SetLength(FAttributes, Kept);
Exclude(FAttributesInUse, Key);
end;

function SameText(const Needle: string; const HayStack: array of string): boolean; overload;
Expand Down Expand Up @@ -629,6 +637,12 @@ procedure TSyntaxNode.AssignPositionFrom(const Node: TSyntaxNode);

{ TCompoundSyntaxNode }

procedure TCompoundSyntaxNode.AssignEndPositionFrom(const Node: TCompoundSyntaxNode);
begin
FEndCol := Node.EndCol;
FEndLine := Node.EndLine;
end;

function TCompoundSyntaxNode.Clone: TSyntaxNode;
begin
Result := inherited;
Expand Down
7 changes: 6 additions & 1 deletion Source/DelphiAST.ProjectIndexer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
interface

uses
Classes, Generics.Defaults, Generics.Collections,
Classes,
{$IFDEF FPC_DOTTEDUNITS}
System.Generics.Defaults, System.Generics.Collections,
{$ELSE}
Generics.Defaults, Generics.Collections,
{$ENDIF}
SimpleParser.Lexer.Types,
DelphiAST, DelphiAST.Classes, DelphiAST.Consts;

Expand Down
2 changes: 1 addition & 1 deletion Source/DelphiAST.Serialize.Binary.pas
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface

uses
Classes,
Generics.Collections,
{$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF},
DelphiAST.Consts,
DelphiAST.Classes;

Expand Down
2 changes: 1 addition & 1 deletion Source/DelphiAST.SimpleParserEx.pas
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
interface

uses
SysUtils, Generics.Collections, SimpleParser, SimpleParser.Lexer.Types,
SysUtils, {$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF}, SimpleParser, SimpleParser.Lexer.Types,
SimpleParser.Lexer, Classes;

type
Expand Down
2 changes: 1 addition & 1 deletion Source/DelphiAST.Writer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ TSyntaxTreeWriter = class
implementation

uses
Generics.Collections,
{$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF},
{$IFNDEF FPC}
DelphiAST.Serialize.Binary,
{$ENDIF}
Expand Down
22 changes: 16 additions & 6 deletions Source/DelphiAST.pas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
interface

uses
SysUtils, Classes, Generics.Collections, SimpleParser, SimpleParser.Lexer,
SysUtils, Classes, {$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF}, SimpleParser, SimpleParser.Lexer,
SimpleParser.Lexer.Types, DelphiAST.Classes, DelphiAST.Consts, DelphiAST.SimpleParserEx;

type
Expand Down Expand Up @@ -1195,9 +1195,11 @@ procedure TPasSyntaxTreeBuilder.CompoundStatement;

procedure TPasSyntaxTreeBuilder.ConstantDeclaration;
begin
FStack.Push(ntConstant);
//compound: a constant's value can span lines, so record where it ends. as TypeDeclaration.
FStack.PushCompoundSyntaxNode(ntConstant);
try
inherited;
SetCurrentCompoundNodesEndPosition;
finally
FStack.Pop;
end;
Expand Down Expand Up @@ -1329,9 +1331,12 @@ procedure TPasSyntaxTreeBuilder.ConstSection;
if Constant.Typ <> ntName then
Continue;

Temp := FStack.Push(ConstList.Typ);
//compound: start from the name, end from the ConstList that measured the value.
Temp := FStack.PushCompoundSyntaxNode(ConstList.Typ);
try
Temp.AssignPositionFrom(Constant);
if ConstList is TCompoundSyntaxNode then
TCompoundSyntaxNode(Temp).AssignEndPositionFrom(TCompoundSyntaxNode(ConstList));

FStack.AddChild(Constant.Clone);
if Assigned(TypeInfo) then
Expand Down Expand Up @@ -2667,7 +2672,7 @@ function TPasSyntaxTreeBuilder.Run(SourceStream: TStream): TSyntaxNode;
on E: EParserException do
raise ESyntaxTreeException.Create(E.Line, E.Col, Lexer.FileName, E.Message, Result);
on E: ESyntaxError do
raise ESyntaxTreeException.Create(E.PosXY.X, E.PosXY.Y, Lexer.FileName, E.Message, Result);
raise ESyntaxTreeException.Create(E.PosXY.Y, E.PosXY.X, Lexer.FileName, E.Message, Result);
else
FreeAndNil(Result);
raise;
Expand Down Expand Up @@ -3205,9 +3210,11 @@ procedure TPasSyntaxTreeBuilder.VarAbsolute;

procedure TPasSyntaxTreeBuilder.VarDeclaration;
begin
FStack.Push(ntVariables);
//compound: a variable's type or initialiser can span lines, so record where it ends.
FStack.PushCompoundSyntaxNode(ntVariables);
try
inherited;
SetCurrentCompoundNodesEndPosition;
finally
FStack.Pop;
end;
Expand Down Expand Up @@ -3298,9 +3305,12 @@ procedure TPasSyntaxTreeBuilder.RearrangeVarSection(const VarSect: TSyntaxNode);
begin
if Variable.Typ <> ntName then
Continue;
Temp := FStack.Push(ntVariable);
//compound: start from the name, end from the VarList that measured the declaration.
Temp := FStack.PushCompoundSyntaxNode(ntVariable);
try
Temp.AssignPositionFrom(Variable);
if VarList is TCompoundSyntaxNode then
TCompoundSyntaxNode(Temp).AssignEndPositionFrom(TCompoundSyntaxNode(VarList));
FStack.AddChild(Variable.Clone);
if Assigned(TypeInfo) then
FStack.AddChild(TypeInfo.Clone);
Expand Down
2 changes: 1 addition & 1 deletion Source/SimpleParser/SimpleParser.Lexer.pas
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ interface
uses
SysUtils, Classes, Character,
{$IFDEF FPC}
Generics.Collections,
{$IFDEF FPC_DOTTEDUNITS}System.Generics.Collections{$ELSE}Generics.Collections{$ENDIF},
{$ENDIF}
SimpleParser.Lexer.Types;

Expand Down
10 changes: 10 additions & 0 deletions Source/SimpleParser/SimpleParser.pas
Original file line number Diff line number Diff line change
Expand Up @@ -3648,6 +3648,16 @@ procedure TmwSimplePasPar.OrdinalType;
begin
ConstantExpression;
end;
{ An operator after the identifier means the bound is a constant
expression, not a type name: array[mlab + 1..mlog]. Reading it as a
type name consumes the identifier alone and leaves the caller at the
operator, where it can only report an error. These are the operators
SimpleExpression and Term accept. }
ptAnd, ptDiv, ptMinus, ptMod, ptOr, ptPlus, ptShl, ptShr, ptSlash,
ptStar, ptXor:
begin
ConstantExpression;
end;
else
begin
TypeID;
Expand Down
22 changes: 22 additions & 0 deletions Test/Snippets/arrayboundexpression.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
unit arrayboundexpression;

interface

const
mlab = 4;
mlog = 12;

type
{ An array bound is a constant EXPRESSION, not just a constant or a type name.
OrdinalType decided on one token of lookahead and read `mlab` as a type name,
so the whole unit failed to parse at the `+`. }
TRanges = record
iu: array[mlab + 1..mlog] of Integer;
du: array[mlab * 2..mlog - 1, 0..mlab shl 1] of Byte;
end;

TSetOfExpression = set of mlab + 1..mlog;

implementation

end.
Loading