|
@@ -36,6 +36,7 @@ resourcestring
|
|
SParserExpectToken2Error = 'Expected "%s" or "%s"';
|
|
SParserExpectToken2Error = 'Expected "%s" or "%s"';
|
|
SParserExpectedCommaRBracket = 'Expected "," or ")"';
|
|
SParserExpectedCommaRBracket = 'Expected "," or ")"';
|
|
SParserExpectedCommaSemicolon = 'Expected "," or ";"';
|
|
SParserExpectedCommaSemicolon = 'Expected "," or ";"';
|
|
|
|
+ SParserExpectedAssignIn = 'Expected := or in';
|
|
SParserExpectedCommaColon = 'Expected "," or ":"';
|
|
SParserExpectedCommaColon = 'Expected "," or ":"';
|
|
SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
|
|
SParserOnlyOneArgumentCanHaveDefault = 'A default value can only be assigned to 1 parameter';
|
|
SParserExpectedLBracketColon = 'Expected "(" or ":"';
|
|
SParserExpectedLBracketColon = 'Expected "(" or ":"';
|
|
@@ -55,10 +56,12 @@ resourcestring
|
|
SParserNotAProcToken = 'Not a procedure or function token';
|
|
SParserNotAProcToken = 'Not a procedure or function token';
|
|
SRangeExpressionExpected = 'Range expression expected';
|
|
SRangeExpressionExpected = 'Range expression expected';
|
|
SParserExpectCase = 'Case label expression expected';
|
|
SParserExpectCase = 'Case label expression expected';
|
|
-
|
|
|
|
|
|
+ SParserHelperNotAllowed = 'Helper objects not allowed for "%s"';
|
|
SLogStartImplementation = 'Start parsing implementation section.';
|
|
SLogStartImplementation = 'Start parsing implementation section.';
|
|
SLogStartInterface = 'Start parsing interface section';
|
|
SLogStartInterface = 'Start parsing interface section';
|
|
SParsingUsedUnit = 'Parsing used unit "%s" with commandLine "%s"';
|
|
SParsingUsedUnit = 'Parsing used unit "%s" with commandLine "%s"';
|
|
|
|
+ SParserNoConstructorAllowed = 'Constructors or Destructors are not allowed in Interfaces or Record helpers';
|
|
|
|
+ SParserNoFieldsAllowed = 'Fields are not allowed in Interfaces';
|
|
|
|
|
|
type
|
|
type
|
|
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
|
|
TPasParserLogHandler = Procedure (Sender : TObject; Const Msg : String) of object;
|
|
@@ -181,6 +184,7 @@ type
|
|
function CurTokenText: String;
|
|
function CurTokenText: String;
|
|
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 ExpectToken(tk: TToken);
|
|
procedure ExpectToken(tk: TToken);
|
|
function ExpectIdentifier: String;
|
|
function ExpectIdentifier: String;
|
|
Function CurTokenIsIdentifier(Const S : String) : Boolean;
|
|
Function CurTokenIsIdentifier(Const S : String) : Boolean;
|
|
@@ -610,12 +614,17 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TPasParser.CheckToken(tk: TToken);
|
|
|
|
+begin
|
|
|
|
+ if (CurToken<>tk) then
|
|
|
|
+ ParseExc(Format(SParserExpectTokenError, [TokenInfos[tk]]));
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
|
|
procedure TPasParser.ExpectToken(tk: TToken);
|
|
procedure TPasParser.ExpectToken(tk: TToken);
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
- if CurToken <> tk then
|
|
|
|
- ParseExc(Format(SParserExpectTokenError, [TokenInfos[tk]]));
|
|
|
|
|
|
+ CheckToken(tk);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPasParser.ExpectIdentifier: String;
|
|
function TPasParser.ExpectIdentifier: String;
|
|
@@ -913,7 +922,7 @@ Const
|
|
// These types are allowed only when full type declarations
|
|
// These types are allowed only when full type declarations
|
|
FullTypeTokens = [tkGeneric,tkSpecialize,tkClass,tkInterface,tkType];
|
|
FullTypeTokens = [tkGeneric,tkSpecialize,tkClass,tkInterface,tkType];
|
|
// Parsing of these types already takes care of hints
|
|
// Parsing of these types already takes care of hints
|
|
- NoHintTokens = [tkClass,tkObject,tkInterface,tkProcedure,tkFunction];
|
|
|
|
|
|
+ NoHintTokens = [tkProcedure,tkFunction];
|
|
var
|
|
var
|
|
PM : TPackMode;
|
|
PM : TPackMode;
|
|
CH : Boolean; // Check hint ?
|
|
CH : Boolean; // Check hint ?
|
|
@@ -945,11 +954,25 @@ begin
|
|
tkSet: Result:=ParseSetType(Parent,TypeName);
|
|
tkSet: Result:=ParseSetType(Parent,TypeName);
|
|
tkProcedure: Result:=ParseProcedureType(Parent,TypeName,ptProcedure);
|
|
tkProcedure: Result:=ParseProcedureType(Parent,TypeName,ptProcedure);
|
|
tkFunction: Result:=ParseProcedureType(Parent,TypeName,ptFunction);
|
|
tkFunction: Result:=ParseProcedureType(Parent,TypeName,ptFunction);
|
|
- tkRecord: Result := ParseRecordDecl(Parent,TypeName,PM);
|
|
|
|
|
|
+ tkRecord:
|
|
|
|
+ begin
|
|
|
|
+ NextToken;
|
|
|
|
+ if (Curtoken=tkHelper) then
|
|
|
|
+ begin
|
|
|
|
+ UnGetToken;
|
|
|
|
+ Result:=ParseClassDecl(Parent,TypeName,okRecordHelper,PM);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ UnGetToken;
|
|
|
|
+ Result := ParseRecordDecl(Parent,TypeName,PM);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
else
|
|
else
|
|
UngetToken;
|
|
UngetToken;
|
|
Result:=ParseRangeType(Parent,TypeName,Full);
|
|
Result:=ParseRangeType(Parent,TypeName,Full);
|
|
end;
|
|
end;
|
|
|
|
+ DumpCurToken('Done');
|
|
if CH then
|
|
if CH then
|
|
CheckHint(Result,True);
|
|
CheckHint(Result,True);
|
|
Except
|
|
Except
|
|
@@ -2009,7 +2032,8 @@ begin
|
|
NextToken;
|
|
NextToken;
|
|
DoParseClassType(ClassEl);
|
|
DoParseClassType(ClassEl);
|
|
Declarations.Declarations.Add(ClassEl);
|
|
Declarations.Declarations.Add(ClassEl);
|
|
- Declarations.Classes.Add(ClassEl)
|
|
|
|
|
|
+ Declarations.Classes.Add(ClassEl);
|
|
|
|
+ CheckHint(classel,True);
|
|
end;
|
|
end;
|
|
tkbegin:
|
|
tkbegin:
|
|
begin
|
|
begin
|
|
@@ -3017,11 +3041,12 @@ var
|
|
VarName: String;
|
|
VarName: String;
|
|
SubBlock: TPasImplElement;
|
|
SubBlock: TPasImplElement;
|
|
CmdElem: TPasImplElement;
|
|
CmdElem: TPasImplElement;
|
|
- ForDownTo: Boolean;
|
|
|
|
left: TPasExpr;
|
|
left: TPasExpr;
|
|
right: TPasExpr;
|
|
right: TPasExpr;
|
|
el : TPasImplElement;
|
|
el : TPasImplElement;
|
|
ak : TAssignKind;
|
|
ak : TAssignKind;
|
|
|
|
+ lt : TLoopType;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
NewImplElement:=nil;
|
|
NewImplElement:=nil;
|
|
CurBlock := Parent;
|
|
CurBlock := Parent;
|
|
@@ -3109,31 +3134,44 @@ begin
|
|
tkfor:
|
|
tkfor:
|
|
begin
|
|
begin
|
|
// for VarName := StartValue to EndValue do
|
|
// for VarName := StartValue to EndValue do
|
|
|
|
+ // for VarName in Expression do
|
|
ExpectIdentifier;
|
|
ExpectIdentifier;
|
|
VarName:=CurTokenString;
|
|
VarName:=CurTokenString;
|
|
- ExpectToken(tkAssign);
|
|
|
|
- NextToken;
|
|
|
|
- Left:=DoParseExpression(Parent);
|
|
|
|
- UnGetToken;
|
|
|
|
- //writeln(i,'FOR Start=',StartValue);
|
|
|
|
NextToken;
|
|
NextToken;
|
|
- if CurToken=tkTo then
|
|
|
|
- ForDownTo:=false
|
|
|
|
- else if CurToken=tkdownto then
|
|
|
|
- ForDownTo:=true
|
|
|
|
|
|
+ Left:=Nil;
|
|
|
|
+ Right:=Nil;
|
|
|
|
+ if Not (CurToken in [tkAssign,tkIn]) then
|
|
|
|
+ ParseExc(SParserExpectedAssignIn);
|
|
|
|
+ if (CurToken=tkAssign) then
|
|
|
|
+ lt:=ltNormal
|
|
else
|
|
else
|
|
- ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkTo]]));
|
|
|
|
|
|
+ lt:=ltin;
|
|
NextToken;
|
|
NextToken;
|
|
- Right:=DoParseExpression(Parent);
|
|
|
|
- UngetToken;
|
|
|
|
|
|
+ Left:=DoParseExpression(Parent);
|
|
|
|
+ Try
|
|
|
|
+ if (Lt=ltNormal) then
|
|
|
|
+ begin
|
|
|
|
+ if Not (CurToken in [tkTo,tkDownTo]) then
|
|
|
|
+ ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkTo]]));
|
|
|
|
+ if CurToken=tkdownto then
|
|
|
|
+ Lt:=ltDown;
|
|
|
|
+ NextToken;
|
|
|
|
+ Right:=DoParseExpression(Parent);
|
|
|
|
+ end;
|
|
|
|
+ if (CurToken<>tkDo) then
|
|
|
|
+ ParseExc(Format(SParserExpectTokenError, [TokenInfos[tkDo]]));
|
|
|
|
+ except
|
|
|
|
+ FreeAndNil(Left);
|
|
|
|
+ FreeAndNil(Right);
|
|
|
|
+ Raise;
|
|
|
|
+ end;
|
|
el:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock));
|
|
el:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock));
|
|
TPasImplForLoop(el).VariableName:=VarName;
|
|
TPasImplForLoop(el).VariableName:=VarName;
|
|
TPasImplForLoop(el).StartExpr:=Left;
|
|
TPasImplForLoop(el).StartExpr:=Left;
|
|
TPasImplForLoop(el).EndExpr:=Right;
|
|
TPasImplForLoop(el).EndExpr:=Right;
|
|
- TPasImplForLoop(el).Down:=forDownto;
|
|
|
|
|
|
+ TPasImplForLoop(el).LoopType:=lt;
|
|
CreateBlock(TPasImplForLoop(el));
|
|
CreateBlock(TPasImplForLoop(el));
|
|
//WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
|
|
//WriteLn(i,'FOR "',VarName,'" := ',StartValue,' to ',EndValue,' Token=',CurTokenText);
|
|
- ExpectToken(tkdo);
|
|
|
|
end;
|
|
end;
|
|
tkwith:
|
|
tkwith:
|
|
begin
|
|
begin
|
|
@@ -3559,15 +3597,15 @@ end;
|
|
Function TPasParser.ParseRecordDecl(Parent: TPasElement; Const TypeName : string; const Packmode : TPackMode = pmNone) : TPasRecordType;
|
|
Function TPasParser.ParseRecordDecl(Parent: TPasElement; Const TypeName : string; const Packmode : TPackMode = pmNone) : TPasRecordType;
|
|
|
|
|
|
begin
|
|
begin
|
|
- Result := TPasRecordType(CreateElement(TPasRecordType, TypeName, Parent));
|
|
|
|
- try
|
|
|
|
- Result.PackMode:=PackMode;
|
|
|
|
- NextToken;
|
|
|
|
- ParseRecordFieldList(Result,tkEnd);
|
|
|
|
- except
|
|
|
|
- FreeAndNil(Result);
|
|
|
|
- Raise;
|
|
|
|
- end;
|
|
|
|
|
|
+ Result := TPasRecordType(CreateElement(TPasRecordType, TypeName, Parent));
|
|
|
|
+ try
|
|
|
|
+ Result.PackMode:=PackMode;
|
|
|
|
+ NextToken;
|
|
|
|
+ ParseRecordFieldList(Result,tkEnd);
|
|
|
|
+ except
|
|
|
|
+ FreeAndNil(Result);
|
|
|
|
+ Raise;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
Function IsVisibility(S : String; Out AVisibility :TPasMemberVisibility) : Boolean;
|
|
Function IsVisibility(S : String; Out AVisibility :TPasMemberVisibility) : Boolean;
|
|
@@ -3719,13 +3757,19 @@ begin
|
|
tkVar,
|
|
tkVar,
|
|
tkIdentifier:
|
|
tkIdentifier:
|
|
begin
|
|
begin
|
|
|
|
+ if (AType.ObjKind=okInterface) then
|
|
|
|
+ ParseExc(SParserNoFieldsAllowed);
|
|
if CurToken=tkVar then
|
|
if CurToken=tkVar then
|
|
ExpectToken(tkIdentifier);
|
|
ExpectToken(tkIdentifier);
|
|
if Not CheckVisibility(CurtokenString,CurVisibility) then
|
|
if Not CheckVisibility(CurtokenString,CurVisibility) then
|
|
ParseClassFields(AType,CurVisibility,false);
|
|
ParseClassFields(AType,CurVisibility,false);
|
|
end;
|
|
end;
|
|
tkProcedure,tkFunction,tkConstructor,tkDestructor:
|
|
tkProcedure,tkFunction,tkConstructor,tkDestructor:
|
|
|
|
+ begin
|
|
|
|
+ if (Curtoken in [tkConstructor,tkDestructor]) and (AType.ObjKind in [okInterface,okRecordHelper]) then
|
|
|
|
+ ParseExc(SParserNoConstructorAllowed);
|
|
ProcessMethod(AType,False,CurVisibility);
|
|
ProcessMethod(AType,False,CurVisibility);
|
|
|
|
+ end;
|
|
tkclass:
|
|
tkclass:
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
@@ -3789,17 +3833,26 @@ begin
|
|
NextToken;
|
|
NextToken;
|
|
AType.IsShortDefinition:=(CurToken=tkSemicolon);
|
|
AType.IsShortDefinition:=(CurToken=tkSemicolon);
|
|
end;
|
|
end;
|
|
- if not (AType.IsShortDefinition or AType.IsForward) then
|
|
|
|
|
|
+ if (AType.ObjKind in [okClassHelper,okRecordHelper]) then
|
|
|
|
+ begin
|
|
|
|
+ if (CurToken<>tkFor) then
|
|
|
|
+ ParseExc(Format(SParserExpectTokenError,[TokenInfos[tkFor]]));
|
|
|
|
+ AType.HelperForType:=ParseType(Nil);
|
|
|
|
+ NextToken;
|
|
|
|
+ end;
|
|
|
|
+ if (AType.IsShortDefinition or AType.IsForward) then
|
|
|
|
+ UngetToken
|
|
|
|
+ else
|
|
begin
|
|
begin
|
|
if (AType.ObjKind=okInterface) and (CurToken = tkSquaredBraceOpen) then
|
|
if (AType.ObjKind=okInterface) and (CurToken = tkSquaredBraceOpen) then
|
|
begin
|
|
begin
|
|
- ExpectToken(tkString);
|
|
|
|
- AType.InterfaceGUID := CurTokenString;
|
|
|
|
- ExpectToken(tkSquaredBraceClose);
|
|
|
|
|
|
+ NextToken;
|
|
|
|
+ AType.GUIDExpr:=DoParseExpression(AType);
|
|
|
|
+ if (CurToken<>tkSquaredBraceClose) then
|
|
|
|
+ ParseExc(Format(SParserExpectTokenError,[TokenInfos[tkSquaredBraceClose]]));
|
|
|
|
+ NextToken;
|
|
end;
|
|
end;
|
|
ParseClassMembers(AType);
|
|
ParseClassMembers(AType);
|
|
- // Eat semicolon after class...end
|
|
|
|
- CheckHint(AType,true);
|
|
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -3817,16 +3870,22 @@ begin
|
|
NextToken;
|
|
NextToken;
|
|
|
|
|
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
|
- begin
|
|
|
|
|
|
+ begin
|
|
Result := TPasClassOfType(Engine.CreateElement(TPasClassOfType, AClassName,
|
|
Result := TPasClassOfType(Engine.CreateElement(TPasClassOfType, AClassName,
|
|
Parent, SourceFilename, SourceLinenumber));
|
|
Parent, SourceFilename, SourceLinenumber));
|
|
ExpectIdentifier;
|
|
ExpectIdentifier;
|
|
UngetToken; // Only names are allowed as following type
|
|
UngetToken; // Only names are allowed as following type
|
|
TPasClassOfType(Result).DestType := ParseType(Result);
|
|
TPasClassOfType(Result).DestType := ParseType(Result);
|
|
- CheckHint(Result,true);
|
|
|
|
exit;
|
|
exit;
|
|
- end;
|
|
|
|
-
|
|
|
|
|
|
+ end;
|
|
|
|
+ if (CurToken = tkHelper) then
|
|
|
|
+ begin
|
|
|
|
+ if Not (AObjKind in [okClass,okRecordHelper]) then
|
|
|
|
+ ParseExc(Format(SParserHelperNotAllowed,[ObjKindNames[AObjKind]]));
|
|
|
|
+ if (AObjKind = okClass) then
|
|
|
|
+ AObjKind:=okClassHelper;
|
|
|
|
+ NextToken;
|
|
|
|
+ end;
|
|
Result := TPasClassType(Engine.CreateElement(TPasClassType, AClassName,
|
|
Result := TPasClassType(Engine.CreateElement(TPasClassType, AClassName,
|
|
Parent, SourceFilename, SourceLinenumber));
|
|
Parent, SourceFilename, SourceLinenumber));
|
|
|
|
|