www.pudn.com > cppcc.rar > ansi_c.cg


/* -*-c++-*- */

/*
 *  File:       ansi_c.cg
 *              $Id: ansi_c.cg,v 1.4 2002/07/09 03:04:58 alec Exp $
 *
 *  Author:     Alec Panoviciu (alecu@email.com)
 *
 *  Comments:
 *
 *  Revision history:
 *
 *  $Log: ansi_c.cg,v $
 *  Revision 1.4  2002/07/09 03:04:58  alec
 *  OWN_STRINGS bu*beep*it finally vanished
 *  gcc 3.1&mingw - related cleanups
 *
 *  Revision 1.3  2002/06/23 23:47:59  alec
 *  sync
 *
 *  Revision 1.2  2002/06/05 21:44:44  alec
 *  release-ready
 *
 *  Revision 1.1  2002/05/31 12:15:47  alec
 *  *** empty log message ***
 *
 */

/*
 * This file is Public Domain software. Use it as you wish and in good
 * health.
 */

/*
 * This grammar is (hopefully) ANSI-C, based on Jeff Lee's (gatech!jeff
 * jeff@gatech jeff%gatech.CSNet@CSNet-Relay.ARPA) YACC one (which is in its
 * turn based on the April '85 draft of the standard).
 */


OPTIONS
{
  //  DEBUG_SCANNER = true
  //    DEBUG_PARSER = true
  //  OWN_STRINGS = true; DEPRECATED !
  PROFILING_FILE = "profile.dat";
}

TOKEN CToken
{}


{
  // probably tis will only compile if you are using the SGI STL.
  // if you don't have the hash_set extension, look for something simmilar in
  // your own STL and replace this stuff
#include 
#if defined __GNUC__
#if __GNUC__ >= 3 
#include 
#include 
  using __gnu_cxx::hash;
  using __gnu_cxx::hash_set;
#else
#include 
#endif
#else
#error "No implementation for hash_map provided for this platoform, please replace this line with an appropriate one." 
#endif 
  using namespace std;
}
SCANNER CScanner
{
 SKIP
{
  
          { newLine(); }
}

 MORE
{
   { pushState(LONG_COMMENT); }
}

 MORE
{
   { newLine(); }
  
  
   { newLine(); }
}

 SKIP
{
   { popState(); }
}


/* THE KEYWORDS */

 KEYWORD
{
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
}

/* CONSTANT LITERALS */
 TOKEN
{
    <#D:    ['0'-'9'] >
    <#L:    ['a'-'z', 'A'-'Z', '_'] >
    <#H:    ['a'-'f', 'A'-'F', '0'-'9'] >
    <#E:    ['E', 'e']['+', '-']?+ >
    <#FS:   ['f', 'F', 'l', 'L'] >
    <#IS:   ['u', 'U', 'l', 'L']* >

    <#SIMPLE_ESCAPE: ['a','b','f','n','r','t','v','\'','\"','\\','?'] >
    <#OCTAL_ESCAPE: ['0'-'7'] (['0'-'7'] ['0'-'7']?)? >
    <#HEX_ESCAPE: "x"['0'-'9', 'a'-'f', 'A'-'F']+ >
              
    <#ESCAPE_SEQ: "\\"(||) >
              
    +? >
    +? >
    +? >

             
    )+"\'" >
    )* "\"" >
}

/* IDENTIFIERS */

 TOKEN
{
  (|)* >
    {
      if (typeNames.find(token->image().c_str()) != typeNames.end())
        token->id = CToken::TYPE_NAME;
    }
}

SPECIAL { TYPE_NAME }

 KEYWORD // these aren't really keywords, of course, it's just that we
                // don't need the scanner to duplicate their images
{
  >=" >
  
  >" >
  
  
  
  " >
  
  
  =" >
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  " >
  
  
  
  
}

{
 public:
  void addType (const string &typeName)
    {
      typeNames.insert(strdup(typeName.c_str()));
    }

 private:

  struct t_strCmp
  {
    bool operator () (const char *s1, const char *s2) const
    {
      return strcmp(s1, s2) == 0;
    }
  };

  hash_set, t_strCmp> typeNames;
}

} // end of scanner

PARSER CParser
{

  /* EXPRESSIONS */
  
  () primaryExpr ()
    {
       | constant() |  expr() 
    }

  () postfixExpr ()
    {
      primaryExpr() postfixOperator()*
    }

  () postfixOperator ()
    {
         expr() 
      |  argumentExprList() ? 
      |  identifier()
      |  identifier()
      | 
      | 
    }

  () argumentExprList ()
    {
      assignmentExpr() (  assignmentExpr() )*
    }

  () unaryExpr ()
    {
        postfixExpr()
      |  unaryExpr()
      |  unaryExpr()
      | unaryOperator() castExpr()
      |  (  LOOKAHEAD( typeSpecifier())
                    (  typeName()  )
                  | unaryExpr() )
    }

  () unaryOperator ()
    {
       |  |  |  |  | 
    }

  () castExpr ()
    {
        LOOKAHEAD( typeSpecifier())
        (  typeName()  castExpr() )
      | unaryExpr()
    }

  () multiplicativeExpr ()
    {
      castExpr() ( multiplicativeOperator() castExpr() ) *
    }

  () multiplicativeOperator ()
    {
       |  | 
    }

  () additiveExpr ()
    {
      multiplicativeExpr () ( additiveOperator() multiplicativeExpr() ) *
    }

  () additiveOperator ()
    {
       | 
    }

  () shiftExpr ()
    {
      additiveExpr() ( shiftOperator() additiveExpr() ) *
    }

  () shiftOperator ()
    {
       | 
    }

  () relationalExpr ()
    {
      shiftExpr() ( relationalOperator() shiftExpr() ) *
    }

  () relationalOperator ()
    {
       |  |  | 
    }

  () equalityExpr ()
    {
      relationalExpr() ( equalityOperator() relationalExpr() ) *
    }

  () equalityOperator ()
    {
       | 
    }

  () andExpr ()
    {
      equalityExpr() (  equalityExpr() ) *
    }

  () exclusiveOrExpr ()
    {
      andExpr() (  andExpr() ) *
    }

  () inclusiveOrExpr ()
    {
      exclusiveOrExpr() (  exclusiveOrExpr() ) *
    }

  () logicalAndExpr ()
    {
      inclusiveOrExpr() (  inclusiveOrExpr() ) *
    }

  () logicalOrExpr ()
    {
      logicalAndExpr() (  logicalAndExpr() ) *
    }

  () conditionalExpr ()
    {
      logicalOrExpr() (  logicalOrExpr()  logicalOrExpr() ) ?
    }

  () assignmentExpr ()
    {
      // ok , i know this is ridiculous, but otherwise id need a lookahead.
      // the correct grammar here only accepts unaryExpression as a lvalue.
      // however, since a lvalue check is needed anyway, why not just put the
      // conditionalExpression and do the check afterwards.
      conditionalExpr() ( assignmentOperator() conditionalExpr() ) *
    }

  () assignmentOperator ()
    {
         |  |  | 
      |  |  |  | 
      |  |  | 
    }

  () expr ()
    {
      assignmentExpr() (  assignmentExpr() ) *
    }

  () constantExpr ()
    {
      conditionalExpr()
    }

  /* DECLARATIONS */

  () declaration ()
    {
      { bool isType; }
      isType = declarationSpecifiers()
        ( initDeclarator(isType) (  initDeclarator(isType) ) * ) ?
      
    }

  (bool) declarationSpecifiers ()
    {
      { bool isType = false; }
      ( isType = storageClassSpecifier() | typeSpecifier() ) *
      { return isType; }
    }

  () initDeclarator (bool isType)
    {
      declarator(isType) (  initializer() ) ?
    }

  (bool) storageClassSpecifier ()
    {
      { bool isType = false; }
      (  {isType = true;} |  |  |  |  )
      { return isType; }
    }

  () typeSpecifier ()
    {
         |  |  |  |  | 
      |  |  |  |  | 
      | structOrUnionSpecifier()
      | enumSpecifier()
      | 
    }

  () structOrUnionSpecifier ()
    {
      ( | )
        (   identifier() (  structDeclaration()+  ) ?
          |  structDeclaration()+ 
        )
    }

  () structDeclaration ()
    {
      typeSpecifier()+ structDeclarator() (  structDeclarator() ) *
      
    }

  () structDeclarator ()
    {
        declarator(false) (  constantExpr() ) ?
      |  constantExpr()
    }

  () enumSpecifier ()
    {
      
        (   identifier() (  enumeratorList()  ) ?
          |  enumeratorList() 
        )
    }

  () enumeratorList ()
    {
      enumerator() (  enumerator() ) *
    }

  () enumerator ()
    {
      identifier() (  constantExpr() ) ?
    }

  () declarator (bool isType)
    {
      pointer() ?
      ( 
          {
            if (isType > 0)
            {
              scanner.addType(token->image());
              // cerr << "GOT A TYPE !!!! " << token->image << endl;
            }
          }
       |  declarator(isType) )
      (LOOKAHEAD( |  (typeSpecifier() | ) ?) (
          constantExpr() ? 
       |  ( parameterTypeList() | parameterIdentifierList() ) ?
         
      ))*
    }

  () pointer ()
    {
      ( typeSpecifier()* )+
    }

  () parameterIdentifierList ()
    {
      identifierList() (  ) ?
    }

  () parameterTypeList ()
    {
      parameterList() (   ) ?
    }

  () identifierList ()
    {
       (LOOKAHEAD(2) (   )) *
    }

  () parameterList ()
    {
      parameterDeclaration()
      ( LOOKAHEAD(2) (  parameterDeclaration() ) ) *
    }

  () parameterDeclaration ()
    {
      typeSpecifier()+ (  LOOKAHEAD(declarator()) declarator(false)
                        | abstractDeclarator() ) ?
    }

  () typeName ()
    {
      typeSpecifier()+ abstractDeclarator()?
    }

  () abstractDeclarator ()
    {
       pointer()?
       (   ( abstractDeclarator() | parameterTypeList() ) ? 
        |  constantExpr()? 
       ) *
    }

  () initializer ()
    {
        assignmentExpr()
      |  initializer()
         (  initializer()? )* 
    }

  /* STATEMENTS */

  () statement ()
    {
        LOOKAHEAD(2) labeledStatement()
      | (   compoundStatement()
          | expressionStatement()
          | selectionStatement()
          | iterationStatement()
          | jumpStatement()
        )
    }

  () labeledStatement ()
    {
        identifier()  statement()
      |  constantExpr()  statement()
      |   statement()
    }

  () compoundStatement ()
    {
       (LOOKAHEAD(declaration()) declaration())* statement()* 
    }

  () expressionStatement ()
    {
      expr() ? 
    }

  () selectionStatement ()
    {
          expr()  statement() (  statement() ) ?
      |   expr()  statement()
    }

  () iterationStatement ()
    {
          expr()  statement()
      |  statement()   expr()  
      |   expr()?  expr()?  expr()?
               statement()
    }

  () jumpStatement ()
    {
      (   identifier()
       | 
       | 
       |  expr()?
      )
      
    }
  
  /* SOURCE FILE STRUCTURE */
  
  () file ()
    {
      externalDefinition() +
    }

  () externalDefinition ()
    {
      LOOKAHEAD(declarationSpecifiers() declarator() declaration()* )
                  functionDefinition()
      | declaration()
    }

  () functionDefinition ()
    {
      declarationSpecifiers() declarator(false) functionBody()
    }

  () functionBody ()
    {
      declaration()* compoundStatement()
    }
  
  () constant ()
    {
       |  | 
       |   | 
    }

  () identifier ()
    {
       | 
    }
}