|
@@ -38,7 +38,7 @@ interface
|
|
|
|
|
|
uses
|
|
uses
|
|
{$ifdef NODEJS}
|
|
{$ifdef NODEJS}
|
|
- NodeJSFS,
|
|
|
|
|
|
+ Node.FS,
|
|
{$endif}
|
|
{$endif}
|
|
SysUtils, Classes, Types, PasTree, PScanner;
|
|
SysUtils, Classes, Types, PasTree, PScanner;
|
|
|
|
|
|
@@ -101,6 +101,7 @@ const
|
|
nParserOnlyOneVariableCanBeAbsolute = 2055;
|
|
nParserOnlyOneVariableCanBeAbsolute = 2055;
|
|
nParserXNotAllowedInY = 2056;
|
|
nParserXNotAllowedInY = 2056;
|
|
nFileSystemsNotSupported = 2057;
|
|
nFileSystemsNotSupported = 2057;
|
|
|
|
+ nInvalidMessageType = 2058;
|
|
|
|
|
|
// resourcestring patterns of messages
|
|
// resourcestring patterns of messages
|
|
resourcestring
|
|
resourcestring
|
|
@@ -161,6 +162,7 @@ resourcestring
|
|
SParserOnlyOneVariableCanBeAbsolute = 'Only one variable can be absolute';
|
|
SParserOnlyOneVariableCanBeAbsolute = 'Only one variable can be absolute';
|
|
SParserXNotAllowedInY = '%s is not allowed in %s';
|
|
SParserXNotAllowedInY = '%s is not allowed in %s';
|
|
SErrFileSystemNotSupported = 'No support for filesystems enabled';
|
|
SErrFileSystemNotSupported = 'No support for filesystems enabled';
|
|
|
|
+ SErrInvalidMessageType = 'Invalid message type: string or integer expression expected';
|
|
|
|
|
|
type
|
|
type
|
|
TPasScopeType = (
|
|
TPasScopeType = (
|
|
@@ -369,8 +371,8 @@ type
|
|
function ParseExprOperand(AParent : TPasElement): TPasExpr;
|
|
function ParseExprOperand(AParent : TPasElement): TPasExpr;
|
|
function ParseExpIdent(AParent : TPasElement): TPasExpr; deprecated 'use ParseExprOperand instead'; // since fpc 3.3.1
|
|
function ParseExpIdent(AParent : TPasElement): TPasExpr; deprecated 'use ParseExprOperand instead'; // since fpc 3.3.1
|
|
procedure DoParseClassType(AType: TPasClassType);
|
|
procedure DoParseClassType(AType: TPasClassType);
|
|
- procedure DoParseClassExternalHeader(AObjKind: TPasObjKind;
|
|
|
|
- out AExternalNameSpace, AExternalName: string);
|
|
|
|
|
|
+ Function DoParseClassExternalHeader(AObjKind: TPasObjKind;
|
|
|
|
+ out AExternalNameSpace, AExternalName: string) : Boolean;
|
|
procedure DoParseArrayType(ArrType: TPasArrayType);
|
|
procedure DoParseArrayType(ArrType: TPasArrayType);
|
|
function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
|
|
function DoParseExpression(AParent: TPaselement;InitExpr: TPasExpr=nil; AllowEqual : Boolean = True): TPasExpr;
|
|
function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
|
function DoParseConstValueExpression(AParent: TPasElement): TPasExpr;
|
|
@@ -453,7 +455,7 @@ type
|
|
procedure ParseInitialization;
|
|
procedure ParseInitialization;
|
|
procedure ParseFinalization;
|
|
procedure ParseFinalization;
|
|
procedure ParseDeclarations(Declarations: TPasDeclarations);
|
|
procedure ParseDeclarations(Declarations: TPasDeclarations);
|
|
- procedure ParseStatement(Parent: TPasImplBlock; out NewImplElement: TPasImplElement);
|
|
|
|
|
|
+ procedure ParseStatement(Parent: TPasImplBlock; out NewImplElement: TPasImplElement);
|
|
procedure ParseLabels(AParent: TPasElement);
|
|
procedure ParseLabels(AParent: TPasElement);
|
|
procedure ParseProcBeginBlock(Parent: TProcedureBody);
|
|
procedure ParseProcBeginBlock(Parent: TProcedureBody);
|
|
procedure ParseProcAsmBlock(Parent: TProcedureBody);
|
|
procedure ParseProcAsmBlock(Parent: TProcedureBody);
|
|
@@ -630,7 +632,9 @@ Function IsCallingConvention(S : String; out CC : TCallingConvention) : Boolean;
|
|
|
|
|
|
Var
|
|
Var
|
|
CCNames : Array[TCallingConvention] of String
|
|
CCNames : Array[TCallingConvention] of String
|
|
- = ('','register','pascal','cdecl','stdcall','oldfpccall','safecall','syscall');
|
|
|
|
|
|
+ = ('','register','pascal','cdecl','stdcall','oldfpccall','safecall','syscall',
|
|
|
|
+ 'mwpascal', 'hardfloat','sysv_abi_default','sysv_abi_cdecl',
|
|
|
|
+ 'ms_abi_default','ms_abi_cdecl','vectorcall');
|
|
Var
|
|
Var
|
|
C : TCallingConvention;
|
|
C : TCallingConvention;
|
|
|
|
|
|
@@ -1354,11 +1358,9 @@ begin
|
|
if Parent is TPasClassType then
|
|
if Parent is TPasClassType then
|
|
begin
|
|
begin
|
|
if PM in [pmPublic,pmForward] then exit(false);
|
|
if PM in [pmPublic,pmForward] then exit(false);
|
|
- case TPasClassType(Parent).ObjKind of
|
|
|
|
- okInterface,okDispInterface:
|
|
|
|
- if not (PM in [pmOverload, pmMessage,
|
|
|
|
- pmDispId,pmNoReturn,pmFar,pmFinal]) then exit(false);
|
|
|
|
- end;
|
|
|
|
|
|
+ if TPasClassType(Parent).ObjKind in [okInterface,okDispInterface] then
|
|
|
|
+ if not (PM in [pmOverload, pmMessage, pmDispId,pmNoReturn,pmFar,pmFinal]) then
|
|
|
|
+ exit(false);
|
|
exit;
|
|
exit;
|
|
end
|
|
end
|
|
else if Parent is TPasRecordType then
|
|
else if Parent is TPasRecordType then
|
|
@@ -1378,7 +1380,11 @@ function TPasParser.TokenIsAnonymousProcedureModifier(Parent: TPasElement;
|
|
begin
|
|
begin
|
|
Result:=IsProcModifier(S,PM);
|
|
Result:=IsProcModifier(S,PM);
|
|
if not Result then exit;
|
|
if not Result then exit;
|
|
- Result:=PM in [pmAssembler];
|
|
|
|
|
|
+ case PM of
|
|
|
|
+ pmAssembler: Result:=true;
|
|
|
|
+ else
|
|
|
|
+ Result:=false;
|
|
|
|
+ end;
|
|
if Parent=nil then ;
|
|
if Parent=nil then ;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1395,6 +1401,11 @@ begin
|
|
Result:=true;
|
|
Result:=true;
|
|
PTM:=ptmStatic;
|
|
PTM:=ptmStatic;
|
|
end
|
|
end
|
|
|
|
+ else if (CompareText(S,ProcTypeModifiers[ptmAsync])=0) and (po_AsyncProcs in Options) then
|
|
|
|
+ begin
|
|
|
|
+ Result:=true;
|
|
|
|
+ PTM:=ptmAsync;
|
|
|
|
+ end
|
|
else
|
|
else
|
|
Result:=false;
|
|
Result:=false;
|
|
if Parent=nil then;
|
|
if Parent=nil then;
|
|
@@ -1452,7 +1463,7 @@ begin
|
|
if (Result<>pmNone) then
|
|
if (Result<>pmNone) then
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
- if Not (CurToken in [tkArray, tkRecord, tkObject, tkClass, tkSet]) then
|
|
|
|
|
|
+ if Not (CurToken in [tkArray, tkRecord, tkObject, tkClass, tkObjCClass, tkSet]) then
|
|
ParseExcTokenError('SET, ARRAY, RECORD, OBJECT or CLASS');
|
|
ParseExcTokenError('SET, ARRAY, RECORD, OBJECT or CLASS');
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -1860,14 +1871,23 @@ function TPasParser.ParseType(Parent: TPasElement;
|
|
const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
|
|
const NamePos: TPasSourcePos; const TypeName: String; Full: Boolean
|
|
): TPasType;
|
|
): TPasType;
|
|
|
|
|
|
|
|
+Type
|
|
|
|
+ TLocalClassType = (lctClass,lctObjcClass,lctObjcCategory,lctHelper);
|
|
|
|
+
|
|
Const
|
|
Const
|
|
// These types are allowed only when full type declarations
|
|
// These types are allowed only when full type declarations
|
|
- FullTypeTokens = [tkGeneric,{tkSpecialize,}tkClass,tkInterface,tkDispInterface,tkType];
|
|
|
|
|
|
+ FullTypeTokens = [tkGeneric,{tkSpecialize,}tkClass,tkObjCClass,tkInterface,tkObjcProtocol,tkDispInterface,tkType];
|
|
// Parsing of these types already takes care of hints
|
|
// Parsing of these types already takes care of hints
|
|
NoHintTokens = [tkProcedure,tkFunction];
|
|
NoHintTokens = [tkProcedure,tkFunction];
|
|
|
|
+ InterfaceKindTypes : Array[Boolean] of TPasObjKind = (okInterface,okObjcProtocol);
|
|
|
|
+ ClassKindTypes : Array[TLocalClassType] of TPasObjKind = (okClass,okObjCClass,okObjcCategory,okClassHelper);
|
|
|
|
+
|
|
|
|
+
|
|
var
|
|
var
|
|
PM: TPackMode;
|
|
PM: TPackMode;
|
|
- CH, isHelper, ok: Boolean;
|
|
|
|
|
|
+ CH, ok, isHelper : Boolean;
|
|
|
|
+ lClassType : TLocalClassType;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
Result := nil;
|
|
Result := nil;
|
|
// NextToken and check pack mode
|
|
// NextToken and check pack mode
|
|
@@ -1887,27 +1907,37 @@ begin
|
|
tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
|
|
tkObject: Result := ParseClassDecl(Parent, NamePos, TypeName, okObject,PM);
|
|
tkDispInterface:
|
|
tkDispInterface:
|
|
Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface,PM);
|
|
Result := ParseClassDecl(Parent, NamePos, TypeName, okDispInterface,PM);
|
|
|
|
+ tkObjcProtocol,
|
|
tkInterface:
|
|
tkInterface:
|
|
- Result := ParseClassDecl(Parent, NamePos, TypeName, okInterface,PM);
|
|
|
|
|
|
+ begin
|
|
|
|
+ Result := ParseClassDecl(Parent, NamePos, TypeName, InterfaceKindTypes[(CurToken=tkObjcProtocol)],PM);
|
|
|
|
+ end;
|
|
tkSpecialize:
|
|
tkSpecialize:
|
|
Result:=ParseSimpleType(Parent,CurSourcePos,TypeName);
|
|
Result:=ParseSimpleType(Parent,CurSourcePos,TypeName);
|
|
|
|
+ tkObjCClass,
|
|
|
|
+ tkobjccategory,
|
|
tkClass:
|
|
tkClass:
|
|
begin
|
|
begin
|
|
- isHelper:=false;
|
|
|
|
- NextToken;
|
|
|
|
- if CurTokenIsIdentifier('Helper') then
|
|
|
|
|
|
+ If (CurToken=tkObjCClass) then
|
|
|
|
+ lClassType:=lctObjcClass
|
|
|
|
+ else if (CurToken=tkobjccategory) then
|
|
|
|
+ lClassType:=lctObjcCategory
|
|
|
|
+ else
|
|
begin
|
|
begin
|
|
- // class helper: atype end;
|
|
|
|
- // class helper for atype end;
|
|
|
|
|
|
+ lClassType:=lctClass;
|
|
NextToken;
|
|
NextToken;
|
|
- isHelper:=CurToken in [tkfor,tkBraceOpen];
|
|
|
|
- UnGetToken;
|
|
|
|
|
|
+ if CurTokenIsIdentifier('Helper') then
|
|
|
|
+ begin
|
|
|
|
+ // class helper: atype end;
|
|
|
|
+ // class helper for atype end;
|
|
|
|
+ NextToken;
|
|
|
|
+ if CurToken in [tkfor,tkBraceOpen] then
|
|
|
|
+ lClassType:=lctHelper;
|
|
|
|
+ UnGetToken;
|
|
|
|
+ end;
|
|
|
|
+ UngetToken;
|
|
end;
|
|
end;
|
|
- UngetToken;
|
|
|
|
- if isHelper then
|
|
|
|
- Result:=ParseClassDecl(Parent,NamePos,TypeName,okClassHelper, PM)
|
|
|
|
- else
|
|
|
|
- Result:=ParseClassDecl(Parent, NamePos, TypeName, okClass, PM);
|
|
|
|
|
|
+ Result:=ParseClassDecl(Parent,NamePos,TypeName,ClassKindTypes[lClasstype], PM);
|
|
end;
|
|
end;
|
|
tkType:
|
|
tkType:
|
|
begin
|
|
begin
|
|
@@ -1997,6 +2027,7 @@ begin
|
|
tkprocedure : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
|
|
tkprocedure : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptProcedure);
|
|
tkfunction : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
|
|
tkfunction : Result:=ParseProcedureType(Parent,NamePos,TypeName,ptFunction);
|
|
else
|
|
else
|
|
|
|
+ result:=Nil; // Fool compiler
|
|
ParseExcTokenError('procedure or function');
|
|
ParseExcTokenError('procedure or function');
|
|
end;
|
|
end;
|
|
Result.IsReferenceTo:=True;
|
|
Result.IsReferenceTo:=True;
|
|
@@ -2066,18 +2097,21 @@ function TPasParser.isEndOfExp(AllowEqual : Boolean = False; CheckHints : Boolea
|
|
const
|
|
const
|
|
EndExprToken = [
|
|
EndExprToken = [
|
|
tkEOF, tkBraceClose, tkSquaredBraceClose, tkSemicolon, tkComma, tkColon,
|
|
tkEOF, tkBraceClose, tkSquaredBraceClose, tkSemicolon, tkComma, tkColon,
|
|
- tkdo, tkdownto, tkelse, tkend, tkof, tkthen, tkto
|
|
|
|
|
|
+ tkdo, tkdownto, tkelse, tkend, tkof, tkthen, tkto, tkotherwise
|
|
];
|
|
];
|
|
begin
|
|
begin
|
|
- Result:=(CurToken in EndExprToken) or (CheckHints and IsCurTokenHint);
|
|
|
|
- if Not (Result or AllowEqual) then
|
|
|
|
- Result:=(Curtoken=tkEqual);
|
|
|
|
|
|
+ if (CurToken in EndExprToken) or (CheckHints and IsCurTokenHint) then
|
|
|
|
+ exit(true);
|
|
|
|
+ if AllowEqual and (CurToken=tkEqual) then
|
|
|
|
+ exit(true);
|
|
|
|
+ Result:=false;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TPasParser.ExprToText(Expr: TPasExpr): String;
|
|
function TPasParser.ExprToText(Expr: TPasExpr): String;
|
|
var
|
|
var
|
|
C: TClass;
|
|
C: TClass;
|
|
begin
|
|
begin
|
|
|
|
+ Result:='';
|
|
C:=Expr.ClassType;
|
|
C:=Expr.ClassType;
|
|
if C=TPrimitiveExpr then
|
|
if C=TPrimitiveExpr then
|
|
Result:=TPrimitiveExpr(Expr).Value
|
|
Result:=TPrimitiveExpr(Expr).Value
|
|
@@ -2263,6 +2297,7 @@ begin
|
|
tkDot : Result:=eopSubIdent;
|
|
tkDot : Result:=eopSubIdent;
|
|
tkCaret : Result:=eopDeref;
|
|
tkCaret : Result:=eopDeref;
|
|
else
|
|
else
|
|
|
|
+ result:=eopAdd; // Fool compiler
|
|
ParseExc(nParserNotAnOperand,SParserNotAnOperand,[AToken,TokenInfos[AToken]]);
|
|
ParseExc(nParserNotAnOperand,SParserNotAnOperand,[AToken,TokenInfos[AToken]]);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -2938,6 +2973,7 @@ var
|
|
OldMember: TPasElement;
|
|
OldMember: TPasElement;
|
|
OverloadedProc: TPasOverloadedProc;
|
|
OverloadedProc: TPasOverloadedProc;
|
|
begin
|
|
begin
|
|
|
|
+ OldMember:=nil;
|
|
With Decs do
|
|
With Decs do
|
|
begin
|
|
begin
|
|
if not (po_nooverloadedprocs in Options) then
|
|
if not (po_nooverloadedprocs in Options) then
|
|
@@ -3394,6 +3430,7 @@ end;
|
|
function TPasParser.GetProcTypeFromToken(tk: TToken; IsClass: Boolean
|
|
function TPasParser.GetProcTypeFromToken(tk: TToken; IsClass: Boolean
|
|
): TProcType;
|
|
): TProcType;
|
|
begin
|
|
begin
|
|
|
|
+ Result:=ptProcedure;
|
|
Case tk of
|
|
Case tk of
|
|
tkProcedure :
|
|
tkProcedure :
|
|
if IsClass then
|
|
if IsClass then
|
|
@@ -3470,7 +3507,7 @@ begin
|
|
HadTypeSection:=false;
|
|
HadTypeSection:=false;
|
|
while True do
|
|
while True do
|
|
begin
|
|
begin
|
|
- if CurBlock in [DeclNone,declConst,declType] then
|
|
|
|
|
|
+ if CurBlock in [DeclNone,declConst,declType,declVar] then
|
|
Scanner.SetTokenOption(toOperatorToken)
|
|
Scanner.SetTokenOption(toOperatorToken)
|
|
else
|
|
else
|
|
Scanner.UnSetTokenOption(toOperatorToken);
|
|
Scanner.UnSetTokenOption(toOperatorToken);
|
|
@@ -4357,6 +4394,8 @@ function TPasParser.ParseGenericTypeDecl(Parent: TPasElement;
|
|
ProcTypeEl: TPasProcedureType;
|
|
ProcTypeEl: TPasProcedureType;
|
|
ProcType: TProcType;
|
|
ProcType: TProcType;
|
|
begin
|
|
begin
|
|
|
|
+ ProcTypeEl:=Nil;
|
|
|
|
+ ProcType:=ptProcedure;
|
|
case CurToken of
|
|
case CurToken of
|
|
tkFunction:
|
|
tkFunction:
|
|
begin
|
|
begin
|
|
@@ -4613,7 +4652,8 @@ begin
|
|
case CurToken of
|
|
case CurToken of
|
|
tkColon: break;
|
|
tkColon: break;
|
|
tkComma: ExpectIdentifier;
|
|
tkComma: ExpectIdentifier;
|
|
- else ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
|
|
|
|
|
|
+ else
|
|
|
|
+ ParseExc(nParserExpectedCommaColon,SParserExpectedCommaColon);
|
|
end;
|
|
end;
|
|
Until (CurToken=tkColon);
|
|
Until (CurToken=tkColon);
|
|
OldForceCaret:=Scanner.SetForceCaret(True);
|
|
OldForceCaret:=Scanner.SetForceCaret(True);
|
|
@@ -5080,8 +5120,13 @@ begin
|
|
begin
|
|
begin
|
|
TPasProcedure(Parent).MessageName:=TPrimitiveExpr(E).Value;
|
|
TPasProcedure(Parent).MessageName:=TPrimitiveExpr(E).Value;
|
|
case E.Kind of
|
|
case E.Kind of
|
|
- pekNumber, pekUnary: TPasProcedure(Parent).Messagetype:=pmtInteger;
|
|
|
|
- pekString: TPasProcedure(Parent).Messagetype:=pmtString;
|
|
|
|
|
|
+ pekNumber, pekUnary:
|
|
|
|
+ TPasProcedure(Parent).Messagetype:=pmtInteger;
|
|
|
|
+ pekString:
|
|
|
|
+ TPasProcedure(Parent).Messagetype:=pmtString;
|
|
|
|
+ pekIdent : ; // unknown at this time
|
|
|
|
+ else
|
|
|
|
+ ParseExc(nInvalidMessageType,SErrInvalidMessageType);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if CurToken<>tkSemicolon then
|
|
if CurToken<>tkSemicolon then
|
|
@@ -5094,6 +5139,8 @@ begin
|
|
if CurToken<>tkSemicolon then
|
|
if CurToken<>tkSemicolon then
|
|
UngetToken;
|
|
UngetToken;
|
|
end;
|
|
end;
|
|
|
|
+ else
|
|
|
|
+ // Do nothing, satisfy compiler
|
|
end; // Case
|
|
end; // Case
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -5222,6 +5269,7 @@ begin
|
|
or (CurModule is TPasProgram))
|
|
or (CurModule is TPasProgram))
|
|
then
|
|
then
|
|
begin
|
|
begin
|
|
|
|
+ OK:=False;
|
|
if Assigned(CurModule.InterfaceSection) then
|
|
if Assigned(CurModule.InterfaceSection) then
|
|
OK:=FindInSection(Parent.Name,CurModule.InterfaceSection)
|
|
OK:=FindInSection(Parent.Name,CurModule.InterfaceSection)
|
|
else if (CurModule is TPasProgram) and Assigned(TPasProgram(CurModule).ProgramSection) then
|
|
else if (CurModule is TPasProgram) and Assigned(TPasProgram(CurModule).ProgramSection) then
|
|
@@ -5256,6 +5304,8 @@ begin
|
|
ParseExc(nParserExpectedColonID,SParserExpectedColonID);
|
|
ParseExc(nParserExpectedColonID,SParserExpectedColonID);
|
|
ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
|
|
ResultEl.ResultType := ParseType(ResultEl,CurSourcePos);
|
|
end;
|
|
end;
|
|
|
|
+ else
|
|
|
|
+ resultEl:=Nil;
|
|
end;
|
|
end;
|
|
if OfObjectPossible then
|
|
if OfObjectPossible then
|
|
begin
|
|
begin
|
|
@@ -5479,6 +5529,7 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
Result := Result + '[';
|
|
Result := Result + '[';
|
|
|
|
+ Param:=Nil;
|
|
Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
|
|
Params:=TParamsExpr(CreateElement(TParamsExpr,'',aParent));
|
|
Params.Kind:=pekArrayParams;
|
|
Params.Kind:=pekArrayParams;
|
|
Params.Value:=Expr;
|
|
Params.Value:=Expr;
|
|
@@ -5531,6 +5582,16 @@ function TPasParser.ParseProperty(Parent: TPasElement; const AName: String;
|
|
until CurToken<>tkComma;
|
|
until CurToken<>tkComma;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+ procedure ConsumeSemi;
|
|
|
|
+ begin
|
|
|
|
+ if (CurToken = tkSemicolon) then
|
|
|
|
+ begin
|
|
|
|
+ NextToken;
|
|
|
|
+ if IsCurTokenHint then
|
|
|
|
+ UngetToken;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
var
|
|
var
|
|
isArray , ok, IsClass: Boolean;
|
|
isArray , ok, IsClass: Boolean;
|
|
ObjKind: TPasObjKind;
|
|
ObjKind: TPasObjKind;
|
|
@@ -5616,7 +5677,7 @@ begin
|
|
end;
|
|
end;
|
|
if CurTokenIsIdentifier('DEFAULT') then
|
|
if CurTokenIsIdentifier('DEFAULT') then
|
|
begin
|
|
begin
|
|
- if not (ObjKind in [okClass]) then
|
|
|
|
|
|
+ if not (ObjKind in [okClass,okClassHelper]) then // FPC allows it in type helpers
|
|
ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['DEFAULT',ObjKindNames[ObjKind]]);
|
|
ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['DEFAULT',ObjKindNames[ObjKind]]);
|
|
if isArray then
|
|
if isArray then
|
|
ParseExc(nParserArrayPropertiesCannotHaveDefaultValue,SParserArrayPropertiesCannotHaveDefaultValue);
|
|
ParseExc(nParserArrayPropertiesCannotHaveDefaultValue,SParserArrayPropertiesCannotHaveDefaultValue);
|
|
@@ -5650,8 +5711,11 @@ begin
|
|
end;
|
|
end;
|
|
// Handle hints
|
|
// Handle hints
|
|
while DoCheckHint(Result) do
|
|
while DoCheckHint(Result) do
|
|
- NextToken;
|
|
|
|
- if Result.Hints=[] then
|
|
|
|
|
|
+ begin
|
|
|
|
+ NextToken; // eat Hint token
|
|
|
|
+ ConsumeSemi; // Now on hint token or semicolon
|
|
|
|
+ end;
|
|
|
|
+// if Result.Hints=[] then
|
|
UngetToken;
|
|
UngetToken;
|
|
end
|
|
end
|
|
else if CurToken=tkend then
|
|
else if CurToken=tkend then
|
|
@@ -5674,6 +5738,10 @@ var
|
|
begin
|
|
begin
|
|
BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
|
|
BeginBlock := TPasImplBeginBlock(CreateElement(TPasImplBeginBlock, '', Parent));
|
|
Parent.Body := BeginBlock;
|
|
Parent.Body := BeginBlock;
|
|
|
|
+ // these can be used in code for typecasts
|
|
|
|
+ Scanner.SetNonToken(tkobjccategory);
|
|
|
|
+ Scanner.SetNonToken(tkobjcprotocol);
|
|
|
|
+ Scanner.SetNonToken(tkobjcclass);
|
|
repeat
|
|
repeat
|
|
NextToken;
|
|
NextToken;
|
|
// writeln('TPasParser.ParseProcBeginBlock ',curtokenstring);
|
|
// writeln('TPasParser.ParseProcBeginBlock ',curtokenstring);
|
|
@@ -5687,6 +5755,10 @@ begin
|
|
ExpectToken(tkend);
|
|
ExpectToken(tkend);
|
|
end;
|
|
end;
|
|
until false;
|
|
until false;
|
|
|
|
+ // A declaration can follow...
|
|
|
|
+ Scanner.UnSetNonToken(tkobjccategory);
|
|
|
|
+ Scanner.UnSetNonToken(tkobjcprotocol);
|
|
|
|
+ Scanner.UnSetNonToken(tkobjcclass);
|
|
Proc:=Parent.Parent as TPasProcedure;
|
|
Proc:=Parent.Parent as TPasProcedure;
|
|
if Proc.GetProcTypeEnum in [ptAnonymousProcedure,ptAnonymousFunction] then
|
|
if Proc.GetProcTypeEnum in [ptAnonymousProcedure,ptAnonymousFunction] then
|
|
NextToken
|
|
NextToken
|
|
@@ -5802,7 +5874,7 @@ var
|
|
begin
|
|
begin
|
|
if CurBlock=Parent then exit(true);
|
|
if CurBlock=Parent then exit(true);
|
|
while CurBlock.CloseOnSemicolon
|
|
while CurBlock.CloseOnSemicolon
|
|
- or (CloseIfs and (CurBlock is TPasImplIfElse)) do
|
|
|
|
|
|
+ or (CloseIfs and (CurBlock is TPasImplIfElse)) do
|
|
if CloseBlock then exit(true);
|
|
if CloseBlock then exit(true);
|
|
Result:=false;
|
|
Result:=false;
|
|
end;
|
|
end;
|
|
@@ -5814,19 +5886,19 @@ var
|
|
if NewImplElement=nil then NewImplElement:=CurBlock;
|
|
if NewImplElement=nil then NewImplElement:=CurBlock;
|
|
end;
|
|
end;
|
|
|
|
|
|
- procedure CheckSemicolon;
|
|
|
|
|
|
+ procedure CheckStatementCanStart;
|
|
var
|
|
var
|
|
t: TToken;
|
|
t: TToken;
|
|
begin
|
|
begin
|
|
- if (CurBlock.Elements.Count=0) then exit;
|
|
|
|
|
|
+ if (CurBlock.Elements.Count=0) then
|
|
|
|
+ exit; // at start of block
|
|
t:=GetPrevToken;
|
|
t:=GetPrevToken;
|
|
- if t in [tkSemicolon,tkColon] then
|
|
|
|
- exit;
|
|
|
|
- if (CurBlock.ClassType=TPasImplIfElse) and (t=tkelse) then
|
|
|
|
|
|
+ if t in [tkSemicolon,tkColon,tkElse,tkotherwise] then
|
|
exit;
|
|
exit;
|
|
{$IFDEF VerbosePasParser}
|
|
{$IFDEF VerbosePasParser}
|
|
writeln('TPasParser.ParseStatement.CheckSemicolon Prev=',GetPrevToken,' Cur=',CurToken,' ',CurBlock.ClassName,' ',CurBlock.Elements.Count,' ',TObject(CurBlock.Elements[0]).ClassName);
|
|
writeln('TPasParser.ParseStatement.CheckSemicolon Prev=',GetPrevToken,' Cur=',CurToken,' ',CurBlock.ClassName,' ',CurBlock.Elements.Count,' ',TObject(CurBlock.Elements[0]).ClassName);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
+ // last statement not complete -> semicolon is missing
|
|
ParseExcTokenError('Semicolon');
|
|
ParseExcTokenError('Semicolon');
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -5860,11 +5932,11 @@ begin
|
|
while True do
|
|
while True do
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
- //WriteLn({$IFDEF VerbosePasParser}i,{$ENDIF}' Token=',CurTokenText);
|
|
|
|
|
|
+ //WriteLn({$IFDEF VerbosePasParser}i,{$ENDIF}' Token=',CurTokenText,' CurBlock=',CurBlock.ClassName);
|
|
case CurToken of
|
|
case CurToken of
|
|
tkasm:
|
|
tkasm:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
El:=TPasImplElement(CreateElement(TPasImplAsmStatement,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplElement(CreateElement(TPasImplAsmStatement,'',CurBlock,CurTokenPos));
|
|
ParseAsmBlock(TPasImplAsmStatement(El));
|
|
ParseAsmBlock(TPasImplAsmStatement(El));
|
|
CurBlock.AddElement(El);
|
|
CurBlock.AddElement(El);
|
|
@@ -5875,98 +5947,85 @@ begin
|
|
end;
|
|
end;
|
|
tkbegin:
|
|
tkbegin:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
El:=TPasImplElement(CreateElement(TPasImplBeginBlock,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplElement(CreateElement(TPasImplBeginBlock,'',CurBlock,CurTokenPos));
|
|
CreateBlock(TPasImplBeginBlock(El));
|
|
CreateBlock(TPasImplBeginBlock(El));
|
|
El:=nil;
|
|
El:=nil;
|
|
end;
|
|
end;
|
|
tkrepeat:
|
|
tkrepeat:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
El:=TPasImplRepeatUntil(CreateElement(TPasImplRepeatUntil,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplRepeatUntil(CreateElement(TPasImplRepeatUntil,'',CurBlock,CurTokenPos));
|
|
CreateBlock(TPasImplRepeatUntil(El));
|
|
CreateBlock(TPasImplRepeatUntil(El));
|
|
El:=nil;
|
|
El:=nil;
|
|
end;
|
|
end;
|
|
tkIf:
|
|
tkIf:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
- SrcPos:=CurTokenPos;
|
|
|
|
- NextToken;
|
|
|
|
- Left:=DoParseExpression(CurBlock);
|
|
|
|
- UngetToken;
|
|
|
|
- El:=TPasImplIfElse(CreateElement(TPasImplIfElse,'',CurBlock,SrcPos));
|
|
|
|
- TPasImplIfElse(El).ConditionExpr:=Left;
|
|
|
|
- Left.Parent:=El;
|
|
|
|
- Left:=nil;
|
|
|
|
- //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
|
|
|
|
- CreateBlock(TPasImplIfElse(El));
|
|
|
|
- El:=nil;
|
|
|
|
- ExpectToken(tkthen);
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
|
|
+ SrcPos:=CurTokenPos;
|
|
|
|
+ NextToken;
|
|
|
|
+ Left:=DoParseExpression(CurBlock);
|
|
|
|
+ UngetToken;
|
|
|
|
+ El:=TPasImplIfElse(CreateElement(TPasImplIfElse,'',CurBlock,SrcPos));
|
|
|
|
+ TPasImplIfElse(El).ConditionExpr:=Left;
|
|
|
|
+ Left.Parent:=El;
|
|
|
|
+ Left:=nil;
|
|
|
|
+ //WriteLn(i,'IF Condition="',Condition,'" Token=',CurTokenText);
|
|
|
|
+ CreateBlock(TPasImplIfElse(El));
|
|
|
|
+ El:=nil;
|
|
|
|
+ ExpectToken(tkthen);
|
|
end;
|
|
end;
|
|
- tkelse:
|
|
|
|
- if (CurBlock is TPasImplIfElse) then
|
|
|
|
- begin
|
|
|
|
- if TPasImplIfElse(CurBlock).IfBranch=nil then
|
|
|
|
- begin
|
|
|
|
- // empty then statement e.g. if condition then else
|
|
|
|
- El:=TPasImplCommand(CreateElement(TPasImplCommand,'', CurBlock,CurTokenPos));
|
|
|
|
- CurBlock.AddElement(El);
|
|
|
|
- El:=nil;
|
|
|
|
- end;
|
|
|
|
- if TPasImplIfElse(CurBlock).ElseBranch<>nil then
|
|
|
|
- begin
|
|
|
|
- // this and the following 3 may solve TPasImplIfElse.AddElement BUG
|
|
|
|
- // ifs without begin end
|
|
|
|
- // if .. then
|
|
|
|
- // if .. then
|
|
|
|
- // else
|
|
|
|
- // else
|
|
|
|
|
|
+ tkelse,tkotherwise:
|
|
|
|
+ // ELSE can close multiple blocks, similar to semicolon
|
|
|
|
+ repeat
|
|
|
|
+ {$IFDEF VerbosePasParser}
|
|
|
|
+ writeln('TPasParser.ParseStatement ELSE CurBlock=',CurBlock.ClassName);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ if CurBlock is TPasImplIfElse then
|
|
|
|
+ begin
|
|
|
|
+ if TPasImplIfElse(CurBlock).IfBranch=nil then
|
|
|
|
+ begin
|
|
|
|
+ // empty THEN statement e.g. if condition then else
|
|
|
|
+ El:=TPasImplCommand(CreateElement(TPasImplCommand,'', CurBlock,CurTokenPos));
|
|
|
|
+ CurBlock.AddElement(El); // this sets TPasImplIfElse(CurBlock).IfBranch:=El
|
|
|
|
+ El:=nil;
|
|
|
|
+ end;
|
|
|
|
+ if (CurToken=tkelse) and (TPasImplIfElse(CurBlock).ElseBranch=nil) then
|
|
|
|
+ break; // add next statement as ElseBranch
|
|
|
|
+ end
|
|
|
|
+ else if (CurBlock is TPasImplTryExcept) and (CurToken=tkelse) then
|
|
|
|
+ begin
|
|
|
|
+ // close TryExcept handler and open an TryExceptElse handler
|
|
CloseBlock;
|
|
CloseBlock;
|
|
- CloseStatement(false);
|
|
|
|
- end;
|
|
|
|
- end else if (CurBlock is TPasImplCaseStatement) then
|
|
|
|
- begin
|
|
|
|
- // Case ... else without semicolon in front.
|
|
|
|
- UngetToken;
|
|
|
|
- CloseStatement(False);
|
|
|
|
- break;
|
|
|
|
- end else if (CurBlock is TPasImplWhileDo) then
|
|
|
|
- begin
|
|
|
|
- CloseBlock;
|
|
|
|
- UngetToken;
|
|
|
|
- end else if (CurBlock is TPasImplForLoop) then
|
|
|
|
- begin
|
|
|
|
- //if .. then for .. do smt else ..
|
|
|
|
- CloseBlock;
|
|
|
|
- UngetToken;
|
|
|
|
- end else if (CurBlock is TPasImplWithDo) then
|
|
|
|
- begin
|
|
|
|
- //if .. then with .. do smt else ..
|
|
|
|
- CloseBlock;
|
|
|
|
- UngetToken;
|
|
|
|
- end else if (CurBlock is TPasImplRaise) then
|
|
|
|
- begin
|
|
|
|
- //if .. then Raise Exception else ..
|
|
|
|
- CloseBlock;
|
|
|
|
- UngetToken;
|
|
|
|
- end else if (CurBlock is TPasImplAsmStatement) then
|
|
|
|
- begin
|
|
|
|
- //if .. then asm end else ..
|
|
|
|
- CloseBlock;
|
|
|
|
- UngetToken;
|
|
|
|
- end else if (CurBlock is TPasImplTryExcept) then
|
|
|
|
- begin
|
|
|
|
|
|
+ El:=TPasImplTryExceptElse(CreateElement(TPasImplTryExceptElse,'',CurBlock,CurTokenPos));
|
|
|
|
+ TPasImplTry(CurBlock).ElseBranch:=TPasImplTryExceptElse(El);
|
|
|
|
+ CurBlock:=TPasImplTryExceptElse(El);
|
|
|
|
+ El:=nil;
|
|
|
|
+ break;
|
|
|
|
+ end
|
|
|
|
+ else if (CurBlock is TPasImplCaseStatement) then
|
|
|
|
+ begin
|
|
|
|
+ UngetToken;
|
|
|
|
+ // Note: a TPasImplCaseStatement is parsed by a call of ParseStatement,
|
|
|
|
+ // so it must be the top level block
|
|
|
|
+ if CurBlock<>Parent then
|
|
|
|
+ CheckToken(tkSemicolon);
|
|
|
|
+ exit;
|
|
|
|
+ end
|
|
|
|
+ else if (CurBlock is TPasImplWhileDo)
|
|
|
|
+ or (CurBlock is TPasImplForLoop)
|
|
|
|
+ or (CurBlock is TPasImplWithDo)
|
|
|
|
+ or (CurBlock is TPasImplRaise)
|
|
|
|
+ or (CurBlock is TPasImplExceptOn) then
|
|
|
|
+ // simply close block
|
|
|
|
+ else
|
|
|
|
+ ParseExcSyntaxError;
|
|
CloseBlock;
|
|
CloseBlock;
|
|
- El:=TPasImplTryExceptElse(CreateElement(TPasImplTryExceptElse,'',CurBlock,CurTokenPos));
|
|
|
|
- TPasImplTry(CurBlock).ElseBranch:=TPasImplTryExceptElse(El);
|
|
|
|
- CurBlock:=TPasImplTryExceptElse(El);
|
|
|
|
- El:=nil;
|
|
|
|
- end else
|
|
|
|
- ParseExcSyntaxError;
|
|
|
|
|
|
+ until false;
|
|
tkwhile:
|
|
tkwhile:
|
|
begin
|
|
begin
|
|
// while Condition do
|
|
// while Condition do
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
SrcPos:=CurTokenPos;
|
|
SrcPos:=CurTokenPos;
|
|
NextToken;
|
|
NextToken;
|
|
Left:=DoParseExpression(CurBlock);
|
|
Left:=DoParseExpression(CurBlock);
|
|
@@ -5982,7 +6041,7 @@ begin
|
|
end;
|
|
end;
|
|
tkgoto:
|
|
tkgoto:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
NextToken;
|
|
NextToken;
|
|
CurBlock.AddCommand('goto '+curtokenstring);
|
|
CurBlock.AddCommand('goto '+curtokenstring);
|
|
// expecttoken(tkSemiColon);
|
|
// expecttoken(tkSemiColon);
|
|
@@ -5991,7 +6050,7 @@ begin
|
|
begin
|
|
begin
|
|
// for VarName := StartValue to EndValue do
|
|
// for VarName := StartValue to EndValue do
|
|
// for VarName in Expression do
|
|
// for VarName in Expression do
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
El:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplForLoop(CreateElement(TPasImplForLoop,'',CurBlock,CurTokenPos));
|
|
ExpectIdentifier;
|
|
ExpectIdentifier;
|
|
Expr:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
|
|
Expr:=CreatePrimitiveExpr(El,pekIdent,CurTokenString);
|
|
@@ -6044,7 +6103,7 @@ begin
|
|
begin
|
|
begin
|
|
// with Expr do
|
|
// with Expr do
|
|
// with Expr, Expr do
|
|
// with Expr, Expr do
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
SrcPos:=CurTokenPos;
|
|
SrcPos:=CurTokenPos;
|
|
NextToken;
|
|
NextToken;
|
|
El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
|
|
El:=TPasImplWithDo(CreateElement(TPasImplWithDo,'',CurBlock,SrcPos));
|
|
@@ -6068,7 +6127,7 @@ begin
|
|
end;
|
|
end;
|
|
tkcase:
|
|
tkcase:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
SrcPos:=CurTokenPos;
|
|
SrcPos:=CurTokenPos;
|
|
NextToken;
|
|
NextToken;
|
|
Left:=DoParseExpression(CurBlock);
|
|
Left:=DoParseExpression(CurBlock);
|
|
@@ -6091,7 +6150,7 @@ begin
|
|
ParseExc(nParserExpectCase,SParserExpectCase);
|
|
ParseExc(nParserExpectCase,SParserExpectCase);
|
|
break; // end without else
|
|
break; // end without else
|
|
end;
|
|
end;
|
|
- tkelse:
|
|
|
|
|
|
+ tkelse,tkotherwise:
|
|
begin
|
|
begin
|
|
// create case-else block
|
|
// create case-else block
|
|
El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock,CurTokenPos));
|
|
@@ -6102,50 +6161,41 @@ begin
|
|
end
|
|
end
|
|
else
|
|
else
|
|
// read case values
|
|
// read case values
|
|
- if (curToken=tkIdentifier) and (LowerCase(CurtokenString)='otherwise') then
|
|
|
|
- begin
|
|
|
|
- // create case-else block
|
|
|
|
- El:=TPasImplCaseElse(CreateElement(TPasImplCaseElse,'',CurBlock,CurTokenPos));
|
|
|
|
- TPasImplCaseOf(CurBlock).ElseBranch:=TPasImplCaseElse(El);
|
|
|
|
- CreateBlock(TPasImplCaseElse(El));
|
|
|
|
- El:=nil;
|
|
|
|
- break;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- repeat
|
|
|
|
- SrcPos:=CurTokenPos;
|
|
|
|
- Left:=DoParseExpression(CurBlock);
|
|
|
|
- //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
|
|
|
|
- if CurBlock is TPasImplCaseStatement then
|
|
|
|
- begin
|
|
|
|
- TPasImplCaseStatement(CurBlock).AddExpression(Left);
|
|
|
|
- Left:=nil;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- El:=TPasImplCaseStatement(CreateElement(TPasImplCaseStatement,'',CurBlock,SrcPos));
|
|
|
|
- TPasImplCaseStatement(El).AddExpression(Left);
|
|
|
|
- Left:=nil;
|
|
|
|
- CreateBlock(TPasImplCaseStatement(El));
|
|
|
|
- El:=nil;
|
|
|
|
- end;
|
|
|
|
- //writeln(i,'CASE after value Token=',CurTokenText);
|
|
|
|
- if (CurToken=tkComma) then
|
|
|
|
- NextToken
|
|
|
|
- else if (CurToken<>tkColon) then
|
|
|
|
- ParseExcTokenError(TokenInfos[tkComma]);
|
|
|
|
- until Curtoken=tkColon;
|
|
|
|
|
|
+ repeat
|
|
|
|
+ SrcPos:=CurTokenPos;
|
|
|
|
+ Left:=DoParseExpression(CurBlock);
|
|
|
|
+ //writeln(i,'CASE value="',Expr,'" Token=',CurTokenText);
|
|
|
|
+ if CurBlock is TPasImplCaseStatement then
|
|
|
|
+ begin
|
|
|
|
+ TPasImplCaseStatement(CurBlock).AddExpression(Left);
|
|
|
|
+ Left:=nil;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ El:=TPasImplCaseStatement(CreateElement(TPasImplCaseStatement,'',CurBlock,SrcPos));
|
|
|
|
+ TPasImplCaseStatement(El).AddExpression(Left);
|
|
|
|
+ Left:=nil;
|
|
|
|
+ CreateBlock(TPasImplCaseStatement(El));
|
|
|
|
+ El:=nil;
|
|
|
|
+ end;
|
|
|
|
+ //writeln(i,'CASE after value Token=',CurTokenText);
|
|
|
|
+ if (CurToken=tkComma) then
|
|
|
|
+ NextToken
|
|
|
|
+ else if (CurToken<>tkColon) then
|
|
|
|
+ ParseExcTokenError(TokenInfos[tkComma]);
|
|
|
|
+ until Curtoken=tkColon;
|
|
// read statement
|
|
// read statement
|
|
ParseStatement(CurBlock,SubBlock);
|
|
ParseStatement(CurBlock,SubBlock);
|
|
|
|
+ // CurToken is now at last token of case-statement
|
|
CloseBlock;
|
|
CloseBlock;
|
|
if CurToken<>tkSemicolon then
|
|
if CurToken<>tkSemicolon then
|
|
- begin
|
|
|
|
NextToken;
|
|
NextToken;
|
|
- if not (CurToken in [tkSemicolon,tkelse,tkend]) then
|
|
|
|
- ParseExcTokenError(TokenInfos[tkSemicolon]);
|
|
|
|
- if CurToken<>tkSemicolon then
|
|
|
|
- UngetToken;
|
|
|
|
- end;
|
|
|
|
|
|
+ if (CurToken in [tkSemicolon,tkelse,tkend,tkotherwise]) then
|
|
|
|
+ // ok
|
|
|
|
+ else
|
|
|
|
+ ParseExcTokenError(TokenInfos[tkSemicolon]);
|
|
|
|
+ if CurToken<>tkSemicolon then
|
|
|
|
+ UngetToken;
|
|
end;
|
|
end;
|
|
until false;
|
|
until false;
|
|
if CurToken=tkend then
|
|
if CurToken=tkend then
|
|
@@ -6156,7 +6206,7 @@ begin
|
|
end;
|
|
end;
|
|
tktry:
|
|
tktry:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
El:=TPasImplTry(CreateElement(TPasImplTry,'',CurBlock,CurTokenPos));
|
|
El:=TPasImplTry(CreateElement(TPasImplTry,'',CurBlock,CurTokenPos));
|
|
CreateBlock(TPasImplTry(El));
|
|
CreateBlock(TPasImplTry(El));
|
|
El:=nil;
|
|
El:=nil;
|
|
@@ -6196,11 +6246,11 @@ begin
|
|
end;
|
|
end;
|
|
tkraise:
|
|
tkraise:
|
|
begin
|
|
begin
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
ImplRaise:=TPasImplRaise(CreateElement(TPasImplRaise,'',CurBlock,CurTokenPos));
|
|
ImplRaise:=TPasImplRaise(CreateElement(TPasImplRaise,'',CurBlock,CurTokenPos));
|
|
CreateBlock(ImplRaise);
|
|
CreateBlock(ImplRaise);
|
|
NextToken;
|
|
NextToken;
|
|
- If Curtoken in [tkElse,tkEnd,tkSemicolon] then
|
|
|
|
|
|
+ If Curtoken in [tkElse,tkEnd,tkSemicolon,tkotherwise] then
|
|
UnGetToken
|
|
UnGetToken
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
@@ -6210,19 +6260,23 @@ begin
|
|
NextToken;
|
|
NextToken;
|
|
ImplRaise.ExceptAddr:=DoParseExpression(ImplRaise);
|
|
ImplRaise.ExceptAddr:=DoParseExpression(ImplRaise);
|
|
end;
|
|
end;
|
|
- if Curtoken in [tkElse,tkEnd,tkSemicolon] then
|
|
|
|
|
|
+ If Curtoken in [tkElse,tkEnd,tkSemicolon,tkotherwise] then
|
|
UngetToken
|
|
UngetToken
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
tkend:
|
|
tkend:
|
|
begin
|
|
begin
|
|
|
|
+ // Note: ParseStatement should return with CurToken at last token of the statement
|
|
if CloseStatement(true) then
|
|
if CloseStatement(true) then
|
|
begin
|
|
begin
|
|
|
|
+ // there was none requiring an END
|
|
UngetToken;
|
|
UngetToken;
|
|
break;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
+ // still a block left
|
|
if CurBlock is TPasImplBeginBlock then
|
|
if CurBlock is TPasImplBeginBlock then
|
|
begin
|
|
begin
|
|
|
|
+ // close at END
|
|
if CloseBlock then break; // close end
|
|
if CloseBlock then break; // close end
|
|
if CloseStatement(false) then break;
|
|
if CloseStatement(false) then break;
|
|
end else if CurBlock is TPasImplCaseElse then
|
|
end else if CurBlock is TPasImplCaseElse then
|
|
@@ -6276,7 +6330,7 @@ begin
|
|
// Do not check this here:
|
|
// Do not check this here:
|
|
// if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
|
|
// if (CurToken=tkAt) and not (msDelphi in CurrentModeswitches) then
|
|
// ParseExc;
|
|
// ParseExc;
|
|
- CheckSemicolon;
|
|
|
|
|
|
+ CheckStatementCanStart;
|
|
|
|
|
|
// On is usable as an identifier
|
|
// On is usable as an identifier
|
|
if lowerCase(CurTokenText)='on' then
|
|
if lowerCase(CurTokenText)='on' then
|
|
@@ -6387,7 +6441,8 @@ var
|
|
begin
|
|
begin
|
|
Labels:=TPasLabels(CreateElement(TPasLabels, '', AParent));
|
|
Labels:=TPasLabels(CreateElement(TPasLabels, '', AParent));
|
|
repeat
|
|
repeat
|
|
- Labels.Labels.Add(ExpectIdentifier);
|
|
|
|
|
|
+ expectTokens([tkIdentifier,tkNumber]);
|
|
|
|
+ Labels.Labels.Add(CurTokenString);
|
|
NextToken;
|
|
NextToken;
|
|
if not (CurToken in [tkSemicolon, tkComma]) then
|
|
if not (CurToken in [tkSemicolon, tkComma]) then
|
|
ParseExcTokenError(TokenInfos[tkSemicolon]);
|
|
ParseExcTokenError(TokenInfos[tkSemicolon]);
|
|
@@ -6398,6 +6453,7 @@ end;
|
|
function TPasParser.GetProcedureClass(ProcType: TProcType): TPTreeElement;
|
|
function TPasParser.GetProcedureClass(ProcType: TProcType): TPTreeElement;
|
|
|
|
|
|
begin
|
|
begin
|
|
|
|
+ Result:=Nil;
|
|
Case ProcType of
|
|
Case ProcType of
|
|
ptFunction : Result:=TPasFunction;
|
|
ptFunction : Result:=TPasFunction;
|
|
ptClassFunction : Result:=TPasClassFunction;
|
|
ptClassFunction : Result:=TPasClassFunction;
|
|
@@ -6615,6 +6671,7 @@ begin
|
|
Case OperatorType of
|
|
Case OperatorType of
|
|
otPositive : OperatorType:=otPlus;
|
|
otPositive : OperatorType:=otPlus;
|
|
otNegative : OperatorType:=otMinus;
|
|
otNegative : OperatorType:=otMinus;
|
|
|
|
+ else
|
|
end;
|
|
end;
|
|
Name:=OperatorNames[OperatorType];
|
|
Name:=OperatorNames[OperatorType];
|
|
TPasOperator(Result).CorrectName;
|
|
TPasOperator(Result).CorrectName;
|
|
@@ -6819,7 +6876,7 @@ begin
|
|
end;
|
|
end;
|
|
tkDestructor:
|
|
tkDestructor:
|
|
ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
|
|
ParseExc(nParserNoConstructorAllowed,SParserNoConstructorAllowed);
|
|
- tkGeneric,tkSelf, // Counts as field name
|
|
|
|
|
|
+ tkabsolute,tkGeneric,tkSelf, // Counts as field name
|
|
tkIdentifier :
|
|
tkIdentifier :
|
|
begin
|
|
begin
|
|
If AllowVisibility and CheckVisibility(CurTokenString,v) then
|
|
If AllowVisibility and CheckVisibility(CurTokenString,v) then
|
|
@@ -7027,6 +7084,7 @@ Var
|
|
T : TPasType;
|
|
T : TPasType;
|
|
Done : Boolean;
|
|
Done : Boolean;
|
|
begin
|
|
begin
|
|
|
|
+ Done:=False;
|
|
//Writeln('Parsing local types');
|
|
//Writeln('Parsing local types');
|
|
while (CurToken=tkSquaredBraceOpen)
|
|
while (CurToken=tkSquaredBraceOpen)
|
|
and (msPrefixedAttributes in CurrentModeswitches) do
|
|
and (msPrefixedAttributes in CurrentModeswitches) do
|
|
@@ -7290,7 +7348,7 @@ begin
|
|
begin
|
|
begin
|
|
case AType.ObjKind of
|
|
case AType.ObjKind of
|
|
okClass,okObject,
|
|
okClass,okObject,
|
|
- okClassHelper,okRecordHelper,okTypeHelper: ;
|
|
|
|
|
|
+ okClassHelper,okRecordHelper,okTypeHelper, okObjCClass, okObjcCategory, okObjcProtocol : ;
|
|
else
|
|
else
|
|
ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CLASS',ObjKindNames[AType.ObjKind]]);
|
|
ParseExc(nParserXNotAllowedInY,SParserXNotAllowedInY,['CLASS',ObjKindNames[AType.ObjKind]]);
|
|
end;
|
|
end;
|
|
@@ -7348,7 +7406,7 @@ begin
|
|
CheckToken(tkend);
|
|
CheckToken(tkend);
|
|
NextToken;
|
|
NextToken;
|
|
AType.AncestorType := ParseTypeReference(AType,false,Expr);
|
|
AType.AncestorType := ParseTypeReference(AType,false,Expr);
|
|
- if AType.ObjKind=okClass then
|
|
|
|
|
|
+ if AType.ObjKind in [okClass,okObjCClass] then
|
|
while CurToken=tkComma do
|
|
while CurToken=tkComma do
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
@@ -7381,17 +7439,27 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure TPasParser.DoParseClassExternalHeader(AObjKind: TPasObjKind; out
|
|
|
|
- AExternalNameSpace, AExternalName: string);
|
|
|
|
|
|
+function TPasParser.DoParseClassExternalHeader(AObjKind: TPasObjKind; out AExternalNameSpace, AExternalName: string): Boolean;
|
|
begin
|
|
begin
|
|
- if ((AObjKind in [okClass,okInterface]) and (msExternalClass in CurrentModeswitches)
|
|
|
|
- and CurTokenIsIdentifier('external')) then
|
|
|
|
|
|
+ Result:=False;
|
|
|
|
+ if ((aObjKind in [okObjcCategory,okObjcClass]) or
|
|
|
|
+ ((AObjKind in [okClass,okInterface]) and (msExternalClass in CurrentModeswitches)))
|
|
|
|
+ and CurTokenIsIdentifier('external') then
|
|
begin
|
|
begin
|
|
|
|
+ Result:=True;
|
|
NextToken;
|
|
NextToken;
|
|
if CurToken<>tkString then
|
|
if CurToken<>tkString then
|
|
UnGetToken
|
|
UnGetToken
|
|
else
|
|
else
|
|
AExternalNameSpace:=CurTokenString;
|
|
AExternalNameSpace:=CurTokenString;
|
|
|
|
+ if (aObjKind in [okObjcCategory,okObjcClass]) then
|
|
|
|
+ begin
|
|
|
|
+ // Name is optional in objcclass/category
|
|
|
|
+ NextToken;
|
|
|
|
+ if CurToken=tkBraceOpen then
|
|
|
|
+ exit;
|
|
|
|
+ UnGetToken;
|
|
|
|
+ end;
|
|
ExpectIdentifier;
|
|
ExpectIdentifier;
|
|
If Not CurTokenIsIdentifier('Name') then
|
|
If Not CurTokenIsIdentifier('Name') then
|
|
ParseExc(nParserExpectedExternalClassName,SParserExpectedExternalClassName);
|
|
ParseExc(nParserExpectedExternalClassName,SParserExpectedExternalClassName);
|
|
@@ -7472,9 +7540,10 @@ function TPasParser.ParseClassDecl(Parent: TPasElement;
|
|
AObjKind: TPasObjKind; PackMode: TPackMode): TPasType;
|
|
AObjKind: TPasObjKind; PackMode: TPackMode): TPasType;
|
|
|
|
|
|
Var
|
|
Var
|
|
- ok: Boolean;
|
|
|
|
|
|
+ isExternal,ok: Boolean;
|
|
AExternalNameSpace,AExternalName : String;
|
|
AExternalNameSpace,AExternalName : String;
|
|
PCT:TPasClassType;
|
|
PCT:TPasClassType;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
NextToken;
|
|
NextToken;
|
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
|
if (AObjKind = okClass) and (CurToken = tkOf) then
|
|
@@ -7494,7 +7563,7 @@ begin
|
|
end;
|
|
end;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
- DoParseClassExternalHeader(AObjKind,AExternalNameSpace,AExternalName);
|
|
|
|
|
|
+ isExternal:=DoParseClassExternalHeader(AObjKind,AExternalNameSpace,AExternalName);
|
|
if AObjKind in okAllHelpers then
|
|
if AObjKind in okAllHelpers then
|
|
begin
|
|
begin
|
|
if not CurTokenIsIdentifier('Helper') then
|
|
if not CurTokenIsIdentifier('Helper') then
|
|
@@ -7507,7 +7576,7 @@ begin
|
|
ok:=false;
|
|
ok:=false;
|
|
try
|
|
try
|
|
PCT.HelperForType:=nil;
|
|
PCT.HelperForType:=nil;
|
|
- PCT.IsExternal:=(AExternalName<>'');
|
|
|
|
|
|
+ PCT.IsExternal:=IsExternal;
|
|
if AExternalName<>'' then
|
|
if AExternalName<>'' then
|
|
PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
|
|
PCT.ExternalName:={$ifdef pas2js}DeQuoteString{$else}AnsiDequotedStr{$endif}(AExternalName,'''');
|
|
if AExternalNameSpace<>'' then
|
|
if AExternalNameSpace<>'' then
|