⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ucodeparser.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:
         //will nevertheless return a TMyForm-object. So the original type
         //needs to be saved, so MyDlgResult can be be found (it wouldn't in
         //TCustomForm).
         ConstructType     :TRecordType;




         //are we parsing an identifier-path (identifiers
         InIdentPath       :(                     //separated by dots etc.)

                             iipNo,     //no, we don't
                             iipIdent,  //yes, we just read an identifier
                             iipDot     //yes, we just read a dot
                            );
         //are brackets [] possible, i.e. indexing (an array)?
         BracketsPossible  :Boolean;
         //is this a message-handler and it has to be taken in account
         IsMessageMethod   :Boolean;         //if "inherited" is found

         PointerOperator   :Boolean;         //if an "@" has been found
begin
 if Token = '' then         //if first token not read yet
  if not GetToken(Token) then //read the first token
   Exception(etSyntax, 'No expression before end of file!');

// if IsWordIn(Token, EndOfExpressions, Index) or
//    ((length(Token) = 1) and (Token[1] in [';', ',', ':', ')', ']'])) or
//    (Token = ':=') then
//  Exception(etSyntax, 'Empty Expression!');


 TypeIdent := nil;          //no identifiers so far
 TypeCast := False;         //not a type itself specified so far
 TheFile := nil;            //and no file as part of an identifier
 InIdentPath := iipNo;      //not parsing an identifier at the moment
 BracketsPossible := False; //nothing found, after that brackets [] can follow
 PointerOperator := False;  //no "@" found so far

 //as long as no keyword or character ending the expression (or the statement)
 //or a closing brace/bracket found
 while ((InIdentPath = iipDot) or
        not IsWordIn(Token, EndOfExpressions, Index) or
        (not StopAtIn and (Index = EndOfExpressionsIn))) and
       ((length(Token) <> 1) or
        not (Token[1] in [';', ',', ':', ')', ']'])) and
       (Token <> ':=') do
  begin


   //found an identifier? (this includes "inherited")
   if (Token <> '') and (Token[1] in StartIdentifierChars) and
      ((InIdentPath = iipDot) or
       (not IsWordIn(Token, Operators, Index) or
        //"at" can be an operator instead of an identifier after "raise"
        ((Index = OperatorAt) and
         //if it follows directly after another identifier treat it as operator
         (InIdentPath <> iipIdent)))) then
    begin
     if InIdentPath = iipIdent then
      ExceptionFmt(etSyntax,
                   'Found identifier "%s" directly after another identifier!',
                   [Token]);


     ConstructType := FFunctionParseSelf;    //assume Self as type
     if InIdentPath = iipDot then  //found a "." before?
      begin

       if LowerCase(Token) = 'inherited' then
        Exception(etSyntax, 'Found inherited after ".", expected identifier!');

       if assigned(TypeIdent) then //type before the "." is known?
        begin
         if not (TypeIdent is TRecordType) then
          ExceptionFmt(etSyntax,
                       '"%s" is not record-like, so ".%s" can''t be found in it!',
                       [TypeIdent.Name, Token]);

         ConstructType := TRecordType(TypeIdent); //save the type

         //try to find the identifier in this type
         Ident := ConstructType.FindMember(Token, FThisFile,
                                        (ConstructType = FFunctionParseSelf) or
                                        (ConstructType.InFile = FThisFile));
        end
       else
        if assigned(TheFile) then  //was it a name of a file before the "."?
         Ident := TheFile.Idents.GetIdentByName(Token) //use identifier in it
        else
         Ident := nil;                        //identifier unknown, like before
       TheFile := nil;                      //not a file anymore

       if not assigned(Ident) then          //identifier unknown?
        AddToUnknownIdents(Token, '.')        //add to list
       else
        //add to list of global identifiers
        AddToGlobalList(Ident);
      end //if InIdentPath = iipDot

     else  //new identifier-path  (no "." before it)

      begin
       assert(not assigned(TheFile));

       if LowerCase(Token) = 'inherited' then  //use of "inherited" identifier?
        begin
         if not assigned(FFunctionParseSelf) then
          Exception(etSyntax, 'Using of "inherited" not in a method!');

         PushPosition;
         if not GetToken(Token) then           //get next token, the identifier
          Exception(etSyntax,
                    'Unexpected end of file in expression after "inherited"!');

         //identifier follows?
         if not IsWordIn(Token, EndOfExpressions, Index) and
            ((length(Token) <> 1) or
             ((Token[1] <> ';') and (Token[1] <> ',') and
              (Token[1] <> ':') and (Token[1] <> ')') and
              (Token[1] <> ']'))) and
            (Token <> ':=') then
          begin
           LosePosition;                  //use this token
           IsMessageMethod := False;      //if not found, add to unknown-list
          end
         else //no identifier: shortcut for calling same inherited function
          begin
           PopPosition;                           //push token back

           assert(assigned(FTopLevelFunctionNS));

           Token := FTopLevelFunctionNS.FuncIdent.Name;
           //save if it is a message-handler, in that case it's possible, that
           //there is no inherited function of the same name
           IsMessageMethod := faMessage in
                              FTopLevelFunctionNS.FuncIdent.Attributes;
          end;

         ConstructType := ConstructType.GetParent; //get parent class
         if assigned(ConstructType) then           //parent class known?
          begin
           //search inherited identifier in parent-class
           Ident := ConstructType.FindMember(Token, FThisFile, True);

           if not assigned(Ident) then   //inherited identifier not found
            begin
             if not IsMessageMethod then   //add to list of unknown identifiers
              AddToUnknownIdents(Token, 'inherited ' +
                                        FFunctionParseSelf.Name + '.');
            end
           else //add to list of used global identifiers
            AddToGlobalList(Ident);
           ConstructType := FFunctionParseSelf;  //in case it was a constructor
          end
         else //no parent-class known
          begin
           Ident := nil;                   //identifier not known
           if not IsMessageMethod then     //add to list of unknown identifiers
            AddToUnknownIdents(Token, 'inherited ' +
                                      FFunctionParseSelf.Name + '.');
          end;
        end //if Token = 'inherited'
       else
        begin
         //try to find the identifier
         Ident := FCurrentNameSpace.FindIdent(Token, TheFile);

         if assigned(Ident) then
          //add to list of used global identifiers
          AddToGlobalList(Ident);

         if not assigned(Ident) and not assigned(TheFile) then
          AddToUnknownIdents(Token);   //add to list of unknown identifiers
        end; //else Token = 'inherited'

      end; //else InIdentPath = iipDot

     if Ident is TFunction then //if it is an function
      //add the function-identifier to list of called functions
      AddToCalledList(TFunction(Ident));

     if (Ident is TFunction) and            //if it is a constructor
        (TFunction(Ident).FuncKind = fkConstructor) and
        assigned(ConstructType) and
        not assigned(TFunction(Ident).ReturnType) then
      TypeIdent := ConstructType              //use the original (class) type
     else
      TypeIdent := GetType(Ident);            //use type of identifier

     TypeCast := Ident is TType;            //a type itself specified?

     InIdentPath := iipIdent;               //we just read an identifier
     BracketsPossible := False;             //brackets [] are possible after it
    end //if Token is an Identifier
   else
    //Token is (, [, ., or ^?
    if (length(Token) = 1) and (Token[1] in ['(', '[', '.', '^']) then
     case Token[1] of
       '.':    begin
                if InIdentPath <> iipIdent then
                 Exception(etSyntax,
                           'Found "." without identifier before it!');
                //auto-dereference pointers
                if TypeIdent is TPointerType then
                 TypeIdent := GetType(TPointerType(TypeIdent).BaseType);
                //for class-variables use the base class
                if TypeIdent is TClassReferenceType then
                 TypeIdent := GetType(TClassReferenceType(TypeIdent).
                                                                   BaseClass);
                if not (TypeIdent is TRecordType) and
                   assigned(TypeIdent) then
                 begin
                  WarningMessage(etSyntax,
                                 'Found "." without record-like-identifier before it (Variant?)!');
                  TypeIdent := nil;
                 end;

                InIdentPath := iipDot;   //another identifier will be expected
                BracketsPossible := False; //brackets [] can't follow a "."
               end; //case Token = '.'

       '(':    begin
                //braces are not allowed directly after a dot
                if InIdentPath = iipDot then
                 Exception(etSyntax,
                           'Found "(" after ".", expected identifier!');

                TheFile := nil;              //not a file anymore

                if InIdentPath = iipNo then  //no identifier before this?
                 begin
                  //parse sub-expression between braces
                  if ParseExpression('', @TypeIdent) <> ')' then
                   Exception(etSyntax,
                             'Expected ")" after "(" without identifier before it, failed!');
                  //use the calculated identifier (if found) as
                  InIdentPath := iipIdent;     //current identifier
                  TypeCast := False;           //type not in braces for casts
                 end
                else
                 begin
                  //parse everything between the braces
                  repeat
                    Token := ParseExpression(''); //parse each expression
                  until
                        //parameter-list of a function-call
                        (Token <> ',') and
                        //Write[Ln], Str: width of parameter
                        (Token <> ':') and
                        //record-constants?
//                        (Token <> ';') and
                        //named parameters (automation objects)
                        (Token <> ':=');

                  if Token <> ')' then
                   Exception(etSyntax, 'Expected ")" after "(", failed!');


                  if TypeCast and assigned(TypeIdent) then
                   //increment statistic
                   FThisFile.Statistic.Increment(psfTypeCastsKnown);

                 end;
                //brackets [] can't follow; or it's a type for
                BracketsPossible := False;              //which it's valid
               end; //case Token = '('
       '[':    if InIdentPath = iipNo then //no identifier before it?
                begin
                 //it seems to be a set-constructor or a constant array
                 repeat
                   Token := ParseExpression(''); //parse each item/range
                 until Token <> ',';             //separated by comma
                 if Token <> ']' then
                  Exception(etSyntax, 'Expected "]" after "[", failed!');
                 BracketsPossible := False;      //no brackets after a set
                 TheFile := nil;                 //not a file anymore
                 TypeCast := False;              //not a type itself specified
                end
               else
                begin
                 //brackets are not allowed directly after a dot
                 if InIdentPath = iipDot then
                  Exception(etSyntax,
                            'Found "[" after ".", expected identifier!');

                 TheFile := nil;                    //not a file anymore

                 if TypeIdent is TPointerType then //auto-dereference pointers
                  TypeIdent := GetType(TPointerType(TypeIdent).BaseType);
//                  BracketsPossible := True;       //PChar is an "array"

                 if TypeIdent is TRecordType then  //an object?
                  begin                              //get default-property
                   Ident := TRecordType(TypeIdent).GetDefaultProperty;
                   TypeIdent := GetType(Ident);
                   if TypeIdent is TPointerType then //dereference pointers
                    TypeIdent := GetType(TPointerType(TypeIdent).BaseType);
                  end;

                 //no brackets allowed?
                 if not (TypeIdent is TArrayType) and
                    not BracketsPossible
                    and assigned(TypeIdent) then
                  begin
                   if not (TypeIdent is TStringType) then //not after string?
                    WarningMessage(etSyntax,
                                   'Found "[" without array-identifier before it (PChar?)!');

                   //type would be char, but simple types don't matter
                   TypeIdent := nil;
                  end;

                 repeat
                   Token := ParseExpression('');  //parse all indizes
                 until Token <> ',';              //separated by comma
                 if Token <> ']' then
                  Exception(etSyntax, 'Expected "]" after "[", failed!');

                 BracketsPossible := True;   //in case it is multi-dimensional
                 while TypeIdent is TArrayType do    //get base-type of array
                  TypeIdent := GetType(TArrayType(TypeIdent).BaseType);
                 TypeCast := False;              //not a type itself specified
                end; //case Token = '['
       '^':    begin
                if InIdentPath = iipDot then     //dereferencing only of idents
                 Exception(etSyntax, 'Found "^" after "."!')
   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -