Browse Source

fcl-passrc: parser: check semicolon after if then

git-svn-id: trunk@38061 -
Mattias Gaertner 7 years ago
parent
commit
517e2e3218
2 changed files with 42 additions and 23 deletions
  1. 14 10
      packages/fcl-passrc/src/pparser.pp
  2. 28 13
      packages/fcl-passrc/tests/tcresolver.pas

+ 14 - 10
packages/fcl-passrc/src/pparser.pp

@@ -4956,15 +4956,19 @@ var
   end;
   end;
 
 
   procedure CheckSemicolon;
   procedure CheckSemicolon;
+  var
+    t: TToken;
   begin
   begin
-    if (CurBlock.Elements.Count>0) and not (GetPrevToken in [tkSemicolon,tkColon])
-        and (CurBlock.ClassType<>TPasImplIfElse) then
-      begin
-      {$IFDEF VerbosePasParser}
-      writeln('TPasParser.ParseStatement.CheckSemicolon Prev=',GetPrevToken,' Cur=',CurToken,' ',CurBlock.ClassName,' ',CurBlock.Elements.Count,' ',TObject(CurBlock.Elements[0]).ClassName);
-      {$ENDIF}
-      ParseExcTokenError('Semicolon');
-      end;
+    if (CurBlock.Elements.Count=0) then exit;
+    t:=GetPrevToken;
+    if t in [tkSemicolon,tkColon] then
+      exit;
+    if (CurBlock.ClassType=TPasImplIfElse) and (t=tkelse) then
+      exit;
+    {$IFDEF VerbosePasParser}
+    writeln('TPasParser.ParseStatement.CheckSemicolon Prev=',GetPrevToken,' Cur=',CurToken,' ',CurBlock.ClassName,' ',CurBlock.Elements.Count,' ',TObject(CurBlock.Elements[0]).ClassName);
+    {$ENDIF}
+    ParseExcTokenError('Semicolon');
   end;
   end;
 
 
 var
 var
@@ -4994,7 +4998,7 @@ 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);
     case CurToken of
     case CurToken of
     tkasm:
     tkasm:
       begin
       begin
@@ -5440,7 +5444,7 @@ begin
             // assign statement
             // assign statement
             Ak:=TokenToAssignKind(CurToken);
             Ak:=TokenToAssignKind(CurToken);
             NextToken;
             NextToken;
-            right:=DoParseExpression(CurBlock); // this may solve TPasImplWhileDo.AddElement BUG
+            right:=DoParseExpression(CurBlock);
             El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock,SrcPos));
             El:=TPasImplAssign(CreateElement(TPasImplAssign,'',CurBlock,SrcPos));
             left.Parent:=El;
             left.Parent:=El;
             right.Parent:=El;
             right.Parent:=El;

+ 28 - 13
packages/fcl-passrc/tests/tcresolver.pas

@@ -317,6 +317,7 @@ type
     Procedure TestRepeatUntilNonBoolFail;
     Procedure TestRepeatUntilNonBoolFail;
     Procedure TestWhileDoNonBoolFail;
     Procedure TestWhileDoNonBoolFail;
     Procedure TestIfThenNonBoolFail;
     Procedure TestIfThenNonBoolFail;
+    Procedure TestIfAssignMissingSemicolonFail;
     Procedure TestForLoopVarNonVarFail;
     Procedure TestForLoopVarNonVarFail;
     Procedure TestForLoopStartIncompFail;
     Procedure TestForLoopStartIncompFail;
     Procedure TestForLoopEndIncompFail;
     Procedure TestForLoopEndIncompFail;
@@ -4227,19 +4228,21 @@ end;
 procedure TTestResolver.TestStatements;
 procedure TTestResolver.TestStatements;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
-  Add('var');
-  Add('  v1,v2,v3:longint;');
-  Add('begin');
-  Add('  v1:=1;');
-  Add('  v2:=v1+v1*v1+v1 div v1;');
-  Add('  v3:=-v1;');
-  Add('  repeat');
-  Add('    v1:=v1+1;');
-  Add('  until v1>=5;');
-  Add('  while v1>=0 do');
-  Add('    v1:=v1-v2;');
-  Add('  for v1:=v2 to v3 do v2:=v1;');
-  Add('  if v1<v2 then v3:=v1 else v3:=v2;');
+  Add([
+  'var',
+  '  v1,v2,v3:longint;',
+  'begin',
+  '  v1:=1;',
+  '  v2:=v1+v1*v1+v1 div v1;',
+  '  v3:=-v1;',
+  '  repeat',
+  '    v1:=v1+1;',
+  '  until v1>=5;',
+  '  while v1>=0 do',
+  '    v1:=v1-v2;',
+  '  for v1:=v2 to v3 do v2:=v1;',
+  '  if v1<v2 then v3:=v1 else v3:=v2;',
+  '']);
   ParseProgram;
   ParseProgram;
   AssertEquals('3 declarations',3,PasProgram.ProgramSection.Declarations.Count);
   AssertEquals('3 declarations',3,PasProgram.ProgramSection.Declarations.Count);
 end;
 end;
@@ -4450,6 +4453,18 @@ begin
   CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
   CheckResolverException('Boolean expected, but Longint found',nXExpectedButYFound);
 end;
 end;
 
 
+procedure TTestResolver.TestIfAssignMissingSemicolonFail;
+begin
+  StartProgram(false);
+  Add([
+  'var',
+  '  v:longint;',
+  'begin',
+  '  if true then v:=1',
+  '  v:=2']);
+  CheckParserException('Expected "Semicolon"',nParserExpectTokenError);
+end;
+
 procedure TTestResolver.TestForLoopVarNonVarFail;
 procedure TTestResolver.TestForLoopVarNonVarFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);