/**
 *
 * Copyright (C) 1996, 1997 Sun Microsystems Inc.
 *
 * Use of this file and the system it is part of is constrained by the
 * file COPYRIGHT in the root directory of this system.  You may, however,
 * make any modifications you wish to this file.
 *
 * Author: Sreenivasa Viswanadha
 * Date: 3/20/97
 *
 * This file contains a Java grammar and actions that implement a front-end.
 *
 *
 * Derived in part from the following work:
 *
 * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g)
 *
 * Authors: Sumana Srinivasan, NeXT Inc.;            sumana_srinivasan@next.com
 *          Terence Parr, Parr Research Corporation; parrt@parr-research.com
 *          Russell Quong, Purdue University;        quong@ecn.purdue.edu
 *
 * VERSION 1.1
 *
 */
options {
  BUILD_PARSER=false;
  CACHE_TOKENS=true;
  UNICODE_INPUT=true;
}

PARSER_BEGIN(CppParser)
package net.sourceforge.pmd.lang.cpp.ast;

import net.sourceforge.pmd.lang.ast.CharStream;
import net.sourceforge.pmd.lang.ast.TokenMgrError;

public final class CppParser {

  private static String vers = "0.1";
  private static String id = "C++ Parser";

  private static void msg(String s) {
      System.out.println(id + " Version " + vers +": " + s);
  }

  public static void main(String args[]) {
    CppParser parser;
    java.io.InputStream input;

    int ai = 0;

    if (ai == (args.length-1)) {
      msg("Reading from file " + args[ai] + " . . .");
      try {
        input = new java.io.FileInputStream(args[ai]);
      } catch (java.io.FileNotFoundException e) {
        msg("File " + args[0] + " not found.");
        return;
      }
    } else if (ai >= args.length) {
      msg("Reading from standard input . . .");
      input = System.in;
    } else {
      msg("Usage: java " + id + " [-d] [inputfile]");
      return;
    }

    try {
      parser = new CppParser(input);
      parser.translation_unit();
      msg("Program parsed successfully.");
    } catch (ParseException e) {
      msg("Encountered errors during parse.");
    }
  }

  /**
   * A symbol table manager object. Currently only types are recorded for
   * doing semantic predicates for parsing.
   */
  static SymtabManager sym;

  /*
   * Methods used in semantics predicates.
   */

  /**
   * Reads a fully qualified name (since it is used during lookahead, we
   * cannot use token. We have to explicitly use getToken).
   */
  static String GetFullyScopedName() throws ParseException
  {
     Token t = getToken(1);

     if (t.kind != ID && t.kind != SCOPE)
        return null;

     StringBuffer s = new StringBuffer();

     int i;
     if (t.kind != SCOPE)
     {
        s.append(t.image);
        t = getToken(2);
        i = 3;
     }
     else
        i = 2;

     while (t.kind == SCOPE)
     {
        s.append(t.image);
        s.append((t = getToken(i++)).image);
        t = getToken(i++);
     }

     return s.toString();
  }

  /**
   * This method first tries to read a sequence of tokens of the form
   *             ("::")? <ID> ("::" <ID>)*
   * and if it succeeds then asks the symbol table manager  if this is
   * the name of a constructor.
   */
  static boolean IsCtor() throws ParseException
  {
      return sym.IsCtor(GetFullyScopedName());
  }
}

PARSER_END(CppParser)

SKIP :
{
  " "
|
  "\f"
|
  "\t"
|
  "\r\n"
|
  "\n"
|
  "//" : IN_LINE_COMMENT
|
  "/*"  : IN_COMMENT
|
  "#" : PREPROCESSOR_OUTPUT
}

<IN_LINE_COMMENT> SKIP:
{
   "\n" : DEFAULT
}

<IN_LINE_COMMENT> MORE:
{
  < ~[] >
}

<IN_COMMENT> SKIP:
{ "*/" : DEFAULT }

<IN_COMMENT,IN_PREPROCESSOR_OUTPUT_COMMENT> MORE:
{ < ~[] > }

<IN_PREPROCESSOR_OUTPUT_COMMENT> SKIP:
{ "*/" : PREPROCESSOR_OUTPUT }

<PREPROCESSOR_OUTPUT> SKIP:
{
   "\n" : DEFAULT
   | "/*" : IN_PREPROCESSOR_OUTPUT_COMMENT
   | "//" : IN_LINE_COMMENT
}

<PREPROCESSOR_OUTPUT> MORE:
{
  "\\\n"
  |
  "\\\r\n"
  |
  < ~[] >
}

TOKEN :
{
  < LCURLYBRACE: "{" >
| < RCURLYBRACE: "}" >
| < LSQUAREBRACKET: "[" >
| < RSQUAREBRACKET: "]" >
| < LPARENTHESIS: "(" >
| < RPARENTHESIS: ")" >
| < SCOPE: "::" >
| < COLON: ":" >
| < SEMICOLON: ";" >
| < COMMA: "," >
| < QUESTIONMARK: "?" >
| < ELLIPSIS: "..." >
| < ASSIGNEQUAL: "=" >
| < TIMESEQUAL: "*=" >
| < DIVIDEEQUAL: "/=" >
| < MODEQUAL: "%=" >
| < PLUSEQUAL: "+=" >
| < MINUSEQUAL: "-=" >
| < SHIFTLEFTEQUAL: "<<=" >
| < SHIFTRIGHTEQUAL: ">>=" >
| < BITWISEANDEQUAL: "&=" >
| < BITWISEXOREQUAL: "^=" >
| < BITWISEOREQUAL: "|=" >
| < OR: "||" >
| < AND: "&&" >
| < BITWISEOR: "|" >
| < BITWISEXOR: "^" >
| < AMPERSAND: "&" >
| < EQUAL: "==" >
| < NOTEQUAL: "!=" >
| < LESSTHAN: "<" >
| < GREATERTHAN: ">" >
| < LESSTHANOREQUALTO: "<=" >
| < GREATERTHANOREQUALTO: ">=" >
| < SHIFTLEFT: "<<" >
| < SHIFTRIGHT: ">>" >
| < PLUS: "+" >
| < MINUS: "-" >
| < STAR: "*" >
| < DIVIDE: "/" >
| < MOD: "%" >
| < PLUSPLUS: "++" >
| < MINUSMINUS: "--" >
| < TILDE: "~" >
| < NOT: "!" >
| < DOT: "." >
| < POINTERTO: "->" >
| < DOTSTAR: ".*" >
| < ARROWSTAR: "->*" >
| < AUTO: "auto" >
| < BREAK: "break" >
| < CASE: "case" >
| < CATCH: "catch" >
| < CHAR: "char" >
| < CONST: "const" >
| < CONTINUE: "continue" >
| < _DEFAULT: "default" >
| < DELETE: "delete" >
| < DO: "do" >
| < DOUBLE: "double" >
| < ELSE: "else" >
| < ENUM: "enum" >
| < EXTERN: "extern" >
| < FLOAT: "float" >
| < FOR: "for" >
| < FRIEND: "friend" >
| < GOTO: "goto" >
| < IF: "if" >
| < INLINE: "inline" >
| < INT: "int" >
| < LONG: "long" >
| < NEW: "new" >
| < PRIVATE: "private" >
| < PROTECTED: "protected" >
| < PUBLIC: "public" >
| < REDECLARED: "redeclared" >
| < REGISTER: "register" >
| < RETURN: "return" >
| < SHORT: "short" >
| < SIGNED: "signed" >
| < SIZEOF: "sizeof" >
| < STATIC: "static" >
| < STRUCT: "struct" >
| < CLASS : "class" >
| < SWITCH: "switch" >
| < TEMPLATE: "template" >
| < THIS: "this" >
| < TRY: "try" >
| < TYPEDEF: "typedef" >
| < UNION: "union" >
| < UNSIGNED: "unsigned" >
| < VIRTUAL: "virtual" >
| < VOID: "void" >
| < VOLATILE: "volatile" >
| < WHILE: "while" >
| < OPERATOR: "operator" >
| < TRUETOK: "true" >
| < FALSETOK: "false" >
| < THROW: "throw" >
| < AT: "@" >
}

TOKEN [IGNORE_CASE] :
{
  <  OCTALINT : "0" (["0"-"7"])* >
| <  OCTALLONG : <OCTALINT> "l" >
| <  UNSIGNED_OCTALINT : <OCTALINT> "u" >
| <  UNSIGNED_OCTALLONG : <OCTALINT> ("ul" | "lu") >

| <  DECIMALINT : ["1"-"9"] (["0"-"9"])* >
| <  DECIMALLONG : <DECIMALINT> ["u","l"] >
| <  UNSIGNED_DECIMALINT : <DECIMALINT> "u" >
| <  UNSIGNED_DECIMALLONG : <DECIMALINT> ("ul" | "lu") >


| <  HEXADECIMALINT : "0x" (["0"-"9","a"-"f"])+ >
| <  HEXADECIMALLONG : <HEXADECIMALINT> (["u","l"])? >
| <  UNSIGNED_HEXADECIMALINT : <HEXADECIMALINT> "u" >
| <  UNSIGNED_HEXADECIMALLONG : <HEXADECIMALINT> ("ul" | "lu") >


| <  FLOATONE : ((["0"-"9"])+ "." (["0"-"9"])* | (["0"-"9"])* "." (["0"-"9"])+)
              ("e" (["-","+"])? (["0"-"9"])+)? (["f","l"])? >

| <  FLOATTWO : (["0"-"9"])+ "e" (["-","+"])?  (["0"-"9"])+ (["f","l"])? >
}

TOKEN :
{

  <  CHARACTER : ("L")? "'" ( ( ~["'","\\","\r","\n"] ) | ( "\\" ( ~["\n","\r"] ) ) )* "'" >

| <  STRING : ("L")? "\"" ( ( ~["\"","\\","\r","\n"] ) | ( "\\" ( ~["\n","\r"] | "\n" | "\r\n" ) ) )* "\"" >

| <  RSTRING : "R\"(" ( ~[")"] | ( ")" ~["\""] ) )* ")\"" >
}

void translation_unit() :
{}
{
   { sym.OpenScope(null, false); }
   ( LOOKAHEAD(2) external_declaration() )* <EOF>
   { sym.CloseScope(); }
}

void external_declaration() :
{ boolean isTypedef = false; }
{
    LOOKAHEAD(("typedef" | template_head())? class_head()  "{")
       ( template_head() )? declaration()
   |
    LOOKAHEAD("enum" (<ID>)? "{")
       enum_specifier() (init_declarator_list(false))?  ";"
   |
    LOOKAHEAD ((template_head())? dtor_ctor_decl_spec()
                               dtor_declarator() "{")
       dtor_definition()
   |
    LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
       ctor_definition()

   |
    LOOKAHEAD((declaration_specifiers())?  function_declarator_lookahead())
       function_definition()

   |
    LOOKAHEAD((scope_override())? "operator")
         conversion_function_decl_or_def()
   |
    template_head()
      (
        LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
           ctor_definition()
      |
        LOOKAHEAD((declaration_specifiers())?  function_declarator_lookahead())
           function_definition()
      |
        isTypedef = declaration_specifiers()
               (init_declarator_list(isTypedef))?  ";"
      )
   |
    declaration()
   |
    ";"
}

void function_definition() :
{
   Scope sc = null;
   boolean isTypedef;
}
{

    LOOKAHEAD(3) isTypedef = declaration_specifiers()
        sc = function_declarator(isTypedef) func_decl_def(sc)
   |
    sc = function_declarator(false) func_decl_def(sc)
}

void func_decl_def(Scope sc) :
{
   boolean closeReqd = false;
}
{
  {
     if (closeReqd = (sc != null && sc != sym.GetCurScope()))
        sym.OpenScope(sc);
  }

  (
    ";"
   |
    compound_statement()
  )

  { if (closeReqd) sym.CloseScope(); }
}

void linkage_specification() :
{}
{
   "extern" <STRING>
   (
    "{" ( external_declaration() )* "}"
      ( LOOKAHEAD(";") ";")?
   |
    declaration()
   )
}

void declaration() :
{ boolean isTypedef = false; }
{
    LOOKAHEAD(2)
      isTypedef = declaration_specifiers()
               (init_declarator_list(isTypedef))? ";"
   |
    linkage_specification()
}

/**
 * Very temporary. Just returns true if it sees a typedef. Finally, we will
 * need a structure that stores all the attributes.
 */
boolean type_modifiers() :
{ boolean isTypedef = false; }
{
   (
     isTypedef = storage_class_specifier()
    |
     type_qualifier()
    |
     "inline"
    |
     "virtual"
    |
     "friend"
   )

   { return isTypedef; }
}

/**
 * Very temporary. Just returns true if it sees a typedef. Finally, we will
 * need a structure that stores all the attributes.
 */
boolean declaration_specifiers() :
{
   Token t;
   boolean isTypedef = false, tmp;
}
{
 (
   (
      LOOKAHEAD(type_modifiers()) tmp = type_modifiers() { isTypedef |= tmp; }
   )+

    [ LOOKAHEAD(2) (
     LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
         (  LOOKAHEAD(2) (
            LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
          |
            LOOKAHEAD(type_modifiers()) tmp = type_modifiers() )
                                        { isTypedef |= tmp; }
         )*
    |
     (
        class_specifier()
      |
        enum_specifier()
      |
        qualified_type()
     )
     (LOOKAHEAD(2) tmp = type_modifiers() { isTypedef |= tmp;} )*
    ) ]
   |
    LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
         ( LOOKAHEAD(2) (
            LOOKAHEAD(builtin_type_specifier()) builtin_type_specifier()
          |
            tmp = type_modifiers() { isTypedef |= tmp; } )
         )*

   |
    (
      class_specifier()
     |
      enum_specifier()
     |
      qualified_type()
    )
    (LOOKAHEAD(2) tmp = type_modifiers() { isTypedef |= tmp; } )*
 )

 { return isTypedef; }
}

/*
void type_specifier() :
{}
{
    simple_type_specifier()
   |
    class_specifier()
   |
    enum_specifier()
}
*/

void simple_type_specifier() :
{}
{
   (
    builtin_type_specifier()
   |
    qualified_type()
   )
}

void scope_override_lookahead() :
{}
{
    "::"
   |
    <ID> ("<" template_argument_list() ">")? "::"
}

String scope_override() :
{
   String name = "";
   Token t;
}
{
  (
    ("::")  { name += "::"; }
    (
      LOOKAHEAD(2) t = <ID> ("<" template_argument_list() ">")? "::"
                   { name += t.image + "::"; }
    )*
   |
    (
      LOOKAHEAD(2) t = <ID> ("<" template_argument_list() ">")? "::"
                   { name += t.image + "::"; }
    )+
  )
  { return name; }
}


String qualified_id() :
{
   String name = "";
   Token t;
}
{
    [ LOOKAHEAD(scope_override_lookahead()) name = scope_override() ]
    (
      t = <ID> [ "<" template_argument_list()  ">" ]
      { return name + t.image; }
     |
      "operator" optor() { return "operator"; }
    )
}

void ptr_to_member() :
{}
{
    scope_override()  "*"
}

void qualified_type() :
{}
{
    LOOKAHEAD({ sym.IsFullyScopedTypeName(GetFullyScopedName()) } )
        qualified_id()
}

void type_qualifier() :
{}
{
    "const" | "volatile"
}

/**
 * Very temporary. Just returns true if it sees a typedef. Finally, we will
 * need a structure that stores all the attributes.
 */
boolean storage_class_specifier() :
{}
{
   ( "auto" | "register" | "static" | "extern" ) { return false; }
   | "typedef"  { return true; }
}

void builtin_type_specifier() :
{}
{
   "void" | "char" | "short" | "int" | "long" | "float" |
   "double" | "signed" | "unsigned"
}

void init_declarator_list(boolean isTypedef) :
{}
{
   init_declarator(isTypedef) ("," init_declarator(isTypedef))*
}

void init_declarator(boolean isTypedef) :
{ String name; }
{
   name = declarator()
   {
      if (isTypedef)
         sym.PutTypeName(name);
   }
   (
    "=" initializer()
   |
    "(" expression_list()  ")"
   )?
}

void class_head() :
{}
{
   ("struct" | "union" | "class")
   (<ID> (base_clause(null))?)?
}

void class_specifier() :
{
   ClassScope sc = null;
   Token t;
}
{
   ("struct" | "union" | "class" )
   (
    "{"
        {
           sym.OpenScope(null, false);
        }
        (member_declaration())*
    "}"
        {
           sym.CloseScope();
        }
   |
    LOOKAHEAD(2) t = <ID>
     {
        sc = (ClassScope)sym.OpenScope(t.image, true);
     }
     (base_clause(sc))?
    "{"
      (member_declaration())*
    "}"
        {
           sym.CloseScope();
        }
   |
    t=<ID> (LOOKAHEAD(2) "<" template_argument_list()  ">")?
    { sym.PutTypeName(t.image); }
   )
}

void base_clause(ClassScope scope) :
{}
{
   ":" base_specifier(scope) ( "," base_specifier(scope) )*
}

void base_specifier(ClassScope scope) :
{ Token t; }
{
   ("virtual" (access_specifier())? | access_specifier() ("virtual")?)?
   (LOOKAHEAD(scope_override_lookahead()) scope_override())?
   t = <ID> ("<" template_argument_list()  ">")?
   {                          scope.AddSuper(sym.GetScope(t.image));
   }
}

void access_specifier() :
{}
{
   "public" | "protected" | "private"
}

void member_declaration() :
{ boolean isTypedef = false; }
{
    LOOKAHEAD(("typedef")? class_head() "{") declaration()

   |
    LOOKAHEAD("enum" (<ID>)? "{") enum_specifier()
       ( member_declarator_list(false) )?  ";"
   |
    LOOKAHEAD( "operator" )
       conversion_function_decl_or_def()
   |
    LOOKAHEAD(dtor_ctor_decl_spec() dtor_declarator() "{")
       dtor_definition()
   |
    LOOKAHEAD(("inline"| "virtual")* "~")
       dtor_ctor_decl_spec() simple_dtor_declarator()  ";"
   |
    LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead())
       ctor_definition()
   |
    LOOKAHEAD(dtor_ctor_decl_spec() ctor_declarator_lookahead() ";")
      (dtor_ctor_decl_spec() ctor_declarator() ";")
   |
    LOOKAHEAD((declaration_specifiers())? function_declarator_lookahead())
       function_definition()
   |
    LOOKAHEAD(declaration_specifiers())
       isTypedef = declaration_specifiers()
           (member_declarator_list(isTypedef))? ";"
   |
    LOOKAHEAD(<ID>) function_declarator(false) ";"
   |
    LOOKAHEAD(3)
     qualified_id() ";"
   |
    access_specifier()  ":"
   |
    ";"
}

void member_declarator_list(boolean isTypedef) :
{}
{
   member_declarator(isTypedef) ("=" <OCTALINT>)?
   ("," member_declarator(isTypedef) ("=" <OCTALINT>)?)*
}

void member_declarator(boolean isTypedef) :
{ String name; }
{
   name = declarator()
   {
      if (isTypedef)
         sym.PutTypeName(name);
   }
}

void conversion_function_decl_or_def() :
{
   Scope sc = null;
   String name = null;
}
{
   [ LOOKAHEAD(scope_override_lookahead()) name = scope_override() ]

   "operator" declaration_specifiers() ("*" | "&")?

   "(" (parameter_list())? ")"
   (LOOKAHEAD(2) type_qualifier())?
   (exception_spec())?
   func_decl_def(null)  // Temporary (fix the null)
}

void enum_specifier() :
{ Token t; }
{
   "enum"
   (
    "{" enumerator_list() "}"
   |
    t=<ID> (LOOKAHEAD(2) "{" enumerator_list() "}")?
           { sym.PutTypeName(t.image); }
   )
}

void enumerator_list() :
{}
{
   enumerator() ("," enumerator())*
}

void enumerator() :
{}
{
   <ID> ("=" constant_expression())?
}

void ptr_operator() :
{}
{
    "&" cv_qualifier_seq()
   |
    "*" cv_qualifier_seq()
   |
    ptr_to_member() cv_qualifier_seq()
}

void cv_qualifier_seq() :
{}
{
   [ LOOKAHEAD(2) (
     "const" [ LOOKAHEAD(2) "volatile" ]
    |
     "volatile" [ LOOKAHEAD(2) "const" ] )
   ]
}

String declarator() :
{ String name; }
{
  (
    LOOKAHEAD(ptr_operator())
      ptr_operator() name = declarator()
   |
    name = direct_declarator()
  )

  { return name; }
}

String direct_declarator() :
{
   String name;
   Token t;
}
{
   LOOKAHEAD(2)
    "~" t = <ID> (LOOKAHEAD(2) declarator_suffixes())?
        { return "~" + t.image; }
   |
    "(" name = declarator() ")" (LOOKAHEAD(2) declarator_suffixes())?
        { return name; }
   |
    name = qualified_id() (LOOKAHEAD(2) declarator_suffixes())?
    { return name; }
}

void declarator_suffixes() :
{}
{
    ("[" (constant_expression())? "]" )+
   |
    "(" (parameter_list())? ")"
    (LOOKAHEAD(2) type_qualifier())?
    (exception_spec())?
}

/**
 * Used only for lookahead.
 */
void function_declarator_lookahead() :
{}
{
   (LOOKAHEAD(2) ptr_operator() )* qualified_id() "("
}

Scope function_declarator(boolean isTypedef) :
{ Scope sc = null; }
{
  (
    LOOKAHEAD(ptr_operator())
       ptr_operator() sc = function_declarator(isTypedef)
   |
     sc = function_direct_declarator(isTypedef)
  )

  { return sc; }
}

Scope function_direct_declarator(boolean isTypedef) :
{
  String name;
  Scope sc = null;
  boolean closeReqd = false;
}
{
     name = qualified_id()

     {
        sc = sym.GetScopeOfFullyScopedName(name);

        if (closeReqd = (sc != null && sc != sym.GetCurScope()))
           sym.OpenScope(sc);
     }

     "(" (parameter_list())?  ")"
     (LOOKAHEAD(2) type_qualifier())?
     (exception_spec())?
     (LOOKAHEAD("=") "=" <OCTALINT>)?

     {
        if (closeReqd)
           sym.CloseScope();

        if (isTypedef)
           sym.PutTypeName(name);

        return sc;
     }
}

void dtor_ctor_decl_spec() :
{}
{
   [
    "virtual" [ "inline"]
   |
    "inline"  [ "virtual"]
   ]
}

void dtor_definition() :
{}
{
   (template_head())?
   dtor_ctor_decl_spec()
   dtor_declarator()
   compound_statement()
}

void ctor_definition() :
{
   Scope sc = null;
   boolean closeReqd = false;
}
{
   dtor_ctor_decl_spec() sc = ctor_declarator()

   {
      if (closeReqd = (sc != null && sc != sym.GetCurScope()))
         sym.OpenScope(sc);
   }

   (exception_spec())?

   (
     ";"
    |
     [ ctor_initializer() ] compound_statement()
   )

   { if (closeReqd) sym.CloseScope(); }
}

void ctor_declarator_lookahead() :
{}
{
   LOOKAHEAD( { IsCtor() } ) qualified_id() "("
}

Scope ctor_declarator() :
{
  String name;
  Scope sc = null;
  boolean closeReqd = false;
}
{
   LOOKAHEAD( { IsCtor() } )
      name = qualified_id()

     {
        sc = sym.GetScopeOfFullyScopedName(name);

        if (closeReqd = (sc != null && sc != sym.GetCurScope()))
           sym.OpenScope(sc);
     }

     "(" [ LOOKAHEAD(2) parameter_list() ]  ")"

     [ LOOKAHEAD(2) exception_spec() ]

     {
        if (closeReqd)
           sym.CloseScope();

        return sc;
     }
}

void ctor_initializer() :
{}
{
   ":" superclass_init() ("," superclass_init())*
}

void superclass_init() :
{}
{
   qualified_id()  "(" (expression_list())?  ")"
}

void dtor_declarator() :
{}
{
   (LOOKAHEAD(scope_override_lookahead()) scope_override())?
    simple_dtor_declarator()
}

void simple_dtor_declarator() :
{}
{
   "~"
   LOOKAHEAD( { IsCtor() } ) <ID> "(" (parameter_list())?  ")"
}

void parameter_list() :
{}
{
    parameter_declaration_list() [ LOOKAHEAD(2) [ "," ] "..." ]
   |
    "..."
}

void parameter_declaration_list() :
{}
{
   parameter_declaration() (LOOKAHEAD(2) "," parameter_declaration())*
}

void parameter_declaration() :
{}
{
   declaration_specifiers()
   (
    LOOKAHEAD(declarator()) declarator()
   |
    abstract_declarator()
   )
   ("=" assignment_expression())?
}

void initializer() :
{}
{
    LOOKAHEAD(3)
     "{" initializer() ("," initializer())* "}"
   |
    assignment_expression()
}

void type_name() :
{}
{
   declaration_specifiers() abstract_declarator()
}

void abstract_declarator() :
{}
{
   [ LOOKAHEAD(2) (
    "(" abstract_declarator()   ")"
    (abstract_declarator_suffix())+
   |
    ("[" (constant_expression())? "]")+
   |
    ptr_operator() abstract_declarator() )
   ]
}

void abstract_declarator_suffix() :
{}
{
    "[" ( constant_expression() )?  "]"
   |
    "(" (parameter_list())? ")"
}

void template_head() :
{}
{
   "template" "<" template_parameter_list() ">"
}

void template_parameter_list() :
{}
{
   template_parameter() ("," template_parameter())*
}

void template_parameter() :
{ Token t; }
{
    LOOKAHEAD(3)
      "class" t=<ID> { sym.PutTypeName(t.image); }
   |
    parameter_declaration()
}

void template_id() :
{}
{
   <ID> "<" template_argument_list() ">"
}

void template_argument_list() :
{}
{
   template_argument() ("," template_argument())*
}

void template_argument() :
{}
{
    LOOKAHEAD(3)
      type_name()
   |
    shift_expression()
}

void statement_list() :
{}
{
   (LOOKAHEAD(statement()) statement())+
}

void statement() :
{}
{
    LOOKAHEAD( declaration() )
      declaration()
   |
    LOOKAHEAD( expression() ";" )
      expression() ";"
   |
    compound_statement()
   |
    selection_statement()
   |
    jump_statement()
   |
    ";"
   |
    try_block()
   |
    throw_statement()
   |
    LOOKAHEAD(2)
      labeled_statement()
   |
    iteration_statement()
}

void labeled_statement() :
{}
{
    <ID> ":" statement()
   |
    "case" constant_expression()  ":" statement()
   |
    "default"  ":" statement()
}

void compound_statement() :
{}
{
   "{"

   { sym.OpenScope(null, false); }

   (statement_list())?

   { sym.CloseScope(); }

   "}"
}

void selection_statement() :
{}
{
    "if" "(" expression() ")" statement()
     (LOOKAHEAD(2) "else" statement())?
   |
    "switch" "(" expression() ")" statement()
}

void iteration_statement() :
{}
{
    "while" "(" expression() ")" statement()
   |
    "do" statement() "while" "(" expression() ")" ";"
   |
    "for" "(" (LOOKAHEAD(3) declaration() | expression() ";" | ";")
    (expression())? ";" (expression())? ")" statement()
}

void jump_statement() :
{}
{
    "goto" <ID> ";"
   |
    "continue" ";"
   |
    "break" ";"
   |
    "return" (expression())? ";"
}

void try_block() :
{}
{
   "try" compound_statement() (handler())*
}

void handler() :
{}
{
   "catch" "(" exception_declaration() ")"
   compound_statement()
 |
   "finally" compound_statement()
}

void exception_declaration() :
{}
{    parameter_declaration_list()
   |
     "..."
}

void throw_statement() :
{}
{    "throw" (assignment_expression())? ";"
}

void expression() :
{}
{
   assignment_expression() ( LOOKAHEAD(2) "," assignment_expression())*
}

void assignment_expression() :
{}
{
    conditional_expression()
    (("="
   | "*="
   | "/="
   | "%="
   | "+="
   | "-="
   | "<<="
   | ">>="
   | "&="
   | "^="
   | "|="
   )
   assignment_expression()
   )?
}

void conditional_expression() :
{}
{   logical_or_expression()
   ("?" conditional_expression()  ":" conditional_expression())?
}

void constant_expression() :
{}
{    conditional_expression()
}

void logical_or_expression() :
{}
{    logical_and_expression() ( "||" logical_and_expression())*
}

void logical_and_expression() :
{}
{    inclusive_or_expression() ( "&&" inclusive_or_expression())*
}

void inclusive_or_expression() :
{}
{    exclusive_or_expression()( "|" exclusive_or_expression())*
}

void exclusive_or_expression() :
{}
{    and_expression()( "^" and_expression())*
}

void and_expression() :
{}
{    equality_expression()( LOOKAHEAD(2) "&" equality_expression())*
}

void equality_expression() :
{}
{    relational_expression()(( "!=" | "==") relational_expression())*
}

void relational_expression() :
{}
{  shift_expression()
   (
     LOOKAHEAD(2)
     (
         "<"
       | ">"
       | "<="
       | ">="
     )
     shift_expression()
   )*
}

void shift_expression() :
{}
{    additive_expression()(( "<<" | ">>") additive_expression())*
}

void additive_expression() :
{}
{    multiplicative_expression()
   (LOOKAHEAD(2) ( "+" | "-") multiplicative_expression())*
}

void multiplicative_expression() :
{}
{  pm_expression()
   (LOOKAHEAD(2) ( "*" | "/" | "%") pm_expression())*
}

void pm_expression() :
{}
{
    cast_expression() (( ".*" | "->*" ) cast_expression())*
}

void cast_expression() :
{}
{
    LOOKAHEAD( "(" type_name() ")" )
     "(" type_name() ")" cast_expression()
   |
     unary_expression()
}

void unary_expression() :
{}
{
     "++" unary_expression()
   |
     "--" unary_expression()
   |
     LOOKAHEAD(3)
     unary_operator() cast_expression()
   |
     "sizeof"
     (
       LOOKAHEAD("(")
       "(" type_name()  ")"
     |
       unary_expression()
     )
   |
     postfix_expression()
}

void new_expression() :
{}
{
   (LOOKAHEAD("::") ("::"))?
   "new"
   (
     LOOKAHEAD("(" type_name() ")" )
      "(" type_name() ")"
    |
     (LOOKAHEAD("(" expression_list() ) "(" expression_list() ")")?
     (
       LOOKAHEAD("(" type_name() ")" )
       "(" type_name() ")"
      |
       LOOKAHEAD(declaration_specifiers())
        new_type_id()
     )
   )
   (LOOKAHEAD(new_initializer()) new_initializer())?
}

void new_type_id() :
{}
{
   declaration_specifiers()
   ( LOOKAHEAD(new_declarator()) new_declarator() )?
}

void new_declarator() :
{}
{
     direct_new_declarator()
   |
     ptr_operator() cv_qualifier_seq()  [ LOOKAHEAD(2) new_declarator() ]
}

void direct_new_declarator() :
{}
{
   (LOOKAHEAD(2) "[" expression() "]" )+
}

void new_initializer() :
{}
{    "(" ( expression_list() )? ")"
}

void delete_expression() :
{}
{    ( "::" )? "delete" ( "[" "]" )? cast_expression()
}

void unary_operator() :
{}
{    "&"
   | "*"
   | "+"
   | "-"
   | "~"
   | "!"
}

void postfix_expression() :
{}
{
   LOOKAHEAD(3)
    primary_expression()
    ( LOOKAHEAD(2) (
     "[" expression() "]"
    |
     "(" ( expression_list() )? ")"
    |
     "." id_expression()
    |
     "->" id_expression()
    |
     "++"
    |
     "--" )
    )*
  |
   simple_type_specifier() "(" ( expression_list() )? ")"
}

void id_expression() :
{}
{
   (LOOKAHEAD(scope_override_lookahead()) scope_override())?
   (     <ID>
   | "operator" optor()
   | "~"  <ID>
   )
}

void primary_expression() :
{}
{
     "this"
   | ( LOOKAHEAD(2) <STRING> )+
   | "(" expression()  ")"
   |
     LOOKAHEAD( ("::")? "new")
     new_expression()
   |
     LOOKAHEAD( ("::")? "delete")
     delete_expression()
   | id_expression()
   | constant()
}

void expression_list() :
{}
{    assignment_expression()( "," assignment_expression())*
}

void constant() :
{}
{    <OCTALINT>
   | <OCTALLONG>
   | <DECIMALINT>
   | <DECIMALLONG>
   | <HEXADECIMALINT>
   | <HEXADECIMALLONG>

   | <UNSIGNED_OCTALINT>
   | <UNSIGNED_OCTALLONG>
   | <UNSIGNED_DECIMALINT>
   | <UNSIGNED_DECIMALLONG>
   | <UNSIGNED_HEXADECIMALINT>
   | <UNSIGNED_HEXADECIMALLONG>

   | <CHARACTER>
   | <FLOATONE>
   | <FLOATTWO>
   | "true"
   | "false"
}

void optor() :
{}
{
     "new" [ LOOKAHEAD(2) "[" "]" ]
   | "delete" [ LOOKAHEAD(2) "[" "]" ]
   | "+"
   | "-"
   | "*"
   | "/"
   | "%"
   | "^"
   | "&"
   | "|"
   | "~"
   | "!"
   | "="
   | "<"
   | ">"
   | "+="
   | "-="
   | "*="
   | "/="
   | "%="
   | "^="
   | "&="
   | "|="
   | "<<"
   | ">>"
   | ">>="
   | "<<="
   | "=="
   | "!="
   | "<="
   | ">="
   | "&&"
   | "||"
   | "++"
   | "--"
   | ","
   | "->*"
   | "->"
   | "(" ")"
   | "[" "]"
   | declaration_specifiers() (LOOKAHEAD(2) ("*"|"&"))?
}

void exception_spec() :
{}
{
   "throw" "(" exception_list() ")"
}

void exception_list() :
{}
{
   type_name() ( "," type_name())*
}

TOKEN :
{
  <  ID : ["$", "a"-"z","A"-"Z", "_"] (["a"-"z","A"-"Z","0"-"9","_","$"])* >
}


/*end*/
