|
@@ -182,6 +182,7 @@ type
|
|
function FindElement(const AName: String): TPasElement; virtual; abstract;
|
|
function FindElement(const AName: String): TPasElement; virtual; abstract;
|
|
procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); virtual;
|
|
procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); virtual;
|
|
function FindModule(const AName: String): TPasModule; virtual;
|
|
function FindModule(const AName: String): TPasModule; virtual;
|
|
|
|
+ function NeedArrayValues(El: TPasElement): boolean; virtual;
|
|
property Package: TPasPackage read FPackage;
|
|
property Package: TPasPackage read FPackage;
|
|
property InterfaceOnly : Boolean Read FInterfaceOnly Write FInterFaceOnly;
|
|
property InterfaceOnly : Boolean Read FInterfaceOnly Write FInterFaceOnly;
|
|
property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
|
|
property ScannerLogEvents : TPScannerLogEvents Read FScannerLogEvents Write FScannerLogEvents;
|
|
@@ -239,6 +240,7 @@ type
|
|
FTokenBufferSize: Integer; // maximum valid index in FTokenBuffer
|
|
FTokenBufferSize: Integer; // maximum valid index in FTokenBuffer
|
|
FDumpIndent : String;
|
|
FDumpIndent : String;
|
|
function CheckOverloadList(AList: TFPList; AName: String; out OldMember: TPasElement): TPasOverloadedProc;
|
|
function CheckOverloadList(AList: TFPList; AName: String; out OldMember: TPasElement): TPasOverloadedProc;
|
|
|
|
+ function DoCheckHint(Element: TPasElement): Boolean;
|
|
procedure DumpCurToken(Const Msg : String; IndentAction : TIndentAction = iaNone);
|
|
procedure DumpCurToken(Const Msg : String; IndentAction : TIndentAction = iaNone);
|
|
function GetCurrentModeSwitches: TModeSwitches;
|
|
function GetCurrentModeSwitches: TModeSwitches;
|
|
Procedure SetCurrentModeSwitches(AValue: TModeSwitches);
|
|
Procedure SetCurrentModeSwitches(AValue: TModeSwitches);
|
|
@@ -327,7 +329,9 @@ type
|
|
procedure NextToken; // read next non whitespace, non space
|
|
procedure NextToken; // read next non whitespace, non space
|
|
procedure UngetToken;
|
|
procedure UngetToken;
|
|
procedure CheckToken(tk: TToken);
|
|
procedure CheckToken(tk: TToken);
|
|
|
|
+ procedure CheckTokens(tk: TTokens);
|
|
procedure ExpectToken(tk: TToken);
|
|
procedure ExpectToken(tk: TToken);
|
|
|
|
+ procedure ExpectTokens(tk: TTokens);
|
|
function ExpectIdentifier: String;
|
|
function ExpectIdentifier: String;
|
|
Function CurTokenIsIdentifier(Const S : String) : Boolean;
|
|
Function CurTokenIsIdentifier(Const S : String) : Boolean;
|
|
// Expression parsing
|
|
// Expression parsing
|
|
@@ -400,9 +404,18 @@ type
|
|
property LastMsgArgs: TMessageArgs read FLastMsgArgs write FLastMsgArgs;
|
|
property LastMsgArgs: TMessageArgs read FLastMsgArgs write FLastMsgArgs;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+Type
|
|
|
|
+ TParseSourceOption = (poUseStreams,poSkipDefaultDefs);
|
|
|
|
+ TParseSourceOptions = set of TParseSourceOption;
|
|
|
|
+function ParseSource(AEngine: TPasTreeContainer;
|
|
|
|
+ const FPCCommandLine, OSTarget, CPUTarget: String): TPasModule;
|
|
|
|
+function ParseSource(AEngine: TPasTreeContainer;
|
|
|
|
+ const FPCCommandLine, OSTarget, CPUTarget: String;
|
|
|
|
+ UseStreams : Boolean): TPasModule; deprecated;
|
|
function ParseSource(AEngine: TPasTreeContainer;
|
|
function ParseSource(AEngine: TPasTreeContainer;
|
|
const FPCCommandLine, OSTarget, CPUTarget: String;
|
|
const FPCCommandLine, OSTarget, CPUTarget: String;
|
|
- UseStreams : Boolean = False): TPasModule;
|
|
|
|
|
|
+ Options : TParseSourceOptions): TPasModule;
|
|
|
|
+
|
|
Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
|
|
Function IsHintToken(T : String; Out AHint : TPasMemberHint) : boolean;
|
|
Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
|
|
Function IsProcModifier(S : String; Out PM : TProcedureModifier) : Boolean;
|
|
Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
|
|
Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
|
|
@@ -495,9 +508,26 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function ParseSource(AEngine: TPasTreeContainer;
|
|
|
|
+ const FPCCommandLine, OSTarget, CPUTarget: String): TPasModule;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Result:=ParseSource(AENgine,FPCCommandLine, OSTarget, CPUTarget,[]);
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function ParseSource(AEngine: TPasTreeContainer;
|
|
|
|
+ const FPCCommandLine, OSTarget, CPUTarget: String; UseStreams : Boolean): TPasModule;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ if UseStreams then
|
|
|
|
+ Result:=ParseSource(AENgine,FPCCommandLine, OSTarget, CPUTarget,[poUseStreams])
|
|
|
|
+ else
|
|
|
|
+ Result:=ParseSource(AENgine,FPCCommandLine, OSTarget, CPUTarget,[]);
|
|
|
|
+end;
|
|
|
|
+
|
|
function ParseSource(AEngine: TPasTreeContainer;
|
|
function ParseSource(AEngine: TPasTreeContainer;
|
|
const FPCCommandLine, OSTarget, CPUTarget: String;
|
|
const FPCCommandLine, OSTarget, CPUTarget: String;
|
|
- UseStreams : Boolean = False): TPasModule;
|
|
|
|
|
|
+ Options : TParseSourceOptions): TPasModule;
|
|
var
|
|
var
|
|
FileResolver: TFileResolver;
|
|
FileResolver: TFileResolver;
|
|
Parser: TPasParser;
|
|
Parser: TPasParser;
|
|
@@ -521,6 +551,8 @@ var
|
|
case s[2] of
|
|
case s[2] of
|
|
'd': // -d define
|
|
'd': // -d define
|
|
Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
|
|
Scanner.AddDefine(UpperCase(Copy(s, 3, Length(s))));
|
|
|
|
+ 'u': // -u undefine
|
|
|
|
+ Scanner.RemoveDefine(UpperCase(Copy(s, 3, Length(s))));
|
|
'F': // -F
|
|
'F': // -F
|
|
if (length(s)>2) and (s[3] = 'i') then // -Fi include path
|
|
if (length(s)>2) and (s[3] = 'i') then // -Fi include path
|
|
FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
|
|
FileResolver.AddIncludePath(Copy(s, 4, Length(s)));
|
|
@@ -528,10 +560,18 @@ var
|
|
FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
|
|
FileResolver.AddIncludePath(Copy(s, 3, Length(s)));
|
|
'S': // -S mode
|
|
'S': // -S mode
|
|
if (length(s)>2) then
|
|
if (length(s)>2) then
|
|
- case S[3] of
|
|
|
|
- 'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
|
|
|
|
- 'd' : Scanner.SetCompilerMode('DELPHI');
|
|
|
|
- '2' : Scanner.SetCompilerMode('OBJFPC');
|
|
|
|
|
|
+ begin
|
|
|
|
+ l:=3;
|
|
|
|
+ While L<=Length(S) do
|
|
|
|
+ begin
|
|
|
|
+ case S[l] of
|
|
|
|
+ 'c' : Scanner.Options:=Scanner.Options+[po_cassignments];
|
|
|
|
+ 'd' : Scanner.SetCompilerMode('DELPHI');
|
|
|
|
+ '2' : Scanner.SetCompilerMode('OBJFPC');
|
|
|
|
+ 'h' : ; // do nothing
|
|
|
|
+ end;
|
|
|
|
+ inc(l);
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
'M' :
|
|
'M' :
|
|
begin
|
|
begin
|
|
@@ -555,51 +595,52 @@ begin
|
|
Parser := nil;
|
|
Parser := nil;
|
|
try
|
|
try
|
|
FileResolver := TFileResolver.Create;
|
|
FileResolver := TFileResolver.Create;
|
|
- FileResolver.UseStreams:=UseStreams;
|
|
|
|
|
|
+ FileResolver.UseStreams:=poUseStreams in Options;
|
|
Scanner := TPascalScanner.Create(FileResolver);
|
|
Scanner := TPascalScanner.Create(FileResolver);
|
|
- Scanner.AddDefine('FPK');
|
|
|
|
- Scanner.AddDefine('FPC');
|
|
|
|
SCanner.LogEvents:=AEngine.ScannerLogEvents;
|
|
SCanner.LogEvents:=AEngine.ScannerLogEvents;
|
|
SCanner.OnLog:=AEngine.Onlog;
|
|
SCanner.OnLog:=AEngine.Onlog;
|
|
-
|
|
|
|
- // TargetOS
|
|
|
|
- s := UpperCase(OSTarget);
|
|
|
|
- Scanner.AddDefine(s);
|
|
|
|
- if s = 'LINUX' then
|
|
|
|
- Scanner.AddDefine('UNIX')
|
|
|
|
- else if s = 'FREEBSD' then
|
|
|
|
- begin
|
|
|
|
- Scanner.AddDefine('BSD');
|
|
|
|
- Scanner.AddDefine('UNIX');
|
|
|
|
- end else if s = 'NETBSD' then
|
|
|
|
- begin
|
|
|
|
- Scanner.AddDefine('BSD');
|
|
|
|
- Scanner.AddDefine('UNIX');
|
|
|
|
- end else if s = 'SUNOS' then
|
|
|
|
- begin
|
|
|
|
- Scanner.AddDefine('SOLARIS');
|
|
|
|
- Scanner.AddDefine('UNIX');
|
|
|
|
- end else if s = 'GO32V2' then
|
|
|
|
- Scanner.AddDefine('DPMI')
|
|
|
|
- else if s = 'BEOS' then
|
|
|
|
- Scanner.AddDefine('UNIX')
|
|
|
|
- else if s = 'QNX' then
|
|
|
|
- Scanner.AddDefine('UNIX')
|
|
|
|
- else if s = 'AROS' then
|
|
|
|
- Scanner.AddDefine('HASAMIGA')
|
|
|
|
- else if s = 'MORPHOS' then
|
|
|
|
- Scanner.AddDefine('HASAMIGA')
|
|
|
|
- else if s = 'AMIGA' then
|
|
|
|
- Scanner.AddDefine('HASAMIGA');
|
|
|
|
-
|
|
|
|
- // TargetCPU
|
|
|
|
- s := UpperCase(CPUTarget);
|
|
|
|
- Scanner.AddDefine('CPU'+s);
|
|
|
|
- if (s='X86_64') then
|
|
|
|
- Scanner.AddDefine('CPU64')
|
|
|
|
- else
|
|
|
|
- Scanner.AddDefine('CPU32');
|
|
|
|
-
|
|
|
|
|
|
+ if not (poSkipDefaultDefs in Options) then
|
|
|
|
+ begin
|
|
|
|
+ Scanner.AddDefine('FPK');
|
|
|
|
+ Scanner.AddDefine('FPC');
|
|
|
|
+ // TargetOS
|
|
|
|
+ s := UpperCase(OSTarget);
|
|
|
|
+ Scanner.AddDefine(s);
|
|
|
|
+ if s = 'LINUX' then
|
|
|
|
+ Scanner.AddDefine('UNIX')
|
|
|
|
+ else if s = 'FREEBSD' then
|
|
|
|
+ begin
|
|
|
|
+ Scanner.AddDefine('BSD');
|
|
|
|
+ Scanner.AddDefine('UNIX');
|
|
|
|
+ end else if s = 'NETBSD' then
|
|
|
|
+ begin
|
|
|
|
+ Scanner.AddDefine('BSD');
|
|
|
|
+ Scanner.AddDefine('UNIX');
|
|
|
|
+ end else if s = 'SUNOS' then
|
|
|
|
+ begin
|
|
|
|
+ Scanner.AddDefine('SOLARIS');
|
|
|
|
+ Scanner.AddDefine('UNIX');
|
|
|
|
+ end else if s = 'GO32V2' then
|
|
|
|
+ Scanner.AddDefine('DPMI')
|
|
|
|
+ else if s = 'BEOS' then
|
|
|
|
+ Scanner.AddDefine('UNIX')
|
|
|
|
+ else if s = 'QNX' then
|
|
|
|
+ Scanner.AddDefine('UNIX')
|
|
|
|
+ else if s = 'AROS' then
|
|
|
|
+ Scanner.AddDefine('HASAMIGA')
|
|
|
|
+ else if s = 'MORPHOS' then
|
|
|
|
+ Scanner.AddDefine('HASAMIGA')
|
|
|
|
+ else if s = 'AMIGA' then
|
|
|
|
+ Scanner.AddDefine('HASAMIGA');
|
|
|
|
+
|
|
|
|
+ // TargetCPU
|
|
|
|
+ s := UpperCase(CPUTarget);
|
|
|
|
+ Scanner.AddDefine('CPU'+s);
|
|
|
|
+ if (s='X86_64') then
|
|
|
|
+ Scanner.AddDefine('CPU64')
|
|
|
|
+ else
|
|
|
|
+ Scanner.AddDefine('CPU32');
|
|
|
|
+ end;
|
|
Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
|
|
Parser := TPasParser.Create(Scanner, FileResolver, AEngine);
|
|
Filename := '';
|
|
Filename := '';
|
|
Parser.LogEvents:=AEngine.ParserLogEvents;
|
|
Parser.LogEvents:=AEngine.ParserLogEvents;
|
|
@@ -691,6 +732,12 @@ begin
|
|
Result := nil;
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasTreeContainer.NeedArrayValues(El: TPasElement): boolean;
|
|
|
|
+begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if El=nil then ;
|
|
|
|
+end;
|
|
|
|
+
|
|
{ ---------------------------------------------------------------------
|
|
{ ---------------------------------------------------------------------
|
|
EParserError
|
|
EParserError
|
|
---------------------------------------------------------------------}
|
|
---------------------------------------------------------------------}
|
|
@@ -895,6 +942,30 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TPasParser.CheckTokens(tk: TTokens);
|
|
|
|
+
|
|
|
|
+Var
|
|
|
|
+ S : String;
|
|
|
|
+ T : TToken;
|
|
|
|
+begin
|
|
|
|
+ if not (CurToken in tk) then
|
|
|
|
+ begin
|
|
|
|
+ {$IFDEF VerbosePasParser}
|
|
|
|
+ writeln('TPasParser.ParseExcTokenError String="',CurTokenString,'" Text="',CurTokenText,'" CurToken=',CurToken,' tk=',tk);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ S:='';
|
|
|
|
+ For T in TToken do
|
|
|
|
+ if t in tk then
|
|
|
|
+ begin
|
|
|
|
+ if (S<>'') then
|
|
|
|
+ S:=S+' or ';
|
|
|
|
+ S:=S+TokenInfos[t];
|
|
|
|
+ end;
|
|
|
|
+ ParseExcTokenError(S);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
|
|
procedure TPasParser.ExpectToken(tk: TToken);
|
|
procedure TPasParser.ExpectToken(tk: TToken);
|
|
begin
|
|
begin
|
|
@@ -902,6 +973,12 @@ begin
|
|
CheckToken(tk);
|
|
CheckToken(tk);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TPasParser.ExpectTokens(tk: TTokens);
|
|
|
|
+begin
|
|
|
|
+ NextToken;
|
|
|
|
+ CheckTokens(tk);
|
|
|
|
+end;
|
|
|
|
+
|
|
function TPasParser.ExpectIdentifier: String;
|
|
function TPasParser.ExpectIdentifier: String;
|
|
begin
|
|
begin
|
|
ExpectToken(tkIdentifier);
|
|
ExpectToken(tkIdentifier);
|
|
@@ -1339,7 +1416,9 @@ begin
|
|
// Always allowed
|
|
// Always allowed
|
|
tkIdentifier:
|
|
tkIdentifier:
|
|
begin
|
|
begin
|
|
- if CurTokenIsIdentifier('reference') then
|
|
|
|
|
|
+ // Bug 31709: PReference = ^Reference;
|
|
|
|
+ // Checked in Delphi: ^Reference to procedure; is not allowed !!
|
|
|
|
+ if CurTokenIsIdentifier('reference') and Not (Parent is TPasPointerType) then
|
|
begin
|
|
begin
|
|
CH:=False;
|
|
CH:=False;
|
|
Result:=ParseReferencetoProcedureType(Parent,NamePos,TypeName)
|
|
Result:=ParseReferencetoProcedureType(Parent,NamePos,TypeName)
|
|
@@ -1725,7 +1804,7 @@ begin
|
|
|
|
|
|
ok:=false;
|
|
ok:=false;
|
|
try
|
|
try
|
|
- if Last.Kind in [pekIdent,pekSelf] then
|
|
|
|
|
|
+ if Last.Kind in [pekIdent,pekSelf,pekNil] then
|
|
begin
|
|
begin
|
|
while CurToken in [tkDot] do
|
|
while CurToken in [tkDot] do
|
|
begin
|
|
begin
|
|
@@ -2015,11 +2094,6 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
|
function TPasParser.DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
|
-var
|
|
|
|
- x : TPasExpr;
|
|
|
|
- n : AnsiString;
|
|
|
|
- r : TRecordValues;
|
|
|
|
- a : TArrayValues;
|
|
|
|
|
|
|
|
function lastfield:boolean;
|
|
function lastfield:boolean;
|
|
|
|
|
|
@@ -2035,76 +2109,95 @@ var
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ procedure ReadArrayValues(x : TPasExpr);
|
|
|
|
+ var
|
|
|
|
+ a: TArrayValues;
|
|
|
|
+ begin
|
|
|
|
+ Result:=nil;
|
|
|
|
+ a:=nil;
|
|
|
|
+ try
|
|
|
|
+ a:=CreateArrayValues(AParent);
|
|
|
|
+ if x<>nil then
|
|
|
|
+ begin
|
|
|
|
+ a.AddValues(x);
|
|
|
|
+ x:=nil;
|
|
|
|
+ end;
|
|
|
|
+ repeat
|
|
|
|
+ NextToken;
|
|
|
|
+ a.AddValues(DoParseConstValueExpression(AParent));
|
|
|
|
+ until CurToken<>tkComma;
|
|
|
|
+ Result:=a;
|
|
|
|
+ finally
|
|
|
|
+ if Result=nil then
|
|
|
|
+ begin
|
|
|
|
+ a.Free;
|
|
|
|
+ x.Free;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ x : TPasExpr;
|
|
|
|
+ n : AnsiString;
|
|
|
|
+ r : TRecordValues;
|
|
begin
|
|
begin
|
|
if CurToken <> tkBraceOpen then
|
|
if CurToken <> tkBraceOpen then
|
|
Result:=DoParseExpression(AParent)
|
|
Result:=DoParseExpression(AParent)
|
|
else begin
|
|
else begin
|
|
Result:=nil;
|
|
Result:=nil;
|
|
- NextToken;
|
|
|
|
- x:=DoParseConstValueExpression(AParent);
|
|
|
|
- case CurToken of
|
|
|
|
- tkComma: // array of values (a,b,c);
|
|
|
|
- try
|
|
|
|
- a:=CreateArrayValues(AParent);
|
|
|
|
- a.AddValues(x);
|
|
|
|
- x:=nil;
|
|
|
|
- repeat
|
|
|
|
- NextToken;
|
|
|
|
- x:=DoParseConstValueExpression(AParent);
|
|
|
|
- a.AddValues(x);
|
|
|
|
- x:=nil;
|
|
|
|
- until CurToken<>tkComma;
|
|
|
|
- Result:=a;
|
|
|
|
- finally
|
|
|
|
- if Result=nil then
|
|
|
|
- begin
|
|
|
|
- a.Free;
|
|
|
|
- x.Free;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- tkColon: // record field (a:xxx;b:yyy;c:zzz);
|
|
|
|
- begin
|
|
|
|
- r:=nil;
|
|
|
|
- try
|
|
|
|
- n:=GetExprIdent(x);
|
|
|
|
- ReleaseAndNil(TPasElement(x));
|
|
|
|
- r:=CreateRecordValues(AParent);
|
|
|
|
- NextToken;
|
|
|
|
- x:=DoParseConstValueExpression(AParent);
|
|
|
|
- r.AddField(n, x);
|
|
|
|
- x:=nil;
|
|
|
|
- if not lastfield then
|
|
|
|
- repeat
|
|
|
|
- n:=ExpectIdentifier;
|
|
|
|
- ExpectToken(tkColon);
|
|
|
|
- NextToken;
|
|
|
|
- x:=DoParseConstValueExpression(AParent);
|
|
|
|
- r.AddField(n, x);
|
|
|
|
- x:=nil;
|
|
|
|
- until lastfield; // CurToken<>tkSemicolon;
|
|
|
|
- Result:=r;
|
|
|
|
- finally
|
|
|
|
- if Result=nil then
|
|
|
|
- begin
|
|
|
|
- r.Free;
|
|
|
|
- x.Free;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ if Engine.NeedArrayValues(AParent) then
|
|
|
|
+ ReadArrayValues(nil)
|
|
else
|
|
else
|
|
- // Binary expression! ((128 div sizeof(longint)) - 3);
|
|
|
|
- Result:=DoParseExpression(AParent,x);
|
|
|
|
- if CurToken<>tkBraceClose then
|
|
|
|
- begin
|
|
|
|
- ReleaseAndNil(TPasElement(Result));
|
|
|
|
- ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
|
|
|
|
- end;
|
|
|
|
|
|
+ begin
|
|
NextToken;
|
|
NextToken;
|
|
- if CurToken <> tkSemicolon then // the continue of expression
|
|
|
|
- Result:=DoParseExpression(AParent,Result);
|
|
|
|
- Exit;
|
|
|
|
- end;
|
|
|
|
|
|
+ x:=DoParseConstValueExpression(AParent);
|
|
|
|
+ case CurToken of
|
|
|
|
+ tkComma: // array of values (a,b,c);
|
|
|
|
+ ReadArrayValues(x);
|
|
|
|
+
|
|
|
|
+ tkColon: // record field (a:xxx;b:yyy;c:zzz);
|
|
|
|
+ begin
|
|
|
|
+ r:=nil;
|
|
|
|
+ try
|
|
|
|
+ n:=GetExprIdent(x);
|
|
|
|
+ ReleaseAndNil(TPasElement(x));
|
|
|
|
+ r:=CreateRecordValues(AParent);
|
|
|
|
+ NextToken;
|
|
|
|
+ x:=DoParseConstValueExpression(AParent);
|
|
|
|
+ r.AddField(n, x);
|
|
|
|
+ x:=nil;
|
|
|
|
+ if not lastfield then
|
|
|
|
+ repeat
|
|
|
|
+ n:=ExpectIdentifier;
|
|
|
|
+ ExpectToken(tkColon);
|
|
|
|
+ NextToken;
|
|
|
|
+ x:=DoParseConstValueExpression(AParent);
|
|
|
|
+ r.AddField(n, x);
|
|
|
|
+ x:=nil;
|
|
|
|
+ until lastfield; // CurToken<>tkSemicolon;
|
|
|
|
+ Result:=r;
|
|
|
|
+ finally
|
|
|
|
+ if Result=nil then
|
|
|
|
+ begin
|
|
|
|
+ r.Free;
|
|
|
|
+ x.Free;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ // Binary expression! ((128 div sizeof(longint)) - 3);
|
|
|
|
+ Result:=DoParseExpression(AParent,x);
|
|
|
|
+ if CurToken<>tkBraceClose then
|
|
|
|
+ begin
|
|
|
|
+ ReleaseAndNil(TPasElement(Result));
|
|
|
|
+ ParseExc(nParserExpectedCommaRBracket,SParserExpectedCommaRBracket);
|
|
|
|
+ end;
|
|
|
|
+ NextToken;
|
|
|
|
+ if CurToken <> tkSemicolon then // the continue of expression
|
|
|
|
+ Result:=DoParseExpression(AParent,Result);
|
|
|
|
+ Exit;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
if CurToken<>tkBraceClose then
|
|
if CurToken<>tkBraceClose then
|
|
begin
|
|
begin
|
|
ReleaseAndNil(TPasElement(Result));
|
|
ReleaseAndNil(TPasElement(Result));
|
|
@@ -2736,7 +2829,8 @@ begin
|
|
if Declarations is TProcedureBody then
|
|
if Declarations is TProcedureBody then
|
|
begin
|
|
begin
|
|
Proc:=Declarations.Parent as TPasProcedure;
|
|
Proc:=Declarations.Parent as TPasProcedure;
|
|
- if not (pmAssembler in Proc.Modifiers) then
|
|
|
|
|
|
+ // Assembler keyword is optional in Delphi mode (bug 31690)
|
|
|
|
+ if not ((pmAssembler in Proc.Modifiers) or (msDelphi in CurrentModeswitches)) then
|
|
ParseExc(nParserExpectTokenError,SParserExpectTokenError,['begin']);
|
|
ParseExc(nParserExpectTokenError,SParserExpectTokenError,['begin']);
|
|
SetBlock(declNone);
|
|
SetBlock(declNone);
|
|
ParseProcAsmBlock(TProcedureBody(Declarations));
|
|
ParseProcAsmBlock(TProcedureBody(Declarations));
|
|
@@ -3597,6 +3691,28 @@ end;
|
|
|
|
|
|
// Next token is expected to be a "(", ";" or for a function ":". The caller
|
|
// Next token is expected to be a "(", ";" or for a function ":". The caller
|
|
// will get the token after the final ";" as next token.
|
|
// will get the token after the final ";" as next token.
|
|
|
|
+
|
|
|
|
+function TPasParser.DoCheckHint(Element : TPasElement): Boolean;
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ ahint : TPasMemberHint;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Result:= IsCurTokenHint(ahint);
|
|
|
|
+ if Result then // deprecated,platform,experimental,library, unimplemented etc
|
|
|
|
+ begin
|
|
|
|
+ Element.Hints:=Element.Hints+[ahint];
|
|
|
|
+ if aHint=hDeprecated then
|
|
|
|
+ begin
|
|
|
|
+ NextToken;
|
|
|
|
+ if (CurToken<>tkString) then
|
|
|
|
+ UngetToken
|
|
|
|
+ else
|
|
|
|
+ Element.HintMessage:=CurTokenString;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TPasParser.ParseProcedureOrFunctionHeader(Parent: TPasElement;
|
|
procedure TPasParser.ParseProcedureOrFunctionHeader(Parent: TPasElement;
|
|
Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
|
|
Element: TPasProcedureType; ProcType: TProcType; OfObjectPossible: Boolean);
|
|
|
|
|
|
@@ -3636,25 +3752,6 @@ procedure TPasParser.ParseProcedureOrFunctionHeader(Parent: TPasElement;
|
|
UngetToken;
|
|
UngetToken;
|
|
end;
|
|
end;
|
|
|
|
|
|
- function DoCheckHint : Boolean;
|
|
|
|
-
|
|
|
|
- var
|
|
|
|
- ahint : TPasMemberHint;
|
|
|
|
- begin
|
|
|
|
- Result:= IsCurTokenHint(ahint);
|
|
|
|
- if Result then // deprecated,platform,experimental,library, unimplemented etc
|
|
|
|
- begin
|
|
|
|
- Element.Hints:=Element.Hints+[ahint];
|
|
|
|
- if aHint=hDeprecated then
|
|
|
|
- begin
|
|
|
|
- NextToken;
|
|
|
|
- if (CurToken<>tkString) then
|
|
|
|
- UngetToken
|
|
|
|
- else
|
|
|
|
- Element.HintMessage:=CurTokenString;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
|
|
Var
|
|
Var
|
|
Tok : String;
|
|
Tok : String;
|
|
@@ -3743,9 +3840,10 @@ begin
|
|
ModCount:=0;
|
|
ModCount:=0;
|
|
Repeat
|
|
Repeat
|
|
inc(ModCount);
|
|
inc(ModCount);
|
|
|
|
+ // Writeln(modcount, curtokentext);
|
|
LastToken:=CurToken;
|
|
LastToken:=CurToken;
|
|
NextToken;
|
|
NextToken;
|
|
- if (ModCount=1) and (CurToken = tkEqual) then
|
|
|
|
|
|
+ if (ModCount in [1,2,3]) and (CurToken = tkEqual) then
|
|
begin
|
|
begin
|
|
// for example: const p: procedure = nil;
|
|
// for example: const p: procedure = nil;
|
|
UngetToken;
|
|
UngetToken;
|
|
@@ -3773,7 +3871,9 @@ begin
|
|
NextToken; // remove offset
|
|
NextToken; // remove offset
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
- ExpectToken(tkSemicolon);
|
|
|
|
|
|
+ ExpectTokens([tkSemicolon,tkEqual]);
|
|
|
|
+ if curtoken=tkEqual then
|
|
|
|
+ ungettoken;
|
|
end
|
|
end
|
|
else if IsProc and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
|
|
else if IsProc and TokenIsProcedureModifier(Parent,CurTokenString,PM) then
|
|
HandleProcedureModifier(Parent,PM)
|
|
HandleProcedureModifier(Parent,PM)
|
|
@@ -3791,7 +3891,7 @@ begin
|
|
ExpectToken(tkSemicolon);
|
|
ExpectToken(tkSemicolon);
|
|
end;
|
|
end;
|
|
end
|
|
end
|
|
- else if DoCheckHint then
|
|
|
|
|
|
+ else if DoCheckHint(Element) then
|
|
ConsumeSemi
|
|
ConsumeSemi
|
|
else if (CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0) then
|
|
else if (CurToken=tkIdentifier) and (CompareText(CurTokenText,'alias')=0) then
|
|
begin
|
|
begin
|
|
@@ -3823,9 +3923,10 @@ begin
|
|
// DumpCurToken('Done '+IntToStr(Ord(Done)));
|
|
// DumpCurToken('Done '+IntToStr(Ord(Done)));
|
|
UngetToken;
|
|
UngetToken;
|
|
end;
|
|
end;
|
|
|
|
+
|
|
// Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
|
|
// Writeln('Done: ',TokenInfos[Curtoken],' ',CurtokenString);
|
|
Until Done;
|
|
Until Done;
|
|
- if DoCheckHint then // deprecated,platform,experimental,library, unimplemented etc
|
|
|
|
|
|
+ if DoCheckHint(Element) then // deprecated,platform,experimental,library, unimplemented etc
|
|
ConsumeSemi;
|
|
ConsumeSemi;
|
|
if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
|
|
if (ProcType in [ptOperator,ptClassOperator]) and (Parent is TPasOperator) then
|
|
TPasOperator(Parent).CorrectName;
|
|
TPasOperator(Parent).CorrectName;
|
|
@@ -3913,8 +4014,6 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
|
|
|
|
|
|
var
|
|
var
|
|
isArray , ok: Boolean;
|
|
isArray , ok: Boolean;
|
|
- h : TPasMemberHint;
|
|
|
|
-
|
|
|
|
begin
|
|
begin
|
|
Result:=TPasProperty(CreateElement(TPasProperty,AName,Parent,AVisibility));
|
|
Result:=TPasProperty(CreateElement(TPasProperty,AName,Parent,AVisibility));
|
|
if IsClassField then
|
|
if IsClassField then
|
|
@@ -4010,14 +4109,10 @@ begin
|
|
end
|
|
end
|
|
end;
|
|
end;
|
|
// Handle hints
|
|
// Handle hints
|
|
- while IsCurTokenHint(h) do
|
|
|
|
- begin
|
|
|
|
- Result.Hints:=Result.Hints+[h];
|
|
|
|
|
|
+ while DoCheckHint(Result) do
|
|
NextToken;
|
|
NextToken;
|
|
- if CurToken=tkSemicolon then
|
|
|
|
- NextToken;
|
|
|
|
- end;
|
|
|
|
- UngetToken;
|
|
|
|
|
|
+ if Result.Hints=[] then
|
|
|
|
+ UngetToken;
|
|
ok:=true;
|
|
ok:=true;
|
|
finally
|
|
finally
|
|
if not ok then
|
|
if not ok then
|
|
@@ -4062,6 +4157,16 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TPasParser.ParseAsmBlock(AsmBlock: TPasImplAsmStatement);
|
|
procedure TPasParser.ParseAsmBlock(AsmBlock: TPasImplAsmStatement);
|
|
|
|
+
|
|
|
|
+Var
|
|
|
|
+ LastToken : TToken;
|
|
|
|
+
|
|
|
|
+ Function atEndofAsm : Boolean;
|
|
|
|
+
|
|
|
|
+ begin
|
|
|
|
+ Result:=(CurToken=tkEnd) and (LastToken<>tkAt);
|
|
|
|
+ end;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
if po_asmwhole in Options then
|
|
if po_asmwhole in Options then
|
|
begin
|
|
begin
|
|
@@ -4094,11 +4199,12 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
|
|
+ LastToken:=tkEOF;
|
|
NextToken;
|
|
NextToken;
|
|
- While CurToken<>tkEnd do
|
|
|
|
|
|
+ While Not AtEndOfAsm do
|
|
begin
|
|
begin
|
|
- // ToDo: allow @@end
|
|
|
|
AsmBlock.Tokens.Add(CurTokenText);
|
|
AsmBlock.Tokens.Add(CurTokenText);
|
|
|
|
+ LastToken:=CurToken;
|
|
NextToken;
|
|
NextToken;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -4177,7 +4283,7 @@ begin
|
|
ParseAsmBlock(TPasImplAsmStatement(El));
|
|
ParseAsmBlock(TPasImplAsmStatement(El));
|
|
CurBlock.AddElement(El);
|
|
CurBlock.AddElement(El);
|
|
if NewImplElement=nil then NewImplElement:=CurBlock;
|
|
if NewImplElement=nil then NewImplElement:=CurBlock;
|
|
- if CloseStatement(true) then
|
|
|
|
|
|
+ if CloseStatement(False) then
|
|
break;
|
|
break;
|
|
end;
|
|
end;
|
|
tkbegin:
|
|
tkbegin:
|
|
@@ -4246,6 +4352,11 @@ begin
|
|
//if .. then Raise Exception else ..
|
|
//if .. then Raise Exception else ..
|
|
CloseBlock;
|
|
CloseBlock;
|
|
UngetToken;
|
|
UngetToken;
|
|
|
|
+ end else if (CurBlock is TPasImplAsmStatement) then
|
|
|
|
+ begin
|
|
|
|
+ //if .. then asm end else ..
|
|
|
|
+ CloseBlock;
|
|
|
|
+ UngetToken;
|
|
end else if (CurBlock is TPasImplTryExcept) then
|
|
end else if (CurBlock is TPasImplTryExcept) then
|
|
begin
|
|
begin
|
|
CloseBlock;
|
|
CloseBlock;
|
|
@@ -4544,6 +4655,8 @@ begin
|
|
end;
|
|
end;
|
|
tkSemiColon:
|
|
tkSemiColon:
|
|
if CloseStatement(true) then break;
|
|
if CloseStatement(true) then break;
|
|
|
|
+ tkFinalization:
|
|
|
|
+ if CloseStatement(true) then break;
|
|
tkuntil:
|
|
tkuntil:
|
|
begin
|
|
begin
|
|
if CloseStatement(true) then
|
|
if CloseStatement(true) then
|
|
@@ -4564,8 +4677,11 @@ begin
|
|
end;
|
|
end;
|
|
tkEOF:
|
|
tkEOF:
|
|
CheckToken(tkend);
|
|
CheckToken(tkend);
|
|
- tkBraceOpen,tkIdentifier,tkNumber,tkSquaredBraceOpen,tkMinus,tkPlus,tkinherited:
|
|
|
|
|
|
+ tkAt,tkBraceOpen,tkIdentifier,tkNumber,tkSquaredBraceOpen,tkMinus,tkPlus,tkinherited:
|
|
begin
|
|
begin
|
|
|
|
+// This should in fact not be checked here.
|
|
|
|
+// if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
|
|
|
|
+// ParseExc;
|
|
left:=DoParseExpression(CurBlock);
|
|
left:=DoParseExpression(CurBlock);
|
|
case CurToken of
|
|
case CurToken of
|
|
tkAssign,
|
|
tkAssign,
|
|
@@ -5091,39 +5207,50 @@ end;
|
|
|
|
|
|
procedure TPasParser.ParseClassMembers(AType: TPasClassType);
|
|
procedure TPasParser.ParseClassMembers(AType: TPasClassType);
|
|
|
|
|
|
|
|
+Type
|
|
|
|
+ TSectionType = (stNone,stConst,stType,stVar);
|
|
|
|
+
|
|
Var
|
|
Var
|
|
CurVisibility : TPasMemberVisibility;
|
|
CurVisibility : TPasMemberVisibility;
|
|
|
|
+ CurSection : TSectionType;
|
|
|
|
|
|
begin
|
|
begin
|
|
|
|
+ CurSection:=stNone;
|
|
CurVisibility := visDefault;
|
|
CurVisibility := visDefault;
|
|
while (CurToken<>tkEnd) do
|
|
while (CurToken<>tkEnd) do
|
|
begin
|
|
begin
|
|
case CurToken of
|
|
case CurToken of
|
|
tkType:
|
|
tkType:
|
|
- begin
|
|
|
|
- ExpectToken(tkIdentifier);
|
|
|
|
- SaveComments;
|
|
|
|
- ParseClassLocalTypes(AType,CurVisibility);
|
|
|
|
- end;
|
|
|
|
|
|
+ CurSection:=stType;
|
|
tkConst:
|
|
tkConst:
|
|
- begin
|
|
|
|
- ExpectToken(tkIdentifier);
|
|
|
|
- SaveComments;
|
|
|
|
- ParseClassLocalConsts(AType,CurVisibility);
|
|
|
|
- end;
|
|
|
|
- tkVar,
|
|
|
|
|
|
+ CurSection:=stConst;
|
|
|
|
+ tkVar:
|
|
|
|
+ CurSection:=stVar;
|
|
tkIdentifier:
|
|
tkIdentifier:
|
|
- begin
|
|
|
|
- if (AType.ObjKind in [okInterface,okDispInterface]) then
|
|
|
|
- ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowed);
|
|
|
|
- if CurToken=tkVar then
|
|
|
|
- ExpectToken(tkIdentifier);
|
|
|
|
- SaveComments;
|
|
|
|
- if Not CheckVisibility(CurtokenString,CurVisibility) then
|
|
|
|
- ParseClassFields(AType,CurVisibility,false);
|
|
|
|
- end;
|
|
|
|
|
|
+ if CheckVisibility(CurtokenString,CurVisibility) then
|
|
|
|
+ CurSection:=stNone
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ SaveComments;
|
|
|
|
+ Case CurSection of
|
|
|
|
+ stType:
|
|
|
|
+ ParseClassLocalTypes(AType,CurVisibility);
|
|
|
|
+ stConst :
|
|
|
|
+ ParseClassLocalConsts(AType,CurVisibility);
|
|
|
|
+ stNone,
|
|
|
|
+ stvar:
|
|
|
|
+ begin
|
|
|
|
+ if (AType.ObjKind in [okInterface,okDispInterface]) then
|
|
|
|
+ ParseExc(nParserNoFieldsAllowed,SParserNoFieldsAllowed);
|
|
|
|
+ ParseClassFields(AType,CurVisibility,false);
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ Raise Exception.Create('Internal error 201704251415');
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
tkProcedure,tkFunction,tkConstructor,tkDestructor:
|
|
tkProcedure,tkFunction,tkConstructor,tkDestructor:
|
|
begin
|
|
begin
|
|
|
|
+ curSection:=stNone;
|
|
SaveComments;
|
|
SaveComments;
|
|
if (Curtoken in [tkConstructor,tkDestructor]) and (AType.ObjKind in [okInterface,okDispInterface,okRecordHelper]) then
|
|
if (Curtoken in [tkConstructor,tkDestructor]) and (AType.ObjKind in [okInterface,okDispInterface,okRecordHelper]) then
|
|
ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
|
|
ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
|
|
@@ -5131,6 +5258,7 @@ begin
|
|
end;
|
|
end;
|
|
tkclass:
|
|
tkclass:
|
|
begin
|
|
begin
|
|
|
|
+ curSection:=stNone;
|
|
SaveComments;
|
|
SaveComments;
|
|
NextToken;
|
|
NextToken;
|
|
if CurToken in [tkConstructor,tkDestructor,tkProcedure,tkFunction] then
|
|
if CurToken in [tkConstructor,tkDestructor,tkProcedure,tkFunction] then
|
|
@@ -5150,6 +5278,7 @@ begin
|
|
end;
|
|
end;
|
|
tkProperty:
|
|
tkProperty:
|
|
begin
|
|
begin
|
|
|
|
+ curSection:=stNone;
|
|
SaveComments;
|
|
SaveComments;
|
|
ExpectIdentifier;
|
|
ExpectIdentifier;
|
|
AType.Members.Add(ParseProperty(AType,CurtokenString,CurVisibility,false));
|
|
AType.Members.Add(ParseProperty(AType,CurtokenString,CurVisibility,false));
|