Blame src/declinfo.l

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * 
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
 * documentation under the terms of the GNU General Public License is hereby 
Packit 1c1d7e
 * granted. No representations are made about the suitability of this software 
Packit 1c1d7e
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
 * See the GNU General Public License for more details.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Documents produced by Doxygen are derivative works derived from the
Packit 1c1d7e
 * input used in their production; they are not affected by this license.
Packit 1c1d7e
 *
Packit 1c1d7e
 */
Packit 1c1d7e
%option never-interactive
Packit 1c1d7e
%option prefix="declinfoYY"
Packit 1c1d7e
Packit 1c1d7e
%{
Packit 1c1d7e
Packit 1c1d7e
/*
Packit 1c1d7e
 *	includes
Packit 1c1d7e
 */
Packit 1c1d7e
#include <stdio.h>
Packit 1c1d7e
//#include <iostream.h>
Packit 1c1d7e
#include <assert.h>
Packit 1c1d7e
#include <ctype.h>
Packit 1c1d7e
Packit 1c1d7e
#include "declinfo.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
Packit 1c1d7e
#define YY_NO_INPUT 1
Packit 1c1d7e
#define YY_NO_UNISTD_H 1
Packit 1c1d7e
  
Packit 1c1d7e
/* -----------------------------------------------------------------
Packit 1c1d7e
 *
Packit 1c1d7e
 *	statics
Packit 1c1d7e
 */
Packit 1c1d7e
  
Packit 1c1d7e
static const char * inputString;
Packit 1c1d7e
static int	    inputPosition;
Packit 1c1d7e
static QCString      scope;
Packit 1c1d7e
static QCString      className;
Packit 1c1d7e
static QCString      classTempList;
Packit 1c1d7e
static QCString      funcTempList;
Packit 1c1d7e
static QCString      type;
Packit 1c1d7e
static QCString      name;
Packit 1c1d7e
static QCString      args;
Packit 1c1d7e
static int          sharpCount;
Packit 1c1d7e
static bool         classTempListFound;
Packit 1c1d7e
static bool         funcTempListFound;
Packit 1c1d7e
static QCString      exceptionString;
Packit 1c1d7e
static bool          insideObjC;
Packit 1c1d7e
Packit 1c1d7e
static void addType()
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("addType() type=`%s' scope=`%s' name=`%s'\n",
Packit 1c1d7e
  //       type.data(),scope.data(),name.data());
Packit 1c1d7e
  if (name.isEmpty() && scope.isEmpty()) return;
Packit 1c1d7e
  if (!type.isEmpty()) type+=" ";
Packit 1c1d7e
  if (!scope.isEmpty()) type+=scope+"::";
Packit 1c1d7e
  type+=name;
Packit 1c1d7e
  scope.resize(0);
Packit 1c1d7e
  name.resize(0);
Packit 1c1d7e
}
Packit 1c1d7e
  
Packit 1c1d7e
static void addTypeName()
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n",
Packit 1c1d7e
  //       type.data(),scope.data(),name.data());
Packit 1c1d7e
  if (name.isEmpty() || 
Packit 1c1d7e
      name.at(name.length()-1)==':')  // end of Objective-C keyword => append to name not type
Packit 1c1d7e
  {
Packit 1c1d7e
    return;
Packit 1c1d7e
  }
Packit 1c1d7e
  if (!type.isEmpty()) type+=' ';
Packit 1c1d7e
  type+=name;
Packit 1c1d7e
  name.resize(0);
Packit 1c1d7e
}
Packit 1c1d7e
  
Packit 1c1d7e
#define YY_NEVER_INTERACTIVE 1
Packit 1c1d7e
  
Packit 1c1d7e
/* -----------------------------------------------------------------
Packit 1c1d7e
 */
Packit 1c1d7e
#undef	YY_INPUT
Packit 1c1d7e
#define	YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
Packit 1c1d7e
Packit 1c1d7e
static int yyread(char *buf,int max_size)
Packit 1c1d7e
{
Packit 1c1d7e
    int c=0;
Packit 1c1d7e
    while( c < max_size && inputString[inputPosition] )
Packit 1c1d7e
    {
Packit 1c1d7e
	*buf = inputString[inputPosition++] ;
Packit 1c1d7e
	c++; buf++;
Packit 1c1d7e
    }
Packit 1c1d7e
    return c;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
%}
Packit 1c1d7e
Packit 1c1d7e
B       [ \t]
Packit 1c1d7e
ID	"$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
Packit 1c1d7e
Packit 1c1d7e
%option nounput
Packit 1c1d7e
%option noyywrap
Packit 1c1d7e
Packit 1c1d7e
%x      Start
Packit 1c1d7e
%x	Template
Packit 1c1d7e
%x	ReadArgs
Packit 1c1d7e
%x	Operator
Packit 1c1d7e
%x	FuncPtr
Packit 1c1d7e
%x	EndTemplate
Packit 1c1d7e
%x	StripTempArgs
Packit 1c1d7e
%x	SkipSharp
Packit 1c1d7e
%x      ReadExceptions
Packit 1c1d7e
Packit 1c1d7e
%%
Packit 1c1d7e
Packit 1c1d7e
<Start>"operator"/({B}*"["{B}*"]")* 	{ // operator rule must be before {ID} rule
Packit 1c1d7e
  				  name += yytext;
Packit 1c1d7e
  				  BEGIN(Operator);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories
Packit 1c1d7e
  				  if (!insideObjC) 
Packit 1c1d7e
				  {
Packit 1c1d7e
				    REJECT;
Packit 1c1d7e
				  }
Packit 1c1d7e
				  else 
Packit 1c1d7e
				  {
Packit 1c1d7e
				    name += yytext;
Packit 1c1d7e
				  }
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>([~!]{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java, 
Packit 1c1d7e
                                        // the / was add to deal with multi-
Packit 1c1d7e
                                        // dimensional C++ arrays like A[][15]
Packit 1c1d7e
                                        // the leading ~ is for a destructor
Packit 1c1d7e
                                        // the leading ! is for a C++/CLI finalizer (see bug 456475 and 635198)
Packit 1c1d7e
  				  addTypeName();
Packit 1c1d7e
				  name += yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*"::"{B}*		{ // found a scope specifier
Packit 1c1d7e
 				  if (!scope.isEmpty())
Packit 1c1d7e
				  {
Packit 1c1d7e
				    scope+="::"+name; // add name to scope
Packit 1c1d7e
				  }
Packit 1c1d7e
				  else
Packit 1c1d7e
				  {
Packit 1c1d7e
  				    scope = name.copy(); // scope becomes name
Packit 1c1d7e
				  }
Packit 1c1d7e
				  name.resize(0);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*":"			{ // Objective-C argument separator
Packit 1c1d7e
  				  name+=yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>[*&]+			{
Packit 1c1d7e
  				  addType();
Packit 1c1d7e
  				  type+=yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}+			{
Packit 1c1d7e
  				  addType();
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)?	{
Packit 1c1d7e
  				  addType();
Packit 1c1d7e
				  QCString text=yytext;
Packit 1c1d7e
				  type+=text.stripWhiteSpace();
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*")"			{
Packit 1c1d7e
  				  type+=")";
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*"("			{ // TODO: function pointers
Packit 1c1d7e
  				  args+="(";
Packit 1c1d7e
  				  BEGIN(ReadArgs);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*"["			{
Packit 1c1d7e
  				  args+="[";
Packit 1c1d7e
				  BEGIN(ReadArgs);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Start>{B}*"<"			{
Packit 1c1d7e
  				  name+="<";
Packit 1c1d7e
				  sharpCount=0;
Packit 1c1d7e
  				  BEGIN(Template);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Template>"<<"			{ name+="<<"; }
Packit 1c1d7e
<Template>">>"			{ name+=">>"; }
Packit 1c1d7e
<Template>"<"			{
Packit 1c1d7e
  				  name+="<";
Packit 1c1d7e
  				  sharpCount++;
Packit 1c1d7e
  				}
Packit 1c1d7e
<Template>">"			{
Packit 1c1d7e
  				  name+=">";
Packit 1c1d7e
  				  if (sharpCount)
Packit 1c1d7e
				    --sharpCount;
Packit 1c1d7e
				  else
Packit 1c1d7e
				  {
Packit 1c1d7e
				    BEGIN(Start);
Packit 1c1d7e
				  }
Packit 1c1d7e
  				}
Packit 1c1d7e
<Template>.			{
Packit 1c1d7e
  				  name+=*yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<Operator>{B}*"("{B}*")"{B}*"<>"{B}*/"("	{
Packit 1c1d7e
  				  name+="() <>";
Packit 1c1d7e
				  BEGIN(ReadArgs);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Operator>{B}*"("{B}*")"{B}*/"("	{
Packit 1c1d7e
  				  name+="()";
Packit 1c1d7e
				  BEGIN(ReadArgs);
Packit 1c1d7e
  				}
Packit 1c1d7e
<Operator>[^(]*{B}*("<>"{B}*)?/"(" {
Packit 1c1d7e
  				  name+=yytext;
Packit 1c1d7e
				  BEGIN(ReadArgs);
Packit 1c1d7e
  				}
Packit 1c1d7e
<ReadArgs>"throw"{B}*"("	{
Packit 1c1d7e
  				  exceptionString="throw(";
Packit 1c1d7e
				  BEGIN(ReadExceptions);
Packit 1c1d7e
  				}
Packit 1c1d7e
<ReadArgs>.			{
Packit 1c1d7e
  				  args+=*yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<ReadExceptions>.		{
Packit 1c1d7e
  				  exceptionString+=*yytext;
Packit 1c1d7e
  				}
Packit 1c1d7e
<*>.
Packit 1c1d7e
<*>\n
Packit 1c1d7e
Packit 1c1d7e
%%
Packit 1c1d7e
Packit 1c1d7e
/*@ ----------------------------------------------------------------------------
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t,
Packit 1c1d7e
                   QCString &n,QCString &a,QCString &ftl,QCString &exc)
Packit 1c1d7e
{
Packit 1c1d7e
  printlex(yy_flex_debug, TRUE, __FILE__, NULL);
Packit 1c1d7e
  inputString   = decl;
Packit 1c1d7e
  //printf("Input=`%s'\n",inputString);
Packit 1c1d7e
  if (inputString==0) return;
Packit 1c1d7e
  inputPosition      = 0;
Packit 1c1d7e
  classTempListFound = FALSE;
Packit 1c1d7e
  funcTempListFound  = FALSE;
Packit 1c1d7e
  insideObjC = objC;
Packit 1c1d7e
  scope.resize(0);
Packit 1c1d7e
  className.resize(0);
Packit 1c1d7e
  classTempList.resize(0);
Packit 1c1d7e
  funcTempList.resize(0);
Packit 1c1d7e
  name.resize(0);
Packit 1c1d7e
  type.resize(0);
Packit 1c1d7e
  args.resize(0);
Packit 1c1d7e
  exceptionString.resize(0);
Packit 1c1d7e
  // first we try to find the type, scope, name and arguments
Packit 1c1d7e
  declinfoYYrestart( declinfoYYin );
Packit 1c1d7e
  BEGIN( Start );
Packit 1c1d7e
  declinfoYYlex();
Packit 1c1d7e
Packit 1c1d7e
  //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
Packit 1c1d7e
  //        type.data(),scope.data(),name.data(),args.data());
Packit 1c1d7e
Packit 1c1d7e
  int nb = name.findRev('[');
Packit 1c1d7e
  if (nb!=-1 && args.isEmpty()) // correct for [] in name ambigity (due to Java return type allowing [])
Packit 1c1d7e
  {
Packit 1c1d7e
    args.prepend(name.right(name.length()-nb));
Packit 1c1d7e
    name=name.left(nb);
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
#if 0
Packit 1c1d7e
  {
Packit 1c1d7e
    int l=scope.length();
Packit 1c1d7e
    int i=0;
Packit 1c1d7e
    int skipCount=0;
Packit 1c1d7e
    cl.resize(0);
Packit 1c1d7e
    ctl.resize(0);
Packit 1c1d7e
    for (i=0;i
Packit 1c1d7e
    {
Packit 1c1d7e
      char c=scope.at(i);
Packit 1c1d7e
      if (c=='<') 
Packit 1c1d7e
	skipCount++;
Packit 1c1d7e
      else if (c=='>') 
Packit 1c1d7e
	skipCount--;
Packit 1c1d7e
      else if (skipCount==0) 
Packit 1c1d7e
	cl+=c;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(scope),FALSE); 
Packit 1c1d7e
  ctl.resize(0);
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
  cl=scope;
Packit 1c1d7e
  n=removeRedundantWhiteSpace(name);
Packit 1c1d7e
  int il,ir;
Packit 1c1d7e
  if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1)
Packit 1c1d7e
    // TODO: handle cases like where n="operator<< <T>" 
Packit 1c1d7e
  {
Packit 1c1d7e
    ftl=removeRedundantWhiteSpace(n.right(n.length()-il));
Packit 1c1d7e
    n=n.left(il);
Packit 1c1d7e
  }
Packit 1c1d7e
  
Packit 1c1d7e
  //ctl=classTempList.copy();
Packit 1c1d7e
  //ftl=funcTempList.copy();
Packit 1c1d7e
  t=removeRedundantWhiteSpace(type);
Packit 1c1d7e
  a=removeRedundantWhiteSpace(args);
Packit 1c1d7e
  exc=removeRedundantWhiteSpace(exceptionString);
Packit 1c1d7e
  
Packit 1c1d7e
  if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers
Packit 1c1d7e
  {
Packit 1c1d7e
    a.prepend(")");
Packit 1c1d7e
    t=t.left(t.length()-1);
Packit 1c1d7e
  }
Packit 1c1d7e
  //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
Packit 1c1d7e
  //        t.data(),cl.data(),n.data(),a.data());
Packit 1c1d7e
Packit 1c1d7e
  printlex(yy_flex_debug, FALSE, __FILE__, NULL);
Packit 1c1d7e
  return;
Packit 1c1d7e
  
Packit 1c1d7e
  
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
//extern "C" { // some bogus code to keep the compiler happy
Packit 1c1d7e
//  int  declinfoYYwrap() { return 1 ; }
Packit 1c1d7e
//  void declinfoYYdummy() { yy_flex_realloc(0,0); } 
Packit 1c1d7e
//}
Packit 1c1d7e
Packit 1c1d7e
#if 0
Packit 1c1d7e
void dumpDecl(const char *s)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString className;
Packit 1c1d7e
  QCString classTNames;
Packit 1c1d7e
  QCString type;
Packit 1c1d7e
  QCString name;
Packit 1c1d7e
  QCString args;
Packit 1c1d7e
  QCString funcTNames;
Packit 1c1d7e
  msg("-----------------------------------------\n");
Packit 1c1d7e
  parseFuncDecl(s,className,classTNames,type,name,args,funcTNames);
Packit 1c1d7e
  msg("type=`%s' class=`%s' classTempl=`%s' name=`%s' "
Packit 1c1d7e
         "funcTemplateNames=`%s' args=`%s'\n",
Packit 1c1d7e
	    type.data(),className.data(),classTNames.data(),
Packit 1c1d7e
	    name.data(),funcTNames.data(),args.data()
Packit 1c1d7e
	);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
// some test code
Packit 1c1d7e
int main()
Packit 1c1d7e
{
Packit 1c1d7e
  dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )");
Packit 1c1d7e
  dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
Packit 1c1d7e
  dumpDecl("func()");
Packit 1c1d7e
  dumpDecl("friend void bla<>()");
Packit 1c1d7e
  dumpDecl("name< T > :: operator () (int bla)");
Packit 1c1d7e
  dumpDecl("name< T > :: operator << (int bla)");
Packit 1c1d7e
  dumpDecl("name< T > :: operator << <> (int bla)");
Packit 1c1d7e
  dumpDecl("className::func()");
Packit 1c1d7e
  dumpDecl("void ( * Name < T > :: bla ) ( int, char * )"); 
Packit 1c1d7e
}
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
#if !defined(YY_FLEX_SUBMINOR_VERSION) 
Packit 1c1d7e
//----------------------------------------------------------------------------
Packit 1c1d7e
extern "C" { // some bogus code to keep the compiler happy
Packit 1c1d7e
  void declinfoYYdummy() { yy_flex_realloc(0,0); } 
Packit 1c1d7e
}
Packit 1c1d7e
#endif
Packit 1c1d7e