view tests/agcl/parsifal/cpp.syn @ 15:f5acaf0c8a29

Don't cast through "volatile int". Causes a gcc warning nowadays. XXX: should put something else back here to frighten the optimizer
author David A. Holland
date Tue, 31 May 2022 01:00:55 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 */
{
//  class AstNode;

  #include "cppdefs.h"
  #include "agstk.h"
  #include <stdio.h>
  #include "mpp.h"

  extern int columnNumber;

  #define INPUT_CODE(t) inputCode(t)

#ifndef SYNTAX_ERROR
#define SYNTAX_ERROR printf("%s\n", (PCB).error_message)
#endif


  parse_pcb_type *pcbPointer = 0;
  #define PCB (*pcbPointer)

  extern char *inputName[];
  InputToken *trackPointer;

  int inputCode(const InputToken &t) {
    int code = t.code;
    if (code == IDENTIFIER) code = getTokenType(t.handle);
    PCB.column = t.column;
    if (PCB.pointer == trackPointer) return code;
    trackPointer = PCB.pointer;
    if (code == LINE) printf("[%02d] %s(%d): %d\n", scopeStack.size(), inputName[code], code, t.handle);
    else printf("[%02d] %s(%d): %s\n", scopeStack.size(), inputName[code], code, td[t.handle]);
    return code;
  }

  AgStack<ParserState> stateStack;

  #include "cpp.h"
}
[
  pointer input
  pointer type = InputToken *
  default Input type = InputToken
  //default token type = AstNode *
  context type = ParserState
  input values
  ~declare PCB
  ~lines and columns
  parser name = parse
  parser file name = "#.cpp"
  line numbers
  disregard line number
  error trace
  ~allow macros
  sticky {
    statement,                // resolve if/else conflict
    type specifier seq,       // conflict between * as dereference and as multiply
    ptr operator,             // conflict between * as dereference and as multiply
    class name,               // qualifying :: on type and global :: on declarator
    IDENTIFIER,               // Resolves ctor/bitfield conflict
    explicitly typed identifier,
    nested name specifier,
    NEW,
    DELETE
  }
  enum {                               // See TOKEN.H
    eof               =0,
    SPACE             =' ',
    AND               ='A', // "&&"
    ADD_EQ,                 // "+="
    AND_EQ,                 // "&="
    ARROW,                  // "->"
    CONCAT,                 // "##"
    DECR,                   // "--"
    DIV_EQ,                 // "/="
    ELLIPSIS,               // "..."
    EQ,                     // "=="
    GE,                     // ">="
    INCR,                   // "++"
    LE,                     // "<="
    LS,                     // "<<"
    LS_EQ,                  // "<<="
    MOD_EQ,                 // "%="
    MULT_EQ,                // "*="
    NE,                     // "!="
    OR,                     // "||"
    OR_EQ,                  // "|="
    RS,                     // ">>"
    RS_EQ,                  // ">>="
    SUB_EQ,                 // "-="
    XOR_EQ,                 // "^="
    CHARACTERconstant,      // character constant
    STRINGliteral,          // character string
    DOT_STAR = 'a',
    ARROW_STAR,
    QUAL,
    LINE,
    IDENTIFIER = 129,
    CLASS_NAME,
    ENUM_NAME,
    TYPEDEF_NAME,
    TEMPLATE_NAME,
    NAMESPACE_NAME,
    NAMESPACE_ALIAS,
    UNSIGNEDqualifier,
    LONGqualifier,
    FLOATqualifier,
    HEXconstant,
    OCTconstant,
    DECconstant,
    FLOATconstant,          // real
    AUTO,                   // "auto"
    BREAK,                  // "break"
    CASE,                   // "case"
    CHAR,                   // "char"
    CONSTANT,               // "const"
    CONTINUE,               // "continue"
    DEFAULT,                // "default"
    DO,                     // "do"
    DOUBLE,                 // "double"
    ELSE,                   // "else"
    ENUM,                   // "enum"
    EXTERN,                 // "extern"
    FLOAT,                  // "float"
    FOR,                    // "for"
    GOTO,                   // "goto"
    IF,                     // "if"
    INT,                    // "int"
    LONG,                   // "long"
    REGISTER,               // "register"
    RETURN,                 // "return"
    SHORT,                  // "short"
    SIGNED,                 // "signed"
    SIZEOF,                 // "sizeof"
    STATIC,                 // "static"
    STRUCT,                 // "struct"
    SWITCH,                 // "switch"
    TYPEDEF,                // "typedef"
    UNION,                  // "union"
    UNSIGNED,               // "unsigned"
    VOID,                   // "void"
    VOLATILE,               // "volatile"
    WHILE,                  // "while"
    ASM,
    BITAND,
    BITOR,
    BOOL,
    CATCH,
    CLASS,
    COMPL,
    CONST_CAST,
    DELETE,
    DYNAMIC_CAST,
    EXPLICIT,
    EXPORT,
    FALSE,
    FRIEND,
    INLINE,
    MUTABLE,
    NAMESPACE,
    NEW,
    NOT,
    NOT_EQ,
    OPERATOR,
    PRIVATE,
    PROTECTED,
    PUBLIC,
    REINTERPRET_CAST,
    STATIC_CAST,
    TEMPLATE,
    THIS,
    THROW,
    TRUE,
    TRY,
    TYPEID,
    TYPENAME,
    USING,
    VIRTUAL,
    WCHAR_T,
    CDECL,
    PASCAL,
    RTLENTRY,
    NEAR,
    FAR,
    UNRECOGNIZED
  }
]

(void) line number
 -> LINE:x                          =PCB.line = x.handle;
 -> CDECL + PASCAL +RTLENTRY + NEAR + FAR           //hack to skip non ANSI stuff

skip = LINE + CDECL + PASCAL + RTLENTRY + NEAR + FAR

translation unit $
 -> declaration list, eof                              // 3.5

literal
 -> HEXconstant
 -> OCTconstant
 -> DECconstant
 -> FLOATconstant
 -> CHARACTERconstant
 -> STRINGliteral...                    //Concatenate adjacent strings

(TypeDefinition) class name
 -> CLASS_NAME:n                    =TypeDefinition(n);
// -> TYPEDEF_NAME
 -> template id:n                   =TypeDefinition(n);

// 5.1
primary expression
 -> literal
 -> THIS
 -> QUAL, IDENTIFIER
 -> QUAL, operator function id
 -> qualified id
 -> '(', expression hack 1, ')'
 -> unqualified id

id expression
 -> unqualified id
 -> qualified id

unqualified id
 -> IDENTIFIER:n                        ={
      TypeDefinition d(n);
      if (typedefFlag) {
        d.tokenType = TYPEDEF_NAME;
        typedefFlag = 0;
      }
      scopeStack.top()->addIdentifier(d);
    }
 -> operator function id
 -> conversion function id

(Scope *) qualified id
 -> nested name specifier:s, QUAL, unqualified id        =s;
 -> nested name specifier:s, QUAL, TEMPLATE, unqualified id    =s;

(Scope *) nested name specifier
 -> class name:n                                  =n.scope;
 -> namespace name:n                              =n.scope;
 -> QUAL, class name:n                            = scopeStack[0]->getNestedScope(n.handle);
 -> QUAL, namespace name:n                        = scopeStack[0]->getNestedScope(n.handle);
 -> nested name specifier:s, QUAL, class name:n   = (s == 0) ? 0 : s->getNestedScope(n.handle);
 -> nested name specifier:s, QUAL, namespace name:n   =(s == 0) ? 0 : s->getNestedScope(n.handle);

//5.2

postfix expression
 -> primary expression
 -> postfix expression, '[', expression, ']'
 -> postfix expression, '(', expression list?, ')'
 -> simple type specifier, '(', expression list?, ')'
 -> postfix expression, '.', id expression
 -> postfix expression, '.', TEMPLATE, id expression
 -> postfix expression, ARROW, id expression
 -> postfix expression, ARROW, TEMPLATE, id expression
 -> postfix expression, '.', pseudo destructor name
 -> postfix expression, ARROW, pseudo destructor name
 -> postfix expression, INCR
 -> postfix expression, DECR
 -> DYNAMIC_CAST, '<', type id, '>', '(', expression, ')'
 -> STATIC_CAST, '<', type id, '>', '(', expression, ')'
 -> REINTERPRET_CAST, '<', type id, '>', '(', expression, ')'
 -> CONST_CAST, '<', type id, '>', '(', expression, ')'
 -> TYPEID, '(', expression hack 1, ')'
 -> TYPEID, '(', type id, ')'

expression list
 -> assignment expression
 -> expression list, ',', assignment expression

pseudo destructor name
 -> nonclass type name, QUAL, '~', nonclass type name
 -> nested name specifier, QUAL, nonclass type name, QUAL, '~', nonclass type name
 -> QUAL, nonclass type name, QUAL, '~', nonclass type name
 -> '~', nonclass type name
 -> nested name specifier, QUAL, '~', nonclass type name
 -> QUAL, '~', nonclass type name

// 5.3

unary expression
 -> postfix expression
 -> INCR, cast expression
 -> DECR, cast expression
 -> unary operator, cast expression
 -> SIZEOF, unary expression
 -> SIZEOF, '(', type id, ')'
 -> new expression
 -> delete expression

unary operator
 -> '&' | '*' | '+' | '-' | '~' | '!'

new expression
 ->  new, new type id, new initializer?
 ->  new, new placement, new type id, new initializer?
 ->  new, '(', type id, ')', new initializer?
 ->  new, new placement, '(', type id, ')', new initializer?

new
 -> NEW
 -> QUAL, NEW

new placement
 -> '(', expression list hack 2, ')'

expression list hack 2
 -> retry, expression list
 -> retry, retry, resynch      =diagnose("expression list hack 2");

new type id
 -> type specifier seq
 -> type specifier seq, new declarator

new declarator
 -> ptr operator
 -> ptr operator, new declarator
 -> direct new declarator

direct new declarator
 -> '[', expression, ']'
 -> direct new declarator, '[', constant expression, ']'

new initializer
 -> '(', expression list?, ')'

delete expression
 -> delete, cast expression
 -> delete, '[', ']', cast expression

delete
 -> DELETE
 -> QUAL, DELETE

cast expression
 -> unary expression
 -> '(', type id, ')', cast expression

expression hack 1
 -> retry, expression
 -> retry, error, resynch       =diagnose("expression hack 1");

restricted assignment expression hack 5
 -> retry, restricted assignment expression
 -> retry, error, resynch       =diagnose("expression hack 1");

pm expression
 -> cast expression
 -> pm expression, DOT_STAR, cast expression
 -> pm expression, ARROW_STAR, cast expression

multiplicative expression
 -> pm expression
 -> multiplicative expression, '*', pm expression
 -> multiplicative expression, '/', pm expression
 -> multiplicative expression, '%', pm expression

additive expression
 -> multiplicative expression
 -> additive expression, '+', multiplicative expression
 -> additive expression, '-', multiplicative expression

shift expression
 -> additive expression
 -> shift expression, LS, additive expression
 -> shift expression, RS, additive expression

relational expression
 -> shift expression
 -> relational expression, '<', shift expression
 -> relational expression, '>', shift expression
 -> relational expression, LE, shift expression
 -> relational expression, GE, shift expression

equality expression
 -> relational expression
 -> equality expression, EQ, relational expression
 -> equality expression, NE, relational expression

and expression
 -> equality expression
 -> and expression, '&', equality expression

exclusive or expression
 -> and expression
 -> exclusive or expression, '^', and expression

inclusive or expression
 -> exclusive or expression
 -> inclusive or expression, '|', exclusive or expression

logical and expression
 -> inclusive or expression
 -> logical and expression, AND, inclusive or expression

logical or expression
 -> logical and expression
 -> logical or expression, OR, logical and expression

conditional expression
 -> logical or expression
 -> logical or expression, '?', expression, ':', conditional expression

assignment expression
 -> conditional expression
 -> logical or expression, assignment operator, assignment expression
 -> throw expression

assignment operator
 -> '=' | MULT_EQ | DIV_EQ | MOD_EQ | ADD_EQ | SUB_EQ
 -> LS_EQ | RS_EQ | AND_EQ | OR_EQ | XOR_EQ

expression
 -> assignment expression
 -> expression, ',', assignment expression

constant expression
 -> conditional expression

statement
 -> labeled statement
 -> compound statement
 -> selection statement
 -> iteration statement
 -> jump statement
 -> try block
 -> block declaration
 -> variable declaration
 -> function definition 2
 -> retry, statement try 2

statement try 2
 -> type qualifier?, declarator list, ';'
 -> function definition 1
 -> retry, statement try 3

statement try 3
 -> expression statement
 -> retry, resynch             =diagnose("statement try 3");

labeled statement
 -> IDENTIFIER, ':', statement
 -> CASE, constant expression, ':', statement
 -> DEFAULT, ':', statement

expression statement
 -> expression, ';'

compound statement
 -> begin block , statement seq?, '}'  =restoreScope();

begin block
 -> '{'                                =nestScope();

statement seq
 -> statement
 -> statement seq, statement

selection statement
 -> IF, '(', condition, ')', statement
 -> IF, '(', condition, ')', statement, ELSE, statement
 -> SWITCH, '(', condition, ')', statement

condition
 -> condition kernel

condition kernel
 -> type specifier seq, declarator, '=', assignment expression
 -> retry, condition kernel 2

condition kernel 2
 -> expression
 -> retry, resynch    =diagnose("condition kernel 2");


iteration statement
 -> WHILE, '(', condition, ')', statement
 -> DO, statement, WHILE, '(', condition, ')', ';'
 -> for header, for init statement?, ';', condition?, ';', expression?, ')', statement =restoreScope();

for header
 -> FOR, '('       =nestScope();

for init statement
 -> for init


for init
 -> for variable declaration
 -> retry, for init 2

for variable declaration
 -> decl specifier seq
 -> decl specifier seq, init declarator list

for init 2
 -> expression
 -> retry, resynch    =diagnose("for init 2");

jump statement
 -> BREAK, ';'
 -> CONTINUE, ';'
 -> RETURN, expression?, ';'
 -> GOTO, IDENTIFIER, ';'

(int) declaration seq
 ->                                               =0;
 -> declaration seq, declaration hack

declaration list
 -> declaration seq

declaration hack
 -> declaration =printf("declaration hack complete\n");

declaration
 -> block declaration
 -> simple declaration
 //-> template declaration
 -> explicit instantiation
 -> explicit specialization
 -> linkage specification
 -> namespace definition

block declaration
 -> asm definition
 -> namespace alias definition
 -> using declaration
 -> using directive

(void) retry
 -> error                =CONTEXT.restore();

simple declaration
 -> variable declaration         =printf("variable declaration\n");
 -> template header, variable declaration         =printf("variable declaration\n"), restoreScope();
 -> EXPORT, template header, variable declaration         =printf("variable declaration\n"), restoreScope();
 -> function definition 2        =printf("function definition 2\n");
 -> template header, function definition 2        =printf("function definition 2\n"), restoreScope();
 -> EXPORT, template header, function definition 2        =printf("function definition 2\n"), restoreScope();
 -> retry, attempt declarator list

attempt declarator list
 -> type qualifier?, declarator list, ';'         =printf("declarator list\n");
 -> template header, type qualifier?, declarator list, ';'         =printf("declarator list\n"), restoreScope();
 -> function definition 1        =printf("function definition 1\n");
 -> retry, resynch =diagnose("attempt declarator list");

resynch
 -> resynch text, ';'
 -> resynch text, balanced braces
 -> resynch text, eof             =PCB.pointer--;

resynch text
// -> resynch item
 ->
 -> resynch text, resynch item

resynch item
 -> ~(eof + skip + '(' + ')' + '[' + ']' + '{' + '}' + ';')
 -> balanced parens
 -> balanced brackets

(void) balanced parens
 -> '(', not right paren, ')'

(void) balanced brackets
 -> '[', not right bracket, ']'

(void) balanced braces
 -> '{', not right brace, '}'

not right paren
 ->
 -> not right paren, resynch item
 -> not right paren, ';' + ']' + '}'
 -> not right paren, balanced braces

not right bracket
 ->
 -> not right bracket, resynch item
 -> not right bracket, ';' + ')' + '}'
 -> not right bracket, balanced braces

not right brace
 ->
 -> not right brace, resynch item
 -> not right brace, ';' + ')' + ']'
 -> not right brace, balanced braces

variable declaration
 -> decl specifier seq?, ';'
 -> decl specifier seq, init declarator list, ';'

/*
 If there are no decl specifiers, then the declarator must be a constructor,
 destructor, or type conversion operator. In this case, there can be no
 initialization, so we use a declarator list instead of an init declarator list
*/

declarator list
 -> declarator
 -> declarator list, ',', declarator


decl specifier seq
 -> fundamental type
 -> fundamental type, predefined specifier...
 -> type qualifier..., fundamental type, predefined specifier?...
 -> user defined specifier, type qualifier?...
 -> type qualifier..., user defined specifier, type qualifier?...

restricted decl specifier seq
 -> fundamental type
 -> fundamental type, predefined specifier...
 -> type qualifier..., fundamental type, predefined specifier?...
 -> restricted specifier, type qualifier?...
 -> type qualifier..., restricted specifier, type qualifier?...

restricted specifier
 -> qualified type name

storage class specifier
 -> AUTO
 -> REGISTER
 -> STATIC
 -> EXTERN
 -> MUTABLE

function specifier
 -> INLINE
 -> VIRTUAL
 -> EXPLICIT

simple type specifier
 -> qualified type name
 -> fundamental type


predefined specifier
 -> type qualifier
 -> fundamental type

type qualifier
 -> storage class specifier
 -> function specifier
 -> FRIEND
 -> TYPEDEF                             =typedefFlag = 1;
 -> cv qualifier

fundamental type
 -> CHAR
 -> WCHAR_T
 -> BOOL
 -> SHORT
 -> INT
 -> LONG
 -> SIGNED
 -> UNSIGNED
 -> FLOAT
 -> DOUBLE
 -> VOID

user defined specifier
 -> class specifier
 -> enum specifier
 -> elaborated type specifier
 -> qualified type name

user type specifier
 -> elaborated type specifier
 -> qualified type name

qualified type name
 -> ENUM_NAME
 -> TYPEDEF_NAME
 -> nested name specifier
 -> nested name specifier, QUAL, ENUM_NAME
 -> nested name specifier, QUAL, TYPEDEF_NAME

nonclass type name
 -> ENUM_NAME
 -> TYPEDEF_NAME

elaborated type specifier
 -> class key, IDENTIFIER:n   ={
      TypeDefinition d(n);
      if (templateFlag) {
        d.tokenType = TEMPLATE_NAME;
        scopeStack[scopeStack.size() - 2]->addIdentifier(d);
      }
      else {
        d.tokenType = CLASS_NAME;
        scopeStack.top()->addIdentifier(d);
      }
    }
 -> class key, class name:d   ={
      if (templateFlag) {
        d.tokenType = TEMPLATE_NAME;
        scopeStack[scopeStack.size() - 2]->addIdentifier(d);
      }
      else {
        d.tokenType = CLASS_NAME;
        scopeStack.top()->addIdentifier(d);
      }
    }
 -> class key, name qualifier:scope, IDENTIFIER:n ={
      TypeDefinition d(n);
      d.tokenType = templateFlag ? TEMPLATE_NAME : CLASS_NAME;
      scope->addIdentifier(d);
    }
 -> class key, name qualifier:scope, class name:d    ={
      d.tokenType = templateFlag ? TEMPLATE_NAME : CLASS_NAME;
      scope->addIdentifier(d);
    }
 -> ENUM, IDENTIFIER
 -> ENUM, name qualifier, IDENTIFIER
 -> explicitly typed identifier
 -> explicitly typed identifier, '<', template argument list, '>'

explicitly typed identifier
 -> TYPENAME, nested name specifier, QUAL, IDENTIFIER

enum specifier
 -> ENUM, '{', enumerator list?, '}'
 -> ENUM, IDENTIFIER:n, '{', enumerator list?, '}' ={
      TypeDefinition d(n);
      d.tokenType = ENUM_NAME;
      scopeStack.top()->addIdentifier(d);
    }

enumerator list
 -> enumerator definition
 -> enumerator list, ',', enumerator definition

enumerator definition
 -> IDENTIFIER
 -> IDENTIFIER, '=', constant expression

(TypeDefinition) namespace name
 -> NAMESPACE_NAME:n          =TypeDefinition(n);
 -> NAMESPACE_ALIAS:n         =TypeDefinition(n);

namespace definition
 -> named namespace definition
 -> unnamed namespace definition

named namespace definition
 -> original namespace definition
 -> extension namespace definition

original namespace definition
 -> NAMESPACE, IDENTIFIER, '{', namespace body, '}'

extension namespace definition
 -> NAMESPACE, NAMESPACE_NAME, '{', namespace body, '}'

unnamed namespace definition
 -> NAMESPACE, '{', namespace body, '}'

namespace body
 -> declaration seq

namespace alias definition
 -> NAMESPACE, IDENTIFIER, '=', qualified namespace specifier, ';'

qualified namespace specifier
 -> name qualifier, namespace name

using declaration
 -> USING, nested name specifier, QUAL, unqualified id, ';'
 -> USING, TYPENAME, nested name specifier, QUAL, unqualified id, ';'
 -> USING, QUAL, unqualified id, ';'

using directive
 -> USING, NAMESPACE, namespace name, ';'
 -> USING, NAMESPACE, name qualifier, namespace name, ';'

(Scope *) name qualifier
 -> QUAL                                         =scopeStack[0];
 -> class name:n, QUAL                           =getNestedScope(n.handle);
 -> namespace name:n, QUAL                       =getNestedScope(n.handle);
 -> name qualifier:s, class name:n, QUAL              =s->getNestedScope(n.handle);
 -> name qualifier:s, namespace name:n, QUAL          =(s == 0) ? 0 : s->getNestedScope(n.handle);

asm definition
 -> ASM, '(', STRINGliteral, ')', ';'

linkage specification
 -> EXTERN, STRINGliteral, '{', declaration list, '}'
 -> EXTERN, STRINGliteral, declaration

init declarator list
 -> init declarator
 -> init declarator list, ',', init declarator

init declarator
 -> direct declarator
 -> direct declarator, initializer
 -> ptr operator, init declarator

(Scope *) declarator
 -> direct declarator:s             =s;
 -> ptr operator, declarator:s      =s;

(Scope *) direct declarator
 -> declarator id:s  =s;
 -> direct declarator:s, '(', parameter declaration clause hack 4, ')', cv qualifier seq?, exception specification? =s;
 -> direct declarator:s, '[', constant expression?, ']' =s;
 -> '(', declarator:s, ')'                              =s;

declarator hack
 -> direct declarator hack
 -> ptr operator, declarator hack

direct declarator hack
 -> declarator id
 -> direct declarator hack, '(', parameter declaration clause hack 4, ')', cv qualifier seq?, exception specification?
 -> direct declarator hack, '[', constant expression?, ']'
 -> '(', declarator hack 3, ')'

ptr operator
 -> '*', cv qualifier seq?
 -> '&'
 -> nested name specifier, QUAL, '*', cv qualifier seq?

cv qualifier seq
 -> cv qualifier, cv qualifier seq?

cv qualifier
 -> CONSTANT
 -> VOLATILE

(Scope *) declarator id
 -> unqualified id                      =new Scope;
 -> nested name specifier:s, QUAL, unqualified id        =s;
 -> nested name specifier:s, QUAL, CLASS_NAME             =s;
 -> nested name specifier:s, QUAL, '~', CLASS_NAME             =s;
 -> nested name specifier:s, QUAL, TEMPLATE_NAME      =s;
 -> nested name specifier:s, QUAL, '~', TEMPLATE_NAME      =s;
 -> CLASS_NAME:n                        ={
      TypeDefinition d(n);
      if (typedefFlag) {
        d.tokenType = TYPEDEF_NAME;
        typedefFlag = 0;
        scopeStack.top()->addIdentifier(d);
      }
      return new Scope;
    }
 -> TEMPLATE_NAME:n                        ={
      TypeDefinition d(n);
      if (typedefFlag) {
        d.tokenType = TYPEDEF_NAME;
        typedefFlag = 0;
        scopeStack.top()->addIdentifier(d);
      }
      return new Scope;
    }
 -> '~',  CLASS_NAME:n     =TypeDefinition(n).scope;        // '~' is a unary operator
 -> '~',  TEMPLATE_NAME:n  =TypeDefinition(n).scope;          // '~' is a unary operator

type id
 -> type specifier seq, abstract declarator?

type specifier seq
 -> fundamental type
 -> fundamental type, predefined specifier...
 -> cv qualifier..., fundamental type
 -> cv qualifier..., fundamental type, predefined specifier...
 -> user type specifier, cv qualifier?...
 -> cv qualifier..., user type specifier, cv qualifier?...


abstract declarator hack
 -> ptr operator, abstract declarator hack?
 -> direct abstract declarator hack

direct abstract declarator hack
 -> '(', ')', cv qualifier seq?, exception specification?
 -> '(', parameter declaration clause hack 3, ')', cv qualifier seq?, exception specification?
 -> '[', constant expression?, ']'
 -> '(', /* hack 3 */ abstract declarator, ')'
 -> direct abstract declarator hack, '(', parameter declaration clause?, ')', cv qualifier seq?, exception specification?
 -> direct abstract declarator hack, '[', constant expression?, ']'

abstract declarator
 -> ptr operator, abstract declarator?
 -> direct abstract declarator

direct abstract declarator
 -> '(', ')', cv qualifier seq?, exception specification?
 -> '(', parameter declaration clause, ')', cv qualifier seq?, exception specification?
 -> '[', constant expression?, ']'
 -> '(', abstract declarator, ')'
 -> direct abstract declarator, '(', parameter declaration clause?, ')', cv qualifier seq?, exception specification?
 -> direct abstract declarator, '[', constant expression?, ']'

parameter declaration clause
 -> parameter declaration list
 -> ELLIPSIS
 -> parameter declaration list, ELLIPSIS
 -> parameter declaration list, ',', ELLIPSIS

parameter declaration list
 -> parameter declaration
 -> parameter declaration list, ',', parameter declaration

parameter declaration
 -> decl specifier seq, declarator hack
 -> decl specifier seq, declarator hack, '=', assignment expression
 -> decl specifier seq, abstract declarator hack?
 -> decl specifier seq, abstract declarator hack?, '=', assignment expression

parameter declaration clause hack 3
 -> parameter declaration clause

declarator hack 3
 -> retry, declarator
 -> retry, error, ~eof, resynch  =diagnose("declarator hack 3");

parameter declaration clause hack 4
 -> parameter declaration clause?

expression list hack 4
 -> retry, expression list
 -> retry, error, ~(eof + skip + ')')?...  =diagnose("expression list hack 4");

function definition 1
 -> constructor identifier, ctor initializer?, function body  ={if (templateFlag) restoreScope();}
 -> constructor identifier, constructor try block             ={if (templateFlag) restoreScope();}

constructor try block
 -> TRY, ctor initializer?, function body, handler seq

constructor identifier
 -> type qualifier?, declarator:s                         =nestScope(s);
 -> template header, type qualifier?, declarator:s        =nestScope(s);
 -> EXPORT, template header, type qualifier?, declarator:s        =nestScope(s);

function definition 2
 -> function identifier, function body
 -> function identifier, function try block

function identifier
 -> decl specifier seq, declarator:s                         =nestScope(s);

function body
 -> '{', statement seq?, '}'          =restoreScope();

function try block
 -> TRY, function body, handler seq


initializer
 -> '=', initializer clause
 -> '(', expression list hack 4, ')'

initializer clause
 -> assignment expression
 -> '{', initializer list, ','?, '}'
 -> '{', '}'

initializer list
 -> initializer clause
 -> initializer list, ',', initializer clause

class specifier
 -> class head, '{', member specification?, '}'                    =restoreScope();
 -> class head, ':', base clause, '{', member specification?, '}'  =restoreScope();

specifier lookahead
 -> '{'+ ':'                   =CONTEXT.restore();

class head
 -> class key, specifier lookahead              ={
      nestScope();
    }
 -> class key, IDENTIFIER:n, specifier lookahead   ={
      TypeDefinition d(n);
      int flag = templateFlag;
      d.scope = nestScope(d.handle);
      if (flag) {
        d.tokenType = TEMPLATE_NAME;
        scopeStack[scopeStack.size() - 3]->addIdentifier(d);
      }
      else {
        d.tokenType = CLASS_NAME;
        scopeStack[scopeStack.size() - 2]->addIdentifier(d);
      }
    }
 -> class key, class name:d, specifier lookahead      ={
      d.tokenType = templateFlag? TEMPLATE_NAME : CLASS_NAME;
      int flag = templateFlag;
      d.scope = nestScope(d.handle);
      if (flag) scopeStack[scopeStack.size() - 3]->addIdentifier(d);
      else scopeStack[scopeStack.size() - 2]->addIdentifier(d);
    }
 -> class key, TEMPLATE_NAME:n, specifier lookahead      ={
      TypeDefinition d(n);
      d.tokenType = templateFlag? TEMPLATE_NAME : CLASS_NAME;
      int flag = templateFlag;
      d.scope = nestScope(d.handle);
      if (flag) scopeStack[scopeStack.size() - 3]->addIdentifier(d);
      else scopeStack[scopeStack.size() - 2]->addIdentifier(d);
    }
 -> class key, name qualifier:s, IDENTIFIER:n, specifier lookahead  ={
      if (s != 0) s->nest(new Scope(n.handle));
    }
 -> class key, name qualifier:s, TEMPLATE, template id:h, specifier lookahead   ={
      if (s != 0) s->nest(new Scope(h.handle));
    }

class key
 -> CLASS
 -> STRUCT
 -> UNION

member specification
 -> member declaration hack
 -> member specification, member declaration hack


member declaration hack
 -> member declaration
 -> member restore, type qualifier?, member declarator list, ';'
 -> member restore, function definition 1
 -> member restore, error, resynch =diagnose("member specification");

member restore
 -> retry  =printf("try member declarator list\n");

member declaration
 -> ';'
 -> decl specifier seq, member declarator list?, ';'
 -> function definition 2
 -> using declaration
// -> template declaration
 -> access specifier, ':'

member declarator list
 -> member declarator
 -> member declarator list, ',', member declarator

member declarator
 -> declarator
 -> declarator, pure specifier
 -> declarator, constant intializer
 -> ':', constant expression
 -> IDENTIFIER, ':', constant expression

pure specifier
 -> '=', '0'

constant intializer
 -> '=', constant expression

base clause
 -> base specifier list

base specifier list
 -> base specifier:s                           =scopeStack.top()->addBase(s);
 -> base specifier list, ',', base specifier:s =scopeStack.top()->addBase(s);

(Scope *) base specifier
 -> CLASS_NAME:n                                            =getNestedScope(n.handle);
 -> TEMPLATE_NAME:n                                            =getNestedScope(n.handle);
 -> qualified class name:s                                  =s;
 -> VIRTUAL, access specifier?, qualified class name:s      =s;
 -> access specifier, VIRTUAL?, qualified class name:s       =s;
 -> access specifier, VIRTUAL?, CLASS_NAME:n                 =getNestedScope(n.handle);
 -> access specifier, VIRTUAL?, TEMPLATE_NAME:n                 =getNestedScope(n.handle);

(Scope *) qualified class name
 -> name qualifier:s, class name:n          =(s == 0) ? 0 : s->getNestedScope(n.handle);

access specifier
 -> PRIVATE
 -> PROTECTED
 -> PUBLIC

conversion function id
 -> OPERATOR, conversion type id

conversion type id
 -> type specifier seq, conversion declarator?

conversion declarator
 -> ptr operator, conversion declarator?

ctor initializer
 -> ':', mem initializer list

mem initializer list
 -> mem initializer
 -> mem initializer list, ',', mem initializer

mem initializer
 -> mem initializer id, '(', expression list?,  ')'

mem initializer id
 -> qualified class name
 -> class name
 -> IDENTIFIER

operator function id
 -> OPERATOR, operator

operator
 -> NEW
 -> DELETE
 -> NEW, '[', ']'
 -> DELETE, '[', ']'
 -> '+'                  // =PLUS_OP;
 -> '-'                  // =MINUS_OP;
 -> '*'                  // =MUL_OP;
 -> '/'                  // =DIV_OP;
 -> '%'                  // =MOD_OP;
 -> '^'                  // =XOR_OP;
 -> '&'                  // =AND_OP;
 -> '|'                  // =OR_OP;
 -> '~'                  // =COM_OP;
 -> '!'                  // =NOT_OP;
 -> '='                  // =ASSIGN_OP;
 -> '<'                  // =LT_OP;
 -> '>'                  // =GT_OP;
 -> MULT_EQ
 -> DIV_EQ
 -> MOD_EQ
 -> ADD_EQ
 -> SUB_EQ
 -> LS_EQ
 -> RS_EQ
 -> AND_EQ
 -> OR_EQ
 -> XOR_EQ
 -> LS
 -> RS
 -> EQ
 -> NE
 -> LE
 -> GE
 -> AND
 -> OR
 -> INCR
 -> DECR
 -> ','
 -> ARROW_STAR
 -> ARROW
 -> '(', ')'             // =PAREN_OP;
 -> '[', ']'             // =BRACKET_OP;

/*
template declaration
 -> template header, declaration                                      =restoreScope();
 -> EXPORT, template header, declaration                              =restoreScope();
*/

template header
 -> TEMPLATE, '<', !nestScope();, template parameter list, '>' =templateFlag = 1;

template parameter list
 -> template parameter
 -> template parameter list, ',', template parameter

template parameter
 -> type parameter
 -> template parameter declaration

template parameter declaration
 -> restricted decl specifier seq, declarator hack
 -> restricted decl specifier seq, declarator hack, '=', restricted assignment expression
 -> restricted decl specifier seq, abstract declarator hack?
 -> restricted decl specifier seq, abstract declarator hack?, '=', restricted assignment expression

restricted assignment expression
 -> restricted conditional expression
 -> shift expression, assignment operator, restricted assignment expression
 -> restricted throw expression

restricted conditional expression
 -> shift expression
 -> shift expression, '?', shift expression, ':', restricted conditional expression

restricted throw expression
 -> THROW, restricted assignment expression?

type parameter
 -> CLASS
 -> CLASS, IDENTIFIER:n                              =scopeStack.top()->addIdentifier(TypeDefinition(n.handle, CLASS_NAME));
 -> CLASS, '=', type id
 -> CLASS, IDENTIFIER, '=', type id
 -> TYPENAME, IDENTIFIER?
 -> TYPENAME, IDENTIFIER?, '=', type id
 -> TEMPLATE, '<', template parameter list, '>', CLASS, IDENTIFIER?
 -> TEMPLATE, '<', template parameter list, '>', CLASS, IDENTIFIER?, '=', TEMPLATE_NAME

(InputToken) template id
 -> TEMPLATE_NAME:n, '<', template argument list, '>'   =n;

template argument list
 -> template argument
 -> template argument list, ',', template argument

template argument
 -> restricted assignment expression hack 5
 -> TEMPLATE_NAME
 -> type id

explicit instantiation
 -> TEMPLATE, declaration

explicit specialization
 -> TEMPLATE, '<', '>', declaration

try block
 -> TRY, compound statement, handler seq

handler seq
 -> handler
 -> handler seq, handler

handler
 -> CATCH, '(', exception declaration, ')', compound statement

exception declaration
 -> type specifier seq, declarator hack
 -> type specifier seq, abstract declarator hack
 -> type specifier seq
 -> ELLIPSIS

throw expression
 -> THROW, assignment expression?

exception specification
 -> THROW, '(', type id list?, ')'

type id list
 -> type id
 -> type id list, ',', type id

{

#include "mpp.h"
#include "token.h"

#define GET_CONTEXT CONTEXT = ParserState()

int typedefFlag = 0;
AgStack<int> typedefStack;
int templateFlag = 0;
AgStack<int> templateStack;

AgStack<InputToken> tokenStack;

ParserState::ParserState()
  : pointer(pcbPointer ? pcbPointer->pointer : 0),
    line(pcbPointer ? pcbPointer->line : 0),
    scopeStackDepth(scopeStack.size()),
    typedefStackDepth(typedefStack.size()),
    nLocalVariables(scopeStackDepth ? scopeStack.top()->nLocals(): 0),
    templateStackDepth(templateStack.size()),
    typedefFlag(::typedefFlag),
    templateFlag(::templateFlag)
{ }

void ParserState::restore() {
  PCB.pointer = pointer;
  PCB.line = line;
  while (scopeStack.size() > scopeStackDepth) scopeStack.pop();
  while (typedefStack.size() > typedefStackDepth) typedefStack.pop();
  while (templateStack.size() > templateStackDepth) templateStack.pop();
  scopeStack.top()->restoreLocals(nLocalVariables);
  ::typedefFlag = typedefFlag;
  ::templateFlag = templateFlag;
}
void diagnose(char *msg) {
  printf("Error: %s\n", msg);
  PCB.exit_flag = AG_SEMANTIC_ERROR_CODE;
}

c_parser::c_parser() {
  pcbPointer = &pcb;
  //init_parse();                                // init parse
}


// Destructor

c_parser::~c_parser() {
}


// Reset Parser

c_parser &reset(c_parser &c) {
  return c;
}


// Transmit token to c_parser

/*
  The overloaded operator "<<" is used to transmit data to a parser.
  Newline tokens are filtered out, since they are passed along by the
  token scanner only in case text output of the preprocessor is
  required.

  If the parser has encountered an error, there is no point in giving
  it any further input.

  Otherwise, the input_code and input_value fields of the pcb are set
  up and cc() is called to deal with the token.
*/

token_sink &c_parser::operator << (InputToken c) {
  printf("%d\n", c.code);
  if (c.code == 10) return *this;
  tokenStack.push(c);
  if (c.code == END_OF_FILE) {
    int k = tokenStack.size();
    int n = k;
    InputToken *tokenArray = new InputToken[k];
    while (k--) {
      tokenStack.pop(tokenArray[k]);
    }
    PCB.pointer = tokenArray;
    trackPointer = tokenArray - 1;
    PCB.line = 1;
    scopeStack.push(new Scope);                      // global scope
    parse();
  }
  return *this;
}

token_sink &c_parser::operator << (InputToken *s) {
  while (s->code != END_OF_FILE) {
    if ((int) s->code == 10) continue;
    tokenStack.push(*s++);
  }
  return *this;
}

}