浏览代码

* Applied patches by Vincent Snijders
* Fixed handling of nested variant records
* Improved operator support (<= and >= were missing)
* Operator support in output: Better names
* HTML writer generates working filenames for operator pages

git-svn-id: trunk@849 -

sg 20 年之前
父节点
当前提交
1a8051f993
共有 4 个文件被更改,包括 127 次插入25 次删除
  1. 37 12
      fcl/passrc/pparser.pp
  2. 25 3
      fcl/passrc/pscanner.pp
  3. 1 0
      utils/fpdoc/dglobals.pp
  4. 64 10
      utils/fpdoc/dw_html.pp

+ 37 - 12
fcl/passrc/pparser.pp

@@ -85,7 +85,7 @@ uses Classes;
 
 type
 
-  TDeclType = (declNone, declConst, declResourcestring, declType, declVar);
+  TDeclType = (declNone, declConst, declResourcestring, declType, declVar, declThreadvar);
 
   TProcType = (ptProcedure, ptFunction, ptOperator);
 
@@ -703,6 +703,8 @@ begin
         CurBlock := declType;
       tkVar:
         CurBlock := declVar;
+      tkThreadVar:
+        CurBlock := declThreadVar;
       tkProcedure:
         begin
           AddProcOrFunction(Section, ParseProcedureOrFunctionDecl(Section, ptProcedure));
@@ -770,7 +772,7 @@ begin
                     Section.Types.Add(TypeEl);
                 end;
               end;
-            declVar:
+            declVar, declThreadVar:
               begin
                 List := TList.Create;
                 try
@@ -1369,8 +1371,7 @@ begin
       begin
 	ParseArgList(Element, Element.Args, tkBraceClose);
 	TPasFunctionType(Element).ResultEl.Name := ExpectIdentifier;
-	if CurToken <> tkColon then
-	  ParseExc(SParserExpectedLBracketColon);
+        ExpectToken(tkColon);
 	if Assigned(Element) then        // !!!
 	  TPasFunctionType(Element).ResultEl.ResultType := ParseType(Parent)
 	else
@@ -1387,7 +1388,8 @@ begin
     UngetToken;
 
   NextToken;
-  if CurToken = tkEqual then begin
+  if CurToken = tkEqual then
+  begin
     // for example: const p: procedure = nil;
     UngetToken;
     exit;
@@ -1407,6 +1409,10 @@ begin
     begin
 {      El['calling-conv'] := 'stdcall';}
       ExpectToken(tkSemicolon);
+    end else if (CurToken = tkInline) then
+    begin
+{      TPasProcedure(Parent).IsInline := True;}
+      ExpectToken(tkSemicolon);
     end else if (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'DEPRECATED') then
     begin
 {      El['calling-conv'] := 'cdecl';}
@@ -1416,6 +1422,12 @@ begin
       repeat
         NextToken
       until CurToken = tkSemicolon;
+    end else if (CurToken = tkSquaredBraceOpen) then
+    begin
+      repeat
+        NextToken
+      until CurToken = tkSquaredBraceClose;
+      ExpectToken(tkSemicolon);
     end else if Parent.InheritsFrom(TPasProcedure) and
       (CurToken = tkIdentifier) and (UpperCase(CurTokenString) = 'OVERLOAD') then
     begin
@@ -1554,6 +1566,7 @@ function TPasParser.ParseProcedureOrFunctionDecl(Parent: TPasElement;
   ProcType: TProcType): TPasProcedure;
 var
   Name: String;
+  i: Integer;
 begin
   case ProcType of
     ptFunction:
@@ -1572,7 +1585,8 @@ begin
       end;
     ptOperator:
       begin
-        Name := TokenInfos[CurToken];
+        NextToken;
+        Name := 'operator ' + TokenInfos[CurToken];
 	Result := TPasOperator(CreateElement(TPasOperator, Name, Parent));
 	Result.ProcType := Engine.CreateFunctionType('', '__INVALID__', Result,
 	  True, Scanner.CurFilename, Scanner.CurRow);
@@ -1580,6 +1594,20 @@ begin
   end;
 
   ParseProcedureOrFunctionHeader(Result, Result.ProcType, ProcType, False);
+
+  if ProcType = ptOperator then
+  begin
+    Result.Name := Result.Name + '(';
+    for i := 0 to Result.ProcType.Args.Count - 1 do
+    begin
+      if i > 0 then
+        Result.Name := Result.Name + ', ';
+      Result.Name := Result.Name +
+        TPasArgument(Result.ProcType.Args[i]).ArgType.Name;
+    end;
+    Result.Name := Result.Name + '): ' +
+      TPasFunctionType(Result.ProcType).ResultEl.ResultType.Name;
+  end;
 end;
 
 
@@ -1646,9 +1674,10 @@ begin
 	  Variant.Members.Free;
 	  raise;
 	end;
-	ExpectToken(tkSemicolon);
 	NextToken;
-	if CurToken = tkEnd then
+	if CurToken = tkSemicolon then
+	  NextToken;
+	if (CurToken = tkEnd) or (CurToken = tkBraceClose) then
 	  break
 	else
 	  UngetToken;
@@ -1817,10 +1846,6 @@ begin
                 VarList := TList.Create;
                 try
                   ParseInlineVarDecl(Result, VarList, CurVisibility, False);
-	          NextToken;
-	          // Records may be terminated with end, no semicolon
-		  if (CurToken <> tkEnd) and (CurToken <> tkSemicolon) then
-		    ParseExc(SParserExpectedSemiColonEnd);
                   for i := 0 to VarList.Count - 1 do
                   begin
                     Element := TPasElement(VarList[i]);

+ 25 - 3
fcl/passrc/pscanner.pp

@@ -61,6 +61,9 @@ type
     tkDotDot,           // '..'
     tkAssign,           // ':='
     tkNotEqual,         // '<>'
+    tkLessEqualThan,	// '<='
+    tkGreaterEqualThan,	// '>='
+    tkPower,            // '**'
     // Reserved words
     tkabsolute,
     tkand,
@@ -118,6 +121,7 @@ type
     tkshr,
 //    tkstring,
     tkthen,
+    tkthreadvar,
     tkto,
     tktrue,
     tktry,
@@ -241,6 +245,9 @@ const
     '..',
     ':=',
     '<>',
+    '<=',
+    '>=',
+    '**',
     // Reserved words
     'absolute',
     'and',
@@ -298,6 +305,7 @@ const
     'shr',
 //    'string',
     'then',
+    'threadvar',
     'to',
     'true',
     'try',
@@ -658,7 +666,12 @@ begin
     '*':
       begin
         Inc(TokenStr);
-        Result := tkMul;
+        if TokenStr[0] = '*' then
+        begin
+          Inc(TokenStr);
+          Result := tkPower;
+        end else
+          Result := tkMul;
       end;
     '+':
       begin
@@ -764,7 +777,11 @@ begin
         begin
           Inc(TokenStr);
           Result := tkNotEqual;
-        end else
+        end else if TokenStr[0] = '=' then
+	begin
+	  Inc(TokenStr);
+	  Result := tkLessEqualThan;
+	end else
           Result := tkLessThan;
       end;
     '=':
@@ -775,7 +792,12 @@ begin
     '>':
       begin
         Inc(TokenStr);
-        Result := tkGreaterThan;
+	if TokenStr[0] = '=' then
+	begin
+	  Inc(TokenStr);
+	  Result := tkGreaterEqualThan;
+	end else
+	  Result := tkGreaterThan;
       end;
     '@':
       begin

+ 1 - 0
utils/fpdoc/dglobals.pp

@@ -131,6 +131,7 @@ resourcestring
   SNeedPackageName            = 'No package name specified. Please specify one using the --package option.';
   SDone                       = 'Done.';
   SErrCouldNotCreateOutputDir = 'Could not create output directory "%s"';
+  SErrCouldNotCreateFile      = 'Could not create file "%s": %s';
 
 Const
   SVisibility: array[TPasMemberVisibility] of string =

+ 64 - 10
utils/fpdoc/dw_html.pp

@@ -302,6 +302,7 @@ end;
 function TLongNameFileAllocator.GetFilename(AElement: TPasElement;
   ASubindex: Integer): String;
 var
+  s: String;
   i: Integer;
 begin
   if AElement.ClassType = TPasPackage then
@@ -309,20 +310,68 @@ begin
   else if AElement.ClassType = TPasModule then
     Result := LowerCase(AElement.Name) + PathDelim + 'index'
   else
+  begin
+    if AElement is TPasOperator then
     begin
-    Result := LowerCase(AElement.PathName);
-    i := 1;
-    if (Length(Result)>0) and (Result[1]='#') then
+      Result := LowerCase(AElement.Parent.PathName) + '.op-';
+      s := Copy(AElement.Name, Pos(' ', AElement.Name) + 1, Length(AElement.Name));
+      s := Copy(s, 1, Pos('(', s) - 1);
+      if s = ':=' then
+        s := 'assign'
+      else if s = '+' then
+        s := 'add'
+      else if s = '-' then
+        s := 'sub'
+      else if s = '*' then
+        s := 'mul'
+      else if s = '/' then
+        s := 'div'
+      else if s = '**' then
+        s := 'power'
+      else if s = '=' then
+        s := 'equal'
+      else if s = '<>' then
+        s := 'unequal'
+      else if s = '<' then
+        s := 'less'
+      else if s = '<=' then
+        s := 'lessequal'
+      else if s = '>' then
+        s := 'greater'
+      else if s = '>=' then
+        s := 'greaterthan';
+      Result := Result + s + '-';
+      s := '';
+      i := 1;
+      while AElement.Name[i] <> '(' do
+        Inc(i);
+      Inc(i);
+      while AElement.Name[i] <> ')' do
       begin
-      while Result[i] <> '.' do
+        if AElement.Name[i] = ',' then
+	begin
+	  s := s + '-';
+	  Inc(i);
+	end else
+	  s := s + AElement.Name[i];
         Inc(i);
-      Result:=Copy(Result,i+1,Length(Result));
       end;
+      Result := Result + LowerCase(s) + '-' + LowerCase(Copy(AElement.Name,
+        Pos('):', AElement.Name) + 3, Length(AElement.Name)));
+    end else
+      Result := LowerCase(AElement.PathName);
     i := 1;
-    while (I<=Length(Result)) and (Result[i]<>'.') do
+    if (Length(Result) > 0) and (Result[1] = '#') then
+    begin
+      while Result[i] <> '.' do
+        Inc(i);
+      Result := Copy(Result, i + 1, Length(Result));
+    end;
+    i := 1;
+    while (i <= Length(Result)) and (Result[i] <> '.') do
       Inc(i);
-    If (I<=Length(Result)) and (I>0) then
-      Result[i]:= PathDelim;
+    if (i <= Length(Result)) and (i > 0) then
+      Result[i] := PathDelim;
   end;
 
   if ASubindex > 0 then
@@ -610,8 +659,13 @@ begin
       PageDoc := CreateHTMLPage(Element, SubpageIndex);
       try
         Filename := Engine.Output + Allocator.GetFilename(Element, SubpageIndex);
-        CreatePath(Filename);
-        WriteHTMLFile(PageDoc, Filename);
+        try
+          CreatePath(Filename);
+          WriteHTMLFile(PageDoc, Filename);
+        except
+	  on E: Exception do
+            WriteLn(Format(SErrCouldNotCreateFile, [FileName, e.Message]));
+        end;
       finally
         PageDoc.Free;
       end;