Changeset b87a5ed


Ignore:
Timestamp:
May 16, 2015, 3:36:19 PM (10 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
Children:
a32b204
Parents:
b8508a2
Message:

licencing: first groups of files

Files:
2 deleted
38 edited

Legend:

Unmodified
Added
Removed
  • INSTALL

    rb8508a2 rb87a5ed  
    22======================================
    33
    4 Cforall is built using GNU Make and the GNU Autoconf system.  It also
    5 requires g++ version 3, bison and flex.  On systems where GNU Make is
    6 the default make it may suffice to build the system by entering the
    7 commands
     4Cforall is built using GNU Make and the GNU Autoconf system.  It also requires
     5g++ version 3, bison and flex.  On systems where GNU Make is the default make
     6it may suffice to build the system by entering the commands
    87
    98        ./configure
     
    1312Options for 'configure'
    1413-----------------------
    15 The script 'configure' accepts many command line arguments.  Run
    16 './configure --help' to see a list of all of them.  This document
    17 attempts to summarize the most useful arguments.
     14The script 'configure' accepts many command line arguments.  Run './configure
     15--help' to see a list of all of them.  This document attempts to summarize the
     16most useful arguments.
    1817
    19 --prefix=/some/directory controls the path prefix common to all
    20 installed cfa-cc components.  Some components will be installed in
    21 /some/directory/bin, others in /some/directory/lib.  If unspecified,
    22 this defaults to /usr/local.
     18--prefix=/some/directory controls the path prefix common to all installed
     19cfa-cc components.  Some components will be installed in /some/directory/bin,
     20others in /some/directory/lib.  If unspecified, this defaults to /usr/local.
    2321
    24 --with-backend-compiler=PROGRAM specifies the installed path of gcc
    25 3.2.  It defaults to the first command named 'gcc' in the current
    26 PATH.
     22--with-backend-compiler=PROGRAM specifies the installed path of gcc 3.2.  It
     23defaults to the first command named 'gcc' in the current PATH.
    2724
    28 cfa-cc itself is built with the version of g++ specified by the
    29 environment variable CXX.  If CXX is unset, cfa-cc is built using the
    30 first command named 'g++' in the current PATH.
     25cfa-cc itself is built with the version of g++ specified by the environment
     26variable CXX.  If CXX is unset, cfa-cc is built using the first command named
     27'g++' in the current PATH.
  • Makefile.in

    rb8508a2 rb87a5ed  
    3838        $(top_srcdir)/libcfa/Makefile.in \
    3939        $(top_srcdir)/translator/Makefile.in \
    40         $(top_srcdir)/translator/examples/Makefile.in AUTHORS COPYING \
    41         ChangeLog INSTALL NEWS install-sh missing mkinstalldirs
     40        $(top_srcdir)/translator/examples/Makefile.in AUTHORS INSTALL \
     41        TODO install-sh missing mkinstalldirs
    4242ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    4343am__aclocal_m4_deps = $(top_srcdir)/configure.in
     
    225225          case '$(am__configure_deps)' in \
    226226            *$$dep*) \
    227               echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
    228               $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
     227              echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
     228              $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
    229229                && exit 0; \
    230230              exit 1;; \
    231231          esac; \
    232232        done; \
    233         echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
     233        echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
    234234        $(am__cd) $(top_srcdir) && \
    235           $(AUTOMAKE) --gnu Makefile
     235          $(AUTOMAKE) --foreign Makefile
    236236.PRECIOUS: Makefile
    237237Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
  • configure

    rb8508a2 rb87a5ed  
    25932593
    25942594# Define the identity of the package.
    2595  PACKAGE=cfa
    2596  VERSION=1.0
     2595 PACKAGE='cfa-cc'
     2596 VERSION='1.0'
    25972597
    25982598
     
    26332633
    26342634
    2635 
     2635                # do not follow GNU standard
    26362636ac_config_headers="$ac_config_headers config.h"
    26372637
     
    64726472
    64736473
    6474 { $as_echo "$as_me:${as_lineno-$LINENO}: result: The Cforall translator is now configured for your system" >&5
    6475 $as_echo "The Cforall translator is now configured for your system" >&6; }
     6474{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Cforall configuraton completed. Type \"make install\"." >&5
     6475$as_echo "Cforall configuraton completed. Type \"make install\"." >&6; }
  • configure.in

    rb8508a2 rb87a5ed  
    22AC_CONFIG_SRCDIR([translator/main.cc])
    33
    4 AM_INIT_AUTOMAKE(cfa, 1.0)
     4AM_INIT_AUTOMAKE([foreign])             # do not follow GNU standard
    55AM_CONFIG_HEADER(config.h)
    66
     
    105105dnl Final text
    106106
    107 AC_MSG_RESULT(The Cforall translator is now configured for your system)
    108 dnl AC_MSG_RESULT()
    109 dnl AC_MSG_RESULT(Perhaps you'd like to inspect the created Makefiles)
     107AC_MSG_RESULT(Cforall configuraton completed. Type "make install".)
  • driver/Makefile.in

    rb8508a2 rb87a5ed  
    1 ###
    2 ### This file is part of the Cforall project
    3 ###
    4 ### $Id: Makefile.in,v 1.5 2005/08/26 19:16:54 rcbilson Exp $
    5 ###
     1######################### -*- Mode: Makefile-Gmake -*- ########################$
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## Makefile.in --
     9##
     10## Author           : Peter A. Buhr
     11## Created On       : Sat May 16 07:50:15 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat May 16 08:34:55 2015
     14## Update Count     : 4
     15###############################################################################
    616
    717CXX=@CXX@
     
    1121
    1222SRCS:=cfa.cc cc1.cc
    13 OBJECTS:=$(SRCS:.cc=.o)
    14 DEPS:=$(SRCS:.cc=.d)
     23OBJECTS:=${SRCS:.cc=.o}
     24DEPS:=${SRCS:.cc=.d}
    1525
    1626all: cfa cc1
    1727
    1828cfa: cfa.o
    19         $(CXX) $< -o $@
     29        ${CXX} $< -o $@
    2030
    2131cc1 : cc1.o
    22         $(CXX) $< -o $@
     32        ${CXX} $< -o $@
    2333
    2434install: cfa cc1
    25         $(INSTALL) -d @CFA_BINDIR@
    26         $(INSTALL) -d @CFA_LIBDIR@
    27         $(INSTALL) cc1 @CFA_LIBDIR@
    28         $(INSTALL) cfa @CFA_BINDIR@
     35        ${INSTALL} -d @CFA_BINDIR@
     36        ${INSTALL} -d @CFA_LIBDIR@
     37        ${INSTALL} cc1 @CFA_LIBDIR@
     38        ${INSTALL} cfa @CFA_BINDIR@
    2939
    3040clean:
    31         rm -f cfa cc1 $(OBJECTS) $(DEPS) core
     41        rm -f cfa cc1 ${OBJECTS} ${DEPS} core
  • driver/cc1.cc

    rb8508a2 rb87a5ed  
    1 //                              -*- Mode: C++ -*-
    2 //
    3 // CForall Version 1.0, Copyright (C) Peter A. Buhr 2005
    4 //
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
    57// cc1.cc --
    6 // 
    7 // Author           : Richard C. Bilson
     8//
     9// Author           : Peter A. Buhr
    810// Created On       : Fri Aug 26 14:23:51 2005
    911// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Thu May 14 13:24:45 2015
    11 // Update Count     : 43
     12// Last Modified On : Sat May 16 07:42:14 2015
     13// Update Count     : 49
    1214//
    13 
    1415
    1516#include <iostream>
     
    1819#include <string>
    1920using std::string;
    20 #include <cstdio>                                       // stderr, stdout, perror, fprintf
    21 #include <cstdlib>                                      // getenv, exit, mkstemp
    22 #include <unistd.h>                                     // execvp, fork, unlink
    23 #include <sys/wait.h>                                   // wait
    24 
    25 #include "config.h"                                     // configure info
     21#include <cstdio>                                                                               // stderr, stdout, perror, fprintf
     22#include <cstdlib>                                                                              // getenv, exit, mkstemp
     23#include <unistd.h>                                                                             // execvp, fork, unlink
     24#include <sys/wait.h>                                                                   // wait
     25
     26#include "config.h"                                                                             // configure info
    2627
    2728
     
    2930
    3031
    31 string compiler_name( GCC_PATH );                       // path/name of C compiler
     32string compiler_name( GCC_PATH );                                               // path/name of C compiler
    3233
    3334string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" );
     
    3940
    4041bool prefix( string arg, string pre ) {
    41     return arg.substr( 0, pre.size() ) == pre;
     42        return arg.substr( 0, pre.size() ) == pre;
    4243} // prefix
    4344
    4445
    4546void checkEnv( const char *args[], int &nargs ) {
    46     char *value;
    47 
    48     value = getenv( "__COMPILER__" );
    49     if ( value != NULL ) {
    50         compiler_name = value;
    51 #ifdef __DEBUG_H__
    52         cerr << "env arg:\"" << compiler_name << "\"" << endl;
    53 #endif // __DEBUG_H__
    54     } // if
    55 
    56     value = getenv( "__GCC_MACHINE__" );
    57     if ( value != NULL ) {
    58         args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
    59 #ifdef __DEBUG_H__
    60         cerr << "env arg:\"" << args[nargs] << "\"" << endl;
    61 #endif // __DEBUG_H__
     47        char *value;
     48
     49        value = getenv( "__COMPILER__" );
     50        if ( value != NULL ) {
     51                compiler_name = value;
     52#ifdef __DEBUG_H__
     53                cerr << "env arg:\"" << compiler_name << "\"" << endl;
     54#endif // __DEBUG_H__
     55        } // if
     56
     57        value = getenv( "__GCC_MACHINE__" );
     58        if ( value != NULL ) {
     59                args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
     60#ifdef __DEBUG_H__
     61                cerr << "env arg:\"" << args[nargs] << "\"" << endl;
     62#endif // __DEBUG_H__
     63                nargs += 1;
     64        } // if
     65
     66        value = getenv( "__GCC_VERSION__" );
     67        if ( value != NULL ) {
     68                args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
     69#ifdef __DEBUG_H__
     70                cerr << "env arg:\"" << args[nargs] << "\"" << endl;
     71#endif // __DEBUG_H__
     72                nargs += 1;
     73        } // if
     74} // checkEnv
     75
     76
     77void rmtmpfile() {
     78        if ( unlink( tmpname ) == -1 ) {                                        // remove tmpname
     79                perror ( "CFA Translator error: cpp failed" );
     80                exit( EXIT_FAILURE );
     81        } // if
     82        tmpfilefd = -1;                                                                         // mark closed
     83} // rmtmpfile
     84
     85
     86void sigTermHandler( int signal ) {
     87        if ( tmpfilefd != -1 ) {                                                        // RACE, file created ?
     88                rmtmpfile();                                                                    // remove
     89                exit( EXIT_FAILURE );                                                   // terminate
     90        } // if
     91} // sigTermHandler
     92
     93
     94void Stage1( const int argc, const char * const argv[] ) {
     95        int code;
     96        int i;
     97
     98        string arg;
     99        string bprefix;
     100
     101        const char *cpp_in = NULL;
     102        const char *cpp_out = NULL;
     103
     104        bool CFA_flag = false;
     105        bool cpp_flag = false;
     106        const char *o_name = NULL;
     107
     108        const char *args[argc + 100];                                           // leave space for 100 additional cpp command line values
     109        int nargs = 1;                                                                          // number of arguments in args list; 0 => command name
     110        const char *uargs[20];                                                          // leave space for 20 additional cfa-cpp command line values
     111        int nuargs = 1;                                                                         // 0 => command name
     112
     113        signal( SIGINT,  sigTermHandler );
     114        signal( SIGTERM, sigTermHandler );
     115
     116        // process all the arguments
     117
     118        checkEnv( args, nargs );                                                        // arguments passed via environment variables
     119
     120        for ( i = 1; i < argc; i += 1 ) {
     121#ifdef __DEBUG_H__
     122                cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     123#endif // __DEBUG_H__
     124                arg = argv[i];
     125#ifdef __DEBUG_H__
     126                cerr << "arg:\"" << arg << "\"" << endl;
     127#endif // __DEBUG_H__
     128                if ( prefix( arg, "-" ) ) {
     129                        // strip g++ flags that are inappropriate or cause duplicates in subsequent passes
     130
     131                        if ( arg == "-quiet" ) {
     132                        } else if ( arg == "-imultilib" || arg == "-imultiarch" ) {
     133                                i += 1;                                                                 // and the argument
     134                        } else if ( prefix( arg, "-A" ) ) {
     135                        } else if ( prefix( arg, "-D__GNU" ) ) {
     136                                //********
     137                                // GCC 5.6.0 SEPARATED THE -D FROM THE ARGUMENT!
     138                                //********
     139                        } else if ( arg == "-D" && prefix( argv[i + 1], "__GNU" ) ) {
     140                                i += 1;                                                                 // and the argument
     141
     142                                // strip flags controlling cpp step
     143
     144                        } else if ( arg == "-D__CPP__" ) {
     145                                cpp_flag = true;
     146                        } else if ( arg == "-D" && string( argv[i + 1] ) == "__CPP__" ) {
     147                                i += 1;                                                                 // and the argument
     148                                cpp_flag = true;
     149                        } else if ( arg == "-D__CFA__" ) {
     150                                CFA_flag = true;
     151                        } else if ( arg == "-D" && string( argv[i + 1] ) == "__CFA__" ) {
     152                                i += 1;                                                                 // and the argument
     153                                CFA_flag = true;
     154                        } else if ( prefix( arg, D__CFA_FLAGPREFIX__ ) ) {
     155                                uargs[nuargs] = ( *new string( arg.substr( D__CFA_FLAGPREFIX__.size() ) ) ).c_str();
     156                                nuargs += 1;
     157                        } else if ( arg == "-D" && prefix( argv[i + 1], D__CFA_FLAGPREFIX__.substr(2) ) ) {
     158                                uargs[nuargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
     159                                nuargs += 1;
     160                                i += 1;                                                                 // and the argument
     161                        } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) {
     162                                bprefix = arg.substr( D__GCC_BPREFIX__.size() );
     163                        } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_BPREFIX__.substr(2) ) ) {
     164                                bprefix = string( argv[i + 1] ).substr( D__GCC_BPREFIX__.size() - 2 );
     165                                i += 1;                                                                 // and the argument
     166
     167                                // all other flags
     168
     169                        } else if ( arg == "-o" ) {
     170                                i += 1;
     171                                o_name = argv[i];
     172                        } else {
     173                                args[nargs] = argv[i];                                  // pass the flag along
     174                                nargs += 1;
     175                                // CPP flags with an argument
     176                                if ( arg == "-D" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" ||
     177                                         arg == "-include" || arg == "-imacros" || arg == "-idirafter" || arg == "-iprefix" ||
     178                                         arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) {
     179                                        i += 1;
     180                                        args[nargs] = argv[i];                          // pass the argument along
     181                                        nargs += 1;
     182#ifdef __DEBUG_H__
     183                                        cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     184#endif // __DEBUG_H__
     185                                } else if ( arg == "-MD" || arg == "-MMD" ) {
     186                                        args[nargs] = "-MF";                            // insert before file
     187                                        nargs += 1;
     188                                        i += 1;
     189                                        args[nargs] = argv[i];                          // pass the argument along
     190                                        nargs += 1;
     191#ifdef __DEBUG_H__
     192                                        cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     193#endif // __DEBUG_H__
     194                                } // if
     195                        } // if
     196                } else {                                                                                // obtain input and possibly output files
     197                        if ( cpp_in == NULL ) {
     198                                cpp_in = argv[i];
     199#ifdef __DEBUG_H__
     200                                cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
     201#endif // __DEBUG_H__
     202                        } else if ( cpp_out == NULL ) {
     203                                cpp_out = argv[i];
     204#ifdef __DEBUG_H__
     205                                cerr << "cpp_out:\"" << cpp_out << "\""<< endl;
     206#endif // __DEBUG_H__
     207                        } else {
     208                                cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
     209                                exit( EXIT_FAILURE );
     210                        } // if
     211                } // if
     212        } // for
     213
     214#ifdef __DEBUG_H__
     215        cerr << "args:";
     216        for ( i = 1; i < nargs; i += 1 ) {
     217                cerr << " " << args[i];
     218        } // for
     219        if ( cpp_in != NULL ) cerr << " " << cpp_in;
     220        if ( cpp_out != NULL ) cerr << " " << cpp_out;
     221        cerr << endl;
     222#endif // __DEBUG_H__
     223
     224        if ( cpp_in == NULL ) {
     225                cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
     226                exit( EXIT_FAILURE );
     227        } // if
     228
     229        if ( cpp_flag ) {
     230                // The -E flag is specified on the cfa command so only run the preprocessor and output is written to standard
     231                // output or -o. The call to cfa has a -E so it does not have to be added to the argument list.
     232
     233                args[0] = compiler_name.c_str();
     234                args[nargs] = cpp_in;
     235                nargs += 1;
     236                if ( o_name != NULL ) {                                                 // location for output
     237                        args[nargs] = "-o";
     238                        nargs += 1;
     239                        args[nargs] = o_name;
     240                        nargs += 1;
     241                } // if
     242                args[nargs] = NULL;                                                             // terminate argument list
     243
     244#ifdef __DEBUG_H__
     245                cerr << "nargs: " << nargs << endl;
     246                for ( i = 0; args[i] != NULL; i += 1 ) {
     247                        cerr << args[i] << " ";
     248                } // for
     249                cerr << endl;
     250#endif // __DEBUG_H__
     251
     252                execvp( args[0], (char *const *)args );                 // should not return
     253                perror( "CFA Translator error: cpp level, execvp" );
     254                exit( EXIT_FAILURE );
     255        } // if
     256
     257        // Create a temporary file to store output of the C preprocessor.
     258
     259        tmpfilefd = mkstemp( tmpname );
     260        if ( tmpfilefd == -1 ) {
     261                perror( "CFA Translator error: cpp level, mkstemp" );
     262                exit( EXIT_FAILURE );
     263        } // if
     264
     265#ifdef __DEBUG_H__
     266        cerr << "tmpname:" << tmpname << " tmpfilefd:" << tmpfilefd << endl;
     267#endif // __DEBUG_H__
     268
     269        // Run the C preprocessor and save the output in tmpfile.
     270
     271        if ( fork() == 0 ) {                                                             // child process ?
     272                // -o xxx.ii cannot be used to write the output file from cpp because no output file is created if cpp detects
     273                // an error (e.g., cannot find include file). Whereas, output is always generated, even when there is an error,
     274                // when cpp writes to stdout. Hence, stdout is redirected into the temporary file.
     275                if ( freopen( tmpname, "w", stdout ) == NULL ) { // redirect stdout to tmpname
     276                        perror( "CFA Translator error: cpp level, freopen" );
     277                        exit( EXIT_FAILURE );
     278                } // if
     279
     280                args[0] = compiler_name.c_str();
     281                args[nargs] = cpp_in;                                                   // input to cpp
     282                nargs += 1;
     283                args[nargs] = NULL;                                                             // terminate argument list
     284
     285#ifdef __DEBUG_H__
     286                cerr << "cpp nargs: " << nargs << endl;
     287                for ( i = 0; args[i] != NULL; i += 1 ) {
     288                        cerr << args[i] << " ";
     289                } // for
     290                cerr << endl;
     291#endif // __DEBUG_H__
     292
     293                execvp( args[0], (char *const *)args );                 // should not return
     294                perror( "CFA Translator error: cpp level, execvp" );
     295                exit( EXIT_FAILURE );
     296        } // if
     297
     298        wait( &code );                                                                          // wait for child to finish
     299
     300#ifdef __DEBUG_H__
     301        cerr << "return code from cpp:" << WEXITSTATUS(code) << endl;
     302#endif // __DEBUG_H__
     303
     304        if ( WIFSIGNALED(code) != 0 ) {                                         // child failed ?
     305                rmtmpfile();                                                                    // remove tmpname
     306                cerr << "CFA Translator error: cpp failed with signal " << WTERMSIG(code) << endl;
     307                exit( EXIT_FAILURE );
     308        } // if
     309
     310        if ( WEXITSTATUS(code) != 0 ) {                                         // child error ?
     311                rmtmpfile();                                                                    // remove tmpname
     312                exit( WEXITSTATUS( code ) );                                    // do not continue
     313        } // if
     314
     315        // If -CFA flag specified, run the cfa-cpp preprocessor on the temporary file, and output is written to standard
     316        // output.  Otherwise, run the cfa-cpp preprocessor on the temporary file and save the result into the output file.
     317
     318        if ( fork() == 0 ) {                                                            // child runs CFA
     319                uargs[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str();
     320
     321                uargs[nuargs] = "-p";
     322                nuargs += 1;
     323
     324                uargs[nuargs] = tmpname;
     325                nuargs += 1;
     326                if ( o_name != NULL ) {
     327                        uargs[nuargs] = o_name;
     328                        nuargs += 1;
     329                } else if ( ! CFA_flag ) {                                              // run cfa-cpp ?
     330                        uargs[nuargs] = cpp_out;
     331                        nuargs += 1;
     332                } // if
     333                uargs[nuargs] = NULL;                                                   // terminate argument list
     334
     335#ifdef __DEBUG_H__
     336                cerr << "cfa-cpp nuargs: " << o_name << " " << CFA_flag << " " << nuargs << endl;
     337                for ( i = 0; uargs[i] != NULL; i += 1 ) {
     338                        cerr << uargs[i] << " ";
     339                } // for
     340                cerr << endl;
     341#endif // __DEBUG_H__
     342
     343                execvp( uargs[0], (char * const *)uargs );              // should not return
     344                perror( "CFA Translator error: cpp level, execvp" );
     345                exit( EXIT_FAILURE );
     346        } // if
     347
     348        wait( &code );                                                                          // wait for child to finish
     349
     350#ifdef __DEBUG_H__
     351        cerr << "return code from cfa-cpp:" << WEXITSTATUS(code) << endl;
     352#endif // __DEBUG_H__
     353
     354        // Must unlink here because file must exist across execvp.
     355        rmtmpfile();                                                                            // remove tmpname
     356
     357        if ( WIFSIGNALED(code) ) {                                                      // child failed ?
     358                cerr << "CFA Translator error: cfa-cpp failed with signal " << WTERMSIG(code) << endl;
     359                exit( EXIT_FAILURE );
     360        } // if
     361
     362        exit( WEXITSTATUS(code) );
     363} // Stage1
     364
     365
     366void Stage2( const int argc, const char * const * argv ) {
     367        int i;
     368
     369        string arg;
     370
     371        const char *cpp_in = NULL;
     372
     373        const char *args[argc + 100];                                           // leave space for 100 additional cfa command line values
     374        int nargs = 1;                                                                          // number of arguments in args list; 0 => command name
     375
     376        // process all the arguments
     377
     378        checkEnv( args, nargs );                                                        // arguments passed via environment variables
     379
     380        for ( i = 1; i < argc; i += 1 ) {
     381#ifdef __DEBUG_H__
     382                cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     383#endif // __DEBUG_H__
     384                arg = argv[i];
     385#ifdef __DEBUG_H__
     386                cerr << "arg:\"" << arg << "\"" << endl;
     387#endif // __DEBUG_H__
     388                if ( prefix( arg, "-" ) ) {
     389                        // strip inappropriate flags
     390
     391                        if ( arg == "-quiet" || arg == "-version" || arg == "-fpreprocessed" ||
     392                                 // Currently CFA does not suppose precompiled .h files.
     393                                 prefix( arg, "--output-pch" ) ) {
     394
     395                                // strip inappropriate flags with an argument
     396
     397                        } else if ( arg == "-auxbase" || arg == "-auxbase-strip" || arg == "-dumpbase" ) {
     398                                i += 1;
     399#ifdef __DEBUG_H__
     400                                cerr << "arg:\"" << argv[i] << "\"" << endl;
     401#endif // __DEBUG_H__
     402
     403                                // all other flags
     404
     405                        } else {
     406                                args[nargs] = argv[i];                                  // pass the flag along
     407                                nargs += 1;
     408                                if ( arg == "-o" ) {
     409                                        i += 1;
     410                                        args[nargs] = argv[i];                          // pass the argument along
     411                                        nargs += 1;
     412#ifdef __DEBUG_H__
     413                                        cerr << "arg:\"" << argv[i] << "\"" << endl;
     414#endif // __DEBUG_H__
     415                                } // if
     416                        } // if
     417                } else {                                                                                // obtain input and possibly output files
     418                        if ( cpp_in == NULL ) {
     419                                cpp_in = argv[i];
     420#ifdef __DEBUG_H__
     421                                cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
     422#endif // __DEBUG_H__
     423                        } else {
     424                                cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
     425                                exit( EXIT_FAILURE );
     426                        } // if
     427                } // if
     428        } // for
     429
     430#ifdef __DEBUG_H__
     431        cerr << "args:";
     432        for ( i = 1; i < nargs; i += 1 ) {
     433                cerr << " " << args[i];
     434        } // for
     435        cerr << endl;
     436        if ( cpp_in != NULL ) cerr << " " << cpp_in;
     437#endif // __DEBUG_H__
     438
     439        args[0] = compiler_name.c_str();
     440        args[nargs] = "-S";                                                                     // only compile and put assembler output in specified file
    62441        nargs += 1;
    63     } // if
    64 
    65     value = getenv( "__GCC_VERSION__" );
    66     if ( value != NULL ) {
    67         args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along
    68 #ifdef __DEBUG_H__
    69         cerr << "env arg:\"" << args[nargs] << "\"" << endl;
    70 #endif // __DEBUG_H__
    71         nargs += 1;
    72     } // if
    73 } // checkEnv
    74 
    75 
    76 void rmtmpfile() {
    77     if ( unlink( tmpname ) == -1 ) {                    // remove tmpname
    78         perror ( "CFA Translator error: cpp failed" );
    79         exit( EXIT_FAILURE );
    80     } // if
    81     tmpfilefd = -1;                                     // mark closed
    82 } // rmtmpfile
    83 
    84 
    85 void sigTermHandler( int signal ) {
    86     if ( tmpfilefd != -1 ) {                            // RACE, file created ?
    87         rmtmpfile();                                    // remove
    88         exit( EXIT_FAILURE );                           // terminate
    89     } // if
    90 } // sigTermHandler
    91 
    92 
    93 void Stage1( const int argc, const char * const argv[] ) {
    94     int code;
    95     int i;
    96 
    97     string arg;
    98     string bprefix;
    99 
    100     const char *cpp_in = NULL;
    101     const char *cpp_out = NULL;
    102 
    103     bool CFA_flag = false;
    104     bool cpp_flag = false;
    105     const char *o_name = NULL;
    106 
    107     const char *args[argc + 100];                       // leave space for 100 additional cpp command line values
    108     int nargs = 1;                                      // number of arguments in args list; 0 => command name
    109     const char *uargs[20];                              // leave space for 20 additional cfa-cpp command line values
    110     int nuargs = 1;                                     // 0 => command name
    111 
    112     signal( SIGINT,  sigTermHandler );
    113     signal( SIGTERM, sigTermHandler );
    114 
    115     // process all the arguments
    116 
    117     checkEnv( args, nargs );                            // arguments passed via environment variables
    118 
    119     for ( i = 1; i < argc; i += 1 ) {
    120 #ifdef __DEBUG_H__
    121         cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    122 #endif // __DEBUG_H__
    123         arg = argv[i];
    124 #ifdef __DEBUG_H__
    125         cerr << "arg:\"" << arg << "\"" << endl;
    126 #endif // __DEBUG_H__
    127         if ( prefix( arg, "-" ) ) {
    128             // strip g++ flags that are inappropriate or cause duplicates in subsequent passes
    129 
    130             if ( arg == "-quiet" ) {
    131             } else if ( arg == "-imultilib" || arg == "-imultiarch" ) {
    132                 i += 1;                                 // and the argument
    133             } else if ( prefix( arg, "-A" ) ) {
    134             } else if ( prefix( arg, "-D__GNU" ) ) {
    135             //********
    136             // GCC 5.6.0 SEPARATED THE -D FROM THE ARGUMENT!
    137             //********
    138             } else if ( arg == "-D" && prefix( argv[i + 1], "__GNU" ) ) {
    139                 i += 1;                                 // and the argument
    140 
    141             // strip flags controlling cpp step
    142 
    143             } else if ( arg == "-D__CPP__" ) {
    144                 cpp_flag = true;
    145             } else if ( arg == "-D" && string( argv[i + 1] ) == "__CPP__" ) {
    146                 i += 1;                                 // and the argument
    147                 cpp_flag = true;
    148             } else if ( arg == "-D__CFA__" ) {
    149                 CFA_flag = true;
    150             } else if ( arg == "-D" && string( argv[i + 1] ) == "__CFA__" ) {
    151                 i += 1;                                 // and the argument
    152                 CFA_flag = true;
    153             } else if ( prefix( arg, D__CFA_FLAGPREFIX__ ) ) {
    154                 uargs[nuargs] = ( *new string( arg.substr( D__CFA_FLAGPREFIX__.size() ) ) ).c_str();
    155                 nuargs += 1;
    156             } else if ( arg == "-D" && prefix( argv[i + 1], D__CFA_FLAGPREFIX__.substr(2) ) ) {
    157                 uargs[nuargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
    158                 nuargs += 1;
    159                 i += 1;                                 // and the argument
    160             } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) {
    161                 bprefix = arg.substr( D__GCC_BPREFIX__.size() );
    162             } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_BPREFIX__.substr(2) ) ) {
    163                 bprefix = string( argv[i + 1] ).substr( D__GCC_BPREFIX__.size() - 2 );
    164                 i += 1;                                 // and the argument
    165 
    166             // all other flags
    167 
    168             } else if ( arg == "-o" ) {
    169                 i += 1;
    170                 o_name = argv[i];
    171             } else {
    172                 args[nargs] = argv[i];                  // pass the flag along
    173                 nargs += 1;
    174                 // CPP flags with an argument
    175                 if ( arg == "-D" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" ||
    176                      arg == "-include" || arg == "-imacros" || arg == "-idirafter" || arg == "-iprefix" ||
    177                      arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) {
    178                     i += 1;
    179                     args[nargs] = argv[i];              // pass the argument along
    180                     nargs += 1;
    181 #ifdef __DEBUG_H__
    182                     cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    183 #endif // __DEBUG_H__
    184                 } else if ( arg == "-MD" || arg == "-MMD" ) {
    185                     args[nargs] = "-MF";                // insert before file
    186                     nargs += 1;
    187                     i += 1;
    188                     args[nargs] = argv[i];              // pass the argument along
    189                     nargs += 1;
    190 #ifdef __DEBUG_H__
    191                     cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    192 #endif // __DEBUG_H__
    193                 } // if
    194             } // if
    195         } else {                                        // obtain input and possibly output files
    196             if ( cpp_in == NULL ) {
    197                 cpp_in = argv[i];
    198 #ifdef __DEBUG_H__
    199                 cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
    200 #endif // __DEBUG_H__
    201             } else if ( cpp_out == NULL ) {
    202                 cpp_out = argv[i];
    203 #ifdef __DEBUG_H__
    204                 cerr << "cpp_out:\"" << cpp_out << "\""<< endl;
    205 #endif // __DEBUG_H__
    206             } else {
    207                 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
    208                 exit( EXIT_FAILURE );
    209             } // if
    210         } // if
    211     } // for
    212 
    213 #ifdef __DEBUG_H__
    214     cerr << "args:";
    215     for ( i = 1; i < nargs; i += 1 ) {
    216         cerr << " " << args[i];
    217     } // for
    218     if ( cpp_in != NULL ) cerr << " " << cpp_in;
    219     if ( cpp_out != NULL ) cerr << " " << cpp_out;
    220     cerr << endl;
    221 #endif // __DEBUG_H__
    222 
    223     if ( cpp_in == NULL ) {
    224         cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
    225         exit( EXIT_FAILURE );
    226     } // if
    227 
    228     if ( cpp_flag ) {
    229         // The -E flag is specified on the cfa command so only run the preprocessor and output is written to standard
    230         // output or -o. The call to cfa has a -E so it does not have to be added to the argument list.
    231 
    232         args[0] = compiler_name.c_str();
    233442        args[nargs] = cpp_in;
    234443        nargs += 1;
    235         if ( o_name != NULL ) {                         // location for output
    236             args[nargs] = "-o";
    237             nargs += 1;
    238             args[nargs] = o_name;
    239             nargs += 1;
    240         } // if
    241         args[nargs] = NULL;                             // terminate argument list
    242 
    243 #ifdef __DEBUG_H__
    244         cerr << "nargs: " << nargs << endl;
     444        args[nargs] = NULL;                                                                     // terminate argument list
     445
     446#ifdef __DEBUG_H__
     447        cerr << "stage2 nargs: " << nargs << endl;
    245448        for ( i = 0; args[i] != NULL; i += 1 ) {
    246             cerr << args[i] << " ";
     449                cerr << args[i] << " ";
    247450        } // for
    248451        cerr << endl;
    249452#endif // __DEBUG_H__
    250453
    251         execvp( args[0], (char *const *)args );         // should not return
     454        execvp( args[0], (char * const *)args );                        // should not return
    252455        perror( "CFA Translator error: cpp level, execvp" );
    253         exit( EXIT_FAILURE );
    254     } // if
    255 
    256     // Create a temporary file to store output of the C preprocessor.
    257 
    258     tmpfilefd = mkstemp( tmpname );
    259     if ( tmpfilefd == -1 ) {
    260         perror( "CFA Translator error: cpp level, mkstemp" );
    261         exit( EXIT_FAILURE );
    262     } // if
    263 
    264 #ifdef __DEBUG_H__
    265     cerr << "tmpname:" << tmpname << " tmpfilefd:" << tmpfilefd << endl;
    266 #endif // __DEBUG_H__
    267 
    268     // Run the C preprocessor and save the output in tmpfile.
    269 
    270     if ( fork() == 0 ) {                                // child process ?
    271         // -o xxx.ii cannot be used to write the output file from cpp because no output file is created if cpp detects
    272         // an error (e.g., cannot find include file). Whereas, output is always generated, even when there is an error,
    273         // when cpp writes to stdout. Hence, stdout is redirected into the temporary file.
    274         if ( freopen( tmpname, "w", stdout ) == NULL ) { // redirect stdout to tmpname
    275             perror( "CFA Translator error: cpp level, freopen" );
    276             exit( EXIT_FAILURE );
    277         } // if
    278 
    279         args[0] = compiler_name.c_str();
    280         args[nargs] = cpp_in;                           // input to cpp
    281         nargs += 1;
    282         args[nargs] = NULL;                             // terminate argument list
    283 
    284 #ifdef __DEBUG_H__
    285         cerr << "cpp nargs: " << nargs << endl;
    286         for ( i = 0; args[i] != NULL; i += 1 ) {
    287             cerr << args[i] << " ";
    288         } // for
    289         cerr << endl;
    290 #endif // __DEBUG_H__
    291 
    292         execvp( args[0], (char *const *)args );         // should not return
    293         perror( "CFA Translator error: cpp level, execvp" );
    294         exit( EXIT_FAILURE );
    295     } // if
    296 
    297     wait( &code );                                      // wait for child to finish
    298 
    299 #ifdef __DEBUG_H__
    300     cerr << "return code from cpp:" << WEXITSTATUS(code) << endl;
    301 #endif // __DEBUG_H__
    302 
    303     if ( WIFSIGNALED(code) != 0 ) {                     // child failed ?
    304         rmtmpfile();                                    // remove tmpname
    305         cerr << "CFA Translator error: cpp failed with signal " << WTERMSIG(code) << endl;
    306         exit( EXIT_FAILURE );
    307     } // if
    308 
    309     if ( WEXITSTATUS(code) != 0 ) {                     // child error ?
    310         rmtmpfile();                                    // remove tmpname
    311         exit( WEXITSTATUS( code ) );                    // do not continue
    312     } // if
    313 
    314     // If -CFA flag specified, run the cfa-cpp preprocessor on the temporary file, and output is written to standard
    315     // output.  Otherwise, run the cfa-cpp preprocessor on the temporary file and save the result into the output file.
    316 
    317     if ( fork() == 0 ) {                                // child runs CFA
    318         uargs[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str();
    319 
    320         uargs[nuargs] = "-p";
    321         nuargs += 1;
    322 
    323         uargs[nuargs] = tmpname;
    324         nuargs += 1;
    325         if ( o_name != NULL ) {
    326             uargs[nuargs] = o_name;
    327             nuargs += 1;
    328         } else if ( ! CFA_flag ) {                      // run cfa-cpp ?
    329             uargs[nuargs] = cpp_out;
    330             nuargs += 1;
    331         } // if
    332         uargs[nuargs] = NULL;                           // terminate argument list
    333 
    334 #ifdef __DEBUG_H__
    335         cerr << "cfa-cpp nuargs: " << o_name << " " << CFA_flag << " " << nuargs << endl;
    336         for ( i = 0; uargs[i] != NULL; i += 1 ) {
    337             cerr << uargs[i] << " ";
    338         } // for
    339         cerr << endl;
    340 #endif // __DEBUG_H__
    341 
    342         execvp( uargs[0], (char * const *)uargs );      // should not return
    343         perror( "CFA Translator error: cpp level, execvp" );
    344         exit( EXIT_FAILURE );
    345     } // if
    346 
    347     wait( &code );                                      // wait for child to finish
    348 
    349 #ifdef __DEBUG_H__
    350     cerr << "return code from cfa-cpp:" << WEXITSTATUS(code) << endl;
    351 #endif // __DEBUG_H__
    352 
    353     // Must unlink here because file must exist across execvp.
    354     rmtmpfile();                                        // remove tmpname
    355 
    356     if ( WIFSIGNALED(code) ) {                          // child failed ?
    357         cerr << "CFA Translator error: cfa-cpp failed with signal " << WTERMSIG(code) << endl;
    358         exit( EXIT_FAILURE );
    359     } // if
    360 
    361     exit( WEXITSTATUS(code) );
    362 } // Stage1
    363 
    364 
    365 void Stage2( const int argc, const char * const * argv ) {
    366     int i;
    367 
    368     string arg;
    369 
    370     const char *cpp_in = NULL;
    371 
    372     const char *args[argc + 100];                       // leave space for 100 additional cfa command line values
    373     int nargs = 1;                                      // number of arguments in args list; 0 => command name
    374 
    375     // process all the arguments
    376 
    377     checkEnv( args, nargs );                            // arguments passed via environment variables
    378 
    379     for ( i = 1; i < argc; i += 1 ) {
    380 #ifdef __DEBUG_H__
    381         cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    382 #endif // __DEBUG_H__
    383         arg = argv[i];
    384 #ifdef __DEBUG_H__
    385         cerr << "arg:\"" << arg << "\"" << endl;
    386 #endif // __DEBUG_H__
    387         if ( prefix( arg, "-" ) ) {
    388             // strip inappropriate flags
    389 
    390             if ( arg == "-quiet" || arg == "-version" || arg == "-fpreprocessed" ||
    391                  // Currently CFA does not suppose precompiled .h files.
    392                  prefix( arg, "--output-pch" ) ) {
    393 
    394             // strip inappropriate flags with an argument
    395 
    396             } else if ( arg == "-auxbase" || arg == "-auxbase-strip" || arg == "-dumpbase" ) {
    397                 i += 1;
    398 #ifdef __DEBUG_H__
    399                 cerr << "arg:\"" << argv[i] << "\"" << endl;
    400 #endif // __DEBUG_H__
    401 
    402             // all other flags
    403 
    404             } else {
    405                 args[nargs] = argv[i];                  // pass the flag along
    406                 nargs += 1;
    407                 if ( arg == "-o" ) {
    408                     i += 1;
    409                     args[nargs] = argv[i];              // pass the argument along
    410                     nargs += 1;
    411 #ifdef __DEBUG_H__
    412                     cerr << "arg:\"" << argv[i] << "\"" << endl;
    413 #endif // __DEBUG_H__
    414                 } // if
    415             } // if
    416         } else {                                        // obtain input and possibly output files
    417             if ( cpp_in == NULL ) {
    418                 cpp_in = argv[i];
    419 #ifdef __DEBUG_H__
    420                 cerr << "cpp_in:\"" << cpp_in << "\"" << endl;
    421 #endif // __DEBUG_H__
    422             } else {
     456        exit( EXIT_FAILURE );                                                           // tell gcc not to go any further
     457} // Stage2
     458
     459
     460int main( const int argc, const char * const argv[], const char * const env[] ) {
     461#ifdef __DEBUG_H__
     462        for ( int i = 0; env[i] != NULL; i += 1 ) {
     463                cerr << env[i] << endl;
     464        } // for
     465#endif // __DEBUG_H__
     466
     467        string arg = argv[1];
     468
     469        // Currently, stage 1 starts with flag -E and stage 2 with flag -fpreprocessed.
     470
     471        if ( arg == "-E" ) {
     472#ifdef __DEBUG_H__
     473                cerr << "Stage1" << endl;
     474#endif // __DEBUG_H__
     475                Stage1( argc, argv );
     476        } else if ( arg == "-fpreprocessed" ) {
     477#ifdef __DEBUG_H__
     478                cerr << "Stage2" << endl;
     479#endif // __DEBUG_H__
     480                Stage2( argc, argv );
     481        } else {
    423482                cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
    424483                exit( EXIT_FAILURE );
    425             } // if
    426         } // if
    427     } // for
    428 
    429 #ifdef __DEBUG_H__
    430     cerr << "args:";
    431     for ( i = 1; i < nargs; i += 1 ) {
    432         cerr << " " << args[i];
    433     } // for
    434     cerr << endl;
    435     if ( cpp_in != NULL ) cerr << " " << cpp_in;
    436 #endif // __DEBUG_H__
    437 
    438     args[0] = compiler_name.c_str();
    439     args[nargs] = "-S";                                 // only compile and put assembler output in specified file
    440     nargs += 1;
    441     args[nargs] = cpp_in;
    442     nargs += 1;
    443     args[nargs] = NULL;                                 // terminate argument list
    444 
    445 #ifdef __DEBUG_H__
    446     cerr << "stage2 nargs: " << nargs << endl;
    447     for ( i = 0; args[i] != NULL; i += 1 ) {
    448         cerr << args[i] << " ";
    449     } // for
    450     cerr << endl;
    451 #endif // __DEBUG_H__
    452 
    453     execvp( args[0], (char * const *)args );            // should not return
    454     perror( "CFA Translator error: cpp level, execvp" );
    455     exit( EXIT_FAILURE );                               // tell gcc not to go any further
    456 } // Stage2
    457 
    458 
    459 int main( const int argc, const char * const argv[], const char * const env[] ) {
    460 #ifdef __DEBUG_H__
    461     for ( int i = 0; env[i] != NULL; i += 1 ) {
    462         cerr << env[i] << endl;
    463     } // for
    464 #endif // __DEBUG_H__
    465 
    466     string arg = argv[1];
    467 
    468     // Currently, stage 1 starts with flag -E and stage 2 with flag -fpreprocessed.
    469 
    470     if ( arg == "-E" ) {
    471 #ifdef __DEBUG_H__
    472         cerr << "Stage1" << endl;
    473 #endif // __DEBUG_H__
    474         Stage1( argc, argv );
    475     } else if ( arg == "-fpreprocessed" ) {
    476 #ifdef __DEBUG_H__
    477         cerr << "Stage2" << endl;
    478 #endif // __DEBUG_H__
    479         Stage2( argc, argv );
    480     } else {
    481         cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl;
    482         exit( EXIT_FAILURE );
    483     } // if
     484        } // if
    484485} // main
    485486
    486 
    487487// Local Variables: //
     488// tab-width: 4 //
     489// mode: c++ //
    488490// compile-command: "make install" //
    489491// End: //
  • driver/cfa.cc

    rb8508a2 rb87a5ed  
    1 //                              -*- Mode: C++ -*-
    2 //
    3 // CForall Version 1.0, Copyright (C) Peter A. Buhr 2002
    4 //
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
    57// cfa.cc --
    6 // 
     8//
    79// Author           : Peter A. Buhr
    810// Created On       : Tue Aug 20 13:44:49 2002
    911// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Fri May 15 15:01:26 2015
    11 // Update Count     : 108
    12 // 
     12// Last Modified On : Sat May 16 07:47:05 2015
     13// Update Count     : 111
     14//
    1315
    1416#include <iostream>
    15 #include <cstdio>                                       // perror
    16 #include <cstdlib>                                      // putenv, exit
    17 #include <unistd.h>                                     // execvp
    18 #include <string>                                       // STL version
    19 
    20 #include "config.h"                                     // configure info
     17#include <cstdio>                                                                               // perror
     18#include <cstdlib>                                                                              // putenv, exit
     19#include <unistd.h>                                                                             // execvp
     20#include <string>                                                                               // STL version
     21
     22#include "config.h"                                                                             // configure info
    2123
    2224using std::cerr;
     
    2931
    3032bool prefix( string arg, string pre ) {
    31     return arg.substr( 0, pre.size() ) == pre;
     33        return arg.substr( 0, pre.size() ) == pre;
    3234} // prefix
    3335
    3436
    3537void shuffle( const char *args[], int S, int E, int N ) {
    36     // S & E index 1 passed the end so adjust with -1
    37 #ifdef __DEBUG_H__
    38     cerr << "shuffle:" << S << " " << E << " " << N << endl;
    39 #endif // __DEBUG_H__
    40     for ( int j = E-1 + N; j > S-1 + N; j -=1 ) {
    41 #ifdef __DEBUG_H__
    42         cerr << "\t" << j << " " << j-N << endl;
    43 #endif // __DEBUG_H__
    44         args[j] = args[j-N];
    45     } // for
     38        // S & E index 1 passed the end so adjust with -1
     39#ifdef __DEBUG_H__
     40        cerr << "shuffle:" << S << " " << E << " " << N << endl;
     41#endif // __DEBUG_H__
     42        for ( int j = E-1 + N; j > S-1 + N; j -=1 ) {
     43#ifdef __DEBUG_H__
     44                cerr << "\t" << j << " " << j-N << endl;
     45#endif // __DEBUG_H__
     46                args[j] = args[j-N];
     47        } // for
    4648} // shuffle
    4749
    4850
    4951int main( int argc, char *argv[] ) {
    50     string Version( VERSION );                          // current version number from CONFIG
    51     string Major( "0" ), Minor( "0" ), Patch( "0" );    // default version numbers
    52     int posn1 = Version.find( "." );                    // find the divider between major and minor version numbers
    53     if ( posn1 == -1 ) {                                // not there ?
    54         Major = Version;
    55     } else {
    56         Major = Version.substr( 0, posn1 );
    57         int posn2 = Version.find( ".", posn1 + 1 );     // find the divider between minor and patch numbers
    58         if ( posn2 == -1 ) {                            // not there ?
    59             Minor = Version.substr( posn1 );
     52        string Version( VERSION );                                                      // current version number from CONFIG
     53        string Major( "0" ), Minor( "0" ), Patch( "0" );        // default version numbers
     54        int posn1 = Version.find( "." );                                        // find the divider between major and minor version numbers
     55        if ( posn1 == -1 ) {                                                            // not there ?
     56                Major = Version;
    6057        } else {
    61             Minor = Version.substr( posn1 + 1, posn2 - posn1 - 1 );
    62             Patch = Version.substr( posn2 + 1 );
    63         } // if
    64     } // if
    65 
    66     string installincdir( CFA_INCDIR );                 // fixed location of cc1 and cfa-cpp commands
    67     string installlibdir( CFA_LIBDIR );                 // fixed location of include files
    68 
    69     string heading;                                     // banner printed at start of cfa compilation
    70     string arg;                                         // current command-line argument during command-line parsing
    71     string Bprefix;                                     // path where gcc looks for compiler command steps
    72     string langstd;                                     // language standard
    73 
    74     string compiler_path( GCC_PATH );                   // path/name of C compiler
    75     string compiler_name;                               // name of C compiler
    76 
    77     bool nonoptarg = false;                             // indicates non-option argument specified
    78     bool link = true;                                   // linking as well as compiling
    79     bool verbose = false;                               // -v flag
    80     bool quiet = false;                                 // -quiet flag
    81     bool debug = true;                                  // -debug flag
    82     bool help = false;                                  // -help flag
    83     bool CFA_flag = false;                              // -CFA flag
    84     bool cpp_flag = false;                              // -E or -M flag, preprocessor only
    85     bool debugging = false;                             // -g flag
    86 
    87     const char *args[argc + 100];                       // cfa command line values, plus some space for additional flags
    88     int sargs = 1;                                      // starting location for arguments in args list
    89     int nargs = sargs;                                  // number of arguments in args list; 0 => command name
    90 
    91     const char *libs[argc + 20];                        // non-user libraries must come separately, plus some added libraries and flags
    92     int nlibs = 0;
    93 
    94 #ifdef __DEBUG_H__
    95     cerr << "CFA:" << endl;
    96 #endif // __DEBUG_H__
    97 
    98     // process command-line arguments
    99 
    100     for ( int i = 1; i < argc; i += 1 ) {
    101 #ifdef __DEBUG_H__
    102         cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    103 #endif // __DEBUG_H__
    104         arg = argv[i];                                  // convert to string value
    105 #ifdef __DEBUG_H__
    106         cerr << "arg:\"" << arg << "\"" << endl;
    107 #endif // __DEBUG_H__
    108         if ( prefix( arg, "-" ) ) {
    109             // pass through arguments
    110 
    111             if ( arg == "-Xlinker" || arg == "-o" ) {
    112                 args[nargs] = argv[i];                  // pass the argument along
    113                 nargs += 1;
    114                 i += 1;
    115                 if ( i == argc ) continue;              // next argument available ?
    116                 args[nargs] = argv[i];                  // pass the argument along
    117                 nargs += 1;
    118             } else if ( arg == "-XCFA" ) {              // CFA pass through
    119                 i += 1;
    120                 args[nargs] = ( *new string( string("-D__CFA_FLAG__=") + argv[i] ) ).c_str();
    121                 nargs += 1;
    122 
    123             // CFA specific arguments
    124 
    125             } else if ( arg == "-CFA" ) {
    126                 CFA_flag = true;                        // strip the -CFA flag
    127                 link = false;
    128                 args[nargs] = "-E";                     // replace the argument with -E
    129                 nargs += 1;
    130             } else if ( arg == "-debug" ) {
    131                 debug = true;                           // strip the debug flag
    132             } else if ( arg == "-nodebug" ) {
    133                 debug = false;                          // strip the nodebug flag
    134             } else if ( arg == "-quiet" ) {
    135                 quiet = true;                           // strip the quiet flag
    136             } else if ( arg == "-noquiet" ) {
    137                 quiet = false;                          // strip the noquiet flag
    138             } else if ( arg == "-help" ) {
    139                 help = true;                            // strip the help flag
    140             } else if ( arg == "-nohelp" ) {
    141                 help = false;                           // strip the nohelp flag
    142             } else if ( arg == "-compiler" ) {
    143                 // use the user specified compiler
    144                 i += 1;
    145                 if ( i == argc ) continue;              // next argument available ?
    146                 compiler_path = argv[i];
    147                 if ( putenv( (char *)( *new string( string( "__U_COMPILER__=" ) + argv[i]) ).c_str() ) != 0 ) {
    148                     cerr << argv[0] << " error, cannot set environment variable." << endl;
    149                     exit( EXIT_FAILURE );
     58                Major = Version.substr( 0, posn1 );
     59                int posn2 = Version.find( ".", posn1 + 1 );             // find the divider between minor and patch numbers
     60                if ( posn2 == -1 ) {                                                    // not there ?
     61                        Minor = Version.substr( posn1 );
     62                } else {
     63                        Minor = Version.substr( posn1 + 1, posn2 - posn1 - 1 );
     64                        Patch = Version.substr( posn2 + 1 );
    15065                } // if
    151 
    152             // C++ specific arguments
    153 
    154             } else if ( arg == "-v" ) {
    155                 verbose = true;                         // verbosity required
    156                 args[nargs] = argv[i];                  // pass the argument along
    157                 nargs += 1;
    158             } else if ( arg == "-g" ) {
    159                 debugging = true;                       // symbolic debugging required
    160                 args[nargs] = argv[i];                  // pass the argument along
    161                 nargs += 1;
    162             } else if ( prefix( arg, "-B" ) ) {
    163                 Bprefix = arg.substr(2);                // strip the -B flag
     66        } // if
     67
     68        string installincdir( CFA_INCDIR );                                     // fixed location of cc1 and cfa-cpp commands
     69        string installlibdir( CFA_LIBDIR );                                     // fixed location of include files
     70
     71        string heading;                                                                         // banner printed at start of cfa compilation
     72        string arg;                                                                                     // current command-line argument during command-line parsing
     73        string Bprefix;                                                                         // path where gcc looks for compiler command steps
     74        string langstd;                                                                         // language standard
     75
     76        string compiler_path( GCC_PATH );                                       // path/name of C compiler
     77        string compiler_name;                                                           // name of C compiler
     78
     79        bool nonoptarg = false;                                                         // indicates non-option argument specified
     80        bool link = true;                                                                       // linking as well as compiling
     81        bool verbose = false;                                                           // -v flag
     82        bool quiet = false;                                                                     // -quiet flag
     83        bool debug = true;                                                                      // -debug flag
     84        bool help = false;                                                                      // -help flag
     85        bool CFA_flag = false;                                                          // -CFA flag
     86        bool cpp_flag = false;                                                          // -E or -M flag, preprocessor only
     87        bool debugging = false;                                                         // -g flag
     88
     89        const char *args[argc + 100];                                           // cfa command line values, plus some space for additional flags
     90        int sargs = 1;                                                                          // starting location for arguments in args list
     91        int nargs = sargs;                                                                      // number of arguments in args list; 0 => command name
     92
     93        const char *libs[argc + 20];                                            // non-user libraries must come separately, plus some added libraries and flags
     94        int nlibs = 0;
     95
     96#ifdef __DEBUG_H__
     97        cerr << "CFA:" << endl;
     98#endif // __DEBUG_H__
     99
     100        // process command-line arguments
     101
     102        for ( int i = 1; i < argc; i += 1 ) {
     103#ifdef __DEBUG_H__
     104                cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     105#endif // __DEBUG_H__
     106                arg = argv[i];                                                                  // convert to string value
     107#ifdef __DEBUG_H__
     108                cerr << "arg:\"" << arg << "\"" << endl;
     109#endif // __DEBUG_H__
     110                if ( prefix( arg, "-" ) ) {
     111                        // pass through arguments
     112
     113                        if ( arg == "-Xlinker" || arg == "-o" ) {
     114                                args[nargs] = argv[i];                                  // pass the argument along
     115                                nargs += 1;
     116                                i += 1;
     117                                if ( i == argc ) continue;                              // next argument available ?
     118                                args[nargs] = argv[i];                                  // pass the argument along
     119                                nargs += 1;
     120                        } else if ( arg == "-XCFA" ) {                          // CFA pass through
     121                                i += 1;
     122                                args[nargs] = ( *new string( string("-D__CFA_FLAG__=") + argv[i] ) ).c_str();
     123                                nargs += 1;
     124
     125                                // CFA specific arguments
     126
     127                        } else if ( arg == "-CFA" ) {
     128                                CFA_flag = true;                                                // strip the -CFA flag
     129                                link = false;
     130                                args[nargs] = "-E";                                             // replace the argument with -E
     131                                nargs += 1;
     132                        } else if ( arg == "-debug" ) {
     133                                debug = true;                                                   // strip the debug flag
     134                        } else if ( arg == "-nodebug" ) {
     135                                debug = false;                                                  // strip the nodebug flag
     136                        } else if ( arg == "-quiet" ) {
     137                                quiet = true;                                                   // strip the quiet flag
     138                        } else if ( arg == "-noquiet" ) {
     139                                quiet = false;                                                  // strip the noquiet flag
     140                        } else if ( arg == "-help" ) {
     141                                help = true;                                                    // strip the help flag
     142                        } else if ( arg == "-nohelp" ) {
     143                                help = false;                                                   // strip the nohelp flag
     144                        } else if ( arg == "-compiler" ) {
     145                                // use the user specified compiler
     146                                i += 1;
     147                                if ( i == argc ) continue;                              // next argument available ?
     148                                compiler_path = argv[i];
     149                                if ( putenv( (char *)( *new string( string( "__U_COMPILER__=" ) + argv[i]) ).c_str() ) != 0 ) {
     150                                        cerr << argv[0] << " error, cannot set environment variable." << endl;
     151                                        exit( EXIT_FAILURE );
     152                                } // if
     153
     154                                // C++ specific arguments
     155
     156                        } else if ( arg == "-v" ) {
     157                                verbose = true;                                                 // verbosity required
     158                                args[nargs] = argv[i];                                  // pass the argument along
     159                                nargs += 1;
     160                        } else if ( arg == "-g" ) {
     161                                debugging = true;                                               // symbolic debugging required
     162                                args[nargs] = argv[i];                                  // pass the argument along
     163                                nargs += 1;
     164                        } else if ( prefix( arg, "-B" ) ) {
     165                                Bprefix = arg.substr(2);                                // strip the -B flag
     166                                args[nargs] = ( *new string( string("-D__GCC_BPREFIX__=") + Bprefix ) ).c_str();
     167                                nargs += 1;
     168                        } else if ( prefix( arg, "-b" ) ) {
     169                                if ( arg.length() == 2 ) {                              // separate argument ?
     170                                        i += 1;
     171                                        if ( i == argc ) continue;                      // next argument available ?
     172                                        arg += argv[i];                                         // concatenate argument
     173                                } // if
     174                                // later versions of gcc require the -b option to appear at the start of the command line
     175                                shuffle( args, sargs, nargs, 1 );               // make room at front of argument list
     176                                args[sargs] = ( *new string( arg ) ).c_str(); // pass the argument along
     177                                if ( putenv( (char *)( *new string( string( "__GCC_MACHINE__=" ) + arg ) ).c_str() ) != 0 ) {
     178                                        cerr << argv[0] << " error, cannot set environment variable." << endl;
     179                                        exit( EXIT_FAILURE );
     180                                } // if
     181                                sargs += 1;
     182                                nargs += 1;
     183                        } else if ( prefix( arg, "-V" ) ) {
     184                                if ( arg.length() == 2 ) {                              // separate argument ?
     185                                        i += 1;
     186                                        if ( i == argc ) continue;                      // next argument available ?
     187                                        arg += argv[i];                                         // concatenate argument
     188                                } // if
     189                                // later versions of gcc require the -V option to appear at the start of the command line
     190                                shuffle( args, sargs, nargs, 1 );               // make room at front of argument list
     191                                args[sargs] = ( *new string( arg ) ).c_str(); // pass the argument along
     192                                if ( putenv( (char *)( *new string( string( "__GCC_VERSION__=" ) + arg ) ).c_str() ) != 0 ) {
     193                                        cerr << argv[0] << " error, cannot set environment variable." << endl;
     194                                        exit( EXIT_FAILURE );
     195                                } // if
     196                                sargs += 1;
     197                                nargs += 1;
     198                        } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) {
     199                                args[nargs] = argv[i];                                  // pass the argument along
     200                                nargs += 1;
     201                                if ( arg == "-E" || arg == "-M" || arg == "-MM" ) {
     202                                        cpp_flag = true;                                        // cpp only
     203                                } // if
     204                                link = false;                           // no linkage required
     205                        } else if ( arg[1] == 'l' ) {
     206                                // if the user specifies a library, load it after user code
     207                                libs[nlibs] = argv[i];
     208                                nlibs += 1;
     209                        } else {
     210                                // concatenate any other arguments
     211                                args[nargs] = argv[i];
     212                                nargs += 1;
     213                        } // if
     214                } else {
     215                        // concatenate other arguments
     216                        args[nargs] = argv[i];
     217                        nargs += 1;
     218                        nonoptarg = true;
     219                } // if
     220        } // for
     221
     222#ifdef __DEBUG_H__
     223        cerr << "args:";
     224        for ( int i = 1; i < nargs; i += 1 ) {
     225                cerr << " " << args[i];
     226        } // for
     227        cerr << endl;
     228#endif // __DEBUG_H__
     229
     230        if ( cpp_flag && CFA_flag ) {
     231                cerr << argv[0] << " error, cannot use -E and -CFA flags together." << endl;
     232                exit( EXIT_FAILURE );
     233        } // if
     234
     235        string d;
     236        if ( debug ) {
     237                d = "-d";
     238        } // if
     239
     240        args[nargs] = "-I" CFA_INCDIR;
     241        nargs += 1;
     242
     243        if ( link ) {
     244                // include the cfa library in case it's needed
     245                args[nargs] = "-L" CFA_LIBDIR;
     246                nargs += 1;
     247                args[nargs] = "-lcfa";
     248                nargs += 1;
     249        } // if
     250
     251        // add the correct set of flags based on the type of compile this is
     252
     253        args[nargs] = ( *new string( string("-D__CFA_MAJOR__=") + Major ) ).c_str();
     254        nargs += 1;
     255        args[nargs] = ( *new string( string("-D__CFA_MINOR__=") + Minor ) ).c_str();
     256        nargs += 1;
     257
     258        if ( cpp_flag ) {
     259                args[nargs] = "-D__CPP__";
     260                nargs += 1;
     261        } // if
     262
     263        if ( CFA_flag ) {
     264                args[nargs] = "-D__CFA__";
     265                nargs += 1;
     266        } // if
     267
     268        if ( debug ) {
     269                heading += " (debug)";
     270                args[nargs] = "-D__CFA_DEBUG__";
     271                nargs += 1;
     272        } else {
     273                heading += " (no debug)";
     274        } // if
     275
     276        if ( Bprefix.length() == 0 ) {
     277                Bprefix = installlibdir;
    164278                args[nargs] = ( *new string( string("-D__GCC_BPREFIX__=") + Bprefix ) ).c_str();
    165279                nargs += 1;
    166             } else if ( prefix( arg, "-b" ) ) {
    167                 if ( arg.length() == 2 ) {              // separate argument ?
    168                     i += 1;
    169                     if ( i == argc ) continue;          // next argument available ?
    170                     arg += argv[i];                     // concatenate argument
     280        } // if
     281
     282        // execute the compilation command
     283
     284        args[0] = compiler_path.c_str();                                        // set compiler command for exec
     285        // find actual name of the compiler independent of the path to it
     286        int p = compiler_path.find_last_of( '/' );                      // scan r -> l for first '/'
     287        if ( p == -1 ) {
     288                compiler_name = compiler_path;
     289        } else {
     290                compiler_name = *new string( compiler_path.substr( p + 1 ) );
     291        } // if
     292
     293        if ( prefix( compiler_name, "gcc" ) ) {                         // allow suffix on gcc name
     294                args[nargs] = "-no-integrated-cpp";
     295                nargs += 1;
     296                args[nargs] = "-Wno-deprecated";
     297                nargs += 1;
     298                args[nargs] = "-std=c99";
     299                nargs += 1;
     300                args[nargs] = ( *new string( string("-B") + Bprefix + "/" ) ).c_str();
     301                nargs += 1;
     302        } else {
     303                cerr << argv[0] << " error, compiler " << compiler_name << " not supported." << endl;
     304                exit( EXIT_FAILURE );
     305        } // if
     306
     307        for ( int i = 0; i < nlibs; i += 1 ) {                          // copy non-user libraries after all user libraries
     308                args[nargs] = libs[i];
     309                nargs += 1;
     310        } // for
     311
     312        args[nargs] = NULL;                                                                     // terminate with NULL
     313
     314#ifdef __DEBUG_H__
     315        cerr << "nargs: " << nargs << endl;
     316        cerr << "args:" << endl;
     317        for ( int i = 0; args[i] != NULL; i += 1 ) {
     318                cerr << " \"" << args[i] << "\"" << endl;
     319        } // for
     320#endif // __DEBUG_H__
     321
     322        if ( ! quiet ) {
     323                cerr << "CFA " << "Version " << Version << heading << endl;
     324
     325                if ( help ) {
     326                        cerr <<
     327                                "-debug\t\t\t: use cfa runtime with debug checking" << endl <<
     328                                "-help\t\t\t: print this help message" << endl <<
     329                                "-quiet\t\t\t: print no messages from the cfa command" << endl <<
     330                                "-CFA\t\t\t: run the cpp preprocessor and the cfa-cpp translator" << endl <<
     331                                "-XCFA -cfa-cpp-flag\t: pass next flag as-is to the cfa-cpp translator" << endl <<
     332                                "...\t\t\t: any other " << compiler_name << " flags" << endl;
    171333                } // if
    172                 // later versions of gcc require the -b option to appear at the start of the command line
    173                 shuffle( args, sargs, nargs, 1 );       // make room at front of argument list
    174                 args[sargs] = ( *new string( arg ) ).c_str(); // pass the argument along
    175                 if ( putenv( (char *)( *new string( string( "__GCC_MACHINE__=" ) + arg ) ).c_str() ) != 0 ) {
    176                     cerr << argv[0] << " error, cannot set environment variable." << endl;
    177                     exit( EXIT_FAILURE );
    178                 } // if
    179                 sargs += 1;
    180                 nargs += 1;
    181             } else if ( prefix( arg, "-V" ) ) {
    182                 if ( arg.length() == 2 ) {              // separate argument ?
    183                     i += 1;
    184                     if ( i == argc ) continue;          // next argument available ?
    185                     arg += argv[i];                     // concatenate argument
    186                 } // if
    187                 // later versions of gcc require the -V option to appear at the start of the command line
    188                 shuffle( args, sargs, nargs, 1 );       // make room at front of argument list
    189                 args[sargs] = ( *new string( arg ) ).c_str(); // pass the argument along
    190                 if ( putenv( (char *)( *new string( string( "__GCC_VERSION__=" ) + arg ) ).c_str() ) != 0 ) {
    191                     cerr << argv[0] << " error, cannot set environment variable." << endl;
    192                     exit( EXIT_FAILURE );
    193                 } // if
    194                 sargs += 1;
    195                 nargs += 1;
    196             } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) {
    197                 args[nargs] = argv[i];                  // pass the argument along
    198                 nargs += 1;
    199                 if ( arg == "-E" || arg == "-M" || arg == "-MM" ) {
    200                     cpp_flag = true;                    // cpp only
    201                 } // if
    202                 link = false;                           // no linkage required
    203             } else if ( arg[1] == 'l' ) {
    204                 // if the user specifies a library, load it after user code
    205                 libs[nlibs] = argv[i];
    206                 nlibs += 1;
    207             } else {
    208                 // concatenate any other arguments
    209                 args[nargs] = argv[i];
    210                 nargs += 1;
    211             } // if
    212         } else {
    213             // concatenate other arguments
    214             args[nargs] = argv[i];
    215             nargs += 1;
    216             nonoptarg = true;
    217         } // if
    218     } // for
    219 
    220 #ifdef __DEBUG_H__
    221     cerr << "args:";
    222     for ( int i = 1; i < nargs; i += 1 ) {
    223         cerr << " " << args[i];
    224     } // for
    225     cerr << endl;
    226 #endif // __DEBUG_H__
    227 
    228     if ( cpp_flag && CFA_flag ) {
    229         cerr << argv[0] << " error, cannot use -E and -CFA flags together." << endl;
     334        } // if
     335
     336        if ( verbose ) {
     337                if ( argc == 2 ) exit( EXIT_SUCCESS );                  // if only the -v flag is specified, do not invoke gcc
     338
     339                for ( int i = 0; args[i] != NULL; i += 1 ) {
     340                        cerr << args[i] << " ";
     341                } // for
     342                cerr << endl;
     343        } // if
     344
     345        if ( ! nonoptarg ) {
     346                cerr << argv[0] << " error, no input files" << endl;
     347                exit( EXIT_FAILURE );
     348        } // if
     349
     350        // execute the command and return the result
     351
     352        execvp( args[0], (char *const *)args );                         // should not return
     353        perror( "CFA Translator error: cfa level, execvp" );
    230354        exit( EXIT_FAILURE );
    231     } // if
    232 
    233     string d;
    234     if ( debug ) {
    235         d = "-d";
    236     } // if
    237 
    238     args[nargs] = "-I" CFA_INCDIR;
    239     nargs += 1;
    240 
    241     if ( link ) {
    242         // include the cfa library in case it's needed
    243         args[nargs] = "-L" CFA_LIBDIR;
    244         nargs += 1;
    245         args[nargs] = "-lcfa";
    246         nargs += 1;
    247     } // if
    248 
    249     // add the correct set of flags based on the type of compile this is
    250 
    251     args[nargs] = ( *new string( string("-D__CFA_MAJOR__=") + Major ) ).c_str();
    252     nargs += 1;
    253     args[nargs] = ( *new string( string("-D__CFA_MINOR__=") + Minor ) ).c_str();
    254     nargs += 1;
    255 
    256     if ( cpp_flag ) {
    257         args[nargs] = "-D__CPP__";
    258         nargs += 1;
    259     } // if
    260 
    261     if ( CFA_flag ) {
    262         args[nargs] = "-D__CFA__";
    263         nargs += 1;
    264     } // if
    265 
    266     if ( debug ) {
    267         heading += " (debug)";
    268         args[nargs] = "-D__CFA_DEBUG__";
    269         nargs += 1;
    270     } else {
    271         heading += " (no debug)";
    272     } // if
    273 
    274     if ( Bprefix.length() == 0 ) {
    275         Bprefix = installlibdir;
    276         args[nargs] = ( *new string( string("-D__GCC_BPREFIX__=") + Bprefix ) ).c_str();
    277         nargs += 1;
    278     } // if
    279 
    280     // execute the compilation command
    281 
    282     args[0] = compiler_path.c_str();                    // set compiler command for exec
    283     // find actual name of the compiler independent of the path to it
    284     int p = compiler_path.find_last_of( '/' );          // scan r -> l for first '/'
    285     if ( p == -1 ) {
    286         compiler_name = compiler_path;
    287     } else {
    288         compiler_name = *new string( compiler_path.substr( p + 1 ) );
    289     } // if
    290 
    291     if ( prefix( compiler_name, "gcc" ) ) {             // allow suffix on gcc name
    292         args[nargs] = "-no-integrated-cpp";
    293         nargs += 1;
    294         args[nargs] = "-Wno-deprecated";
    295         nargs += 1;
    296         args[nargs] = "-std=c99";
    297         nargs += 1;
    298         args[nargs] = ( *new string( string("-B") + Bprefix + "/" ) ).c_str();
    299         nargs += 1;
    300     } else {
    301         cerr << argv[0] << " error, compiler " << compiler_name << " not supported." << endl;
    302         exit( EXIT_FAILURE );
    303     } // if
    304 
    305     for ( int i = 0; i < nlibs; i += 1 ) {              // copy non-user libraries after all user libraries
    306         args[nargs] = libs[i];
    307         nargs += 1;
    308     } // for
    309 
    310     args[nargs] = NULL;                                 // terminate with NULL
    311 
    312 #ifdef __DEBUG_H__
    313     cerr << "nargs: " << nargs << endl;
    314     cerr << "args:" << endl;
    315     for ( int i = 0; args[i] != NULL; i += 1 ) {
    316         cerr << " \"" << args[i] << "\"" << endl;
    317     } // for
    318 #endif // __DEBUG_H__
    319 
    320     if ( ! quiet ) {
    321         cerr << "CFA " << "Version " << Version << heading << endl;
    322 
    323         if ( help ) {
    324             cerr <<
    325                 "-debug\t\t\t: use cfa runtime with debug checking" << endl <<
    326                 "-help\t\t\t: print this help message" << endl <<
    327                 "-quiet\t\t\t: print no messages from the cfa command" << endl <<
    328                 "-CFA\t\t\t: run the cpp preprocessor and the cfa-cpp translator" << endl <<
    329                 "-XCFA -cfa-cpp-flag\t: pass next flag as-is to the cfa-cpp translator" << endl <<
    330                 "...\t\t\t: any other " << compiler_name << " flags" << endl;
    331         } // if
    332     } // if
    333 
    334     if ( verbose ) {
    335         if ( argc == 2 ) exit( EXIT_SUCCESS );          // if only the -v flag is specified, do not invoke gcc
    336 
    337         for ( int i = 0; args[i] != NULL; i += 1 ) {
    338             cerr << args[i] << " ";
    339         } // for
    340         cerr << endl;
    341     } // if
    342 
    343     if ( ! nonoptarg ) {
    344         cerr << argv[0] << " error, no input files" << endl;
    345         exit( EXIT_FAILURE );
    346     } // if
    347 
    348     // execute the command and return the result
    349 
    350     execvp( args[0], (char *const *)args );             // should not return
    351     perror( "CFA Translator error: cfa level, execvp" );
    352     exit( EXIT_FAILURE );
    353355} // main
    354356
    355357// Local Variables: //
     358// tab-width: 4 //
     359// mode: c++ //
    356360// compile-command: "make install" //
    357361// End: //
  • include/bfd.h

    rb8508a2 rb87a5ed  
    1 //                              -*- Mode: C++ -*-
    2 //
    3 // Cforall Version 1.0.0, Copyright (C) Peter A. Buhr 2015
    4 //
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
    57// bfd.h --
    6 // 
     8//
    79// Author           : Peter A. Buhr
    810// Created On       : Thu Jan  8 15:50:56 2015
    911// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Sat Jan 10 14:12:35 2015
    11 // Update Count     : 3
     12// Last Modified On : Sat May 16 07:54:59 2015
     13// Update Count     : 5
    1214
    1315// This include file uses the CFA keyword "type" as a field name of a structure.
     
    1921
    2022// Local Variables: //
     23// tab-width: 4 //
     24// mode: c++ //
    2125// compile-command: "make install" //
    2226// End: //
  • include/math.h

    rb8508a2 rb87a5ed  
    1 //                              -*- Mode: C++ -*-
    2 //
    3 // Cforall Version 1.0.0, Copyright (C) Peter A. Buhr 2014
    4 //
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
    57// math.h --
    6 // 
     8//
    79// Author           : Peter A. Buhr
    810// Created On       : Mon Nov 10 23:41:29 2014
    911// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Sat Jan 10 14:12:21 2015
    11 // Update Count     : 2
     12// Last Modified On : Sat May 16 07:55:52 2015
     13// Update Count     : 3
    1214
    1315// This include file uses the CFA keyword "type" as a field name of a structure.
     
    1921
    2022// Local Variables: //
     23// tab-width: 4 //
     24// mode: c++ //
    2125// compile-command: "make install" //
    2226// End: //
  • libcfa/Makefile.in

    rb8508a2 rb87a5ed  
     1######################### -*- Mode: Makefile-Gmake -*- ########################
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## Makefile.in --
     9##
     10## Author           : Peter A. Buhr
     11## Created On       : Sat May 16 08:05:18 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat May 16 08:06:05 2015
     14## Update Count     : 1
     15###############################################################################
     16
    117INSTALL=@INSTALL@
    218BACKEND_CC := @BACKEND_CC@
  • libcfa/prototypes.awk

    rb8508a2 rb87a5ed  
     1#
     2# Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3#
     4# The contents of this file are covered under the licence agreement in the
     5# file "LICENCE" distributed with Cforall.
     6#
     7# prototypes.awk --
     8#
     9# Author           : Peter A. Buhr
     10# Created On       : Sat May 16 07:57:37 2015
     11# Last Modified By : Peter A. Buhr
     12# Last Modified On : Sat May 16 08:02:10 2015
     13# Update Count     : 3
     14#
     15
    116# http://llvm.org/svn/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def
    217
     
    419    FS = "("
    520    # order so string search is longest string
    6     types[0]  = "UINTMAX";                      vtypes[0]  = "unsigned long int"
    7     types[1]  = "UINT16";                       vtypes[1]  = "short int"
    8     types[2]  = "UINT32";                       vtypes[2]  = "int"
    9     types[3]  = "UINT64";                       vtypes[3]  = "long long int"
    10     types[4]  = "UINT";                         vtypes[4]  = "unsigned int"
    11     types[5]  = "INTMAX";                       vtypes[5]  = "long int"
    12     types[6]  = "INTPTR";                       vtypes[6]  = "int *"
    13     types[7]  = "WINT";                         vtypes[7]  = "unsigned int"
    14     types[8]  = "INT";                          vtypes[8]  = "int"
    15     types[9]  = "ULONGLONG";                    vtypes[9]  = "unsigned long long"
    16     types[10] = "ULONG";                        vtypes[10] = "unsigned long"
    17     types[11] = "UNSIGNED";                     vtypes[11] = "unsigned"
     21    types[0]  = "UINTMAX";                                      vtypes[0]  = "unsigned long int"
     22    types[1]  = "UINT16";                                       vtypes[1]  = "short int"
     23    types[2]  = "UINT32";                                       vtypes[2]  = "int"
     24    types[3]  = "UINT64";                                       vtypes[3]  = "long long int"
     25    types[4]  = "UINT";                                         vtypes[4]  = "unsigned int"
     26    types[5]  = "INTMAX";                                       vtypes[5]  = "long int"
     27    types[6]  = "INTPTR";                                       vtypes[6]  = "int *"
     28    types[7]  = "WINT";                                         vtypes[7]  = "unsigned int"
     29    types[8]  = "INT";                                          vtypes[8]  = "int"
     30    types[9]  = "ULONGLONG";                            vtypes[9]  = "unsigned long long"
     31    types[10] = "ULONG";                                        vtypes[10] = "unsigned long"
     32    types[11] = "UNSIGNED";                                     vtypes[11] = "unsigned"
    1833    types[12] = "COMPLEX_LONGDOUBLE";           vtypes[12] = "_Complex long double"
    19     types[13] = "COMPLEX_DOUBLE";               vtypes[13] = "_Complex double"
    20     types[14] = "COMPLEX_FLOAT";                vtypes[14] = "_Complex float"
    21     types[15] = "LONGDOUBLEPTR";                vtypes[15] = "long double *"
    22     types[16] = "LONGDOUBLE";                   vtypes[16] = "long double"
    23     types[17] = "LONGLONG";                     vtypes[17] = "long long"
    24     types[18] = "LONG";                         vtypes[18] = "long"
    25     types[19] = "DFLOAT32";                     vtypes[19] = "_Decimal32"
    26     types[20] = "DFLOAT64";                     vtypes[20] = "_Decimal64"
    27     types[21] = "DFLOAT128";                    vtypes[21] = "_Decimal128"
    28     types[22] = "DOUBLEPTR";                    vtypes[22] = "double *"
    29     types[23] = "DOUBLE";                       vtypes[23] = "double"
    30     types[24] = "FLOATPTR";                     vtypes[24] = "float *"
    31     types[25] = "FLOAT";                        vtypes[25] = "float"
    32     types[26] = "CONST_PTR";                    vtypes[26] = "const void *"
    33     types[27] = "CONST_STRING";                 vtypes[27] = "const char *"
     34    types[13] = "COMPLEX_DOUBLE";                       vtypes[13] = "_Complex double"
     35    types[14] = "COMPLEX_FLOAT";                        vtypes[14] = "_Complex float"
     36    types[15] = "LONGDOUBLEPTR";                        vtypes[15] = "long double *"
     37    types[16] = "LONGDOUBLE";                           vtypes[16] = "long double"
     38    types[17] = "LONGLONG";                                     vtypes[17] = "long long"
     39    types[18] = "LONG";                                         vtypes[18] = "long"
     40    types[19] = "DFLOAT32";                                     vtypes[19] = "_Decimal32"
     41    types[20] = "DFLOAT64";                                     vtypes[20] = "_Decimal64"
     42    types[21] = "DFLOAT128";                            vtypes[21] = "_Decimal128"
     43    types[22] = "DOUBLEPTR";                            vtypes[22] = "double *"
     44    types[23] = "DOUBLE";                                       vtypes[23] = "double"
     45    types[24] = "FLOATPTR";                                     vtypes[24] = "float *"
     46    types[25] = "FLOAT";                                        vtypes[25] = "float"
     47    types[26] = "CONST_PTR";                            vtypes[26] = "const void *"
     48    types[27] = "CONST_STRING";                         vtypes[27] = "const char *"
    3449    types[28] = "PTR_FN_VOID_VAR_PTR_SIZE";     vtypes[28] = ""
    35     types[29] = "PTR_CONST_STRING";             vtypes[29] = "char *const"
    36     types[30] = "PTRMODE_PTR";                  vtypes[30] = ""
    37     types[31] = "PTRPTR";                       vtypes[31] = "void **"
    38     types[32] = "PTR";                          vtypes[32] = "void *"
    39     types[33] = "VOID";                         vtypes[33] = "void"
    40     types[34] = "STRING";                       vtypes[34] = "char *"
    41     types[35] = "FILEPTR";                      vtypes[35] = "struct _IO_FILE *"
    42     types[36] = "SIZE";                         vtypes[36] = "unsigned long"
    43     types[37] = "VAR";                          vtypes[37] = "..."
    44     types[38] = "VALIST_ARG";                   vtypes[38] = "void **"
    45     types[39] = "VALIST_REF";                   vtypes[39] = "void **"
    46     types[40] = "UNWINDWORD";                   vtypes[40] = "void *"
    47     types[41] = "WORD";                         vtypes[41] = ""
    48     types[42] = "SSIZE";                        vtypes[42] = "long int"
    49     types[43] = "PID";                          vtypes[43] = "int"
     50    types[29] = "PTR_CONST_STRING";                     vtypes[29] = "char *const"
     51    types[30] = "PTRMODE_PTR";                          vtypes[30] = ""
     52    types[31] = "PTRPTR";                                       vtypes[31] = "void **"
     53    types[32] = "PTR";                                          vtypes[32] = "void *"
     54    types[33] = "VOID";                                         vtypes[33] = "void"
     55    types[34] = "STRING";                                       vtypes[34] = "char *"
     56    types[35] = "FILEPTR";                                      vtypes[35] = "struct _IO_FILE *"
     57    types[36] = "SIZE";                                         vtypes[36] = "unsigned long"
     58    types[37] = "VAR";                                          vtypes[37] = "..."
     59    types[38] = "VALIST_ARG";                           vtypes[38] = "void **"
     60    types[39] = "VALIST_REF";                           vtypes[39] = "void **"
     61    types[40] = "UNWINDWORD";                           vtypes[40] = "void *"
     62    types[41] = "WORD";                                         vtypes[41] = ""
     63    types[42] = "SSIZE";                                        vtypes[42] = "long int"
     64    types[43] = "PID";                                          vtypes[43] = "int"
    5065    N = 44
    5166} # BEGIN
     
    6075    # generate C types for macros names
    6176    for ( i = 0; i < N; i += 1 ) {
    62         printf( "#define BT_%s %s\n", types[i], vtypes[i] )
     77                printf( "#define BT_%s %s\n", types[i], vtypes[i] )
    6378    } # for
    6479    printf( "\n" )
    6580
    6681    for ( prototype in prototypes ) {
    67         if ( index( "BT_LAST", prototype ) == 1 ) {
    68             continue
    69         } # if
     82                if ( index( "BT_LAST", prototype ) == 1 ) {
     83                        continue
     84                } # if
    7085
    71         printf( "#define %s(NAME) FUNC_SIMPLE(", prototype )
     86                printf( "#define %s(NAME) FUNC_SIMPLE(", prototype )
    7287
    73         if ( sub( "BT_FN_", "", prototype ) == 0 ) {
    74             printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype )
    75             exit 0
    76         } # if
     88                if ( sub( "BT_FN_", "", prototype ) == 0 ) {
     89                        printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype )
     90                        exit 0
     91                } # if
    7792
    78         # generate function return type as macro
    79         for ( t = 0; t < N; t += 1 ) {                  # find longest match
    80             type = types[t];
    81             if ( index( prototype, type ) == 1 ) {      # found match
    82                 printf( "BT_%s, NAME", type )
    83                 sub( type, "", prototype )
    84                 break;
    85             } # if
    86         } # for
     93                # generate function return type as macro
     94                for ( t = 0; t < N; t += 1 ) {                                  # find longest match
     95                        type = types[t];
     96                        if ( index( prototype, type ) == 1 ) {          # found match
     97                                printf( "BT_%s, NAME", type )
     98                                sub( type, "", prototype )
     99                                break;
     100                        } # if
     101                } # for
    87102
    88         # generate function parameter types as macro
    89         if ( index( prototype, "VAR" ) != 2 ) {         # C-style empty parameters ?
    90             for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed
    91                 sub( "_", "", prototype)                # remove "_"
    92                 printf( ", ", type )
    93                 temp = prototype
    94                 for ( t = 0; t < N; t += 1 ) {          # find longest match
    95                     type = types[t];
    96                     if ( index( prototype, type ) == 1 ) { # found match
    97                         printf( "BT_%s", type )
    98                         sub( type, "", prototype )
    99                         break;
    100                     } # if
    101                 } # for
    102                 if ( temp == prototype ) {              # no match found for parameter in macro table
    103                     printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype )
    104                     exit 0
     103                # generate function parameter types as macro
     104                if ( index( prototype, "VAR" ) != 2 ) {                 # C-style empty parameters ?
     105                        for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed
     106                                sub( "_", "", prototype)                                # remove "_"
     107                                printf( ", ", type )
     108                                temp = prototype
     109                                for ( t = 0; t < N; t += 1 ) {                  # find longest match
     110                                        type = types[t];
     111                                        if ( index( prototype, type ) == 1 ) { # found match
     112                                                printf( "BT_%s", type )
     113                                                sub( type, "", prototype )
     114                                                break;
     115                                        } # if
     116                                } # for
     117                                if ( temp == prototype ) {                              # no match found for parameter in macro table
     118                                        printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype )
     119                                        exit 0
     120                                } # if
     121                        } # for
    105122                } # if
    106             } # for
    107         } # if
    108         printf( ")\n" )
     123                printf( ")\n" )
    109124    } # for
    110125
     
    115130    printf( "typedef int wchar_t;\n" );
    116131} # END
     132
     133# Local Variables: #
     134# tab-width: 4 #
     135# mode: awk #
     136# compile-command: "make install" #
     137# End: #
  • translator/ArgTweak/FunctionFixer.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// FunctionFixer.cc --
     8//
     9// Author           : Peter A. Buhr
     10// Created On       : Sat May 16 08:12:38 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 08:17:07 2015
     13// Update Count     : 5
     14//
     15
    116#include <list>
    217#include <vector>
     
    1025
    1126namespace ArgTweak {
     27        FunctionFixer::FunctionFixer( SymTab::Indexer *ind ) : index( ind ) {
     28                if ( index == 0 ) index = new SymTab::Indexer();
     29        }
    1230
     31        FunctionFixer::~FunctionFixer() {
     32                delete index;
     33        }
    1334
    14   FunctionFixer::FunctionFixer( SymTab::Indexer *ind ) : index( ind )
    15   {
    16     if ( index == 0 ) index = new SymTab::Indexer();
    17   }
     35        DeclarationWithType *FunctionFixer::mutate( FunctionDecl *functionDecl ) {
     36                index->visit( functionDecl );
     37                /* check for duplicate named parameters here?  It might not be an error if they're never used, on the other hand, it
     38                   might be to costly to check for duplicates every time we try a match */
     39                return Parent::mutate( functionDecl );
     40        }
    1841
    19   FunctionFixer::~FunctionFixer()
    20   {
    21     delete index;
    22   }
     42        Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr ) throw ( SemanticError ) {
     43                assert( untypedExpr != 0 );
     44                NameExpr *function;
    2345
    24   DeclarationWithType *FunctionFixer::mutate( FunctionDecl *functionDecl )
    25   {
    26     index->visit( functionDecl );
    27     /* check for duplicate named parameters here?  It might not be an
    28     error if they're never used, on the other hand, it might be to
    29     costly to check for duplicates every time we try a match */
    30     return Parent::mutate( functionDecl );
    31   }
     46                if ( ( function = dynamic_cast< NameExpr *>(untypedExpr->get_function()) ) != 0 ) {
     47                        std::list < DeclarationWithType * > options;
     48                        index->lookupId ( function->get_name(), options );
     49                        for ( std::list < DeclarationWithType * >::iterator i = options.begin(); i != options.end(); i++ ) {
     50                                FunctionType *f;
     51                                if ( ( f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) ) != 0 ) {
     52                                        std::list < DeclarationWithType * > &pars = f->get_parameters();
    3253
    33   Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr )
    34     throw ( SemanticError )
    35   {
    36     assert( untypedExpr != 0 );
    37     NameExpr *function;
     54                                        bool candidateExists ;
     55                                        for ( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ )
     56                                                if ( ( candidateExists = align( f->get_parameters(), untypedExpr->get_args(), Matcher() ) ) ) break;
    3857
    39     if ( ( function = dynamic_cast< NameExpr *>(untypedExpr->get_function()) ) != 0 )
    40       {
    41         std::list < DeclarationWithType * > options;
    42         index->lookupId ( function->get_name(), options );
    43         for ( std::list < DeclarationWithType * >::iterator i = options.begin(); i != options.end(); i++ )
    44           {
    45             FunctionType *f;
    46             if ( ( f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) ) != 0 )
    47               {
    48                 std::list < DeclarationWithType * > &pars = f->get_parameters();
     58                                        if ( !candidateExists ) throw SemanticError("Error in function call");
     59                                } // if
     60                        } // for
     61                } // if
     62                return untypedExpr;
     63        }
    4964
    50                 bool candidateExists ;
    51                 for( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ )
    52                   if ( ( candidateExists = align( f->get_parameters(), untypedExpr->get_args(), Matcher() ) ) ) break;
     65        template < class L1, class L2, class Helper >
     66        bool align( L1 &pattern, L2 &possible_permutation, Helper help ) {
     67                std::map < typename Helper::key, int > positions;
     68                int p = 0;
    5369
    54                 if ( !candidateExists ) throw SemanticError("Error in function call");
    55               }
    56           }
    57       }
    58     return untypedExpr;
    59   }
     70                for ( typename L1::iterator i = pattern.begin(); i != pattern.end(); i++, p++ )
     71                        if ( help.extract_key( *i ) != Helper::null_key )
     72                                positions[ help.extract_key( *i ) ] = p;
    6073
    61   template < class L1, class L2, class Helper >
    62   bool align( L1 &pattern, L2 &possible_permutation, Helper help )
    63   {
    64     std::map < typename Helper::key, int > positions;
    65     int p = 0;
     74                L2 copy_pp( possible_permutation );
    6675
    67     for ( typename L1::iterator i = pattern.begin(); i != pattern.end(); i++, p++ )
    68       if ( help.extract_key( *i ) != Helper::null_key )
    69         positions[ help.extract_key( *i ) ] = p;
     76                std::vector< typename L2::value_type > temp(copy_pp.size(), Helper::null_value );
     77                for ( typename L2::iterator i = copy_pp.begin(); i != copy_pp.end(); i++ )
     78                        if ( positions.find( help.extract_key( *i ) ) != positions.end() ) {
     79                                temp [ positions [ help.extract_key( *i ) ] ] = *i;
     80                                *i = Helper::null_value;
     81                        } // if
    7082
    71     L2 copy_pp( possible_permutation );
     83                // rest of the arguments
     84                int a = 0;
     85                bool goAhead = true;                                                    // go ahead and change the list
     86                for ( typename L2::iterator i = copy_pp.begin(); i != copy_pp.end(); i++, a++ ) {
     87                        if (  *i != Helper::null_value )
     88                                if ( temp[a] == Helper::null_value )
     89                                        temp[a] = *i;
     90                                else
     91                                        { goAhead = false; /* there's something there already */; break; }
     92                        else
     93                                if ( temp[a] == Helper::null_value )
     94                                        { goAhead = false; /* can't leave empty spaces */ break; }
     95                                else
     96                                        ;                                                                       // all good, this was filled during the first pass
     97                        assert ( temp[a] != Helper::null_value );
     98                } // for
    7299
    73     std::vector< typename L2::value_type > temp(copy_pp.size(), Helper::null_value );
    74     for ( typename L2::iterator i = copy_pp.begin(); i != copy_pp.end(); i++ )
    75       if ( positions.find( help.extract_key( *i ) ) != positions.end() ) {
    76         temp [ positions [ help.extract_key( *i ) ] ] = *i;
    77         *i = Helper::null_value;
    78       }
     100                // Change the original list
     101                if ( goAhead ) std::copy( temp.begin(), temp.end(), possible_permutation.begin() );
    79102
    80     // rest of the arguments
    81     int a = 0;
    82     bool goAhead = true;  // go ahead and change the list
    83     for ( typename L2::iterator i = copy_pp.begin(); i != copy_pp.end(); i++, a++ ) {
    84       if (  *i != Helper::null_value )
    85         if ( temp[a] == Helper::null_value )
    86           temp[a] = *i;
    87         else
    88           { goAhead = false; /* there's something there already */; break; }
    89       else
    90         if ( temp[a] == Helper::null_value )
    91           { goAhead = false; /* can't leave empty spaces */ break; }
    92         else
    93           ; // all good, this was filled during the first pass
    94       assert ( temp[a] != Helper::null_value );
    95     }
     103                return goAhead;
     104        }
    96105
    97     // Change the original list
    98     if ( goAhead ) std::copy( temp.begin(), temp.end(), possible_permutation.begin() );
     106        std::string FunctionFixer::Matcher::null_key("");
     107        Expression *FunctionFixer::Matcher::null_value = 0;
    99108
    100     return goAhead;
    101   }
     109        std::string FunctionFixer::Matcher::extract_key ( DeclarationWithType *decl ) {
     110                return decl->get_name();
     111        }
    102112
    103   std::string FunctionFixer::Matcher::null_key("");
    104   Expression *FunctionFixer::Matcher::null_value = 0;
     113        std::string FunctionFixer::Matcher::extract_key ( Expression *expression ) {
     114                if ( expression->get_argName() == 0 )
     115                        return std::string("");
     116                else
     117                        return *(expression->get_argName());
     118        }
     119} // namespace ArgTweak
    105120
    106   std::string FunctionFixer::Matcher::extract_key ( DeclarationWithType *decl ) {
    107     return decl->get_name();
    108   }
    109 
    110   std::string FunctionFixer::Matcher::extract_key ( Expression *expression ) {
    111     if ( expression->get_argName() == 0 )
    112       return std::string("");
    113     else
    114       return *(expression->get_argName());
    115   }
    116 
    117 } // namespace ArgTweak
     121// Local Variables: //
     122// tab-width: 4 //
     123// mode: c++ //
     124// compile-command: "make install" //
     125// End: //
  • translator/MakeLibCfa.cc

    rb8508a2 rb87a5ed  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: MakeLibCfa.cc,v 1.6 2005/08/29 20:14:14 rcbilson Exp $
    5  *
    6  */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// MakeLibCfa.cc --
     8//
     9// Author           : Richard C. Bilson
     10// Created On       : Sat May 16 10:33:33 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 10:40:44 2015
     13// Update Count     : 13
     14//
    715
    816#include "MakeLibCfa.h"
     17#include "SynTree/Visitor.h"
    918#include "SynTree/Declaration.h"
    1019#include "SynTree/Type.h"
     
    1221#include "SynTree/Statement.h"
    1322#include "SynTree/Initializer.h"
    14 #include "SynTree/Visitor.h"
    1523#include "CodeGen/OperatorTable.h"
    1624#include "UniqueName.h"
    1725
     26namespace LibCfa {
     27        class MakeLibCfa : public Visitor {
     28          public:
     29                void visit( FunctionDecl* funcDecl );
     30                void visit( ObjectDecl* objDecl );
     31 
     32                std::list< Declaration* > &get_newDecls() { return newDecls; }
     33          private:
     34                std::list< Declaration* > newDecls;
     35        };
    1836
    19 namespace LibCfa {
     37        void makeLibCfa( std::list< Declaration* > &prelude ) {
     38                MakeLibCfa maker;
     39                acceptAll( prelude, maker );
     40                prelude.splice( prelude.end(), maker.get_newDecls() );
     41        }
    2042
    21 class MakeLibCfa : public Visitor
    22 {
    23 public:
    24   void visit( FunctionDecl* funcDecl );
    25   void visit( ObjectDecl* objDecl );
     43        void MakeLibCfa::visit( FunctionDecl* origFuncDecl ) {
     44                if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
    2645 
    27   std::list< Declaration* > &get_newDecls() { return newDecls; }
     46                FunctionDecl *funcDecl = origFuncDecl->clone();
     47                CodeGen::OperatorInfo opInfo;
     48                bool lookResult = CodeGen::operatorLookup( funcDecl->get_name(), opInfo );
     49                assert( lookResult );
     50                assert( !funcDecl->get_statements() );
     51                UntypedExpr *newExpr = new UntypedExpr( new NameExpr( funcDecl->get_name() ) );
     52                UniqueName paramNamer( "_p" );
     53                std::list< DeclarationWithType* >::iterator param = funcDecl->get_functionType()->get_parameters().begin();
     54                assert( param != funcDecl->get_functionType()->get_parameters().end() );
     55
     56                if ( (*param)->get_name() == "" ) {
     57                        (*param)->set_name( paramNamer.newName() );
     58                        (*param)->set_linkage( LinkageSpec::C );
     59                } // if
     60
     61                switch( opInfo.type ) {
     62                  case CodeGen::OT_INDEX:
     63                  case CodeGen::OT_CALL:
     64                  case CodeGen::OT_PREFIX:
     65                  case CodeGen::OT_POSTFIX:
     66                  case CodeGen::OT_INFIX:
     67                        newExpr->get_args().push_back( new VariableExpr( *param ) );
     68                        break;
     69                  case CodeGen::OT_PREFIXASSIGN:
     70                  case CodeGen::OT_POSTFIXASSIGN:
     71                  case CodeGen::OT_INFIXASSIGN:
     72                        {
     73                                newExpr->get_args().push_back( new VariableExpr( *param ) );
     74                                // UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     75                                // deref->get_args().push_back( new VariableExpr( *param ) );
     76                                // newExpr->get_args().push_back( deref );
     77                                break;
     78                        }
     79                  case CodeGen::OT_CONSTANT:
     80                        assert( false );
     81                } // switch
     82
     83                for ( param++; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
     84                        if ( (*param)->get_name() == "" ) {
     85                                (*param)->set_name( paramNamer.newName() );
     86                                (*param)->set_linkage( LinkageSpec::C );
     87                        }
     88                        newExpr->get_args().push_back( new VariableExpr( *param ) );
     89                } // for
     90                funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
     91                funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
     92                newDecls.push_back( funcDecl );
     93        }
     94
     95        void MakeLibCfa::visit( ObjectDecl* origObjDecl ) {
     96                if ( origObjDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
    2897 
    29 private:
    30   std::list< Declaration* > newDecls;
    31 };
     98                ObjectDecl *objDecl = origObjDecl->clone();
     99                assert( !objDecl->get_init() );
     100                std::list< Expression* > noDesignators;
     101                objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators ) );
     102                newDecls.push_back( objDecl );
     103        }
     104} // namespace LibCfa
    32105
    33 void
    34 makeLibCfa( std::list< Declaration* > &prelude )
    35 {
    36   MakeLibCfa maker;
    37   acceptAll( prelude, maker );
    38   prelude.splice( prelude.end(), maker.get_newDecls() );
    39 }
    40 
    41 void
    42 MakeLibCfa::visit( FunctionDecl* origFuncDecl )
    43 {
    44   if( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
    45  
    46   FunctionDecl *funcDecl = origFuncDecl->clone();
    47   CodeGen::OperatorInfo opInfo;
    48   bool lookResult = CodeGen::operatorLookup( funcDecl->get_name(), opInfo );
    49   assert( lookResult );
    50   assert( !funcDecl->get_statements() );
    51   UntypedExpr *newExpr = new UntypedExpr( new NameExpr( funcDecl->get_name() ) );
    52   UniqueName paramNamer( "_p" );
    53   std::list< DeclarationWithType* >::iterator param = funcDecl->get_functionType()->get_parameters().begin();
    54   assert( param != funcDecl->get_functionType()->get_parameters().end() );
    55   if( (*param)->get_name() == "" ) {
    56     (*param)->set_name( paramNamer.newName() );
    57     (*param)->set_linkage( LinkageSpec::C );
    58   }
    59   switch( opInfo.type ) {
    60   case CodeGen::OT_INDEX:
    61   case CodeGen::OT_CALL:
    62   case CodeGen::OT_PREFIX:
    63   case CodeGen::OT_POSTFIX:
    64   case CodeGen::OT_INFIX:
    65     newExpr->get_args().push_back( new VariableExpr( *param ) );
    66     break;
    67    
    68   case CodeGen::OT_PREFIXASSIGN:
    69   case CodeGen::OT_POSTFIXASSIGN:
    70   case CodeGen::OT_INFIXASSIGN:
    71   {
    72     newExpr->get_args().push_back( new VariableExpr( *param ) );
    73 ///     UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    74 ///     deref->get_args().push_back( new VariableExpr( *param ) );
    75 ///     newExpr->get_args().push_back( deref );
    76     break;
    77   }
    78    
    79   case CodeGen::OT_CONSTANT:
    80     assert( false );
    81   }
    82   for( param++; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
    83     if( (*param)->get_name() == "" ) {
    84       (*param)->set_name( paramNamer.newName() );
    85       (*param)->set_linkage( LinkageSpec::C );
    86     }
    87     newExpr->get_args().push_back( new VariableExpr( *param ) );
    88   }
    89   funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
    90   funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
    91   newDecls.push_back( funcDecl );
    92 }
    93 
    94 void
    95 MakeLibCfa::visit( ObjectDecl* origObjDecl )
    96 {
    97   if( origObjDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
    98  
    99   ObjectDecl *objDecl = origObjDecl->clone();
    100   assert( !objDecl->get_init() );
    101   std::list< Expression* > noDesignators;
    102   objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators ) );
    103   newDecls.push_back( objDecl );
    104 }
    105 
    106 } // namespace LibCfa
     106// Local Variables: //
     107// tab-width: 4 //
     108// mode: c++ //
     109// compile-command: "make install" //
     110// End: //
  • translator/MakeLibCfa.h

    rb8508a2 rb87a5ed  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: MakeLibCfa.h,v 1.2 2005/08/29 20:14:14 rcbilson Exp $
    5  *
    6  */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// MakeLibCfa.h --
     8//
     9// Author           : Richard C. Bilson
     10// Created On       : Sat May 16 10:42:14 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 10:43:29 2015
     13// Update Count     : 1
     14//
    715
    816#ifndef LIBCFA_MAKELIBCFA_H
     
    1321
    1422namespace LibCfa {
    15 
    16 void makeLibCfa( std::list< Declaration* > &prelude );
    17 
     23        void makeLibCfa( std::list< Declaration* > &prelude );
    1824} // namespace LibCfa
    1925
    20 #endif /* #ifndef LIBCFA_MAKELIBCFA_H */
     26#endif // LIBCFA_MAKELIBCFA_H
     27
     28// Local Variables: //
     29// tab-width: 4 //
     30// mode: c++ //
     31// compile-command: "make install" //
     32// End: //
  • translator/Makefile.in

    rb8508a2 rb87a5ed  
    1 # This makefile is adapted from Peter Miller's article
    2 # "Recursive Make Considered Harmful"
    3 #
    4 # http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html
     1######################### -*- Mode: Makefile-Gmake -*- ########################
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## Makefile.in --
     9##
     10## Author           : Peter A. Buhr
     11## Created On       : Sat May 16 08:37:37 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat May 16 08:38:52 2015
     14## Update Count     : 2
     15###############################################################################
    516
    6 MODULES := Common Parser SynTree SymTab ResolvExpr CodeGen ControlStruct GenPoly Tuples InitTweak Designators #Try ArgTweak Explain
     17# This makefile is adapted from Peter Miller's article "Recursive Make Considered Harmful"
     18
     19MODULES := Common Parser SynTree SymTab ResolvExpr CodeGen ControlStruct GenPoly Tuples InitTweak Designators # Try ArgTweak Explain
    720TARGET := cfa-cpp
    821
    9 all: $(TARGET)
     22all: ${TARGET}
    1023
    1124# look for include files in each of the modules
     
    1629# this is the back-end compiler, used to compile libcfa & builtins to link with user code
    1730BACKEND_CC := @BACKEND_CC@
    18 
    19 # uncomment the definition of this variable to enable purify
    20 #  (do a "purerun" first)
    21 #PURIFY := purify --cache-dir=$(HOME)/tmp
    2231
    2332# extra libraries if required
     
    3140
    3241# include the description for each module
    33 include $(patsubst %,%/module.mk,$(MODULES))
     42include ${patsubst %,%/module.mk,${MODULES}}
    3443
    3544# determine the object files
    36 OBJ := $(patsubst %.cc,%.o,$(filter %.cc,$(SRC))) \
    37        $(patsubst %.y,%.tab.o,$(filter %.y,$(SRC))) \
    38        $(patsubst %.l,%.yy.o,$(filter %.l,$(SRC)))
     45OBJ := ${patsubst %.cc,%.o,${filter %.cc,${SRC}}} \
     46       ${patsubst %.y,%.tab.o,${filter %.y,${SRC}}} \
     47       ${patsubst %.l,%.yy.o,${filter %.l,${SRC}}}
    3948
    4049# include the C include dependencies
    41 DEPS := $(OBJ:.o=.d)
    42 -include $(DEPS)
     50DEPS := ${OBJ:.o=.d}
     51-include ${DEPS}
    4352
    4453# link the program
    45 $(TARGET): $(OBJ)
    46         $(PURIFY) $(CXX) -o $@ $(OBJ) $(LIBS)
     54${TARGET}: ${OBJ}
     55        ${PURIFY} ${CXX} -o $@ ${OBJ} ${LIBS}
    4756
    4857#installing
    49 install: $(TARGET)
    50         $(INSTALL) -d @CFA_LIBDIR@
    51         $(INSTALL) $(TARGET) @CFA_LIBDIR@
     58install: ${TARGET}
     59        ${INSTALL} -d @CFA_LIBDIR@
     60        ${INSTALL} ${TARGET} @CFA_LIBDIR@
    5261
    5362# clean-up rule
    5463clean:
    55         rm -f $(OBJ) $(DEPS) $(TARGET) tags $(EXTRA_OUTPUT)
     64        rm -f ${OBJ} ${DEPS} ${TARGET} tags ${EXTRA_OUTPUT}
    5665        find . -name "Expected*" -prune -o \( -name "*.tst" -o -name "report" \) -print | xargs rm -f
    5766        find . -name "core*" -print | xargs rm -f
  • translator/Parser/DeclarationNode.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// DeclarationNode.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 12:34:05 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 12:38:20 2015
     13// Update Count     : 4
     14//
     15
    116#include <string>
    217#include <list>
     
    2338
    2439DeclarationNode *DeclarationNode::clone() const {
    25     DeclarationNode *newnode = new DeclarationNode;
    26     newnode->type = maybeClone( type );
    27     newnode->name = name;
    28     newnode->storageClasses = storageClasses;
    29     newnode->bitfieldWidth = maybeClone( bitfieldWidth );
    30     newnode->hasEllipsis = hasEllipsis;
    31     newnode->initializer = initializer;
    32     newnode->next = maybeClone( next );
    33     newnode->linkage = linkage;
    34     return newnode;
     40        DeclarationNode *newnode = new DeclarationNode;
     41        newnode->type = maybeClone( type );
     42        newnode->name = name;
     43        newnode->storageClasses = storageClasses;
     44        newnode->bitfieldWidth = maybeClone( bitfieldWidth );
     45        newnode->hasEllipsis = hasEllipsis;
     46        newnode->initializer = initializer;
     47        newnode->next = maybeClone( next );
     48        newnode->linkage = linkage;
     49        return newnode;
    3550}
    3651
     
    3954
    4055DeclarationNode::~DeclarationNode() {
    41     delete type;
    42     delete bitfieldWidth;
    43     delete initializer;
     56        delete type;
     57        delete bitfieldWidth;
     58        delete initializer;
    4459}
    4560
    4661bool DeclarationNode::get_hasEllipsis() const {
    47     return hasEllipsis;
     62        return hasEllipsis;
    4863}
    4964
    5065const char *storageClassName[] = {
    51     // order must correspond with DeclarationNode::StorageClass
    52     "extern",
    53     "static",
    54     "auto",
    55     "register",
    56     "inline",
    57     "fortran",
     66        // order must correspond with DeclarationNode::StorageClass
     67        "extern",
     68        "static",
     69        "auto",
     70        "register",
     71        "inline",
     72        "fortran",
    5873};
    5974
    6075void DeclarationNode::print( std::ostream &os, int indent ) const {
    61     os << string(indent, ' ' );
    62     if ( name == "" ) {
    63         os << "unnamed: ";
    64     } else {
    65         os << name << ": ";
    66     }
    67 
    68     if ( linkage != LinkageSpec::Cforall ) {
    69         os << LinkageSpec::toString( linkage ) << " ";
    70     }
    71 
    72     printEnums( storageClasses.begin(), storageClasses.end(), storageClassName, os );
    73     if ( type ) {
    74         type->print( os, indent );
    75     } else {
    76         os << "untyped entity ";
    77     }
    78 
    79     if ( bitfieldWidth ) {
    80         os << endl << string(indent+2,  ' ') << "with bitfield width ";
    81         bitfieldWidth->printOneLine( os );
    82     }
    83 
    84     if ( initializer != 0 ) {
    85         os << endl << string(indent+2,  ' ') << "with initializer ";
    86         initializer->printOneLine( os );
    87     }
    88 
    89     os << endl;
     76        os << string(indent, ' ' );
     77        if ( name == "" ) {
     78                os << "unnamed: ";
     79        } else {
     80                os << name << ": ";
     81        }
     82
     83        if ( linkage != LinkageSpec::Cforall ) {
     84                os << LinkageSpec::toString( linkage ) << " ";
     85        }
     86
     87        printEnums( storageClasses.begin(), storageClasses.end(), storageClassName, os );
     88        if ( type ) {
     89                type->print( os, indent );
     90        } else {
     91                os << "untyped entity ";
     92        }
     93
     94        if ( bitfieldWidth ) {
     95                os << endl << string(indent+2,  ' ') << "with bitfield width ";
     96                bitfieldWidth->printOneLine( os );
     97        }
     98
     99        if ( initializer != 0 ) {
     100                os << endl << string(indent+2,  ' ') << "with initializer ";
     101                initializer->printOneLine( os );
     102        }
     103
     104        os << endl;
    90105}
    91106
    92107void DeclarationNode::printList( std::ostream &os, int indent ) const {
    93     ParseNode::printList( os, indent );
    94     if ( hasEllipsis ) {
    95         os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
    96     }
     108        ParseNode::printList( os, indent );
     109        if ( hasEllipsis ) {
     110                os << string( indent, ' ' )  << "and a variable number of other arguments" << endl;
     111        }
    97112}
    98113
    99114DeclarationNode *DeclarationNode::newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle ) {
    100     DeclarationNode *newnode = new DeclarationNode;
    101     newnode->name = assign_strptr( name );
    102 
    103     newnode->type = new TypeData( TypeData::Function );
    104     newnode->type->function->params = param;
    105     newnode->type->function->newStyle = newStyle;
    106     newnode->type->function->body = body;
    107 
    108     if ( body ) {
    109         newnode->type->function->hasBody = true;
    110     }
    111 
    112     if ( ret ) {
    113         newnode->type->base = ret->type;
    114         ret->type = 0;
    115         delete ret;
    116     }
    117 
    118     return newnode;
     115        DeclarationNode *newnode = new DeclarationNode;
     116        newnode->name = assign_strptr( name );
     117
     118        newnode->type = new TypeData( TypeData::Function );
     119        newnode->type->function->params = param;
     120        newnode->type->function->newStyle = newStyle;
     121        newnode->type->function->body = body;
     122
     123        if ( body ) {
     124                newnode->type->function->hasBody = true;
     125        }
     126
     127        if ( ret ) {
     128                newnode->type->base = ret->type;
     129                ret->type = 0;
     130                delete ret;
     131        }
     132
     133        return newnode;
    119134}
    120135
    121136DeclarationNode *DeclarationNode::newQualifier( Qualifier q ) {
    122     DeclarationNode *newnode = new DeclarationNode;
    123     newnode->type = new TypeData();
    124     newnode->type->qualifiers.push_back( q );
    125     return newnode;
     137        DeclarationNode *newnode = new DeclarationNode;
     138        newnode->type = new TypeData();
     139        newnode->type->qualifiers.push_back( q );
     140        return newnode;
    126141}
    127142
    128143DeclarationNode *DeclarationNode::newStorageClass( StorageClass sc ) {
    129     DeclarationNode *newnode = new DeclarationNode;
    130     newnode->storageClasses.push_back( sc );
    131     return newnode;
     144        DeclarationNode *newnode = new DeclarationNode;
     145        newnode->storageClasses.push_back( sc );
     146        return newnode;
    132147}
    133148
    134149DeclarationNode *DeclarationNode::newBasicType( BasicType bt ) {
    135     DeclarationNode *newnode = new DeclarationNode;
    136     newnode->type = new TypeData( TypeData::Basic );
    137     newnode->type->basic->typeSpec.push_back( bt );
    138     return newnode;
     150        DeclarationNode *newnode = new DeclarationNode;
     151        newnode->type = new TypeData( TypeData::Basic );
     152        newnode->type->basic->typeSpec.push_back( bt );
     153        return newnode;
    139154}
    140155
    141156DeclarationNode *DeclarationNode::newModifier( Modifier mod ) {
    142     DeclarationNode *newnode = new DeclarationNode;
    143     newnode->type = new TypeData( TypeData::Basic );
    144     newnode->type->basic->modifiers.push_back( mod );
    145     return newnode;
     157        DeclarationNode *newnode = new DeclarationNode;
     158        newnode->type = new TypeData( TypeData::Basic );
     159        newnode->type->basic->modifiers.push_back( mod );
     160        return newnode;
    146161}
    147162
    148163DeclarationNode *DeclarationNode::newForall( DeclarationNode* forall ) {
    149     DeclarationNode *newnode = new DeclarationNode;
    150     newnode->type = new TypeData( TypeData::Unknown );
    151     newnode->type->forall = forall;
    152     return newnode;
     164        DeclarationNode *newnode = new DeclarationNode;
     165        newnode->type = new TypeData( TypeData::Unknown );
     166        newnode->type->forall = forall;
     167        return newnode;
    153168}
    154169
    155170DeclarationNode *DeclarationNode::newFromTypedef( std::string* name ) {
    156     DeclarationNode *newnode = new DeclarationNode;
    157     newnode->type = new TypeData( TypeData::SymbolicInst );
    158     newnode->type->symbolic->name = assign_strptr( name );
    159     newnode->type->symbolic->isTypedef = true;
    160     newnode->type->symbolic->params = 0;
    161     return newnode;
     171        DeclarationNode *newnode = new DeclarationNode;
     172        newnode->type = new TypeData( TypeData::SymbolicInst );
     173        newnode->type->symbolic->name = assign_strptr( name );
     174        newnode->type->symbolic->isTypedef = true;
     175        newnode->type->symbolic->params = 0;
     176        return newnode;
    162177}
    163178
    164179DeclarationNode *DeclarationNode::newAggregate( TyCon kind, std::string* name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields ) {
    165     DeclarationNode *newnode = new DeclarationNode;
    166     newnode->type = new TypeData( TypeData::Aggregate );
    167     newnode->type->aggregate->kind = kind;
    168     newnode->type->aggregate->name = assign_strptr( name );
    169     if ( newnode->type->aggregate->name == "" ) {
    170         newnode->type->aggregate->name = DeclarationNode::anonymous.newName();
    171     }
    172     newnode->type->aggregate->params = formals;
    173     newnode->type->aggregate->actuals = actuals;
    174     newnode->type->aggregate->members = fields;
    175     return newnode;
     180        DeclarationNode *newnode = new DeclarationNode;
     181        newnode->type = new TypeData( TypeData::Aggregate );
     182        newnode->type->aggregate->kind = kind;
     183        newnode->type->aggregate->name = assign_strptr( name );
     184        if ( newnode->type->aggregate->name == "" ) {
     185                newnode->type->aggregate->name = DeclarationNode::anonymous.newName();
     186        }
     187        newnode->type->aggregate->params = formals;
     188        newnode->type->aggregate->actuals = actuals;
     189        newnode->type->aggregate->members = fields;
     190        return newnode;
    176191}
    177192
    178193DeclarationNode *DeclarationNode::newEnum( std::string *name, DeclarationNode *constants ) {
    179     DeclarationNode *newnode = new DeclarationNode;
    180     newnode->name = assign_strptr( name );
    181     newnode->type = new TypeData( TypeData::Enum );
    182     newnode->type->enumeration->name = newnode->name;
    183     if ( newnode->type->enumeration->name == "" ) {
    184         newnode->type->enumeration->name = DeclarationNode::anonymous.newName();
    185     }
    186     newnode->type->enumeration->constants = constants;
    187     return newnode;
     194        DeclarationNode *newnode = new DeclarationNode;
     195        newnode->name = assign_strptr( name );
     196        newnode->type = new TypeData( TypeData::Enum );
     197        newnode->type->enumeration->name = newnode->name;
     198        if ( newnode->type->enumeration->name == "" ) {
     199                newnode->type->enumeration->name = DeclarationNode::anonymous.newName();
     200        }
     201        newnode->type->enumeration->constants = constants;
     202        return newnode;
    188203}
    189204
    190205DeclarationNode *DeclarationNode::newEnumConstant( std::string* name, ExpressionNode *constant ) {
    191     DeclarationNode *newnode = new DeclarationNode;
    192     newnode->name = assign_strptr( name );
    193     // do something with the constant
    194     return newnode;
     206        DeclarationNode *newnode = new DeclarationNode;
     207        newnode->name = assign_strptr( name );
     208        // do something with the constant
     209        return newnode;
    195210}
    196211
    197212DeclarationNode *DeclarationNode::newName( std::string* name ) {
    198     DeclarationNode *newnode = new DeclarationNode;
    199     newnode->name = assign_strptr( name );
    200     return newnode;
     213        DeclarationNode *newnode = new DeclarationNode;
     214        newnode->name = assign_strptr( name );
     215        return newnode;
    201216}
    202217
    203218DeclarationNode *DeclarationNode::newFromTypeGen( std::string* name, ExpressionNode *params ) {
    204     DeclarationNode *newnode = new DeclarationNode;
    205     newnode->type = new TypeData( TypeData::SymbolicInst );
    206     newnode->type->symbolic->name = assign_strptr( name );
    207     newnode->type->symbolic->isTypedef = false;
    208     newnode->type->symbolic->actuals = params;
    209     return newnode;
     219        DeclarationNode *newnode = new DeclarationNode;
     220        newnode->type = new TypeData( TypeData::SymbolicInst );
     221        newnode->type->symbolic->name = assign_strptr( name );
     222        newnode->type->symbolic->isTypedef = false;
     223        newnode->type->symbolic->actuals = params;
     224        return newnode;
    210225}
    211226
    212227DeclarationNode *DeclarationNode::newTypeParam( TypeClass tc, std::string* name ) {
    213     DeclarationNode *newnode = new DeclarationNode;
    214     newnode->name = assign_strptr( name );
    215     newnode->type = new TypeData( TypeData::Variable );
    216     newnode->type->variable->tyClass = tc;
    217     newnode->type->variable->name = newnode->name;
    218     return newnode;
     228        DeclarationNode *newnode = new DeclarationNode;
     229        newnode->name = assign_strptr( name );
     230        newnode->type = new TypeData( TypeData::Variable );
     231        newnode->type->variable->tyClass = tc;
     232        newnode->type->variable->name = newnode->name;
     233        return newnode;
    219234}
    220235
    221236DeclarationNode *DeclarationNode::newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts ) {
    222     DeclarationNode *newnode = new DeclarationNode;
    223     newnode->type = new TypeData( TypeData::Aggregate );
    224     newnode->type->aggregate->kind = Context;
    225     newnode->type->aggregate->params = params;
    226     newnode->type->aggregate->members = asserts;
    227     newnode->type->aggregate->name = assign_strptr( name );
    228     return newnode;
     237        DeclarationNode *newnode = new DeclarationNode;
     238        newnode->type = new TypeData( TypeData::Aggregate );
     239        newnode->type->aggregate->kind = Context;
     240        newnode->type->aggregate->params = params;
     241        newnode->type->aggregate->members = asserts;
     242        newnode->type->aggregate->name = assign_strptr( name );
     243        return newnode;
    229244}
    230245
    231246DeclarationNode *DeclarationNode::newContextUse( std::string *name, ExpressionNode *params ) {
    232     DeclarationNode *newnode = new DeclarationNode;
    233     newnode->type = new TypeData( TypeData::AggregateInst );
    234     newnode->type->aggInst->aggregate = new TypeData( TypeData::Aggregate );
    235     newnode->type->aggInst->aggregate->aggregate->kind = Context;
    236     newnode->type->aggInst->aggregate->aggregate->name = assign_strptr( name );
    237     newnode->type->aggInst->params = params;
    238     return newnode;
     247        DeclarationNode *newnode = new DeclarationNode;
     248        newnode->type = new TypeData( TypeData::AggregateInst );
     249        newnode->type->aggInst->aggregate = new TypeData( TypeData::Aggregate );
     250        newnode->type->aggInst->aggregate->aggregate->kind = Context;
     251        newnode->type->aggInst->aggregate->aggregate->name = assign_strptr( name );
     252        newnode->type->aggInst->params = params;
     253        return newnode;
    239254}
    240255
    241256DeclarationNode *DeclarationNode::newTypeDecl( std::string *name, DeclarationNode *typeParams ) {
    242     DeclarationNode *newnode = new DeclarationNode;
    243     newnode->name = assign_strptr( name );
    244     newnode->type = new TypeData( TypeData::Symbolic );
    245     newnode->type->symbolic->isTypedef = false;
    246     newnode->type->symbolic->params = typeParams;
    247     newnode->type->symbolic->name = newnode->name;
    248     return newnode;
     257        DeclarationNode *newnode = new DeclarationNode;
     258        newnode->name = assign_strptr( name );
     259        newnode->type = new TypeData( TypeData::Symbolic );
     260        newnode->type->symbolic->isTypedef = false;
     261        newnode->type->symbolic->params = typeParams;
     262        newnode->type->symbolic->name = newnode->name;
     263        return newnode;
    249264}
    250265
    251266DeclarationNode *DeclarationNode::newPointer( DeclarationNode *qualifiers ) {
    252     DeclarationNode *newnode = new DeclarationNode;
    253     newnode->type = new TypeData( TypeData::Pointer );
    254     return newnode->addQualifiers( qualifiers );
     267        DeclarationNode *newnode = new DeclarationNode;
     268        newnode->type = new TypeData( TypeData::Pointer );
     269        return newnode->addQualifiers( qualifiers );
    255270}
    256271
    257272DeclarationNode *DeclarationNode::newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic ) {
    258     DeclarationNode *newnode = new DeclarationNode;
    259     newnode->type = new TypeData( TypeData::Array );
    260     newnode->type->array->dimension = size;
    261     newnode->type->array->isStatic = isStatic;
    262     newnode->type->array->isVarLen = false;
    263     return newnode->addQualifiers( qualifiers );
     273        DeclarationNode *newnode = new DeclarationNode;
     274        newnode->type = new TypeData( TypeData::Array );
     275        newnode->type->array->dimension = size;
     276        newnode->type->array->isStatic = isStatic;
     277        newnode->type->array->isVarLen = false;
     278        return newnode->addQualifiers( qualifiers );
    264279}
    265280
    266281DeclarationNode *DeclarationNode::newVarArray( DeclarationNode *qualifiers ) {
    267     DeclarationNode *newnode = new DeclarationNode;
    268     newnode->type = new TypeData( TypeData::Array );
    269     newnode->type->array->dimension = 0;
    270     newnode->type->array->isStatic = false;
    271     newnode->type->array->isVarLen = true;
    272     return newnode->addQualifiers( qualifiers );
     282        DeclarationNode *newnode = new DeclarationNode;
     283        newnode->type = new TypeData( TypeData::Array );
     284        newnode->type->array->dimension = 0;
     285        newnode->type->array->isStatic = false;
     286        newnode->type->array->isVarLen = true;
     287        return newnode->addQualifiers( qualifiers );
    273288}
    274289
    275290DeclarationNode *DeclarationNode::newBitfield( ExpressionNode *size ) {
    276     DeclarationNode *newnode = new DeclarationNode;
    277     newnode->bitfieldWidth = size;
    278     return newnode;
     291        DeclarationNode *newnode = new DeclarationNode;
     292        newnode->bitfieldWidth = size;
     293        return newnode;
    279294}
    280295
    281296DeclarationNode *DeclarationNode::newTuple( DeclarationNode *members ) {
    282     DeclarationNode *newnode = new DeclarationNode;
    283     newnode->type = new TypeData( TypeData::Tuple );
    284     newnode->type->tuple->members = members;
    285     return newnode;
     297        DeclarationNode *newnode = new DeclarationNode;
     298        newnode->type = new TypeData( TypeData::Tuple );
     299        newnode->type->tuple->members = members;
     300        return newnode;
    286301}
    287302
    288303DeclarationNode *DeclarationNode::newTypeof( ExpressionNode *expr ) {
    289     DeclarationNode *newnode = new DeclarationNode;
    290     newnode->type = new TypeData( TypeData::Typeof );
    291     newnode->type->typeexpr->expr = expr;
    292     return newnode;
     304        DeclarationNode *newnode = new DeclarationNode;
     305        newnode->type = new TypeData( TypeData::Typeof );
     306        newnode->type->typeexpr->expr = expr;
     307        return newnode;
    293308}
    294309
    295310DeclarationNode *DeclarationNode::newAttr( std::string *name, ExpressionNode *expr ) {
    296     DeclarationNode *newnode = new DeclarationNode;
    297     newnode->type = new TypeData( TypeData::Attr );
    298     newnode->type->attr->name = assign_strptr( name );
    299     newnode->type->attr->expr = expr;
    300     return newnode;
     311        DeclarationNode *newnode = new DeclarationNode;
     312        newnode->type = new TypeData( TypeData::Attr );
     313        newnode->type->attr->name = assign_strptr( name );
     314        newnode->type->attr->expr = expr;
     315        return newnode;
    301316}
    302317
    303318DeclarationNode *DeclarationNode::newAttr( std::string *name, DeclarationNode *type ) {
    304     DeclarationNode *newnode = new DeclarationNode;
    305     newnode->type = new TypeData( TypeData::Attr );
    306     newnode->type->attr->name = assign_strptr( name );
    307     newnode->type->attr->type = type;
    308     return newnode;
     319        DeclarationNode *newnode = new DeclarationNode;
     320        newnode->type = new TypeData( TypeData::Attr );
     321        newnode->type->attr->name = assign_strptr( name );
     322        newnode->type->attr->type = type;
     323        return newnode;
    309324}
    310325
    311326static void addQualifiersToType( TypeData *&src, TypeData *dst ) {
    312     if ( src && dst ) {
    313         if ( src->forall && dst->kind == TypeData::Function ) {
    314             if ( dst->forall ) {
    315                 dst->forall->appendList( src->forall );
    316             } else {
    317                 dst->forall = src->forall;
    318             }
    319             src->forall = 0;
    320         }
    321         if ( dst->base ) {
    322             addQualifiersToType( src, dst->base );
    323         } else if ( dst->kind == TypeData::Function ) {
    324             dst->base = src;
    325             src = 0;
    326         } else {
    327             dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
    328         }
    329     }
    330 }
    331      
     327        if ( src && dst ) {
     328                if ( src->forall && dst->kind == TypeData::Function ) {
     329                        if ( dst->forall ) {
     330                                dst->forall->appendList( src->forall );
     331                        } else {
     332                                dst->forall = src->forall;
     333                        }
     334                        src->forall = 0;
     335                }
     336                if ( dst->base ) {
     337                        addQualifiersToType( src, dst->base );
     338                } else if ( dst->kind == TypeData::Function ) {
     339                        dst->base = src;
     340                        src = 0;
     341                } else {
     342                        dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
     343                }
     344        }
     345}
     346         
    332347DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) {
    333     if ( q ) {
    334         storageClasses.splice( storageClasses.end(), q->storageClasses );
    335         if ( q->type ) {
    336             if ( ! type ) {
    337                 type = new TypeData;
    338             }
    339             addQualifiersToType( q->type, type );
    340             if ( q->type && q->type->forall ) {
    341                 if ( type->forall ) {
    342                     type->forall->appendList( q->type->forall );
     348        if ( q ) {
     349                storageClasses.splice( storageClasses.end(), q->storageClasses );
     350                if ( q->type ) {
     351                        if ( ! type ) {
     352                                type = new TypeData;
     353                        }
     354                        addQualifiersToType( q->type, type );
     355                        if ( q->type && q->type->forall ) {
     356                                if ( type->forall ) {
     357                                        type->forall->appendList( q->type->forall );
     358                                } else {
     359                                        type->forall = q->type->forall;
     360                                }
     361                                q->type->forall = 0;
     362                        }
     363                }
     364        }
     365        delete q;
     366        return this;
     367}
     368
     369DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) {
     370        storageClasses = q->storageClasses;
     371        return this;
     372}
     373
     374static void addTypeToType( TypeData *&src, TypeData *&dst ) {
     375        if ( src && dst ) {
     376                if ( src->forall && dst->kind == TypeData::Function ) {
     377                        if ( dst->forall ) {
     378                                dst->forall->appendList( src->forall );
     379                        } else {
     380                                dst->forall = src->forall;
     381                        }
     382                        src->forall = 0;
     383                }
     384                if ( dst->base ) {
     385                        addTypeToType( src, dst->base );
    343386                } else {
    344                     type->forall = q->type->forall;
    345                 }
    346                 q->type->forall = 0;
    347             }
    348         }
    349     }
    350     delete q;
    351     return this;
    352 }
    353 
    354 DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) {
    355     storageClasses = q->storageClasses;
    356     return this;
    357 }
    358 
    359 static void addTypeToType( TypeData *&src, TypeData *&dst ) {
    360     if ( src && dst ) {
    361         if ( src->forall && dst->kind == TypeData::Function ) {
    362             if ( dst->forall ) {
    363                 dst->forall->appendList( src->forall );
    364             } else {
    365                 dst->forall = src->forall;
    366             }
    367             src->forall = 0;
    368         }
    369         if ( dst->base ) {
    370             addTypeToType( src, dst->base );
    371         } else {
    372             switch ( dst->kind ) {
    373               case TypeData::Unknown:
    374                 src->qualifiers.splice( src->qualifiers.end(), dst->qualifiers );
    375                 dst = src;
    376                 src = 0;
     387                        switch ( dst->kind ) {
     388                          case TypeData::Unknown:
     389                                src->qualifiers.splice( src->qualifiers.end(), dst->qualifiers );
     390                                dst = src;
     391                                src = 0;
     392                                break;
     393
     394                          case TypeData::Basic:
     395                                dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
     396                                if ( src->kind != TypeData::Unknown ) {
     397                                        assert( src->kind == TypeData::Basic );
     398                                        dst->basic->modifiers.splice( dst->basic->modifiers.end(), src->basic->modifiers );
     399                                        dst->basic->typeSpec.splice( dst->basic->typeSpec.end(), src->basic->typeSpec );
     400                                }
     401                                break;
     402
     403                          default:
     404                                switch ( src->kind ) {
     405                                  case TypeData::Aggregate:
     406                                  case TypeData::Enum:
     407                                        dst->base = new TypeData( TypeData::AggregateInst );
     408                                        dst->base->aggInst->aggregate = src;
     409                                        if ( src->kind == TypeData::Aggregate ) {
     410                                                dst->base->aggInst->params = maybeClone( src->aggregate->actuals );
     411                                        }
     412                                        dst->base->qualifiers.splice( dst->base->qualifiers.end(), src->qualifiers );
     413                                        src = 0;
     414                                        break;
     415
     416                                  default:
     417                                        if ( dst->forall ) {
     418                                                dst->forall->appendList( src->forall );
     419                                        } else {
     420                                                dst->forall = src->forall;
     421                                        }
     422                                        src->forall = 0;
     423                                        dst->base = src;
     424                                        src = 0;
     425                                }
     426                        }
     427                }
     428        }
     429}
     430
     431DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) {
     432        if ( o ) {
     433                storageClasses.splice( storageClasses.end(), o->storageClasses );
     434                if ( o->type ) {
     435                        if ( ! type ) {
     436                                if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
     437                                        type = new TypeData( TypeData::AggregateInst );
     438                                        type->aggInst->aggregate = o->type;
     439                                        if ( o->type->kind == TypeData::Aggregate ) {
     440                                                type->aggInst->params = maybeClone( o->type->aggregate->actuals );
     441                                        }
     442                                        type->qualifiers.splice( type->qualifiers.end(), o->type->qualifiers );
     443                                } else {
     444                                        type = o->type;
     445                                }
     446                                o->type = 0;
     447                        } else {
     448                                addTypeToType( o->type, type );
     449                        }
     450                }
     451                if ( o->bitfieldWidth ) {
     452                        bitfieldWidth = o->bitfieldWidth;
     453                }
     454        }
     455        delete o;
     456        return this;
     457}
     458
     459DeclarationNode *DeclarationNode::addTypedef() {
     460        TypeData *newtype = new TypeData( TypeData::Symbolic );
     461        newtype->symbolic->params = 0;
     462        newtype->symbolic->isTypedef = true;
     463        newtype->symbolic->name = name;
     464        newtype->base = type;
     465        type = newtype;
     466        return this;
     467}
     468
     469DeclarationNode *DeclarationNode::addAssertions( DeclarationNode* assertions ) {
     470        assert( type );
     471        switch ( type->kind ) {
     472          case TypeData::Symbolic:
     473                if ( type->symbolic->assertions ) {
     474                        type->symbolic->assertions->appendList( assertions );
     475                } else {
     476                        type->symbolic->assertions = assertions;
     477                }
    377478                break;
    378 
    379               case TypeData::Basic:
    380                 dst->qualifiers.splice( dst->qualifiers.end(), src->qualifiers );
    381                 if ( src->kind != TypeData::Unknown ) {
    382                     assert( src->kind == TypeData::Basic );
    383                     dst->basic->modifiers.splice( dst->basic->modifiers.end(), src->basic->modifiers );
    384                     dst->basic->typeSpec.splice( dst->basic->typeSpec.end(), src->basic->typeSpec );
     479       
     480          case TypeData::Variable:
     481                if ( type->variable->assertions ) {
     482                        type->variable->assertions->appendList( assertions );
     483                } else {
     484                        type->variable->assertions = assertions;
    385485                }
    386486                break;
    387 
    388               default:
    389                 switch ( src->kind ) {
    390                   case TypeData::Aggregate:
    391                   case TypeData::Enum:
    392                     dst->base = new TypeData( TypeData::AggregateInst );
    393                     dst->base->aggInst->aggregate = src;
    394                     if ( src->kind == TypeData::Aggregate ) {
    395                         dst->base->aggInst->params = maybeClone( src->aggregate->actuals );
    396                     }
    397                     dst->base->qualifiers.splice( dst->base->qualifiers.end(), src->qualifiers );
    398                     src = 0;
    399                     break;
    400          
    401                   default:
    402                     if ( dst->forall ) {
    403                         dst->forall->appendList( src->forall );
    404                     } else {
    405                         dst->forall = src->forall;
    406                     }
    407                     src->forall = 0;
    408                     dst->base = src;
    409                     src = 0;
    410                 }
    411             }
    412         }
    413     }
    414 }
    415 
    416 DeclarationNode *DeclarationNode::addType( DeclarationNode *o ) {
    417     if ( o ) {
    418         storageClasses.splice( storageClasses.end(), o->storageClasses );
    419         if ( o->type ) {
    420             if ( ! type ) {
    421                 if ( o->type->kind == TypeData::Aggregate || o->type->kind == TypeData::Enum ) {
    422                     type = new TypeData( TypeData::AggregateInst );
    423                     type->aggInst->aggregate = o->type;
    424                     if ( o->type->kind == TypeData::Aggregate ) {
    425                         type->aggInst->params = maybeClone( o->type->aggregate->actuals );
    426                     }
    427                     type->qualifiers.splice( type->qualifiers.end(), o->type->qualifiers );
    428                 } else {
    429                     type = o->type;
    430                 }
    431                 o->type = 0;
    432             } else {
    433                 addTypeToType( o->type, type );
    434             }
    435         }
    436         if ( o->bitfieldWidth ) {
    437             bitfieldWidth = o->bitfieldWidth;
    438         }
    439     }
    440     delete o;
    441     return this;
    442 }
    443 
    444 DeclarationNode *DeclarationNode::addTypedef() {
    445     TypeData *newtype = new TypeData( TypeData::Symbolic );
    446     newtype->symbolic->params = 0;
    447     newtype->symbolic->isTypedef = true;
    448     newtype->symbolic->name = name;
    449     newtype->base = type;
    450     type = newtype;
    451     return this;
    452 }
    453 
    454 DeclarationNode *DeclarationNode::addAssertions( DeclarationNode* assertions ) {
    455     assert( type );
    456     switch ( type->kind ) {
    457       case TypeData::Symbolic:
    458         if ( type->symbolic->assertions ) {
    459             type->symbolic->assertions->appendList( assertions );
    460         } else {
    461             type->symbolic->assertions = assertions;
    462         }
    463         break;
    464    
    465       case TypeData::Variable:
    466         if ( type->variable->assertions ) {
    467             type->variable->assertions->appendList( assertions );
    468         } else {
    469             type->variable->assertions = assertions;
    470         }
    471         break;
    472    
    473       default:
    474         assert( false );
    475     }
    476    
    477     return this;
     487       
     488          default:
     489                assert( false );
     490        }
     491       
     492        return this;
    478493}
    479494
    480495DeclarationNode *DeclarationNode::addName( std::string* newname ) {
    481     name = assign_strptr( newname );
    482     return this;
     496        name = assign_strptr( newname );
     497        return this;
    483498}
    484499
    485500DeclarationNode *DeclarationNode::addBitfield( ExpressionNode *size ) {
    486     bitfieldWidth = size;
    487     return this;
     501        bitfieldWidth = size;
     502        return this;
    488503}
    489504
    490505DeclarationNode *DeclarationNode::addVarArgs() {
    491     assert( type );
    492     hasEllipsis = true;
    493     return this;
     506        assert( type );
     507        hasEllipsis = true;
     508        return this;
    494509}
    495510
    496511DeclarationNode *DeclarationNode::addFunctionBody( StatementNode *body ) {
    497     assert( type );
    498     assert( type->kind == TypeData::Function );
    499     assert( type->function->body == 0 );
    500     type->function->body = body;
    501     type->function->hasBody = true;
    502     return this;
     512        assert( type );
     513        assert( type->kind == TypeData::Function );
     514        assert( type->function->body == 0 );
     515        type->function->body = body;
     516        type->function->hasBody = true;
     517        return this;
    503518}
    504519
    505520DeclarationNode *DeclarationNode::addOldDeclList( DeclarationNode *list ) {
    506     assert( type );
    507     assert( type->kind == TypeData::Function );
    508     assert( type->function->oldDeclList == 0 );
    509     type->function->oldDeclList = list;
    510     return this;
     521        assert( type );
     522        assert( type->kind == TypeData::Function );
     523        assert( type->function->oldDeclList == 0 );
     524        type->function->oldDeclList = list;
     525        return this;
    511526}
    512527
    513528static void
    514529setBase( TypeData *&type, TypeData *newType ) {
    515     if ( type ) {
    516         TypeData *prevBase = type;
    517         TypeData *curBase = type->base;
    518         while( curBase != 0 ) {
    519             prevBase = curBase;
    520             curBase = curBase->base;
    521         }
    522         prevBase->base = newType;
    523     } else {
    524         type = newType;
    525     }
     530        if ( type ) {
     531                TypeData *prevBase = type;
     532                TypeData *curBase = type->base;
     533                while( curBase != 0 ) {
     534                        prevBase = curBase;
     535                        curBase = curBase->base;
     536                }
     537                prevBase->base = newType;
     538        } else {
     539                type = newType;
     540        }
    526541}
    527542
    528543DeclarationNode *DeclarationNode::addPointer( DeclarationNode *p ) {
    529     if ( p ) {
    530         assert( p->type->kind == TypeData::Pointer );
    531         setBase( type, p->type );
    532         p->type = 0;
    533         delete p;
    534     }
    535     return this;
     544        if ( p ) {
     545                assert( p->type->kind == TypeData::Pointer );
     546                setBase( type, p->type );
     547                p->type = 0;
     548                delete p;
     549        }
     550        return this;
    536551}
    537552
    538553DeclarationNode *DeclarationNode::addArray( DeclarationNode *a ) {
    539     if ( a ) {
    540         assert( a->type->kind == TypeData::Array );
    541         setBase( type, a->type );
    542         a->type = 0;
    543         delete a;
    544     }
    545     return this;
     554        if ( a ) {
     555                assert( a->type->kind == TypeData::Array );
     556                setBase( type, a->type );
     557                a->type = 0;
     558                delete a;
     559        }
     560        return this;
    546561}
    547562
    548563DeclarationNode *DeclarationNode::addNewPointer( DeclarationNode *p ) {
    549     if ( p ) {
    550         assert( p->type->kind == TypeData::Pointer );
     564        if ( p ) {
     565                assert( p->type->kind == TypeData::Pointer );
     566                if ( type ) {
     567                        switch ( type->kind ) {
     568                          case TypeData::Aggregate:
     569                          case TypeData::Enum:
     570                                p->type->base = new TypeData( TypeData::AggregateInst );
     571                                p->type->base->aggInst->aggregate = type;
     572                                if ( type->kind == TypeData::Aggregate ) {
     573                                        p->type->base->aggInst->params = maybeClone( type->aggregate->actuals );
     574                                }
     575                                p->type->base->qualifiers.splice( p->type->base->qualifiers.end(), type->qualifiers );
     576                                break;
     577
     578                          default:
     579                                p->type->base = type;
     580                        }
     581                        type = 0;
     582                }
     583                delete this;
     584                return p;
     585        } else {
     586                return this;
     587        }
     588}
     589
     590static TypeData *findLast( TypeData *a ) {
     591        assert( a );
     592        TypeData *cur = a;
     593        while( cur->base ) {
     594                cur = cur->base;
     595        }
     596        return cur;
     597}
     598
     599DeclarationNode *DeclarationNode::addNewArray( DeclarationNode *a ) {
     600        if ( a ) {
     601                assert( a->type->kind == TypeData::Array );
     602                TypeData *lastArray = findLast( a->type );
     603                if ( type ) { 
     604                        switch ( type->kind ) {
     605                          case TypeData::Aggregate:
     606                          case TypeData::Enum:
     607                                lastArray->base = new TypeData( TypeData::AggregateInst );
     608                                lastArray->base->aggInst->aggregate = type;
     609                                if ( type->kind == TypeData::Aggregate ) {
     610                                        lastArray->base->aggInst->params = maybeClone( type->aggregate->actuals );
     611                                }
     612                                lastArray->base->qualifiers.splice( lastArray->base->qualifiers.end(), type->qualifiers );
     613                                break;
     614                          default:
     615                                lastArray->base = type;
     616                        }
     617                        type = 0;
     618                }
     619                delete this;
     620                return a;
     621        } else {
     622                return this;
     623        }
     624}
     625
     626DeclarationNode *DeclarationNode::addParamList( DeclarationNode *params ) {
     627        TypeData *ftype = new TypeData( TypeData::Function );
     628        ftype->function->params = params;
     629        setBase( type, ftype );
     630        return this;
     631}
     632
     633static TypeData *addIdListToType( TypeData *type, DeclarationNode *ids ) {
    551634        if ( type ) {
    552             switch ( type->kind ) {
    553               case TypeData::Aggregate:
    554               case TypeData::Enum:
    555                 p->type->base = new TypeData( TypeData::AggregateInst );
    556                 p->type->base->aggInst->aggregate = type;
    557                 if ( type->kind == TypeData::Aggregate ) {
    558                     p->type->base->aggInst->params = maybeClone( type->aggregate->actuals );
    559                 }
    560                 p->type->base->qualifiers.splice( p->type->base->qualifiers.end(), type->qualifiers );
    561                 break;
    562        
    563               default:
    564                 p->type->base = type;
    565             }
    566             type = 0;
    567         }
    568         delete this;
    569         return p;
    570     } else {
    571         return this;
    572     }
    573 }
    574 
    575 static TypeData *findLast( TypeData *a ) {
    576     assert( a );
    577     TypeData *cur = a;
    578     while( cur->base ) {
    579         cur = cur->base;
    580     }
    581     return cur;
    582 }
    583 
    584 DeclarationNode *DeclarationNode::addNewArray( DeclarationNode *a ) {
    585     if ( a ) {
    586         assert( a->type->kind == TypeData::Array );
    587         TypeData *lastArray = findLast( a->type );
    588         if ( type ) { 
    589             switch ( type->kind ) {
    590               case TypeData::Aggregate:
    591               case TypeData::Enum:
    592                 lastArray->base = new TypeData( TypeData::AggregateInst );
    593                 lastArray->base->aggInst->aggregate = type;
    594                 if ( type->kind == TypeData::Aggregate ) {
    595                     lastArray->base->aggInst->params = maybeClone( type->aggregate->actuals );
    596                 }
    597                 lastArray->base->qualifiers.splice( lastArray->base->qualifiers.end(), type->qualifiers );
    598                 break;
    599        
    600               default:
    601                 lastArray->base = type;
    602             }
    603             type = 0;
    604         }
    605         delete this;
    606         return a;
    607     } else {
    608         return this;
    609     }
    610 }
    611 
    612 DeclarationNode *DeclarationNode::addParamList( DeclarationNode *params ) {
    613     TypeData *ftype = new TypeData( TypeData::Function );
    614     ftype->function->params = params;
    615     setBase( type, ftype );
    616     return this;
    617 }
    618 
    619 static TypeData *addIdListToType( TypeData *type, DeclarationNode *ids ) {
    620     if ( type ) {
    621         if ( type->kind != TypeData::Function ) {
    622             type->base = addIdListToType( type->base, ids );
     635                if ( type->kind != TypeData::Function ) {
     636                        type->base = addIdListToType( type->base, ids );
     637                } else {
     638                        type->function->idList = ids;
     639                }
     640                return type;
    623641        } else {
    624             type->function->idList = ids;
    625         }
    626         return type;
    627     } else {
    628         TypeData *newtype = new TypeData( TypeData::Function );
    629         newtype->function->idList = ids;
    630         return newtype;
    631     }
    632 }
    633    
     642                TypeData *newtype = new TypeData( TypeData::Function );
     643                newtype->function->idList = ids;
     644                return newtype;
     645        }
     646}
     647       
    634648DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) {
    635     type = addIdListToType( type, ids );
    636     return this;
     649        type = addIdListToType( type, ids );
     650        return this;
    637651}
    638652
    639653DeclarationNode *DeclarationNode::addInitializer( InitializerNode *init ) {
    640     //assert
    641     initializer = init;
    642     return this;
     654        //assert
     655        initializer = init;
     656        return this;
    643657}
    644658
    645659DeclarationNode *DeclarationNode::cloneBaseType( string *newName ) {
    646     DeclarationNode *newnode = new DeclarationNode;
    647     TypeData *srcType = type;
    648     while( srcType->base ) {
    649         srcType = srcType->base;
    650     }
    651     newnode->type = maybeClone( srcType );
    652     if ( newnode->type->kind == TypeData::AggregateInst ) {
    653         // don't duplicate members
    654         if ( newnode->type->aggInst->aggregate->kind == TypeData::Enum ) {
    655             delete newnode->type->aggInst->aggregate->enumeration->constants;
    656             newnode->type->aggInst->aggregate->enumeration->constants = 0;
     660        DeclarationNode *newnode = new DeclarationNode;
     661        TypeData *srcType = type;
     662        while( srcType->base ) {
     663                srcType = srcType->base;
     664        }
     665        newnode->type = maybeClone( srcType );
     666        if ( newnode->type->kind == TypeData::AggregateInst ) {
     667                // don't duplicate members
     668                if ( newnode->type->aggInst->aggregate->kind == TypeData::Enum ) {
     669                        delete newnode->type->aggInst->aggregate->enumeration->constants;
     670                        newnode->type->aggInst->aggregate->enumeration->constants = 0;
     671                } else {
     672                        assert( newnode->type->aggInst->aggregate->kind == TypeData::Aggregate );
     673                        delete newnode->type->aggInst->aggregate->aggregate->members;
     674                        newnode->type->aggInst->aggregate->aggregate->members = 0;
     675                }
     676        }
     677        newnode->type->forall = maybeClone( type->forall );
     678        newnode->storageClasses = storageClasses;
     679        newnode->name = assign_strptr( newName );
     680        return newnode;
     681}
     682
     683DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) {
     684        if ( o ) {
     685                o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
     686                if ( type ) {
     687                        TypeData *srcType = type;
     688                        while( srcType->base ) {
     689                                srcType = srcType->base;
     690                        }
     691                        TypeData *newType = srcType->clone();
     692                        if ( newType->kind == TypeData::AggregateInst ) {
     693                                // don't duplicate members
     694                                if ( newType->aggInst->aggregate->kind == TypeData::Enum ) {
     695                                        delete newType->aggInst->aggregate->enumeration->constants;
     696                                        newType->aggInst->aggregate->enumeration->constants = 0;
     697                                } else {
     698                                        assert( newType->aggInst->aggregate->kind == TypeData::Aggregate );
     699                                        delete newType->aggInst->aggregate->aggregate->members;
     700                                        newType->aggInst->aggregate->aggregate->members = 0;
     701                                }
     702                        }
     703                        newType->forall = maybeClone( type->forall );
     704                        if ( ! o->type ) {
     705                                o->type = newType;
     706                        } else {
     707                                addTypeToType( newType, o->type );
     708                                delete newType;
     709                        }
     710                }
     711        }
     712        return o;
     713}
     714
     715DeclarationNode *DeclarationNode::cloneType( string *newName ) {
     716        DeclarationNode *newnode = new DeclarationNode;
     717        newnode->type = maybeClone( type );
     718        newnode->storageClasses = storageClasses;
     719        newnode->name = assign_strptr( newName );
     720        return newnode;
     721}
     722
     723DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) {
     724        if ( o ) {
     725                o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
     726                if ( type ) {
     727                        TypeData *newType = type->clone();
     728                        if ( ! o->type ) {
     729                                o->type = newType;
     730                        } else {
     731                                addTypeToType( newType, o->type );
     732                                delete newType;
     733                        }
     734                }
     735        }
     736        return o;
     737}
     738
     739DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) {
     740        if ( node != 0 ) {
     741                set_link( node );
     742        }
     743        return this;
     744}
     745
     746DeclarationNode *DeclarationNode::extractAggregate() const {
     747        if ( type ) {
     748                TypeData *ret = type->extractAggregate();
     749                if ( ret ) {
     750                        DeclarationNode *newnode = new DeclarationNode;
     751                        newnode->type = ret;
     752                        return newnode;
     753                } else {
     754                        return 0;
     755                }
    657756        } else {
    658             assert( newnode->type->aggInst->aggregate->kind == TypeData::Aggregate );
    659             delete newnode->type->aggInst->aggregate->aggregate->members;
    660             newnode->type->aggInst->aggregate->aggregate->members = 0;
    661         }
    662     }
    663     newnode->type->forall = maybeClone( type->forall );
    664     newnode->storageClasses = storageClasses;
    665     newnode->name = assign_strptr( newName );
    666     return newnode;
    667 }
    668 
    669 DeclarationNode *DeclarationNode::cloneBaseType( DeclarationNode *o ) {
    670     if ( o ) {
    671         o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
    672         if ( type ) {
    673             TypeData *srcType = type;
    674             while( srcType->base ) {
    675                 srcType = srcType->base;
    676             }
    677             TypeData *newType = srcType->clone();
    678             if ( newType->kind == TypeData::AggregateInst ) {
    679                 // don't duplicate members
    680                 if ( newType->aggInst->aggregate->kind == TypeData::Enum ) {
    681                     delete newType->aggInst->aggregate->enumeration->constants;
    682                     newType->aggInst->aggregate->enumeration->constants = 0;
    683                 } else {
    684                     assert( newType->aggInst->aggregate->kind == TypeData::Aggregate );
    685                     delete newType->aggInst->aggregate->aggregate->members;
    686                     newType->aggInst->aggregate->aggregate->members = 0;
    687                 }
    688             }
    689             newType->forall = maybeClone( type->forall );
    690             if ( ! o->type ) {
    691                 o->type = newType;
    692             } else {
    693                 addTypeToType( newType, o->type );
    694                 delete newType;
    695             }
    696         }
    697     }
    698     return o;
    699 }
    700 
    701 DeclarationNode *DeclarationNode::cloneType( string *newName ) {
    702     DeclarationNode *newnode = new DeclarationNode;
    703     newnode->type = maybeClone( type );
    704     newnode->storageClasses = storageClasses;
    705     newnode->name = assign_strptr( newName );
    706     return newnode;
    707 }
    708 
    709 DeclarationNode *DeclarationNode::cloneType( DeclarationNode *o ) {
    710     if ( o ) {
    711         o->storageClasses.insert( o->storageClasses.end(), storageClasses.begin(), storageClasses.end() );
    712         if ( type ) {
    713             TypeData *newType = type->clone();
    714             if ( ! o->type ) {
    715                 o->type = newType;
    716             } else {
    717                 addTypeToType( newType, o->type );
    718                 delete newType;
    719             }
    720         }
    721     }
    722     return o;
    723 }
    724 
    725 DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) {
    726     if ( node != 0 ) {
    727         set_link( node );
    728     }
    729     return this;
    730 }
    731 
    732 DeclarationNode *DeclarationNode::extractAggregate() const {
    733     if ( type ) {
    734         TypeData *ret = type->extractAggregate();
    735         if ( ret ) {
    736             DeclarationNode *newnode = new DeclarationNode;
    737             newnode->type = ret;
    738             return newnode;
    739         } else {
    740             return 0;
    741         }
    742     } else {
    743         return 0;
    744     }
     757                return 0;
     758        }
    745759}
    746760
    747761void buildList( const DeclarationNode *firstNode, std::list< Declaration* > &outputList ) {
    748     SemanticError errors;
    749     std::back_insert_iterator< std::list< Declaration* > > out( outputList );
    750     const DeclarationNode *cur = firstNode;
    751     while( cur ) {
    752         try {
    753             if ( DeclarationNode *extr = cur->extractAggregate() ) {
    754                 // handle the case where a structure declaration is contained within an object or type
    755                 // declaration
    756                 Declaration *decl = extr->build();
    757                 if ( decl ) {
    758                    *out++ = decl;
    759                 }
    760             }
    761             Declaration *decl = cur->build();
    762             if ( decl ) {
    763                 *out++ = decl;
    764             }
    765         } catch( SemanticError &e ) {
    766             errors.append( e );
    767         }
    768         cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
    769     }
    770     if ( ! errors.isEmpty() ) {
    771         throw errors;
    772     }
     762        SemanticError errors;
     763        std::back_insert_iterator< std::list< Declaration* > > out( outputList );
     764        const DeclarationNode *cur = firstNode;
     765        while( cur ) {
     766                try {
     767                        if ( DeclarationNode *extr = cur->extractAggregate() ) {
     768                                // handle the case where a structure declaration is contained within an object or type declaration
     769                                Declaration *decl = extr->build();
     770                                if ( decl ) {
     771                                        *out++ = decl;
     772                                }
     773                        }
     774                        Declaration *decl = cur->build();
     775                        if ( decl ) {
     776                                *out++ = decl;
     777                        }
     778                } catch( SemanticError &e ) {
     779                        errors.append( e );
     780                }
     781                cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
     782        }
     783        if ( ! errors.isEmpty() ) {
     784                throw errors;
     785        }
    773786}
    774787
    775788void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType* > &outputList ) {
    776     SemanticError errors;
    777     std::back_insert_iterator< std::list< DeclarationWithType* > > out( outputList );
    778     const DeclarationNode *cur = firstNode;
    779     while( cur ) {
    780         try {
     789        SemanticError errors;
     790        std::back_insert_iterator< std::list< DeclarationWithType* > > out( outputList );
     791        const DeclarationNode *cur = firstNode;
     792        while( cur ) {
     793                try {
    781794///       if ( DeclarationNode *extr = cur->extractAggregate() ) {
    782795///     // handle the case where a structure declaration is contained within an object or type
     
    787800///     }
    788801///       }
    789             Declaration *decl = cur->build();
    790             if ( decl ) {
    791                 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
    792                    *out++ = dwt;
    793                 } else if ( StructDecl *agg = dynamic_cast< StructDecl* >( decl ) ) {
    794                     StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
    795                     *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
    796                     delete agg;
    797                 } else if ( UnionDecl *agg = dynamic_cast< UnionDecl* >( decl ) ) {
    798                     UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
    799                     *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
    800                 }
    801             }
    802         } catch( SemanticError &e ) {
    803             errors.append( e );
    804         }
    805         cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
    806     }
    807     if ( ! errors.isEmpty() ) {
    808         throw errors;
    809     }
     802                        Declaration *decl = cur->build();
     803                        if ( decl ) {
     804                                if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     805                                        *out++ = dwt;
     806                                } else if ( StructDecl *agg = dynamic_cast< StructDecl* >( decl ) ) {
     807                                        StructInstType *inst = new StructInstType( Type::Qualifiers(), agg->get_name() );
     808                                        *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
     809                                        delete agg;
     810                                } else if ( UnionDecl *agg = dynamic_cast< UnionDecl* >( decl ) ) {
     811                                        UnionInstType *inst = new UnionInstType( Type::Qualifiers(), agg->get_name() );
     812                                        *out++ = new ObjectDecl( "", Declaration::NoStorageClass, linkage, 0, inst, 0 );
     813                                }
     814                        }
     815                } catch( SemanticError &e ) {
     816                        errors.append( e );
     817                }
     818                cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
     819        }
     820        if ( ! errors.isEmpty() ) {
     821                throw errors;
     822        }
    810823}
    811824
    812825void buildTypeList( const DeclarationNode *firstNode, std::list< Type* > &outputList ) {
    813     SemanticError errors;
    814     std::back_insert_iterator< std::list< Type* > > out( outputList );
    815     const DeclarationNode *cur = firstNode;
    816     while( cur ) {
    817         try {
    818            *out++ = cur->buildType();
    819         } catch( SemanticError &e ) {
    820             errors.append( e );
    821         }
    822         cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
    823     }
    824     if ( ! errors.isEmpty() ) {
    825         throw errors;
    826     }
     826        SemanticError errors;
     827        std::back_insert_iterator< std::list< Type* > > out( outputList );
     828        const DeclarationNode *cur = firstNode;
     829        while( cur ) {
     830                try {
     831                        *out++ = cur->buildType();
     832                } catch( SemanticError &e ) {
     833                        errors.append( e );
     834                }
     835                cur = dynamic_cast< DeclarationNode* >( cur->get_link() );
     836        }
     837        if ( ! errors.isEmpty() ) {
     838                throw errors;
     839        }
    827840}
    828841
    829842Declaration *DeclarationNode::build() const {
    830843
    831     if ( ! type ) {
    832         if ( buildInline() ) {
    833             throw SemanticError( "invalid inline specification in declaration of ", this );
     844        if ( ! type ) {
     845                if ( buildInline() ) {
     846                        throw SemanticError( "invalid inline specification in declaration of ", this );
     847                } else {
     848                        return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) );
     849                }
    834850        } else {
    835             return new ObjectDecl( name, buildStorageClass(), linkage, maybeBuild< Expression >( bitfieldWidth ), 0, maybeBuild< Initializer >( initializer ) );
    836         }
    837     } else {
    838         Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildInline(), linkage, maybeBuild< Initializer >(initializer) );
    839         return newDecl;
    840     }
    841     // we should never get here
    842     assert( false );
    843     return 0;
     851                Declaration *newDecl = type->buildDecl( name, buildStorageClass(), maybeBuild< Expression >( bitfieldWidth ), buildInline(), linkage, maybeBuild< Initializer >(initializer) );
     852                return newDecl;
     853        }
     854        // we should never get here
     855        assert( false );
     856        return 0;
    844857}
    845858
    846859Type *DeclarationNode::buildType() const {
    847     assert( type );
     860        assert( type );
    848861 
    849     switch ( type->kind ) {
    850       case TypeData::Enum:
    851         return new EnumInstType( type->buildQualifiers(), type->enumeration->name );
    852       case TypeData::Aggregate: {
    853           ReferenceToType *ret;
    854           switch ( type->aggregate->kind ) {
    855             case DeclarationNode::Struct:
    856               ret = new StructInstType( type->buildQualifiers(), type->aggregate->name );
    857               break;
    858             case DeclarationNode::Union:
    859               ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name );
    860               break;
    861             case DeclarationNode::Context:
    862               ret = new ContextInstType( type->buildQualifiers(), type->aggregate->name );
    863               break;
    864             default:
    865               assert( false );
    866           } // switch
    867           buildList( type->aggregate->actuals, ret->get_parameters() );
    868           return ret;
    869       }
    870       case TypeData::Symbolic: {
    871           TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false );
    872           buildList( type->symbolic->actuals, ret->get_parameters() );
    873           return ret;
    874       }
    875       default:
    876         return type->build();
    877     } // switch
     862        switch ( type->kind ) {
     863          case TypeData::Enum:
     864                return new EnumInstType( type->buildQualifiers(), type->enumeration->name );
     865          case TypeData::Aggregate: {
     866                  ReferenceToType *ret;
     867                  switch ( type->aggregate->kind ) {
     868                        case DeclarationNode::Struct:
     869                          ret = new StructInstType( type->buildQualifiers(), type->aggregate->name );
     870                          break;
     871                        case DeclarationNode::Union:
     872                          ret = new UnionInstType( type->buildQualifiers(), type->aggregate->name );
     873                          break;
     874                        case DeclarationNode::Context:
     875                          ret = new ContextInstType( type->buildQualifiers(), type->aggregate->name );
     876                          break;
     877                        default:
     878                          assert( false );
     879                  } // switch
     880                  buildList( type->aggregate->actuals, ret->get_parameters() );
     881                  return ret;
     882          }
     883          case TypeData::Symbolic: {
     884                  TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false );
     885                  buildList( type->symbolic->actuals, ret->get_parameters() );
     886                  return ret;
     887          }
     888          default:
     889                return type->build();
     890        } // switch
    878891}
    879892
    880893Declaration::StorageClass DeclarationNode::buildStorageClass() const {
    881     static const Declaration::StorageClass scMap[] = { 
    882         Declaration::Extern,
    883         Declaration::Static,
    884         Declaration::Auto,
    885         Declaration::Register,
    886         Declaration::Inline,
    887         Declaration::Fortran
    888     }; 
     894        static const Declaration::StorageClass scMap[] = { 
     895                Declaration::Extern,
     896                Declaration::Static,
     897                Declaration::Auto,
     898                Declaration::Register,
     899                Declaration::Inline,
     900                Declaration::Fortran
     901        }; 
    889902 
    890     Declaration::StorageClass ret = Declaration::NoStorageClass;
    891     for ( std::list< StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) {
    892         assert( unsigned( *i ) < sizeof( scMap ) / sizeof( scMap[0] ) );
    893         if ( *i == Inline ) continue;
    894         if ( ret == Declaration::NoStorageClass ) {
    895             ret = scMap[ *i ];
     903        Declaration::StorageClass ret = Declaration::NoStorageClass;
     904        for ( std::list< StorageClass >::const_iterator i = storageClasses.begin(); i != storageClasses.end(); ++i ) {
     905                assert( unsigned( *i ) < sizeof( scMap ) / sizeof( scMap[0] ) );
     906                if ( *i == Inline ) continue;
     907                if ( ret == Declaration::NoStorageClass ) {
     908                        ret = scMap[ *i ];
     909                } else {
     910                        throw SemanticError( "invalid combination of storage classes in declaration of ", this );
     911                }
     912        }
     913        return ret;
     914}
     915
     916bool DeclarationNode::buildInline() const {
     917        std::list< StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), Inline );
     918        if ( first == storageClasses.end() ) {
     919                return false;
    896920        } else {
    897             throw SemanticError( "invalid combination of storage classes in declaration of ", this );
    898         }
    899     }
    900     return ret;
    901 }
    902 
    903 bool DeclarationNode::buildInline() const {
    904     std::list< StorageClass >::const_iterator first = std::find( storageClasses.begin(), storageClasses.end(), Inline );
    905     if ( first == storageClasses.end() ) {
     921                std::list< StorageClass >::const_iterator next = std::find( ++first, storageClasses.end(), Inline );
     922                if ( next == storageClasses.end() ) {
     923                        return true;
     924                } else {
     925                        throw SemanticError( "duplicate inline specification in declaration of ", this );
     926                }
     927        }
     928        // we should never get here
    906929        return false;
    907     } else {
    908         std::list< StorageClass >::const_iterator next = std::find( ++first, storageClasses.end(), Inline );
    909         if ( next == storageClasses.end() ) {
    910             return true;
    911         } else {
    912             throw SemanticError( "duplicate inline specification in declaration of ", this );
    913         }
    914     }
    915     // we should never get here
    916     return false;
    917 }
     930}
     931
     932// Local Variables: //
     933// tab-width: 4 //
     934// mode: c++ //
     935// compile-command: "make install" //
     936// End: //
  • translator/Parser/ExpressionNode.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// ExpressionNode.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:17:07 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:19:35 2015
     13// Update Count     : 2
     14//
     15
    116#include <cassert>
    217#include <cctype>
     
    1732
    1833ExpressionNode::ExpressionNode( string *name_) : ParseNode( *name_ ), argName( 0 ) {
    19     delete name_;
     34        delete name_;
    2035}
    2136
    2237ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.name ) {
    23     if ( other.argName ) {
    24         argName = other.argName->clone();
    25     } else {
    26         argName = 0;
    27     } // if
     38        if ( other.argName ) {
     39                argName = other.argName->clone();
     40        } else {
     41                argName = 0;
     42        } // if
    2843}
    2944
    3045ExpressionNode * ExpressionNode::set_asArgName( std::string *aName ) {
    31     argName = new VarRefNode( aName );
    32     return this;
     46        argName = new VarRefNode( aName );
     47        return this;
    3348}
    3449
    3550ExpressionNode * ExpressionNode::set_asArgName( ExpressionNode *aDesignator ) {
    36     argName = aDesignator;
    37     return this;
     51        argName = aDesignator;
     52        return this;
    3853}
    3954
    4055void ExpressionNode::printDesignation( std::ostream &os, int indent ) const {
    41     if ( argName ) {
    42         os << string(' ', indent ) << "(designated by:  ";
    43         argName->printOneLine( os, indent );
    44         os << ")" << std::endl;
    45     } // if
     56        if ( argName ) {
     57                os << string(' ', indent ) << "(designated by:  ";
     58                argName->printOneLine( os, indent );
     59                os << ")" << std::endl;
     60        } // if
    4661}
    4762
     
    4964
    5065NullExprNode *NullExprNode::clone() const {
    51     return new NullExprNode();
     66        return new NullExprNode();
    5267}
    5368
    5469void NullExprNode::print( std::ostream & os, int indent ) const {
    55     printDesignation( os );
    56     os << "null expression";
     70        printDesignation( os );
     71        os << "null expression";
    5772}
    5873
    5974void NullExprNode::printOneLine( std::ostream & os, int indent ) const {
    60     printDesignation( os );
    61     os << "null";
     75        printDesignation( os );
     76        os << "null";
    6277}
    6378
    6479Expression *NullExprNode::build() const {
    65     return 0;
     80        return 0;
    6681}
    6782
    6883CommaExprNode *ExpressionNode::add_to_list( ExpressionNode *exp ){
    69     return new CommaExprNode( this, exp );
     84        return new CommaExprNode( this, exp );
    7085}
    7186
     
    7792
    7893ConstantNode::ConstantNode( Type t, string *inVal ) : type( t ), sign( true ), longs(0), size(0) {
    79     if ( inVal ) {
    80         value = *inVal;
    81         delete inVal;
    82     } else {
    83         value = "";
    84     } // if
    85 
    86     classify( value );
    87 }
    88 
    89 ConstantNode::ConstantNode( const ConstantNode &other )
    90     : ExpressionNode( other ), type( other.type ), value( other.value ), sign( other.sign ), base( other.base ), longs( other.longs ), size( other.size ) {
     94        if ( inVal ) {
     95                value = *inVal;
     96                delete inVal;
     97        } else {
     98                value = "";
     99        } // if
     100
     101        classify( value );
     102}
     103
     104ConstantNode::ConstantNode( const ConstantNode &other ) : ExpressionNode( other ), type( other.type ), value( other.value ), sign( other.sign ),
     105                                                                                                                  base( other.base ), longs( other.longs ), size( other.size ) {
    91106}
    92107
    93108// for some reason, std::tolower doesn't work as an argument to std::transform in g++ 3.1
    94109inline char tolower_hack( char c ) {
    95     return std::tolower( c );
     110        return std::tolower( c );
    96111}
    97112
    98113void ConstantNode::classify( std::string &str ){
    99     switch ( type ){
    100       case Integer:
    101       case Float:
    102         {
    103             std::string sfx("");
    104             char c;
    105             int i = str.length() - 1;
    106 
    107             while ( i >= 0 && !isxdigit( c = str.at( i--)) )
    108                 sfx += c;
    109 
    110             value = str.substr( 0, i + 2 );
    111 
    112             // get rid of underscores
    113             value.erase( remove( value.begin(), value.end(), '_'), value.end());
    114 
    115             std::transform( sfx.begin(), sfx.end(), sfx.begin(), tolower_hack );
    116 
    117             if ( sfx.find("ll") != string::npos ){
    118                 longs = 2;
    119             } else if ( sfx.find("l") != string::npos ){
    120                 longs = 1;
    121             } // if
    122 
    123             assert(( longs >= 0) && ( longs <= 2));
    124 
    125             if ( sfx.find("u") != string::npos )
    126                 sign = false;
    127 
    128             break;
     114        switch ( type ){
     115          case Integer:
     116          case Float:
     117                {
     118                        std::string sfx("");
     119                        char c;
     120                        int i = str.length() - 1;
     121
     122                        while ( i >= 0 && !isxdigit( c = str.at( i--)) )
     123                                sfx += c;
     124
     125                        value = str.substr( 0, i + 2 );
     126
     127                        // get rid of underscores
     128                        value.erase( remove( value.begin(), value.end(), '_'), value.end());
     129
     130                        std::transform( sfx.begin(), sfx.end(), sfx.begin(), tolower_hack );
     131
     132                        if ( sfx.find("ll") != string::npos ){
     133                                longs = 2;
     134                        } else if ( sfx.find("l") != string::npos ){
     135                                longs = 1;
     136                        } // if
     137
     138                        assert(( longs >= 0) && ( longs <= 2));
     139
     140                        if ( sfx.find("u") != string::npos )
     141                                sign = false;
     142
     143                        break;
     144                }
     145          case Character:
     146                {
     147                        // remove underscores from hex and oct escapes
     148                        if ( str.substr(1,2) == "\\x")
     149                                value.erase( remove( value.begin(), value.end(), '_'), value.end());
     150
     151                        break;
     152                }
     153          default:
     154                // shouldn't be here
     155                ;
    129156        }
    130       case Character:
    131         {
    132             // remove underscores from hex and oct escapes
    133             if ( str.substr(1,2) == "\\x")
    134                 value.erase( remove( value.begin(), value.end(), '_'), value.end());
    135 
    136             break;
     157}
     158
     159ConstantNode::Type ConstantNode::get_type( void ) const {
     160        return type;
     161}
     162
     163ConstantNode *ConstantNode::append( std::string *newValue ) {
     164        if ( newValue ) {
     165                if ( type == String ){
     166                        std::string temp = *newValue;
     167                        value.resize( value.size() - 1 );
     168                        value += newValue->substr(1, newValue->size());
     169                } else
     170                        value += *newValue;
     171
     172                delete newValue;
     173        } // if
     174        return this;
     175}
     176
     177void ConstantNode::printOneLine( std::ostream &os, int indent ) const {
     178        os << string( indent, ' ');
     179        printDesignation( os );
     180
     181        switch ( type ) {
     182                /* integers */
     183          case Integer:
     184                os << value ;
     185                break;
     186          case Float:
     187                os << value ;
     188                break;
     189
     190          case Character:
     191                os << "'" << value << "'";
     192                break;
     193
     194          case String:
     195                os << '"' << value << '"';
     196                break;
    137197        }
    138       default:
    139         // shouldn't be here
    140         ;
    141     }
    142 }
    143 
    144 ConstantNode::Type ConstantNode::get_type( void ) const {
    145     return type;
    146 }
    147 
    148 ConstantNode *ConstantNode::append( std::string *newValue ) {
    149     if ( newValue ) {
    150         if ( type == String ){
    151             std::string temp = *newValue;
    152             value.resize( value.size() - 1 );
    153             value += newValue->substr(1, newValue->size());
    154         } else
    155             value += *newValue;
    156 
    157         delete newValue;
    158     } // if
    159     return this;
    160 }
    161 
    162 void ConstantNode::printOneLine( std::ostream &os, int indent ) const {
    163     os << string( indent, ' ');
    164     printDesignation( os );
    165 
    166     switch ( type ) {
    167         /* integers */
    168       case Integer:
    169         os << value ;
    170         break;
    171       case Float:
    172         os << value ;
    173         break;
    174 
    175       case Character:
    176         os << "'" << value << "'";
    177         break;
    178 
    179       case String:
    180         os << '"' << value << '"';
    181         break;
    182     }
    183 
    184     os << ' ';
     198
     199        os << ' ';
    185200}
    186201
    187202void ConstantNode::print( std::ostream &os, int indent ) const {
    188     printOneLine( os, indent );
    189     os << endl;
     203        printOneLine( os, indent );
     204        os << endl;
    190205}
    191206
    192207Expression *ConstantNode::build() const {
    193     ::Type::Qualifiers q;
    194     BasicType *bt;
    195 
    196     switch ( get_type()){
    197       case Integer:
    198         /* Cfr. standard 6.4.4.1 */
    199         //bt.set_kind( BasicType::SignedInt );
    200         bt = new BasicType( q, BasicType::SignedInt );
    201         break;
    202       case Float:
    203         bt = new BasicType( q, BasicType::Float );
    204         break;
    205       case Character:
    206         bt = new BasicType( q, BasicType::Char );
    207         break;
    208       case String:
    209         // string should probably be a primitive type
    210         ArrayType *at;
    211         std::string value = get_value();
    212         at = new ArrayType( q, new BasicType( q, BasicType::Char ),
    213                            new ConstantExpr( Constant( new BasicType( q, BasicType::SignedInt ),
    214                                                        toString( value.size() - 1 ) ) ),  // account for '\0'
    215                            false, false );
    216         return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) );
    217     }
    218     return new ConstantExpr(  Constant( bt, get_value()),  maybeBuild< Expression >( get_argName() ) );
     208        ::Type::Qualifiers q;
     209        BasicType *bt;
     210
     211        switch ( get_type()){
     212          case Integer:
     213                /* Cfr. standard 6.4.4.1 */
     214                //bt.set_kind( BasicType::SignedInt );
     215                bt = new BasicType( q, BasicType::SignedInt );
     216                break;
     217          case Float:
     218                bt = new BasicType( q, BasicType::Float );
     219                break;
     220          case Character:
     221                bt = new BasicType( q, BasicType::Char );
     222                break;
     223          case String:
     224                // string should probably be a primitive type
     225                ArrayType *at;
     226                std::string value = get_value();
     227                at = new ArrayType( q, new BasicType( q, BasicType::Char ),
     228                                                        new ConstantExpr( Constant( new BasicType( q, BasicType::SignedInt ),
     229                                                                                                                toString( value.size() - 1 ) ) ),  // account for '\0'
     230                                                        false, false );
     231                return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) );
     232        }
     233        return new ConstantExpr(  Constant( bt, get_value()),  maybeBuild< Expression >( get_argName() ) );
    219234}
    220235
     
    227242
    228243Expression *VarRefNode::build() const {
    229     return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) );
     244        return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) );
    230245}
    231246
    232247void VarRefNode::printOneLine( std::ostream &os, int indent ) const {
    233     printDesignation( os );
    234     os << get_name() << ' ';
     248        printDesignation( os );
     249        os << get_name() << ' ';
    235250}
    236251
    237252void VarRefNode::print( std::ostream &os, int indent ) const {
    238     printDesignation( os );
    239     os << '\r' << string( indent, ' ') << "Referencing: ";
    240     os << "Variable: " << get_name();
    241     os << endl;
     253        printDesignation( os );
     254        os << '\r' << string( indent, ' ') << "Referencing: ";
     255        os << "Variable: " << get_name();
     256        os << endl;
    242257}
    243258
     
    250265
    251266OperatorNode::Type OperatorNode::get_type( void ) const{
    252     return type;
     267        return type;
    253268}
    254269
    255270void OperatorNode::printOneLine( std::ostream &os, int indent ) const {
    256     printDesignation( os );
    257     os << OpName[ type ] << ' ';
     271        printDesignation( os );
     272        os << OpName[ type ] << ' ';
    258273}
    259274
    260275void OperatorNode::print( std::ostream &os, int indent ) const{
    261     printDesignation( os );
    262     os << '\r' << string( indent, ' ') << "Operator: " << OpName[type] << endl;
    263     return;
     276        printDesignation( os );
     277        os << '\r' << string( indent, ' ') << "Operator: " << OpName[type] << endl;
     278        return;
    264279}
    265280
    266281std::string OperatorNode::get_typename( void ) const{
    267     return string( OpName[ type ]);
     282        return string( OpName[ type ]);
    268283}
    269284
    270285const char *OperatorNode::OpName[] = {
    271     "TupleC",  "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic
    272     // triadic
    273     "Cond",   "NCond",
    274     // diadic
    275     "SizeOf",      "AlignOf", "Attr", "CompLit", "Plus",    "Minus",   "Mul",     "Div",     "Mod",      "Or",
    276     "And",       "BitOr",   "BitAnd",  "Xor",     "Cast",    "LShift",  "RShift",  "LThan",   "GThan",
    277     "LEThan",    "GEThan", "Eq",      "Neq",     "Assign",  "MulAssn", "DivAssn", "ModAssn", "PlusAssn",
    278     "MinusAssn", "LSAssn", "RSAssn",  "AndAssn", "ERAssn",  "OrAssn",  "Index",   "FieldSel","PFieldSel",
    279     "Range",
    280     // monadic
    281     "UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress"
     286        "TupleC",  "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic
     287        // triadic
     288        "Cond",   "NCond",
     289        // diadic
     290        "SizeOf",      "AlignOf", "Attr", "CompLit", "Plus",    "Minus",   "Mul",     "Div",     "Mod",      "Or",
     291        "And",       "BitOr",   "BitAnd",  "Xor",     "Cast",    "LShift",  "RShift",  "LThan",   "GThan",
     292        "LEThan",    "GEThan", "Eq",      "Neq",     "Assign",  "MulAssn", "DivAssn", "ModAssn", "PlusAssn",
     293        "MinusAssn", "LSAssn", "RSAssn",  "AndAssn", "ERAssn",  "OrAssn",  "Index",   "FieldSel","PFieldSel",
     294        "Range",
     295        // monadic
     296        "UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress"
    282297};
    283298
     
    289304
    290305CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *args ):
    291     function( f ), arguments( args ) {
     306        function( f ), arguments( args ) {
    292307}
    293308
    294309CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2):
    295     function( f ), arguments( arg1) {
    296     arguments->set_link( arg2);
     310        function( f ), arguments( arg1) {
     311        arguments->set_link( arg2);
    297312}
    298313
    299314CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) {
    300     ParseNode *cur = other.arguments;
    301     while ( cur ) {
    302         if ( arguments ) {
    303             arguments->set_link( cur->clone() );
    304         } else {
    305             arguments = ( ExpressionNode*)cur->clone();
    306         } // if
    307         cur = cur->get_link();
    308     }
     315        ParseNode *cur = other.arguments;
     316        while ( cur ) {
     317                if ( arguments ) {
     318                        arguments->set_link( cur->clone() );
     319                } else {
     320                        arguments = ( ExpressionNode*)cur->clone();
     321                } // if
     322                cur = cur->get_link();
     323        }
    309324}
    310325
    311326CompositeExprNode::~CompositeExprNode() {
    312     delete function;
    313     delete arguments;
     327        delete function;
     328        delete arguments;
    314329}
    315330
    316331// the names that users use to define operator functions
    317332static const char *opFuncName[] = {
    318     "",  "", "",
    319     "",   "",
    320     // diadic
    321     "",   "", "", "", "?+?",    "?-?",   "?*?",     "?/?",     "?%?",     "",       "",
    322     "?|?",  "?&?",  "?^?",     "",    "?<<?",  "?>>?",  "?<?",   "?>?",    "?<=?",
    323     "?>=?", "?==?",      "?!=?",     "?=?",  "?*=?", "?/=?", "?%=?", "?+=?", "?-=?",
    324     "?<<=?", "?>>=?",  "?&=?", "?^=?",  "?|=?",  "?[?]",   "","","Range",
    325     // monadic
    326     "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress"
     333        "",  "", "",
     334        "",   "",
     335        // diadic
     336        "",   "", "", "", "?+?",    "?-?",   "?*?",     "?/?",     "?%?",     "",       "",
     337        "?|?",  "?&?",  "?^?",     "",    "?<<?",  "?>>?",  "?<?",   "?>?",    "?<=?",
     338        "?>=?", "?==?",      "?!=?",     "?=?",  "?*=?", "?/=?", "?%=?", "?+=?", "?-=?",
     339        "?<<=?", "?>>=?",  "?&=?", "?^=?",  "?|=?",  "?[?]",   "","","Range",
     340        // monadic
     341        "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress"
    327342};
    328343
     
    330345
    331346Expression *CompositeExprNode::build() const {
    332     OperatorNode *op;
    333     std::list<Expression *> args;
    334 
    335     buildList( get_args(), args );
    336 
    337     if ( ! ( op = dynamic_cast<OperatorNode *>( function )) ) {
    338         // a function as opposed to an operator
    339         return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() ));
    340     } else {
    341         switch ( op->get_type()){
    342           case OperatorNode::Incr:
    343           case OperatorNode::Decr:
    344           case OperatorNode::IncrPost:
    345           case OperatorNode::DecrPost:
    346           case OperatorNode::Assign:
    347           case OperatorNode::MulAssn:
    348           case OperatorNode::DivAssn:
    349           case OperatorNode::ModAssn:
    350           case OperatorNode::PlusAssn:
    351           case OperatorNode::MinusAssn:
    352           case OperatorNode::LSAssn:
    353           case OperatorNode::RSAssn:
    354           case OperatorNode::AndAssn:
    355           case OperatorNode::ERAssn:
    356           case OperatorNode::OrAssn:
    357             // the rewrite rules for these expressions specify that the first argument has its address taken
    358             assert( !args.empty() );
    359             args.front() = new AddressExpr( args.front() );
    360             break;
    361           default:
    362             /* do nothing */
    363             ;
    364         }
    365 
    366         switch ( op->get_type() ) {
    367           case OperatorNode::Incr:
    368           case OperatorNode::Decr:
    369           case OperatorNode::IncrPost:
    370           case OperatorNode::DecrPost:
    371           case OperatorNode::Assign:
    372           case OperatorNode::MulAssn:
    373           case OperatorNode::DivAssn:
    374           case OperatorNode::ModAssn:
    375           case OperatorNode::PlusAssn:
    376           case OperatorNode::MinusAssn:
    377           case OperatorNode::LSAssn:
    378           case OperatorNode::RSAssn:
    379           case OperatorNode::AndAssn:
    380           case OperatorNode::ERAssn:
    381           case OperatorNode::OrAssn:
    382           case OperatorNode::Plus:
    383           case OperatorNode::Minus:
    384           case OperatorNode::Mul:
    385           case OperatorNode::Div:
    386           case OperatorNode::Mod:
    387           case OperatorNode::BitOr:
    388           case OperatorNode::BitAnd:
    389           case OperatorNode::Xor:
    390           case OperatorNode::LShift:
    391           case OperatorNode::RShift:
    392           case OperatorNode::LThan:
    393           case OperatorNode::GThan:
    394           case OperatorNode::LEThan:
    395           case OperatorNode::GEThan:
    396           case OperatorNode::Eq:
    397           case OperatorNode::Neq:
    398           case OperatorNode::Index:
    399           case OperatorNode::Range:
    400           case OperatorNode::UnPlus:
    401           case OperatorNode::UnMinus:
    402           case OperatorNode::PointTo:
    403           case OperatorNode::Neg:
    404           case OperatorNode::BitNeg:
    405           case OperatorNode::LabelAddress:
    406             return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args );
    407           case OperatorNode::AddressOf:
    408             assert( args.size() == 1 );
    409             assert( args.front() );
    410 
    411             return new AddressExpr( args.front() );
    412           case OperatorNode::Cast:
    413             {
    414                 TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args());
    415                 assert( arg );
    416 
    417                 DeclarationNode *decl_node = arg->get_decl();
    418                 ExpressionNode *expr_node = dynamic_cast<ExpressionNode *>( arg->get_link());
    419 
    420                 Type *targetType = decl_node->buildType();
    421                 if ( dynamic_cast< VoidType* >( targetType ) ) {
    422                     delete targetType;
    423                     return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) );
    424                 } else {
    425                     return new CastExpr( expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) );
    426                 } // if
    427             }
    428           case OperatorNode::FieldSel:
    429             {
    430                 assert( args.size() == 2 );
    431 
    432                 NameExpr *member = dynamic_cast<NameExpr *>( args.back());
    433                 // TupleExpr *memberTup = dynamic_cast<TupleExpr *>( args.back());
    434 
    435                 if ( member != 0 ) {
    436                     UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), args.front());
    437                     delete member;
    438                     return ret;
    439                 /* else if ( memberTup != 0 )
    440                    {
    441                    UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front());
    442                    delete member;
    443                    return ret;
    444                    } */
    445                 } else
    446                     assert( false );
    447             }
    448           case OperatorNode::PFieldSel:
    449             {
    450                 assert( args.size() == 2 );
    451 
    452                 NameExpr *member = dynamic_cast<NameExpr *>( args.back());  // modify for Tuples   xxx
    453                 assert( member != 0 );
    454 
    455                 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    456                 deref->get_args().push_back( args.front() );
    457 
    458                 UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref );
    459                 delete member;
    460                 return ret;
    461             }
    462           case OperatorNode::AlignOf:
    463           case OperatorNode::SizeOf:
    464             {
     347        OperatorNode *op;
     348        std::list<Expression *> args;
     349
     350        buildList( get_args(), args );
     351
     352        if ( ! ( op = dynamic_cast<OperatorNode *>( function )) ) {
     353                // a function as opposed to an operator
     354                return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() ));
     355        } else {
     356                switch ( op->get_type()){
     357                  case OperatorNode::Incr:
     358                  case OperatorNode::Decr:
     359                  case OperatorNode::IncrPost:
     360                  case OperatorNode::DecrPost:
     361                  case OperatorNode::Assign:
     362                  case OperatorNode::MulAssn:
     363                  case OperatorNode::DivAssn:
     364                  case OperatorNode::ModAssn:
     365                  case OperatorNode::PlusAssn:
     366                  case OperatorNode::MinusAssn:
     367                  case OperatorNode::LSAssn:
     368                  case OperatorNode::RSAssn:
     369                  case OperatorNode::AndAssn:
     370                  case OperatorNode::ERAssn:
     371                  case OperatorNode::OrAssn:
     372                        // the rewrite rules for these expressions specify that the first argument has its address taken
     373                        assert( !args.empty() );
     374                        args.front() = new AddressExpr( args.front() );
     375                        break;
     376                  default:
     377                        /* do nothing */
     378                        ;
     379                }
     380
     381                switch ( op->get_type() ) {
     382                  case OperatorNode::Incr:
     383                  case OperatorNode::Decr:
     384                  case OperatorNode::IncrPost:
     385                  case OperatorNode::DecrPost:
     386                  case OperatorNode::Assign:
     387                  case OperatorNode::MulAssn:
     388                  case OperatorNode::DivAssn:
     389                  case OperatorNode::ModAssn:
     390                  case OperatorNode::PlusAssn:
     391                  case OperatorNode::MinusAssn:
     392                  case OperatorNode::LSAssn:
     393                  case OperatorNode::RSAssn:
     394                  case OperatorNode::AndAssn:
     395                  case OperatorNode::ERAssn:
     396                  case OperatorNode::OrAssn:
     397                  case OperatorNode::Plus:
     398                  case OperatorNode::Minus:
     399                  case OperatorNode::Mul:
     400                  case OperatorNode::Div:
     401                  case OperatorNode::Mod:
     402                  case OperatorNode::BitOr:
     403                  case OperatorNode::BitAnd:
     404                  case OperatorNode::Xor:
     405                  case OperatorNode::LShift:
     406                  case OperatorNode::RShift:
     407                  case OperatorNode::LThan:
     408                  case OperatorNode::GThan:
     409                  case OperatorNode::LEThan:
     410                  case OperatorNode::GEThan:
     411                  case OperatorNode::Eq:
     412                  case OperatorNode::Neq:
     413                  case OperatorNode::Index:
     414                  case OperatorNode::Range:
     415                  case OperatorNode::UnPlus:
     416                  case OperatorNode::UnMinus:
     417                  case OperatorNode::PointTo:
     418                  case OperatorNode::Neg:
     419                  case OperatorNode::BitNeg:
     420                  case OperatorNode::LabelAddress:
     421                        return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args );
     422                  case OperatorNode::AddressOf:
     423                        assert( args.size() == 1 );
     424                        assert( args.front() );
     425
     426                        return new AddressExpr( args.front() );
     427                  case OperatorNode::Cast:
     428                        {
     429                                TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args());
     430                                assert( arg );
     431
     432                                DeclarationNode *decl_node = arg->get_decl();
     433                                ExpressionNode *expr_node = dynamic_cast<ExpressionNode *>( arg->get_link());
     434
     435                                Type *targetType = decl_node->buildType();
     436                                if ( dynamic_cast< VoidType* >( targetType ) ) {
     437                                        delete targetType;
     438                                        return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) );
     439                                } else {
     440                                        return new CastExpr( expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) );
     441                                } // if
     442                        }
     443                  case OperatorNode::FieldSel:
     444                        {
     445                                assert( args.size() == 2 );
     446
     447                                NameExpr *member = dynamic_cast<NameExpr *>( args.back());
     448                                // TupleExpr *memberTup = dynamic_cast<TupleExpr *>( args.back());
     449
     450                                if ( member != 0 ) {
     451                                        UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), args.front());
     452                                        delete member;
     453                                        return ret;
     454                                        /* else if ( memberTup != 0 )
     455                                           {
     456                                           UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front());
     457                                           delete member;
     458                                           return ret;
     459                                           } */
     460                                } else
     461                                        assert( false );
     462                        }
     463                  case OperatorNode::PFieldSel:
     464                        {
     465                                assert( args.size() == 2 );
     466
     467                                NameExpr *member = dynamic_cast<NameExpr *>( args.back());  // modify for Tuples   xxx
     468                                assert( member != 0 );
     469
     470                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     471                                deref->get_args().push_back( args.front() );
     472
     473                                UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref );
     474                                delete member;
     475                                return ret;
     476                        }
     477                  case OperatorNode::AlignOf:
     478                  case OperatorNode::SizeOf:
     479                        {
    465480///     bool isSizeOf = ( op->get_type() == OperatorNode::SizeOf );
    466481
    467                 if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()) ) {
    468                     return new SizeofExpr( arg->get_decl()->buildType());
    469                 } else {
    470                     return new SizeofExpr( args.front());
    471                 } // if
    472             }
    473           case OperatorNode::Attr:
    474             {
    475                 VarRefNode *var = dynamic_cast<VarRefNode *>( get_args());
    476                 assert( var );
    477                 if ( !get_args()->get_link() ) {
    478                     return new AttrExpr( var->build(), ( Expression*)0);
    479                 } else if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()->get_link()) ) {
    480                     return new AttrExpr( var->build(), arg->get_decl()->buildType());
    481                 } else {
    482                     return new AttrExpr( var->build(), args.back());
    483                 } // if
    484             }
    485           case OperatorNode::CompLit:
    486             throw UnimplementedError( "C99 compound literals" );
    487             // the short-circuited operators
    488           case OperatorNode::Or:
    489           case OperatorNode::And:
    490             assert( args.size() == 2);
    491             return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), ( op->get_type() == OperatorNode::And ) );
    492           case OperatorNode::Cond:
    493             {
    494                 assert( args.size() == 3);
    495                 std::list< Expression* >::const_iterator i = args.begin();
    496                 Expression *arg1 = notZeroExpr( *i++ );
    497                 Expression *arg2 = *i++;
    498                 Expression *arg3 = *i++;
    499                 return new ConditionalExpr( arg1, arg2, arg3 );
    500             }
    501           case OperatorNode::NCond:
    502             throw UnimplementedError( "GNU 2-argument conditional expression" );
    503           case OperatorNode::Comma:
    504             {
    505                 assert( args.size() == 2);
    506                 std::list< Expression* >::const_iterator i = args.begin();
    507                 Expression *ret = *i++;
    508                 while ( i != args.end() ) {
    509                     ret = new CommaExpr( ret, *i++ );
    510                 }
    511                 return ret;
    512             }
    513             // Tuples
    514           case OperatorNode::TupleC:
    515             {
    516                 TupleExpr *ret = new TupleExpr();
    517                 std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
    518                 return ret;
    519             }
    520           default:
    521             // shouldn't happen
    522             return 0;
    523         }
    524     }
    525 }
    526 
    527 void CompositeExprNode::printOneLine( std::ostream &os, int indent ) const {
    528     printDesignation( os );
    529     os << "( ";
    530     function->printOneLine( os, indent );
    531     for ( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
    532         cur->printOneLine( os, indent );
    533     }
    534     os << ") ";
    535 }
    536 
    537 void CompositeExprNode::print( std::ostream &os, int indent ) const {
    538     printDesignation( os );
    539     os << '\r' << string( indent, ' ') << "Application of: " << endl;
    540     function->print( os, indent + ParseNode::indent_by );
    541 
    542     os << '\r' << string( indent, ' ') ;
    543     if ( arguments ) {
    544         os << "... on arguments: " << endl;
    545         arguments->printList( os, indent + ParseNode::indent_by );
    546     } else
    547         os << "... on no arguments: " << endl;
    548 }
    549 
    550 void CompositeExprNode::set_function( ExpressionNode *f ){
    551     function = f;
    552 }
    553 
    554 void CompositeExprNode::set_args( ExpressionNode *args ){
    555     arguments = args;
    556 }
    557 
    558 ExpressionNode *CompositeExprNode::get_function( void ) const {
    559     return function;
    560 }
    561 
    562 ExpressionNode *CompositeExprNode::get_args( void ) const {
    563     return arguments;
    564 }
    565 
    566 void CompositeExprNode::add_arg( ExpressionNode *arg ){
    567     if ( arguments )
    568         arguments->set_link( arg );
    569     else
    570         set_args( arg );
    571 }
    572 
    573 CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {}
    574 
    575 CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) {
    576 }
    577 
    578 CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) {
    579 }
    580 
    581 CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ){
    582     add_arg( exp );
    583 
    584     return this;
    585 }
    586 
    587 CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) {
    588 }
    589 
    590 ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {}
    591 
    592 ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) {
    593 }
    594 
    595 ValofExprNode::~ValofExprNode() {
    596     delete body;
    597 }
    598 
    599 void ValofExprNode::print( std::ostream &os, int indent ) const {
    600     printDesignation( os );
    601     os << string( indent, ' ') << "Valof Expression:" << std::endl;
    602     get_body()->print( os, indent + 4);
    603 }
    604 
    605 void ValofExprNode::printOneLine( std::ostream &, int indent ) const {
    606     assert( false );
    607 }
    608 
    609 Expression *ValofExprNode::build() const {
    610     return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
    611 }
    612 
    613 ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) {
    614     if ( init_ == 0 )
    615         init = 0;
    616     else {
    617         DeclarationNode *decl;
    618         ExpressionNode *exp;
    619 
    620         if (( decl = dynamic_cast<DeclarationNode *>( init_)) != 0)
    621             init = new StatementNode( decl );
    622         else if (( exp = dynamic_cast<ExpressionNode *>( init_)) != 0)
    623             init = new StatementNode( StatementNode::Exp, exp );
    624         else
    625             throw SemanticError("Error in for control expression");
    626     }
    627 }
    628 
    629 ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
    630     : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) {
    631 }
    632 
    633 ForCtlExprNode::~ForCtlExprNode(){
    634     delete init;
    635     delete condition;
    636     delete change;
    637 }
    638 
    639 Expression *ForCtlExprNode::build() const {
    640     // this shouldn't be used!
    641     assert( false );
    642     return 0;
    643 }
    644 
    645 void ForCtlExprNode::print( std::ostream &os, int indent ) const{
    646     os << string( indent,' ') << "For Control Expression -- : " << endl;
    647 
    648     os << "\r" << string( indent + 2,' ') << "initialization: ";
    649     if ( init != 0)
    650         init->print( os, indent + 4);
    651 
    652     os << "\n\r" << string( indent + 2,' ') << "condition: ";
    653     if ( condition != 0)
    654         condition->print( os, indent + 4);
    655     os << "\n\r" << string( indent + 2,' ') << "increment: ";
    656     if ( change != 0)
    657         change->print( os, indent + 4);
    658 }
    659 
    660 void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const {
    661     assert( false );
    662 }
    663 
    664 TypeValueNode::TypeValueNode( DeclarationNode *decl )
    665     : decl( decl ) {
    666 }
    667 
    668 TypeValueNode::TypeValueNode( const TypeValueNode &other )
    669     : ExpressionNode( other ), decl( maybeClone( other.decl ) ) {
    670 }
    671 
    672 Expression *TypeValueNode::build() const {
    673     return new TypeExpr( decl->buildType() );
    674 }
    675 
    676 void TypeValueNode::print( std::ostream &os, int indent ) const {
    677     os << std::string( indent, ' ' ) << "Type:";
    678     get_decl()->print( os, indent + 2);
    679 }
    680 
    681 void TypeValueNode::printOneLine( std::ostream &os, int indent ) const {
    682     os << "Type:";
    683     get_decl()->print( os, indent + 2);
    684 }
    685 
    686 ExpressionNode *flattenCommas( ExpressionNode *list ) {
    687     if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
    688         {
    689             OperatorNode *op;
    690             if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::Comma ) )
    691                 {
    692                     if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
    693                         composite->add_arg( next );
    694                     return flattenCommas( composite->get_args() );
     482                                if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()) ) {
     483                                        return new SizeofExpr( arg->get_decl()->buildType());
     484                                } else {
     485                                        return new SizeofExpr( args.front());
     486                                } // if
     487                        }
     488                  case OperatorNode::Attr:
     489                        {
     490                                VarRefNode *var = dynamic_cast<VarRefNode *>( get_args());
     491                                assert( var );
     492                                if ( !get_args()->get_link() ) {
     493                                        return new AttrExpr( var->build(), ( Expression*)0);
     494                                } else if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()->get_link()) ) {
     495                                        return new AttrExpr( var->build(), arg->get_decl()->buildType());
     496                                } else {
     497                                        return new AttrExpr( var->build(), args.back());
     498                                } // if
     499                        }
     500                  case OperatorNode::CompLit:
     501                        throw UnimplementedError( "C99 compound literals" );
     502                        // the short-circuited operators
     503                  case OperatorNode::Or:
     504                  case OperatorNode::And:
     505                        assert( args.size() == 2);
     506                        return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), ( op->get_type() == OperatorNode::And ) );
     507                  case OperatorNode::Cond:
     508                        {
     509                                assert( args.size() == 3);
     510                                std::list< Expression* >::const_iterator i = args.begin();
     511                                Expression *arg1 = notZeroExpr( *i++ );
     512                                Expression *arg2 = *i++;
     513                                Expression *arg3 = *i++;
     514                                return new ConditionalExpr( arg1, arg2, arg3 );
     515                        }
     516                  case OperatorNode::NCond:
     517                        throw UnimplementedError( "GNU 2-argument conditional expression" );
     518                  case OperatorNode::Comma:
     519                        {
     520                                assert( args.size() == 2);
     521                                std::list< Expression* >::const_iterator i = args.begin();
     522                                Expression *ret = *i++;
     523                                while ( i != args.end() ) {
     524                                        ret = new CommaExpr( ret, *i++ );
     525                                }
     526                                return ret;
     527                        }
     528                        // Tuples
     529                  case OperatorNode::TupleC:
     530                        {
     531                                TupleExpr *ret = new TupleExpr();
     532                                std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
     533                                return ret;
     534                        }
     535                  default:
     536                        // shouldn't happen
     537                        return 0;
    695538                }
    696539        }
    697 
    698     if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
    699         list->set_next( flattenCommas( next ) );
    700 
    701     return list;
     540}
     541
     542void CompositeExprNode::printOneLine( std::ostream &os, int indent ) const {
     543        printDesignation( os );
     544        os << "( ";
     545        function->printOneLine( os, indent );
     546        for ( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
     547                cur->printOneLine( os, indent );
     548        }
     549        os << ") ";
     550}
     551
     552void CompositeExprNode::print( std::ostream &os, int indent ) const {
     553        printDesignation( os );
     554        os << '\r' << string( indent, ' ') << "Application of: " << endl;
     555        function->print( os, indent + ParseNode::indent_by );
     556
     557        os << '\r' << string( indent, ' ') ;
     558        if ( arguments ) {
     559                os << "... on arguments: " << endl;
     560                arguments->printList( os, indent + ParseNode::indent_by );
     561        } else
     562                os << "... on no arguments: " << endl;
     563}
     564
     565void CompositeExprNode::set_function( ExpressionNode *f ){
     566        function = f;
     567}
     568
     569void CompositeExprNode::set_args( ExpressionNode *args ){
     570        arguments = args;
     571}
     572
     573ExpressionNode *CompositeExprNode::get_function( void ) const {
     574        return function;
     575}
     576
     577ExpressionNode *CompositeExprNode::get_args( void ) const {
     578        return arguments;
     579}
     580
     581void CompositeExprNode::add_arg( ExpressionNode *arg ){
     582        if ( arguments )
     583                arguments->set_link( arg );
     584        else
     585                set_args( arg );
     586}
     587
     588CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {}
     589
     590CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) {
     591}
     592
     593CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) {
     594}
     595
     596CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ){
     597        add_arg( exp );
     598
     599        return this;
     600}
     601
     602CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) {
     603}
     604
     605ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {}
     606
     607ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) {
     608}
     609
     610ValofExprNode::~ValofExprNode() {
     611        delete body;
     612}
     613
     614void ValofExprNode::print( std::ostream &os, int indent ) const {
     615        printDesignation( os );
     616        os << string( indent, ' ') << "Valof Expression:" << std::endl;
     617        get_body()->print( os, indent + 4);
     618}
     619
     620void ValofExprNode::printOneLine( std::ostream &, int indent ) const {
     621        assert( false );
     622}
     623
     624Expression *ValofExprNode::build() const {
     625        return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
     626}
     627
     628ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) {
     629        if ( init_ == 0 )
     630                init = 0;
     631        else {
     632                DeclarationNode *decl;
     633                ExpressionNode *exp;
     634
     635                if (( decl = dynamic_cast<DeclarationNode *>( init_)) != 0)
     636                        init = new StatementNode( decl );
     637                else if (( exp = dynamic_cast<ExpressionNode *>( init_)) != 0)
     638                        init = new StatementNode( StatementNode::Exp, exp );
     639                else
     640                        throw SemanticError("Error in for control expression");
     641        }
     642}
     643
     644ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
     645        : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) {
     646}
     647
     648ForCtlExprNode::~ForCtlExprNode(){
     649        delete init;
     650        delete condition;
     651        delete change;
     652}
     653
     654Expression *ForCtlExprNode::build() const {
     655        // this shouldn't be used!
     656        assert( false );
     657        return 0;
     658}
     659
     660void ForCtlExprNode::print( std::ostream &os, int indent ) const{
     661        os << string( indent,' ') << "For Control Expression -- : " << endl;
     662
     663        os << "\r" << string( indent + 2,' ') << "initialization: ";
     664        if ( init != 0)
     665                init->print( os, indent + 4);
     666
     667        os << "\n\r" << string( indent + 2,' ') << "condition: ";
     668        if ( condition != 0)
     669                condition->print( os, indent + 4);
     670        os << "\n\r" << string( indent + 2,' ') << "increment: ";
     671        if ( change != 0)
     672                change->print( os, indent + 4);
     673}
     674
     675void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const {
     676        assert( false );
     677}
     678
     679TypeValueNode::TypeValueNode( DeclarationNode *decl )
     680        : decl( decl ) {
     681}
     682
     683TypeValueNode::TypeValueNode( const TypeValueNode &other )
     684        : ExpressionNode( other ), decl( maybeClone( other.decl ) ) {
     685}
     686
     687Expression *TypeValueNode::build() const {
     688        return new TypeExpr( decl->buildType() );
     689}
     690
     691void TypeValueNode::print( std::ostream &os, int indent ) const {
     692        os << std::string( indent, ' ' ) << "Type:";
     693        get_decl()->print( os, indent + 2);
     694}
     695
     696void TypeValueNode::printOneLine( std::ostream &os, int indent ) const {
     697        os << "Type:";
     698        get_decl()->print( os, indent + 2);
     699}
     700
     701ExpressionNode *flattenCommas( ExpressionNode *list ) {
     702        if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
     703                {
     704                        OperatorNode *op;
     705                        if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::Comma ) )
     706                                {
     707                                        if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
     708                                                composite->add_arg( next );
     709                                        return flattenCommas( composite->get_args() );
     710                                }
     711                }
     712
     713        if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
     714                list->set_next( flattenCommas( next ) );
     715
     716        return list;
    702717}
    703718
    704719ExpressionNode *tupleContents( ExpressionNode *tuple ) {
    705     if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
    706         OperatorNode *op = 0;
    707         if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::TupleC ) )
    708             return composite->get_args();
    709     }
    710     return tuple;
    711 }
     720        if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
     721                OperatorNode *op = 0;
     722                if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::TupleC ) )
     723                        return composite->get_args();
     724        }
     725        return tuple;
     726}
     727
     728// Local Variables: //
     729// tab-width: 4 //
     730// mode: c++ //
     731// compile-command: "make install" //
     732// End: //
  • translator/Parser/InitializerNode.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// InitializerNode.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:20:24 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:21:40 2015
     13// Update Count     : 2
     14//
     15
    116#include <cassert>
    217#include <iostream>
     
    924InitializerNode::InitializerNode( ExpressionNode *_expr, bool aggrp, ExpressionNode *des )
    1025        : expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) {
    11     if ( aggrp )
    12         kids = dynamic_cast< InitializerNode *>( get_link() );
     26        if ( aggrp )
     27                kids = dynamic_cast< InitializerNode *>( get_link() );
    1328
    14     if ( kids != 0 )
    15         set_link( 0 );
     29        if ( kids != 0 )
     30                set_link( 0 );
    1631}
    1732
    1833InitializerNode::InitializerNode( InitializerNode *init, bool aggrp, ExpressionNode *des )
    19     : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) {
    20     if ( init != 0 )
    21         set_link(init);
     34        : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) {
     35        if ( init != 0 )
     36                set_link(init);
    2237
    23     if ( aggrp )
    24         kids = dynamic_cast< InitializerNode *>( get_link() );
     38        if ( aggrp )
     39                kids = dynamic_cast< InitializerNode *>( get_link() );
    2540
    26     if ( kids != 0 )
    27         set_next( 0 );
     41        if ( kids != 0 )
     42                set_next( 0 );
    2843}
    2944
    3045InitializerNode::~InitializerNode() {
    31     delete expr;
     46        delete expr;
    3247}
    3348
    3449void InitializerNode::print( std::ostream &os, int indent ) const {
    35     os << std::string(indent, ' ') << "Initializer expression" << std::endl;
     50        os << std::string(indent, ' ') << "Initializer expression" << std::endl;
    3651}
    3752
    3853void InitializerNode::printOneLine( std::ostream &os ) const {
    39     if ( ! aggregate ) {
    40         if ( designator != 0 ) {
    41             os << "designated by: (";
    42             ExpressionNode *curdes = designator;
    43             while( curdes != 0) {
    44                 curdes->printOneLine(os);
    45                 curdes = (ExpressionNode *)(curdes->get_link());
    46                 if ( curdes ) os << ", ";
    47             } // while
    48             os << ")";
     54        if ( ! aggregate ) {
     55                if ( designator != 0 ) {
     56                        os << "designated by: (";
     57                        ExpressionNode *curdes = designator;
     58                        while( curdes != 0) {
     59                                curdes->printOneLine(os);
     60                                curdes = (ExpressionNode *)(curdes->get_link());
     61                                if ( curdes ) os << ", ";
     62                        } // while
     63                        os << ")";
     64                } // if
     65                if ( expr ) expr->printOneLine(os);
     66        } else {  // It's an aggregate
     67                os << "[--";
     68                if ( next_init() != 0 )
     69                        next_init()->printOneLine(os);
     70                if (aggregate) os << "--]";
    4971        } // if
    50         if ( expr ) expr->printOneLine(os);
    51     } else {  // It's an aggregate
    52         os << "[--";
    53         if ( next_init() != 0 )
    54             next_init()->printOneLine(os);
    55         if (aggregate) os << "--]";
    56     } // if
    5772
    58     InitializerNode *moreInit;
    59     if  ( get_link() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_link() ) ) != 0) )
    60         moreInit->printOneLine( os );
     73        InitializerNode *moreInit;
     74        if  ( get_link() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_link() ) ) != 0) )
     75                moreInit->printOneLine( os );
    6176}
    6277
    6378Initializer *InitializerNode::build() const {
    64     // if ( get_expression() == 0 ) return 0;  // XXX (?)
     79        // if ( get_expression() == 0 ) return 0;  // XXX (?)
    6580
    66     if ( aggregate ) {
    67         assert( next_init() != 0 );
     81        if ( aggregate ) {
     82                assert( next_init() != 0 );
    6883
    69         std::list< Initializer *> initlist;
    70         buildList<Initializer, InitializerNode>( next_init(), initlist );
     84                std::list< Initializer *> initlist;
     85                buildList<Initializer, InitializerNode>( next_init(), initlist );
    7186
    72         std::list< Expression *> designlist;
     87                std::list< Expression *> designlist;
    7388
    74         if ( designator != 0 ) {
    75             buildList<Expression, ExpressionNode>( designator, designlist );
     89                if ( designator != 0 ) {
     90                        buildList<Expression, ExpressionNode>( designator, designlist );
     91                } // if
     92
     93                return new ListInit( initlist, designlist );
     94        } else {
     95                std::list< Expression *> designators;
     96
     97                if ( designator != 0 )
     98                        buildList<Expression, ExpressionNode>( designator, designators );
     99
     100                if ( get_expression() != 0)
     101                        return new SingleInit( get_expression()->build(), designators );
    76102        } // if
    77103
    78         return new ListInit( initlist, designlist );
    79     } else {
    80         std::list< Expression *> designators;
     104        return 0;
     105}
    81106
    82         if ( designator != 0 )
    83             buildList<Expression, ExpressionNode>( designator, designators );
    84 
    85         if ( get_expression() != 0)
    86             return new SingleInit( get_expression()->build(), designators );
    87     } // if
    88 
    89     return 0;
    90 }
     107// Local Variables: //
     108// tab-width: 4 //
     109// mode: c++ //
     110// compile-command: "make install" //
     111// End: //
  • translator/Parser/LinkageSpec.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// LinkageSpec.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:22:09 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:23:21 2015
     13// Update Count     : 2
     14//
     15
    116#include <string>
    217#include <cassert>
     
    621
    722LinkageSpec::Type LinkageSpec::fromString( const std::string &stringSpec ) {
    8     if ( stringSpec == "\"Cforall\"" ) {
    9         return Cforall;
    10     } else if ( stringSpec == "\"C\"" ) {
    11         return C;
    12     } else {
    13         throw SemanticError( "Invalid linkage specifier " + stringSpec );
    14     }
     23        if ( stringSpec == "\"Cforall\"" ) {
     24                return Cforall;
     25        } else if ( stringSpec == "\"C\"" ) {
     26                return C;
     27        } else {
     28                throw SemanticError( "Invalid linkage specifier " + stringSpec );
     29        }
    1530}
    1631
    1732std::string LinkageSpec::toString( LinkageSpec::Type linkage ) {
    18     switch ( linkage ) {
    19       case Intrinsic:
    20         return "intrinsic";
    21       case Cforall:
    22         return "Cforall";
    23       case C:
    24         return "C";
    25       case AutoGen:
    26         return "automatically generated";
    27       case Compiler:
    28         return "compiler built-in";
    29     }
    30     assert( false );
    31     return "";
     33        switch ( linkage ) {
     34          case Intrinsic:
     35                return "intrinsic";
     36          case Cforall:
     37                return "Cforall";
     38          case C:
     39                return "C";
     40          case AutoGen:
     41                return "automatically generated";
     42          case Compiler:
     43                return "compiler built-in";
     44        }
     45        assert( false );
     46        return "";
    3247}
    3348
    3449bool LinkageSpec::isDecoratable( Type t ) {
    35     switch ( t ) {
    36       case Intrinsic:
    37       case Cforall:
    38       case AutoGen:
    39         return true;
    40       case C:
    41       case Compiler:
     50        switch ( t ) {
     51          case Intrinsic:
     52          case Cforall:
     53          case AutoGen:
     54                return true;
     55          case C:
     56          case Compiler:
     57                return false;
     58        }
     59        assert( false );
    4260        return false;
    43     }
    44     assert( false );
    45     return false;
    4661}
    4762
    4863bool LinkageSpec::isGeneratable( Type t ) {
    49     switch ( t ) {
    50       case Intrinsic:
    51       case Cforall:
    52       case AutoGen:
    53       case C:
    54         return true;
    55       case Compiler:
     64        switch ( t ) {
     65          case Intrinsic:
     66          case Cforall:
     67          case AutoGen:
     68          case C:
     69                return true;
     70          case Compiler:
     71                return false;
     72        }
     73        assert( false );
    5674        return false;
    57     }
    58     assert( false );
    59     return false;
    6075}
    6176
    6277bool LinkageSpec::isOverloadable( Type t ) {
    63     return isDecoratable( t );
     78        return isDecoratable( t );
    6479}
    6580
    6681bool LinkageSpec::isBuiltin( Type t ) {
    67     switch ( t ) {
    68       case Cforall:
    69       case AutoGen:
    70       case C:
     82        switch ( t ) {
     83          case Cforall:
     84          case AutoGen:
     85          case C:
     86                return false;
     87          case Intrinsic:
     88          case Compiler:
     89                return true;
     90        }
     91        assert( false );
    7192        return false;
    72       case Intrinsic:
    73       case Compiler:
    74         return true;
    75     }
    76     assert( false );
    77     return false;
    7893}
     94
     95// Local Variables: //
     96// tab-width: 4 //
     97// mode: c++ //
     98// compile-command: "make install" //
     99// End: //
  • translator/Parser/LinkageSpec.h

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// LinkageSpec.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:24:28 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:26:14 2015
     13// Update Count     : 3
     14//
     15
    116#ifndef LINKAGESPEC_H
    217#define LINKAGESPEC_H
     
    520
    621struct LinkageSpec {
    7     enum Type {
    8         Intrinsic,              // C built-in defined in prelude
    9         Cforall,                // ordinary
    10         C,                      // not overloadable, not mangled
    11         AutoGen,                // built by translator (struct assignment)
    12         Compiler                // gcc internal
    13     };
     22        enum Type {
     23                Intrinsic,                                                                              // C built-in defined in prelude
     24                Cforall,                                                                                // ordinary
     25                C,                                                                                              // not overloadable, not mangled
     26                AutoGen,                                                                                // built by translator (struct assignment)
     27                Compiler                                                                                // gcc internal
     28        };
    1429 
    15     static Type fromString( const std::string & );
    16     static std::string toString( Type );
     30        static Type fromString( const std::string & );
     31        static std::string toString( Type );
    1732 
    18     static bool isDecoratable( Type );
    19     static bool isGeneratable( Type );
    20     static bool isOverloadable( Type );
    21     static bool isBuiltin( Type );
     33        static bool isDecoratable( Type );
     34        static bool isGeneratable( Type );
     35        static bool isOverloadable( Type );
     36        static bool isBuiltin( Type );
    2237};
    2338
    2439#endif // LINKAGESPEC_H
     40
     41// Local Variables: //
     42// tab-width: 4 //
     43// mode: c++ //
     44// compile-command: "make install" //
     45// End: //
  • translator/Parser/ParseNode.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// ParseNode.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:26:29 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:27:51 2015
     13// Update Count     : 2
     14//
     15
    116#include "ParseNode.h"
    217using namespace std;
     
    7489
    7590ParseNode *mkList( ParseNode &pn ) {
    76     /* it just relies on `operator,' to take care of the "arguments" and provides
    77        a nice interface to an awful-looking address-of, rendering, for example
    78        (StatementNode *)(&(*$5 + *$7)) into (StatementNode *)mkList(($5, $7))
    79        (although "nice" is probably not the word)
    80     */
     91    // it just relies on `operator,' to take care of the "arguments" and provides a nice interface to an awful-looking
     92    // address-of, rendering, for example (StatementNode *)(&(*$5 + *$7)) into (StatementNode *)mkList(($5, $7))
     93    // (although "nice" is probably not the word)
    8194    return &pn;
    8295}
    8396
    84 
    8597// Local Variables: //
    86 // mode: C++                //
    87 // compile-command: "gmake" //
     98// tab-width: 4 //
     99// mode: c++ //
     100// compile-command: "make install" //
    88101// End: //
  • translator/Parser/ParseNode.h

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// ParseNode.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 13:28:16 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 13:30:24 2015
     13// Update Count     : 3
     14//
     15
    116#ifndef PARSENODE_H
    217#define PARSENODE_H
     
    2136class ParseNode {
    2237  public:
    23     ParseNode( void );
    24     ParseNode ( std::string );
    25     virtual ~ParseNode( void );
    26 
    27     ParseNode *set_name ( std::string ) ;
    28     ParseNode *set_name ( std::string * ) ;
    29 
    30     std::string get_name( void );
    31 
    32     ParseNode *get_link( void ) const;
    33     ParseNode *get_last( void );
    34     ParseNode *set_link( ParseNode * );
    35     void set_next( ParseNode *newlink ) { next = newlink; }
    36 
    37     virtual ParseNode *clone() const { return 0; };
    38 
    39     const std::string get_name( void ) const;
    40     virtual void print( std::ostream &, int indent = 0 ) const;
    41     virtual void printList( std::ostream &, int indent = 0 ) const;
    42 
    43     ParseNode &operator,( ParseNode &);
     38        ParseNode( void );
     39        ParseNode ( std::string );
     40        virtual ~ParseNode( void );
     41
     42        ParseNode *set_name ( std::string ) ;
     43        ParseNode *set_name ( std::string * ) ;
     44
     45        std::string get_name( void );
     46
     47        ParseNode *get_link( void ) const;
     48        ParseNode *get_last( void );
     49        ParseNode *set_link( ParseNode * );
     50        void set_next( ParseNode *newlink ) { next = newlink; }
     51
     52        virtual ParseNode *clone() const { return 0; };
     53
     54        const std::string get_name( void ) const;
     55        virtual void print( std::ostream &, int indent = 0 ) const;
     56        virtual void printList( std::ostream &, int indent = 0 ) const;
     57
     58        ParseNode &operator,( ParseNode &);
    4459  protected:
    45     std::string name;
    46     ParseNode *next;
    47     static int indent_by;
     60        std::string name;
     61        ParseNode *next;
     62        static int indent_by;
    4863};
    4964
     
    5267class ExpressionNode : public ParseNode {
    5368  public:
    54     ExpressionNode();
    55     ExpressionNode( std::string * );
    56     ExpressionNode( const ExpressionNode &other );
    57     virtual ~ExpressionNode() { /* can't delete asArgName because it might be referenced elsewhere */ };
    58 
    59     virtual ExpressionNode *clone() const = 0;
    60 
    61     virtual CommaExprNode *add_to_list( ExpressionNode * );
    62 
    63     ExpressionNode *get_argName() const { return argName; }
    64     ExpressionNode *set_asArgName( std::string *aName );
    65     ExpressionNode *set_asArgName( ExpressionNode *aDesignator );
    66 
    67     virtual void print( std::ostream &, int indent = 0) const = 0;
    68     virtual void printOneLine( std::ostream &, int indent = 0) const = 0;
    69 
    70     virtual Expression *build() const = 0;
     69        ExpressionNode();
     70        ExpressionNode( std::string * );
     71        ExpressionNode( const ExpressionNode &other );
     72        virtual ~ExpressionNode() {} // cannot delete asArgName because it might be referenced elsewhere
     73
     74        virtual ExpressionNode *clone() const = 0;
     75
     76        virtual CommaExprNode *add_to_list( ExpressionNode * );
     77
     78        ExpressionNode *get_argName() const { return argName; }
     79        ExpressionNode *set_asArgName( std::string *aName );
     80        ExpressionNode *set_asArgName( ExpressionNode *aDesignator );
     81
     82        virtual void print( std::ostream &, int indent = 0) const = 0;
     83        virtual void printOneLine( std::ostream &, int indent = 0) const = 0;
     84
     85        virtual Expression *build() const = 0;
    7186  protected:
    72     void printDesignation ( std::ostream &, int indent = 0) const;
    73   private:
    74     ExpressionNode *argName;
     87        void printDesignation ( std::ostream &, int indent = 0) const;
     88  private:
     89        ExpressionNode *argName;
    7590};
    7691
     
    7893class NullExprNode : public ExpressionNode {
    7994  public:
    80     NullExprNode();
    81 
    82     virtual NullExprNode *clone() const;
    83 
    84     virtual void print( std::ostream &, int indent = 0) const;
    85     virtual void printOneLine( std::ostream &, int indent = 0) const;
    86 
    87     virtual Expression *build() const;
     95        NullExprNode();
     96
     97        virtual NullExprNode *clone() const;
     98
     99        virtual void print( std::ostream &, int indent = 0) const;
     100        virtual void printOneLine( std::ostream &, int indent = 0) const;
     101
     102        virtual Expression *build() const;
    88103};
    89104
    90105class ConstantNode : public ExpressionNode {
    91106  public:
    92     enum Type {
    93         Integer, Float, Character, String /* , Range, EnumConstant  */
    94     };
    95 
    96     ConstantNode( void );
    97     ConstantNode( std::string * );
    98     ConstantNode( Type, std::string * );
    99     ConstantNode( const ConstantNode &other );
    100 
    101     virtual ConstantNode *clone() const { return new ConstantNode( *this ); }
    102 
    103     Type get_type( void ) const ;
    104     virtual void print( std::ostream &, int indent = 0) const;
    105     virtual void printOneLine( std::ostream &, int indent = 0) const;
    106 
    107     std::string get_value() const { return value; }
    108     ConstantNode *append( std::string *newValue );
    109 
    110     Expression *build() const;
    111   private:
    112     void classify( std::string &);
    113     Type type;
    114     std::string value;
    115     bool sign;
    116     short base;
    117     int longs, size;
     107        enum Type {
     108                Integer, Float, Character, String /* , Range, EnumConstant  */
     109        };
     110
     111        ConstantNode( void );
     112        ConstantNode( std::string * );
     113        ConstantNode( Type, std::string * );
     114        ConstantNode( const ConstantNode &other );
     115
     116        virtual ConstantNode *clone() const { return new ConstantNode( *this ); }
     117
     118        Type get_type( void ) const ;
     119        virtual void print( std::ostream &, int indent = 0) const;
     120        virtual void printOneLine( std::ostream &, int indent = 0) const;
     121
     122        std::string get_value() const { return value; }
     123        ConstantNode *append( std::string *newValue );
     124
     125        Expression *build() const;
     126  private:
     127        void classify( std::string &);
     128        Type type;
     129        std::string value;
     130        bool sign;
     131        short base;
     132        int longs, size;
    118133};
    119134
    120135class VarRefNode : public ExpressionNode {
    121136  public:
    122     VarRefNode();
    123     VarRefNode( std::string *, bool isLabel = false );
    124     VarRefNode( const VarRefNode &other );
    125 
    126     virtual Expression *build() const ;
    127 
    128     virtual VarRefNode *clone() const { return new VarRefNode( *this ); }
    129 
    130     virtual void print( std::ostream &, int indent = 0) const;
    131     virtual void printOneLine( std::ostream &, int indent = 0) const;
    132   private:
    133     bool isLabel;
     137        VarRefNode();
     138        VarRefNode( std::string *, bool isLabel = false );
     139        VarRefNode( const VarRefNode &other );
     140
     141        virtual Expression *build() const ;
     142
     143        virtual VarRefNode *clone() const { return new VarRefNode( *this ); }
     144
     145        virtual void print( std::ostream &, int indent = 0) const;
     146        virtual void printOneLine( std::ostream &, int indent = 0) const;
     147  private:
     148        bool isLabel;
    134149};
    135150
    136151class TypeValueNode : public ExpressionNode {
    137152  public:
    138     TypeValueNode( DeclarationNode * );
    139     TypeValueNode( const TypeValueNode &other );
    140 
    141     DeclarationNode *get_decl() const { return decl; }
    142 
    143     virtual Expression *build() const ;
    144 
    145     virtual TypeValueNode *clone() const { return new TypeValueNode( *this ); }
    146 
    147     virtual void print( std::ostream &, int indent = 0) const;
    148     virtual void printOneLine( std::ostream &, int indent = 0) const;
    149   private:
    150     DeclarationNode *decl;
     153        TypeValueNode( DeclarationNode * );
     154        TypeValueNode( const TypeValueNode &other );
     155
     156        DeclarationNode *get_decl() const { return decl; }
     157
     158        virtual Expression *build() const ;
     159
     160        virtual TypeValueNode *clone() const { return new TypeValueNode( *this ); }
     161
     162        virtual void print( std::ostream &, int indent = 0) const;
     163        virtual void printOneLine( std::ostream &, int indent = 0) const;
     164  private:
     165        DeclarationNode *decl;
    151166};
    152167
    153168class OperatorNode : public ExpressionNode {
    154169  public:
    155     enum Type { TupleC, Comma, TupleFieldSel,
    156                 Cond, NCond,
    157                 SizeOf, AlignOf, Attr, CompLit, Plus, Minus, Mul, Div, Mod, Or, And,
    158                 BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq,
    159                 Assign, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn,
    160                 ERAssn, OrAssn, Index, FieldSel, PFieldSel, Range,
    161                 UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress
    162     };
    163 
    164     OperatorNode( Type t );
    165     OperatorNode( const OperatorNode &other );
    166     virtual ~OperatorNode();
    167 
    168     virtual OperatorNode *clone() const { return new OperatorNode( *this ); }
    169 
    170     Type get_type( void ) const;
    171     std::string get_typename( void ) const;
    172 
    173     virtual void print( std::ostream &, int indent = 0) const;
    174     virtual void printOneLine( std::ostream &, int indent = 0) const;
    175 
    176     virtual Expression *build() const { return 0; }
    177   private:
    178     Type type;
    179     static const char *OpName[];
     170        enum Type { TupleC, Comma, TupleFieldSel,
     171                                Cond, NCond,
     172                                SizeOf, AlignOf, Attr, CompLit, Plus, Minus, Mul, Div, Mod, Or, And,
     173                                BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq,
     174                                Assign, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn,
     175                                ERAssn, OrAssn, Index, FieldSel, PFieldSel, Range,
     176                                UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress
     177        };
     178
     179        OperatorNode( Type t );
     180        OperatorNode( const OperatorNode &other );
     181        virtual ~OperatorNode();
     182
     183        virtual OperatorNode *clone() const { return new OperatorNode( *this ); }
     184
     185        Type get_type( void ) const;
     186        std::string get_typename( void ) const;
     187
     188        virtual void print( std::ostream &, int indent = 0) const;
     189        virtual void printOneLine( std::ostream &, int indent = 0) const;
     190
     191        virtual Expression *build() const { return 0; }
     192  private:
     193        Type type;
     194        static const char *OpName[];
    180195};
    181196
     
    183198class CompositeExprNode : public ExpressionNode {
    184199  public:
    185     CompositeExprNode( void );
    186     CompositeExprNode( std::string * );
    187     CompositeExprNode( ExpressionNode *f, ExpressionNode *args = 0 );
    188     CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2 );
    189     CompositeExprNode( const CompositeExprNode &other );
    190     virtual ~CompositeExprNode();
    191 
    192     virtual CompositeExprNode *clone() const { return new CompositeExprNode( *this ); }
    193     virtual Expression *build() const;
    194 
    195     virtual void print( std::ostream &, int indent = 0) const;
    196     virtual void printOneLine( std::ostream &, int indent = 0) const;
    197 
    198     void set_function( ExpressionNode * );
    199     void set_args( ExpressionNode * );
    200 
    201     void add_arg( ExpressionNode * );
    202 
    203     ExpressionNode *get_function() const;
    204     ExpressionNode *get_args() const;
    205   private:
    206     ExpressionNode *function;
    207     ExpressionNode *arguments;
     200        CompositeExprNode( void );
     201        CompositeExprNode( std::string * );
     202        CompositeExprNode( ExpressionNode *f, ExpressionNode *args = 0 );
     203        CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2 );
     204        CompositeExprNode( const CompositeExprNode &other );
     205        virtual ~CompositeExprNode();
     206
     207        virtual CompositeExprNode *clone() const { return new CompositeExprNode( *this ); }
     208        virtual Expression *build() const;
     209
     210        virtual void print( std::ostream &, int indent = 0) const;
     211        virtual void printOneLine( std::ostream &, int indent = 0) const;
     212
     213        void set_function( ExpressionNode * );
     214        void set_args( ExpressionNode * );
     215
     216        void add_arg( ExpressionNode * );
     217
     218        ExpressionNode *get_function() const;
     219        ExpressionNode *get_args() const;
     220  private:
     221        ExpressionNode *function;
     222        ExpressionNode *arguments;
    208223};
    209224
    210225class CommaExprNode : public CompositeExprNode {
    211226  public:
    212     CommaExprNode();
    213     CommaExprNode( ExpressionNode * );
    214     CommaExprNode( ExpressionNode *, ExpressionNode * );
    215     CommaExprNode( const CommaExprNode &other );
    216 
    217     virtual CommaExprNode *add_to_list( ExpressionNode * );
    218     virtual CommaExprNode *clone() const { return new CommaExprNode( *this ); }
     227        CommaExprNode();
     228        CommaExprNode( ExpressionNode * );
     229        CommaExprNode( ExpressionNode *, ExpressionNode * );
     230        CommaExprNode( const CommaExprNode &other );
     231
     232        virtual CommaExprNode *add_to_list( ExpressionNode * );
     233        virtual CommaExprNode *clone() const { return new CommaExprNode( *this ); }
    219234};
    220235
    221236class ForCtlExprNode : public ExpressionNode {
    222237  public:
    223     ForCtlExprNode( ParseNode *, ExpressionNode *, ExpressionNode * ) throw ( SemanticError );
    224     ForCtlExprNode( const ForCtlExprNode &other );
    225     ~ForCtlExprNode();
    226 
    227     StatementNode *get_init() const { return init; }
    228     ExpressionNode *get_condition() const { return condition; }
    229     ExpressionNode *get_change() const { return change; }
    230 
    231     virtual ForCtlExprNode *clone() const { return new ForCtlExprNode( *this ); }
    232     virtual Expression *build() const;
    233 
    234     virtual void print( std::ostream &, int indent = 0 ) const;
    235     virtual void printOneLine( std::ostream &, int indent = 0 ) const;
    236   private:
    237     StatementNode *init;
    238     ExpressionNode *condition;
    239     ExpressionNode *change;
     238        ForCtlExprNode( ParseNode *, ExpressionNode *, ExpressionNode * ) throw ( SemanticError );
     239        ForCtlExprNode( const ForCtlExprNode &other );
     240        ~ForCtlExprNode();
     241
     242        StatementNode *get_init() const { return init; }
     243        ExpressionNode *get_condition() const { return condition; }
     244        ExpressionNode *get_change() const { return change; }
     245
     246        virtual ForCtlExprNode *clone() const { return new ForCtlExprNode( *this ); }
     247        virtual Expression *build() const;
     248
     249        virtual void print( std::ostream &, int indent = 0 ) const;
     250        virtual void printOneLine( std::ostream &, int indent = 0 ) const;
     251  private:
     252        StatementNode *init;
     253        ExpressionNode *condition;
     254        ExpressionNode *change;
    240255};
    241256
    242257class ValofExprNode : public ExpressionNode {
    243258  public:
    244     ValofExprNode();
    245     ValofExprNode( StatementNode *s = 0 );
    246     ValofExprNode( const ValofExprNode &other );
    247     ~ValofExprNode();
     259        ValofExprNode();
     260        ValofExprNode( StatementNode *s = 0 );
     261        ValofExprNode( const ValofExprNode &other );
     262        ~ValofExprNode();
    248263 
    249     virtual ValofExprNode *clone() const { return new ValofExprNode( *this ); }
    250 
    251     StatementNode *get_body() const { return body; }
    252     void print( std::ostream &, int indent = 0 ) const;
    253     void printOneLine( std::ostream &, int indent = 0 ) const;
    254     Expression *build() const;
    255 
    256   private:
    257     StatementNode *body;
     264        virtual ValofExprNode *clone() const { return new ValofExprNode( *this ); }
     265
     266        StatementNode *get_body() const { return body; }
     267        void print( std::ostream &, int indent = 0 ) const;
     268        void printOneLine( std::ostream &, int indent = 0 ) const;
     269        Expression *build() const;
     270
     271  private:
     272        StatementNode *body;
    258273};
    259274
     
    262277class DeclarationNode : public ParseNode {
    263278  public:
    264     enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, Attribute };
    265     enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran };
    266     enum BasicType { Char, Int, Float, Double, Void, Bool, Complex, Imaginary };
    267     enum Modifier { Signed, Unsigned, Short, Long };
    268     enum TyCon { Struct, Union, Context };
    269     enum TypeClass { Type, Dtype, Ftype };
    270 
    271     static const char *qualifierName[];
    272     static const char *basicTypeName[];
    273     static const char *modifierName[];
    274     static const char *tyConName[];
    275     static const char *typeClassName[];
    276 
    277     static DeclarationNode *newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param,
    278                                         StatementNode *body, bool newStyle = false );
    279     static DeclarationNode *newQualifier( Qualifier );
    280     static DeclarationNode *newStorageClass( StorageClass );
    281     static DeclarationNode *newBasicType( BasicType );
    282     static DeclarationNode *newModifier( Modifier );
    283     static DeclarationNode *newForall( DeclarationNode *);
    284     static DeclarationNode *newFromTypedef( std::string *);
    285     static DeclarationNode *newAggregate( TyCon kind, std::string *name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields );
    286     static DeclarationNode *newEnum( std::string *name, DeclarationNode *constants );
    287     static DeclarationNode *newEnumConstant( std::string *name, ExpressionNode *constant );
    288     static DeclarationNode *newName( std::string *);
    289     static DeclarationNode *newFromTypeGen( std::string*, ExpressionNode *params );
    290     static DeclarationNode *newTypeParam( TypeClass, std::string *);
    291     static DeclarationNode *newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts );
    292     static DeclarationNode *newContextUse( std::string *name, ExpressionNode *params );
    293     static DeclarationNode *newTypeDecl( std::string *name, DeclarationNode *typeParams );
    294     static DeclarationNode *newPointer( DeclarationNode *qualifiers );
    295     static DeclarationNode *newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic );
    296     static DeclarationNode *newVarArray( DeclarationNode *qualifiers );
    297     static DeclarationNode *newBitfield( ExpressionNode *size );
    298     static DeclarationNode *newTuple( DeclarationNode *members );
    299     static DeclarationNode *newTypeof( ExpressionNode *expr );
    300     static DeclarationNode *newAttr( std::string*, ExpressionNode *expr );
    301     static DeclarationNode *newAttr( std::string*, DeclarationNode *type );
    302 
    303     DeclarationNode *addQualifiers( DeclarationNode *);
    304     DeclarationNode *copyStorageClasses( DeclarationNode *);
    305     DeclarationNode *addType( DeclarationNode *);
    306     DeclarationNode *addTypedef();
    307     DeclarationNode *addAssertions( DeclarationNode *);
    308     DeclarationNode *addName( std::string *);
    309     DeclarationNode *addBitfield( ExpressionNode *size );
    310     DeclarationNode *addVarArgs();
    311     DeclarationNode *addFunctionBody( StatementNode *body );
    312     DeclarationNode *addOldDeclList( DeclarationNode *list );
    313     DeclarationNode *addPointer( DeclarationNode *qualifiers );
    314     DeclarationNode *addArray( DeclarationNode *array );
    315     DeclarationNode *addNewPointer( DeclarationNode *pointer );
    316     DeclarationNode *addNewArray( DeclarationNode *array );
    317     DeclarationNode *addParamList( DeclarationNode *list );
    318     DeclarationNode *addIdList( DeclarationNode *list );       // old-style functions
    319     DeclarationNode *addInitializer( InitializerNode *init );
    320 
    321     DeclarationNode *cloneType( std::string *newName );
    322     DeclarationNode *cloneType( DeclarationNode *existing );
    323     DeclarationNode *cloneType( int ) { return cloneType( ( std::string *)0 ); }
    324     DeclarationNode *cloneBaseType( std::string *newName );
    325     DeclarationNode *cloneBaseType( DeclarationNode *newdecl );
    326 
    327     DeclarationNode *appendList( DeclarationNode  *);
    328 
    329     DeclarationNode *clone() const;
    330     void print( std::ostream &, int indent = 0 ) const;
    331     void printList( std::ostream &, int indent = 0 ) const;
    332 
    333     Declaration *build() const;
    334     ::Type *buildType() const;
    335 
    336     bool get_hasEllipsis() const;
    337     std::string get_name() const { return name; }
    338     LinkageSpec::Type get_linkage() const { return linkage; }
    339     DeclarationNode *extractAggregate() const;
    340 
    341     DeclarationNode();
    342     ~DeclarationNode();
    343   private:
    344     Declaration::StorageClass buildStorageClass() const;
    345     bool buildInline() const;
    346 
    347     TypeData *type;
    348     std::string name;
    349     std::list< StorageClass > storageClasses;
    350     ExpressionNode *bitfieldWidth;
    351     InitializerNode *initializer;
    352     bool hasEllipsis;
    353     LinkageSpec::Type linkage;
    354 
    355     static UniqueName anonymous;
     279        enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, Attribute };
     280        enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran };
     281        enum BasicType { Char, Int, Float, Double, Void, Bool, Complex, Imaginary };
     282        enum Modifier { Signed, Unsigned, Short, Long };
     283        enum TyCon { Struct, Union, Context };
     284        enum TypeClass { Type, Dtype, Ftype };
     285
     286        static const char *qualifierName[];
     287        static const char *basicTypeName[];
     288        static const char *modifierName[];
     289        static const char *tyConName[];
     290        static const char *typeClassName[];
     291
     292        static DeclarationNode *newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param,
     293                                                                                StatementNode *body, bool newStyle = false );
     294        static DeclarationNode *newQualifier( Qualifier );
     295        static DeclarationNode *newStorageClass( StorageClass );
     296        static DeclarationNode *newBasicType( BasicType );
     297        static DeclarationNode *newModifier( Modifier );
     298        static DeclarationNode *newForall( DeclarationNode *);
     299        static DeclarationNode *newFromTypedef( std::string *);
     300        static DeclarationNode *newAggregate( TyCon kind, std::string *name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields );
     301        static DeclarationNode *newEnum( std::string *name, DeclarationNode *constants );
     302        static DeclarationNode *newEnumConstant( std::string *name, ExpressionNode *constant );
     303        static DeclarationNode *newName( std::string *);
     304        static DeclarationNode *newFromTypeGen( std::string*, ExpressionNode *params );
     305        static DeclarationNode *newTypeParam( TypeClass, std::string *);
     306        static DeclarationNode *newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts );
     307        static DeclarationNode *newContextUse( std::string *name, ExpressionNode *params );
     308        static DeclarationNode *newTypeDecl( std::string *name, DeclarationNode *typeParams );
     309        static DeclarationNode *newPointer( DeclarationNode *qualifiers );
     310        static DeclarationNode *newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic );
     311        static DeclarationNode *newVarArray( DeclarationNode *qualifiers );
     312        static DeclarationNode *newBitfield( ExpressionNode *size );
     313        static DeclarationNode *newTuple( DeclarationNode *members );
     314        static DeclarationNode *newTypeof( ExpressionNode *expr );
     315        static DeclarationNode *newAttr( std::string*, ExpressionNode *expr );
     316        static DeclarationNode *newAttr( std::string*, DeclarationNode *type );
     317
     318        DeclarationNode *addQualifiers( DeclarationNode *);
     319        DeclarationNode *copyStorageClasses( DeclarationNode *);
     320        DeclarationNode *addType( DeclarationNode *);
     321        DeclarationNode *addTypedef();
     322        DeclarationNode *addAssertions( DeclarationNode *);
     323        DeclarationNode *addName( std::string *);
     324        DeclarationNode *addBitfield( ExpressionNode *size );
     325        DeclarationNode *addVarArgs();
     326        DeclarationNode *addFunctionBody( StatementNode *body );
     327        DeclarationNode *addOldDeclList( DeclarationNode *list );
     328        DeclarationNode *addPointer( DeclarationNode *qualifiers );
     329        DeclarationNode *addArray( DeclarationNode *array );
     330        DeclarationNode *addNewPointer( DeclarationNode *pointer );
     331        DeclarationNode *addNewArray( DeclarationNode *array );
     332        DeclarationNode *addParamList( DeclarationNode *list );
     333        DeclarationNode *addIdList( DeclarationNode *list );       // old-style functions
     334        DeclarationNode *addInitializer( InitializerNode *init );
     335
     336        DeclarationNode *cloneType( std::string *newName );
     337        DeclarationNode *cloneType( DeclarationNode *existing );
     338        DeclarationNode *cloneType( int ) { return cloneType( ( std::string *)0 ); }
     339        DeclarationNode *cloneBaseType( std::string *newName );
     340        DeclarationNode *cloneBaseType( DeclarationNode *newdecl );
     341
     342        DeclarationNode *appendList( DeclarationNode  *);
     343
     344        DeclarationNode *clone() const;
     345        void print( std::ostream &, int indent = 0 ) const;
     346        void printList( std::ostream &, int indent = 0 ) const;
     347
     348        Declaration *build() const;
     349        ::Type *buildType() const;
     350
     351        bool get_hasEllipsis() const;
     352        std::string get_name() const { return name; }
     353        LinkageSpec::Type get_linkage() const { return linkage; }
     354        DeclarationNode *extractAggregate() const;
     355
     356        DeclarationNode();
     357        ~DeclarationNode();
     358  private:
     359        Declaration::StorageClass buildStorageClass() const;
     360        bool buildInline() const;
     361
     362        TypeData *type;
     363        std::string name;
     364        std::list< StorageClass > storageClasses;
     365        ExpressionNode *bitfieldWidth;
     366        InitializerNode *initializer;
     367        bool hasEllipsis;
     368        LinkageSpec::Type linkage;
     369
     370        static UniqueName anonymous;
    356371};
    357372
    358373class StatementNode : public ParseNode {
    359374  public:
    360     enum Type { Exp,   If,        Switch,  Case,    Default,  Choose,   Fallthru,
    361                 While, Do,        For,
    362                 Goto,  Continue,  Break,   Return,  Throw,
    363                 Try,   Catch,     Finally, Asm,
    364                 Decl
    365     };
    366 
    367     StatementNode( void );
    368     StatementNode( std::string );
    369     StatementNode( Type, ExpressionNode *e = 0, StatementNode *s = 0 );
    370     StatementNode( Type, std::string *target );
    371     StatementNode( DeclarationNode *decl );
    372 
    373 
    374     ~StatementNode( void );
    375 
    376     static StatementNode  *newCatchStmt( DeclarationNode *d = 0, StatementNode *s = 0, bool catchRestP = false );
    377 
    378     void set_control( ExpressionNode * );
    379     StatementNode * set_block( StatementNode * );
    380 
    381     ExpressionNode *get_control() const ;
    382     StatementNode *get_block() const;
    383     StatementNode::Type get_type( void ) const;
    384 
    385     StatementNode *add_label( std::string * );
    386     std::list<std::string> *get_labels() const;
    387 
    388     void addDeclaration( DeclarationNode *newDecl ) { decl = newDecl; }
    389     void setCatchRest( bool newVal ) { isCatchRest = newVal; }
    390 
    391     std::string get_target() const;
    392 
    393     StatementNode *add_controlexp( ExpressionNode * );
    394     StatementNode *append_block( StatementNode * );
    395     StatementNode *append_last_case( StatementNode * );
    396 
    397     void print( std::ostream &, int indent = 0) const;
    398 
    399     virtual StatementNode *clone() const;
    400 
    401     virtual Statement *build() const;
    402   private:
    403     static const char *StType[];
    404     Type type;
    405     ExpressionNode *control;
    406     StatementNode *block;
    407     std::list<std::string> *labels;
    408     std::string *target;                                // target label for jump statements
    409     DeclarationNode *decl;
    410 
    411     bool isCatchRest;
     375        enum Type { Exp,   If,        Switch,  Case,    Default,  Choose,   Fallthru,
     376                                While, Do,        For,
     377                                Goto,  Continue,  Break,   Return,  Throw,
     378                                Try,   Catch,     Finally, Asm,
     379                                Decl
     380        };
     381
     382        StatementNode( void );
     383        StatementNode( std::string );
     384        StatementNode( Type, ExpressionNode *e = 0, StatementNode *s = 0 );
     385        StatementNode( Type, std::string *target );
     386        StatementNode( DeclarationNode *decl );
     387
     388
     389        ~StatementNode( void );
     390
     391        static StatementNode  *newCatchStmt( DeclarationNode *d = 0, StatementNode *s = 0, bool catchRestP = false );
     392
     393        void set_control( ExpressionNode * );
     394        StatementNode * set_block( StatementNode * );
     395
     396        ExpressionNode *get_control() const ;
     397        StatementNode *get_block() const;
     398        StatementNode::Type get_type( void ) const;
     399
     400        StatementNode *add_label( std::string * );
     401        std::list<std::string> *get_labels() const;
     402
     403        void addDeclaration( DeclarationNode *newDecl ) { decl = newDecl; }
     404        void setCatchRest( bool newVal ) { isCatchRest = newVal; }
     405
     406        std::string get_target() const;
     407
     408        StatementNode *add_controlexp( ExpressionNode * );
     409        StatementNode *append_block( StatementNode * );
     410        StatementNode *append_last_case( StatementNode * );
     411
     412        void print( std::ostream &, int indent = 0) const;
     413
     414        virtual StatementNode *clone() const;
     415
     416        virtual Statement *build() const;
     417  private:
     418        static const char *StType[];
     419        Type type;
     420        ExpressionNode *control;
     421        StatementNode *block;
     422        std::list<std::string> *labels;
     423        std::string *target;                            // target label for jump statements
     424        DeclarationNode *decl;
     425
     426        bool isCatchRest;
    412427};
    413428
    414429class CompoundStmtNode : public StatementNode {
    415430  public:
    416     CompoundStmtNode( void );
    417     CompoundStmtNode( std::string * );
    418     CompoundStmtNode( StatementNode * );
    419     ~CompoundStmtNode();
    420 
    421     void add_statement( StatementNode * );
    422 
    423     void print( std::ostream &, int indent = 0 ) const;
    424 
    425     virtual Statement *build() const;
    426   private:
    427     StatementNode *first, *last;
     431        CompoundStmtNode( void );
     432        CompoundStmtNode( std::string * );
     433        CompoundStmtNode( StatementNode * );
     434        ~CompoundStmtNode();
     435
     436        void add_statement( StatementNode * );
     437
     438        void print( std::ostream &, int indent = 0 ) const;
     439
     440        virtual Statement *build() const;
     441  private:
     442        StatementNode *first, *last;
    428443};
    429444
    430445class NullStmtNode : public CompoundStmtNode {
    431446  public:
    432     Statement *build() const;
    433     void print( std::ostream &, int indent = 0) const;
     447        Statement *build() const;
     448        void print( std::ostream &, int indent = 0) const;
    434449};
    435450
    436451class InitializerNode : public ParseNode {
    437452  public:
    438     InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode *des = 0 );
    439     InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode *des = 0 );
    440     ~InitializerNode();
    441 
    442     ExpressionNode *get_expression() const { return expr; }
    443 
    444     InitializerNode *set_designators( ExpressionNode *des ) { designator = des; return this; }
    445     ExpressionNode *get_designators() const { return designator; }
    446 
    447     InitializerNode *next_init() const { return kids; }
    448 
    449     void print( std::ostream &, int indent = 0 ) const;
    450     void printOneLine( std::ostream & ) const;
    451 
    452     virtual Initializer *build() const;
    453   private:
    454     ExpressionNode *expr;
    455     bool aggregate;
    456     ExpressionNode *designator; // may be list
    457     InitializerNode *kids;
     453        InitializerNode( ExpressionNode *, bool aggrp = false,  ExpressionNode *des = 0 );
     454        InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode *des = 0 );
     455        ~InitializerNode();
     456
     457        ExpressionNode *get_expression() const { return expr; }
     458
     459        InitializerNode *set_designators( ExpressionNode *des ) { designator = des; return this; }
     460        ExpressionNode *get_designators() const { return designator; }
     461
     462        InitializerNode *next_init() const { return kids; }
     463
     464        void print( std::ostream &, int indent = 0 ) const;
     465        void printOneLine( std::ostream & ) const;
     466
     467        virtual Initializer *build() const;
     468  private:
     469        ExpressionNode *expr;
     470        bool aggregate;
     471        ExpressionNode *designator; // may be list
     472        InitializerNode *kids;
    458473};
    459474
     
    461476
    462477template< typename SynTreeType, typename NodeType >
    463 void
    464 buildList( const NodeType *firstNode, std::list< SynTreeType *> &outputList )
    465 {
    466     SemanticError errors;
    467     std::back_insert_iterator< std::list< SynTreeType *> > out( outputList );
    468     const NodeType *cur = firstNode;
    469 
    470     while ( cur ) {
    471         try {
    472             SynTreeType *result = dynamic_cast< SynTreeType *>( cur->build() );
    473             if ( result ) {
    474                 *out++ = result;
    475             } else {
    476             } // if
    477         } catch( SemanticError &e ) {
    478             errors.append( e );
    479         } // try
    480         cur = dynamic_cast< NodeType *>( cur->get_link() );
    481     } // while
    482     if ( !errors.isEmpty() ) {
    483         throw errors;
    484     } // if
     478void buildList( const NodeType *firstNode, std::list< SynTreeType *> &outputList ) {
     479        SemanticError errors;
     480        std::back_insert_iterator< std::list< SynTreeType *> > out( outputList );
     481        const NodeType *cur = firstNode;
     482
     483        while ( cur ) {
     484                try {
     485                        SynTreeType *result = dynamic_cast< SynTreeType *>( cur->build() );
     486                        if ( result ) {
     487                                *out++ = result;
     488                        } else {
     489                        } // if
     490                } catch( SemanticError &e ) {
     491                        errors.append( e );
     492                } // try
     493                cur = dynamic_cast< NodeType *>( cur->get_link() );
     494        } // while
     495        if ( !errors.isEmpty() ) {
     496                throw errors;
     497        } // if
    485498}
    486499
     
    497510
    498511// Local Variables: //
    499 // mode: C++ //
    500 // compile-command: "gmake" //
     512// tab-width: 4 //
     513// mode: c++ //
     514// compile-command: "make install" //
    501515// End: //
  • translator/Parser/Parser.cc

    rb8508a2 rb87a5ed  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: Parser.cc,v 1.6 2002/11/15 20:07:18 rcbilson Exp $
    5  *
    6  */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// Parser.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 14:54:28 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 14:55:59 2015
     13// Update Count     : 2
     14//
    715
    816#include "Parser.h"
     
    1119#include "cfa.tab.h"
    1220
    13 /* global variables in cfa.y */
     21// global variables in cfa.y
    1422extern int yyparse(void);
    15 
    1623extern int yydebug;
    1724extern LinkageSpec::Type linkage;
    18 
    1925extern TypedefTable typedefTable;
    2026extern DeclarationNode *theTree;
    21 /* end of globals */
    2227
    2328Parser *Parser::theParser = 0;
     
    2530Parser::Parser(): parseTree( 0 ), parseStatus( 1 ) {}
    2631
    27 Parser::~Parser()
    28 {
    29   delete parseTree;
     32Parser::~Parser() {
     33        delete parseTree;
    3034}
    3135
    32 /* static class method */
    33 Parser &
    34 Parser::get_parser()
    35 {
    36   if( theParser == 0 ) {
    37     theParser = new Parser;
    38   }
    39   return *theParser;
     36Parser &Parser::get_parser() {
     37        if ( theParser == 0 ) {
     38                theParser = new Parser;
     39        } // if
     40        return *theParser;
    4041}
    4142
    42 void
    43 Parser::parse( FILE *input )
    44 {
    45   extern FILE *yyin;
    46   yyin = input;
    47   extern int yylineno;
    48   yylineno = 1;
    49   typedefTable.enterScope();
    50   parseStatus = yyparse();
    51   parseTree = theTree;
     43void Parser::parse( FILE *input ) {
     44        extern FILE *yyin;
     45        yyin = input;
     46        extern int yylineno;
     47        yylineno = 1;
     48        typedefTable.enterScope();
     49        parseStatus = yyparse();
     50        parseTree = theTree;
    5251}
    5352
    54 void
    55 Parser::set_debug( bool debug )
    56 {
    57   yydebug = debug;
     53void Parser::set_debug( bool debug ) {
     54        yydebug = debug;
    5855}
    5956
    60 void
    61 Parser::set_linkage( LinkageSpec::Type linkage )
    62 {
    63   ::linkage = linkage;
     57void Parser::set_linkage( LinkageSpec::Type linkage ) {
     58        ::linkage = linkage;
    6459}
    6560
    66 
    67 void
    68 Parser::freeTree()
    69 {
    70   delete parseTree;
    71   parseTree = 0;
     61void Parser::freeTree() {
     62        delete parseTree;
     63        parseTree = 0;
    7264}
    7365
     66// Local Variables: //
     67// tab-width: 4 //
     68// mode: c++ //
     69// compile-command: "make install" //
     70// End: //
  • translator/Parser/Parser.h

    rb8508a2 rb87a5ed  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * A singleton class to encapsulate the bison-generated parser
    5  *
    6  * $Id: Parser.h,v 1.4 2002/09/09 16:47:14 rcbilson Exp $
    7  *
    8  */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// Parser.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 14:56:50 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 14:58:56 2015
     13// Update Count     : 2
     14//
    915
    1016#ifndef PARSER_H
     
    1622#include "LinkageSpec.h"
    1723
    18 class Parser
    19 {
    20 public:
    21   static Parser &get_parser();
     24class Parser {
     25  public:
     26        static Parser &get_parser();
    2227
    23   /* do the actual parse */
    24   void parse( FILE *input );
     28        // do the actual parse
     29        void parse( FILE *input );
    2530
    26   /* accessors to return the result of the parse */
    27   DeclarationNode *get_parseTree() const { return parseTree; }
    28   int get_parseStatus() const { return parseStatus; }
     31        // accessors to return the result of the parse
     32        DeclarationNode *get_parseTree() const { return parseTree; }
     33        int get_parseStatus() const { return parseStatus; }
    2934
    30   /* mutators to control parse options */
    31   void set_debug( bool debug );
    32   void set_linkage( LinkageSpec::Type linkage );
     35        // mutators to control parse options
     36        void set_debug( bool debug );
     37        void set_linkage( LinkageSpec::Type linkage );
    3338
    34   /* free the parse tree without actually destroying the parser */
    35   void freeTree();
     39        // free the parse tree without actually destroying the parser
     40        void freeTree();
    3641
    37   ~Parser();
    38 
    39 private:
    40   Parser();
    41   static Parser *theParser;
    42   DeclarationNode *parseTree;
    43   int parseStatus;
     42        ~Parser();
     43  private:
     44        Parser();
     45        static Parser *theParser;
     46        DeclarationNode *parseTree;
     47        int parseStatus;
    4448};
    4549
    46 #endif /* #ifndef PARSER_H */
     50#endif // PARSER_H
     51
     52// Local Variables: //
     53// tab-width: 4 //
     54// mode: c++ //
     55// compile-command: "make install" //
     56// End: //
  • translator/Parser/StatementNode.cc

    rb8508a2 rb87a5ed  
    1 /* -*- C++ -*- */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// StatementNode.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 14:59:41 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:10:45 2015
     13// Update Count     : 7
     14//
     15
    216#include <list>
    317#include <algorithm>
     
    1226using namespace std;
    1327
    14 const char *StatementNode::StType[] =
    15   { "Exp",   "If",       "Switch", "Case",    "Default",  "Choose",   "Fallthru",
    16     "While", "Do",       "For",
    17     "Goto",  "Continue", "Break",  "Return",  "Throw",
    18     "Try",   "Catch",    "Finally", "Asm",
    19     "Decl"
    20   };
    21 
    22 StatementNode::StatementNode(void) :
    23   ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
    24 
    25 StatementNode::StatementNode(string name_) :
    26   ParseNode(name_), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
    27 
    28 StatementNode::StatementNode( DeclarationNode *decl ) :
    29   type( Decl ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), isCatchRest ( false )
    30 {
    31   if( decl ) {
    32     if( DeclarationNode *agg = decl->extractAggregate() ) {
    33       this->decl = agg;
    34       StatementNode *nextStmt = new StatementNode;
    35       nextStmt->type = Decl;
    36       nextStmt->decl = decl;
    37       next = nextStmt;
    38       if( decl->get_link() ) {
    39         next->set_next( new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) ) );
    40         decl->set_next( 0 );
    41       }
    42     } else {
    43       if( decl->get_link() ) {
    44         next = new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) );
    45         decl->set_next( 0 );
    46       }
    47       this->decl = decl;
    48     }
    49   }
    50 }
    51 
    52 StatementNode::StatementNode(Type t, ExpressionNode *ctrl_label, StatementNode *block_ ) :
    53   type(t), control(ctrl_label), block(block_), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false )
    54 {
    55   if (t == Default)
    56     control = 0;
     28const char *StatementNode::StType[] = {
     29        "Exp",   "If",       "Switch", "Case",    "Default",  "Choose",   "Fallthru",
     30        "While", "Do",       "For",
     31        "Goto",  "Continue", "Break",  "Return",  "Throw",
     32        "Try",   "Catch",    "Finally", "Asm",
     33        "Decl"
     34};
     35
     36StatementNode::StatementNode() : ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
     37
     38StatementNode::StatementNode( string name_) : ParseNode( name_), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {}
     39
     40StatementNode::StatementNode( DeclarationNode *decl ) : type( Decl ), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), isCatchRest ( false ) {
     41        if ( decl ) {
     42                if ( DeclarationNode *agg = decl->extractAggregate() ) {
     43                        this->decl = agg;
     44                        StatementNode *nextStmt = new StatementNode;
     45                        nextStmt->type = Decl;
     46                        nextStmt->decl = decl;
     47                        next = nextStmt;
     48                        if ( decl->get_link() ) {
     49                                next->set_next( new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) ) );
     50                                decl->set_next( 0 );
     51                        }
     52                } else {
     53                        if ( decl->get_link() ) {
     54                                next = new StatementNode( dynamic_cast< DeclarationNode* >( decl->get_link() ) );
     55                                decl->set_next( 0 );
     56                        }
     57                        this->decl = decl;
     58                }
     59        }
     60}
     61
     62StatementNode::StatementNode( Type t, ExpressionNode *ctrl_label, StatementNode *block_ ) :
     63                type( t ), control( ctrl_label ), block( block_), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {
     64        if ( t == Default )
     65                control = 0;
    5766}
    5867
    59 StatementNode::StatementNode(Type t, string *_target) :
    60   type(t), control(0), block(0),   labels( 0 ), target(_target), decl( 0 ), isCatchRest ( false ) {}
    61 
    62 StatementNode::~StatementNode(void){
    63   delete control;
    64   delete block;
    65   delete labels;
    66   delete target;
    67   delete decl;
    68 }
    69 
    70 StatementNode * StatementNode::newCatchStmt(DeclarationNode *d, StatementNode *s, bool catchRestP ) {
    71   StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s );
    72   ret->addDeclaration( d );
    73   ret->setCatchRest( catchRestP );
    74 
    75   return ret;
     68StatementNode::StatementNode( Type t, string *_target ) :
     69                type( t ), control( 0 ), block( 0 ),   labels( 0 ), target(_target ), decl( 0 ), isCatchRest ( false ) {}
     70
     71StatementNode::~StatementNode() {
     72        delete control;
     73        delete block;
     74        delete labels;
     75        delete target;
     76        delete decl;
     77}
     78
     79StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) {
     80        StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s );
     81        ret->addDeclaration( d );
     82        ret->setCatchRest( catchRestP );
     83
     84        return ret;
    7685}
    7786
    7887std::string StatementNode::get_target() const{
    79   if(target)
    80     return *target;
    81 
    82   return string("");
    83 }
    84 
    85 StatementNode *
    86 StatementNode::clone() const
    87 {
    88   StatementNode *newnode = new StatementNode( type, maybeClone( control ), maybeClone( block ) );
    89   if( target ) {
    90     newnode->target = new string( *target );
    91   } else {
    92     newnode->target = 0;
    93   }
    94   newnode->decl = maybeClone( decl );
    95   return newnode;
    96 }
    97 
    98 void StatementNode::set_control(ExpressionNode *c){
    99   control = c;
    100 }
    101 
    102 StatementNode * StatementNode::set_block(StatementNode *b){
    103   block = b;
    104 
    105   return this;
    106 }
    107 
    108 ExpressionNode *StatementNode::get_control(void) const {
    109   return control;
    110 }
    111 
    112 StatementNode *StatementNode::get_block(void) const {
    113   return block;
    114 }
    115 
    116 StatementNode::Type StatementNode::get_type(void) const {
    117   return type;
    118 }
    119 
    120 StatementNode *StatementNode::add_label(std::string *l){
    121   if(l != 0){
    122     if(labels == 0)
    123       labels = new std::list<std::string>();
    124 
    125     labels->push_front(*l);
    126     delete l;
    127   }
    128 
    129   return this;
    130 }
    131 
    132 std::list<std::string> *StatementNode::get_labels() const
    133 {  return labels; }
    134 
    135 StatementNode *StatementNode::add_controlexp(ExpressionNode *e){
    136 
    137   if(control && e)
    138     control->add_to_list(e); // xxx - check this
    139 
    140   return this;
    141 }
    142 
    143 StatementNode *StatementNode::append_block(StatementNode *stmt){
    144   if( stmt != 0) {
    145     if( block == 0 )
    146       block = stmt;
    147     else
    148       block->set_link(stmt);
    149   }
    150   return this;
    151 }
    152 
    153 
    154 StatementNode *StatementNode::append_last_case(StatementNode *stmt){
    155   if( stmt != 0 ) {
    156     StatementNode *next = (StatementNode *)get_link();
    157     if ( next && ( next->get_type() == StatementNode::Case || next->get_type() == StatementNode::Default) )
    158       next->append_last_case ( stmt );
    159     else
    160       if( block == 0 )
    161         block = stmt;
    162       else
    163         block->set_link(stmt);
    164   }
    165 
    166   return this;
     88        if ( target )
     89                return *target;
     90
     91        return string("");
     92}
     93
     94StatementNode * StatementNode::clone() const {
     95        StatementNode *newnode = new StatementNode( type, maybeClone( control ), maybeClone( block ) );
     96        if ( target ) {
     97                newnode->target = new string( *target );
     98        } else {
     99                newnode->target = 0;
     100        }
     101        newnode->decl = maybeClone( decl );
     102        return newnode;
     103}
     104
     105void StatementNode::set_control( ExpressionNode *c ) {
     106        control = c;
     107}
     108
     109StatementNode * StatementNode::set_block( StatementNode *b ) {
     110        block = b;
     111
     112        return this;
     113}
     114
     115ExpressionNode *StatementNode::get_control() const {
     116        return control;
     117}
     118
     119StatementNode *StatementNode::get_block() const {
     120        return block;
     121}
     122
     123StatementNode::Type StatementNode::get_type() const {
     124        return type;
     125}
     126
     127StatementNode *StatementNode::add_label( std::string *l ) {
     128        if ( l != 0 ) {
     129                if ( labels == 0 )
     130                        labels = new std::list<std::string>();
     131
     132                labels->push_front(*l );
     133                delete l;
     134        }
     135        return this;
     136}
     137
     138std::list<std::string> *StatementNode::get_labels() const { return labels; }
     139
     140StatementNode *StatementNode::add_controlexp( ExpressionNode *e ) {
     141        if ( control && e )
     142                control->add_to_list( e ); // xxx - check this
     143
     144        return this;
     145}
     146
     147StatementNode *StatementNode::append_block( StatementNode *stmt ) {
     148        if ( stmt != 0 ) {
     149                if ( block == 0 )
     150                        block = stmt;
     151                else
     152                        block->set_link( stmt );
     153        }
     154        return this;
     155}
     156
     157StatementNode *StatementNode::append_last_case( StatementNode *stmt ) {
     158        if ( stmt != 0 ) {
     159                StatementNode *next = ( StatementNode *)get_link();
     160                if ( next && ( next->get_type() == StatementNode::Case || next->get_type() == StatementNode::Default ) )
     161                        next->append_last_case ( stmt );
     162                else
     163                        if ( block == 0 )
     164                                block = stmt;
     165                        else
     166                                block->set_link( stmt );
     167        }
     168        return this;
    167169}
    168170
    169171void StatementNode::print( std::ostream &os, int indent ) const {
    170 
    171   if(labels != 0)
    172     if(!labels->empty()){
    173       std::list<std::string>::const_iterator i;
    174 
    175       os << '\r' << string(indent, ' ');
    176       for( i = labels->begin(); i != labels->end(); i++ )
    177         os << *i << ":";
    178       os << endl;
    179     }
    180 
    181   switch( type ) {
    182   case Decl:
    183     decl->print( os, indent );
    184     break;
    185  
    186   case Exp:
    187     if( control ) {
    188       os << string( indent, ' ' );
    189       control->print( os, indent );
    190       os << endl;
    191     } else
    192       os << string( indent, ' ' ) << "Null Statement" << endl;
    193     break;
    194 
    195   default:
    196     os << '\r' << string(indent, ' ') << StatementNode::StType[type] << endl;
    197 
    198     if   ( type == Catch ) {
    199       if( decl ){
    200         os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Declaration: " << endl;
    201         decl->print( os, indent + 2*ParseNode::indent_by);
    202       } else if ( isCatchRest ) {
    203         os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Catches the rest " << endl;
    204       } else {
    205         ; // should never reach here
    206       }
    207     }
    208 
    209     if( control ){
    210       os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Expression: " << endl;
    211       control->printList( os, indent + 2*ParseNode::indent_by);
    212     }
    213 
    214     if( block ){
    215       os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Branches of execution: " << endl;
    216       block->printList( os, indent + 2*ParseNode::indent_by); 
    217     }
    218 
    219     if( target ){
    220       os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Target: " << get_target() << endl;
    221     }
    222 
    223     break;
    224   }
     172        if ( labels != 0 )
     173                if (!labels->empty()) {
     174                        std::list<std::string>::const_iterator i;
     175
     176                        os << '\r' << string( indent, ' ');
     177                        for( i = labels->begin(); i != labels->end(); i++ )
     178                                os << *i << ":";
     179                        os << endl;
     180                }
     181
     182        switch( type ) {
     183          case Decl:
     184                decl->print( os, indent );
     185                break;
     186          case Exp:
     187                if ( control ) {
     188                        os << string( indent, ' ' );
     189                        control->print( os, indent );
     190                        os << endl;
     191                } else
     192                        os << string( indent, ' ' ) << "Null Statement" << endl;
     193                break;
     194          default:
     195                os << '\r' << string( indent, ' ') << StatementNode::StType[type] << endl;
     196                if ( type == Catch ) {
     197                        if ( decl ) {
     198                                os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Declaration: " << endl;
     199                                decl->print( os, indent + 2*ParseNode::indent_by );
     200                        } else if ( isCatchRest ) {
     201                                os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Catches the rest " << endl;
     202                        } else {
     203                                ; // should never reach here
     204                        }
     205                }
     206                if ( control ) {
     207                        os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Expression: " << endl;
     208                        control->printList( os, indent + 2*ParseNode::indent_by );
     209                }
     210                if ( block ) {
     211                        os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Branches of execution: " << endl;
     212                        block->printList( os, indent + 2*ParseNode::indent_by ); 
     213                }
     214                if ( target ) {
     215                        os << '\r' << string( indent + ParseNode::indent_by, ' ' ) << "Target: " << get_target() << endl;
     216                }
     217                break;
     218        }
    225219}
    226220
    227221Statement *StatementNode::build() const {
    228 
    229   std::list<Statement *> branches;
    230   std::list<Expression *> exps;
    231   std::list<Label> labs;
    232 
    233   if(labels != 0){
    234     std::back_insert_iterator< std::list<Label> > lab_it(labs);
    235     copy(labels->begin(), labels->end(), lab_it);
    236   }
    237 
    238   // try {
    239   buildList<Statement, StatementNode>(get_block(), branches);
    240  
    241   switch( type ) {
    242   case Decl:
    243     return new DeclStmt( labs, maybeBuild< Declaration >( decl ) );
    244 
    245   case Exp:
    246     {
    247       Expression *e = maybeBuild< Expression >( get_control() );
    248 
    249       if(e)
    250         return new ExprStmt( labs, e );
    251       else
    252         return new NullStmt( labs );
    253     }
    254 
    255   case If:
    256     {
    257       Statement *thenb = 0, *elseb = 0;
    258 
    259       assert( branches.size() >= 1 );
    260 
    261       thenb = branches.front();  branches.pop_front();
    262       if(!branches.empty())
    263         { elseb = branches.front();  branches.pop_front(); }
    264 
    265       return new IfStmt( labs, notZeroExpr( get_control()->build() ), thenb, elseb);
    266     }
    267 
    268   case While:
    269     assert(branches.size() == 1);
    270     return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front() );
    271 
    272   case Do:
    273     assert(branches.size() == 1);
    274     return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front(), true );
    275    
    276   case For:
    277     {
    278       assert(branches.size() == 1);
    279 
    280       ForCtlExprNode *ctl = dynamic_cast<ForCtlExprNode *>(get_control());
    281       assert(ctl != 0);
    282 
    283       Statement *stmt = 0;
    284       if(ctl->get_init() != 0)
    285         stmt = ctl->get_init()->build();
    286 
    287       Expression *cond = 0;
    288       if(ctl->get_condition() != 0)
    289         cond = notZeroExpr( ctl->get_condition()->build() );
    290 
    291       Expression *incr = 0;
    292       if(ctl->get_change() != 0)
    293         incr = ctl->get_change()->build();
    294 
    295       return new ForStmt( labs, stmt, cond, incr, branches.front() );
    296     }
    297 
    298   case Switch:
    299     // try{
    300     return new SwitchStmt( labs, get_control()->build(), branches );
    301 
    302   case Choose:
    303     return new ChooseStmt( labs, get_control()->build(), branches );
    304 
    305   case Fallthru:
    306     return new FallthruStmt( labs );
    307 
    308   case Case:
    309     return new CaseStmt( labs, get_control()->build(), branches);
    310 
    311   case Default:
    312     return new CaseStmt( labs, 0, branches, true);
    313 
    314   case Goto:
    315     {
    316       if (get_target() == "")  { // computed goto
    317         assert( get_control() != 0 );
    318         return new BranchStmt( labs, get_control()->build(), BranchStmt::Goto );
    319       }
    320 
    321       return new BranchStmt( labs, get_target(), BranchStmt::Goto);
    322     }
    323 
    324   case Break:
    325     return new BranchStmt( labs, get_target(), BranchStmt::Break);
    326 
    327   case Continue:
    328     return new BranchStmt( labs, get_target(), BranchStmt::Continue);
    329 
    330   case Return:
    331   case Throw :
    332     buildList( get_control(), exps );
    333     if( exps.size() ==0 )
    334       return new ReturnStmt( labs, 0, type == Throw );
    335     if( exps.size() > 0 )
    336       return new ReturnStmt( labs, exps.back(), type == Throw );
    337 
    338   case Try:
    339     {
    340       assert( branches.size() >= 0 );
    341       CompoundStmt *tryBlock = dynamic_cast<CompoundStmt *>(branches.front());
    342       branches.pop_front();
    343       FinallyStmt *finallyBlock = 0;
    344       if( (finallyBlock = dynamic_cast<FinallyStmt *>(branches.back())) ) {
    345         branches.pop_back();
    346       }
    347       return new TryStmt( labs, tryBlock, branches, finallyBlock );
    348     }
    349 
    350   case Catch:
    351     {
    352       assert( branches.size() == 1 );
    353 
    354       return new CatchStmt( labs, maybeBuild< Declaration >( decl ), branches.front(), isCatchRest );
    355     }
    356 
    357   case Finally:
    358     {
    359       assert( branches.size() == 1 );
    360       CompoundStmt *block = dynamic_cast<CompoundStmt *>( branches.front() );
    361       assert( block != 0 );
    362 
    363       return new FinallyStmt( labs, block );
    364     }
    365 
    366   default:
    367     // shouldn't be here
    368     return 0;
    369   }
    370 
    371   // shouldn't be here
    372 }
    373 
    374 CompoundStmtNode::CompoundStmtNode(void)
    375   : first( 0 ), last( 0 )
    376 {
    377 }
    378 
    379 CompoundStmtNode::CompoundStmtNode(string *name_)
    380   : StatementNode(*name_), first( 0 ), last( 0 )
    381 {
    382 }
    383 
    384 CompoundStmtNode::CompoundStmtNode(StatementNode *stmt): first(stmt)
    385 {
    386   if( first ) {
    387     last = (StatementNode *)(stmt->get_last());
    388   } else {
    389     last = 0;
    390   }
    391 }
    392 
    393 CompoundStmtNode::~CompoundStmtNode()
    394 {
    395   delete first;
    396 }
    397 
    398 void CompoundStmtNode::add_statement(StatementNode *stmt) {
    399   if(stmt != 0){
    400     last->set_link(stmt);
    401     last = (StatementNode *)(stmt->get_link());
    402   }
    403 }
    404 
    405 void CompoundStmtNode::print(ostream &os, int indent) const {
    406   if( first ) {
    407     first->printList( os, indent+2 );
    408   }
     222        std::list<Statement *> branches;
     223        std::list<Expression *> exps;
     224        std::list<Label> labs;
     225
     226        if ( labels != 0 ) {
     227                std::back_insert_iterator< std::list<Label> > lab_it( labs );
     228                copy( labels->begin(), labels->end(), lab_it );
     229        }
     230
     231        // try {
     232        buildList<Statement, StatementNode>( get_block(), branches );
     233
     234        switch( type ) {
     235          case Decl:
     236                return new DeclStmt( labs, maybeBuild< Declaration >( decl ) );
     237          case Exp:
     238                {
     239                        Expression *e = maybeBuild< Expression >( get_control() );
     240
     241                        if ( e )
     242                                return new ExprStmt( labs, e );
     243                        else
     244                                return new NullStmt( labs );
     245                }
     246          case If:
     247                {
     248                        Statement *thenb = 0, *elseb = 0;
     249                        assert( branches.size() >= 1 );
     250
     251                        thenb = branches.front();
     252                        branches.pop_front();
     253                        if ( !branches.empty() ) {
     254                                elseb = branches.front();
     255                                branches.pop_front();
     256                        }
     257                        return new IfStmt( labs, notZeroExpr( get_control()->build() ), thenb, elseb );
     258                }
     259          case While:
     260                assert( branches.size() == 1 );
     261                return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front() );
     262          case Do:
     263                assert( branches.size() == 1 );
     264                return new WhileStmt( labs, notZeroExpr( get_control()->build() ), branches.front(), true );
     265          case For:
     266                {
     267                        assert( branches.size() == 1 );
     268
     269                        ForCtlExprNode *ctl = dynamic_cast<ForCtlExprNode *>( get_control() );
     270                        assert( ctl != 0 );
     271
     272                        Statement *stmt = 0;
     273                        if ( ctl->get_init() != 0 )
     274                                stmt = ctl->get_init()->build();
     275
     276                        Expression *cond = 0;
     277                        if ( ctl->get_condition() != 0 )
     278                                cond = notZeroExpr( ctl->get_condition()->build() );
     279
     280                        Expression *incr = 0;
     281                        if ( ctl->get_change() != 0 )
     282                                incr = ctl->get_change()->build();
     283
     284                        return new ForStmt( labs, stmt, cond, incr, branches.front() );
     285                }
     286          case Switch:
     287                return new SwitchStmt( labs, get_control()->build(), branches );
     288          case Choose:
     289                return new ChooseStmt( labs, get_control()->build(), branches );
     290          case Fallthru:
     291                return new FallthruStmt( labs );
     292          case Case:
     293                return new CaseStmt( labs, get_control()->build(), branches );
     294          case Default:
     295                return new CaseStmt( labs, 0, branches, true );
     296          case Goto:
     297                {
     298                        if ( get_target() == "" ) {                                     // computed goto
     299                                assert( get_control() != 0 );
     300                                return new BranchStmt( labs, get_control()->build(), BranchStmt::Goto );
     301                        }
     302
     303                        return new BranchStmt( labs, get_target(), BranchStmt::Goto );
     304                }
     305          case Break:
     306                return new BranchStmt( labs, get_target(), BranchStmt::Break );
     307          case Continue:
     308                return new BranchStmt( labs, get_target(), BranchStmt::Continue );
     309          case Return:
     310          case Throw :
     311                buildList( get_control(), exps );
     312                if ( exps.size() ==0 )
     313                        return new ReturnStmt( labs, 0, type == Throw );
     314                if ( exps.size() > 0 )
     315                        return new ReturnStmt( labs, exps.back(), type == Throw );
     316          case Try:
     317                {
     318                        assert( branches.size() >= 0 );
     319                        CompoundStmt *tryBlock = dynamic_cast<CompoundStmt *>( branches.front());
     320                        branches.pop_front();
     321                        FinallyStmt *finallyBlock = 0;
     322                        if ( ( finallyBlock = dynamic_cast<FinallyStmt *>( branches.back())) ) {
     323                                branches.pop_back();
     324                        }
     325                        return new TryStmt( labs, tryBlock, branches, finallyBlock );
     326                }
     327          case Catch:
     328                {
     329                        assert( branches.size() == 1 );
     330
     331                        return new CatchStmt( labs, maybeBuild< Declaration >( decl ), branches.front(), isCatchRest );
     332                }
     333          case Finally:
     334                {
     335                        assert( branches.size() == 1 );
     336                        CompoundStmt *block = dynamic_cast<CompoundStmt *>( branches.front() );
     337                        assert( block != 0 );
     338
     339                        return new FinallyStmt( labs, block );
     340                }
     341          default:
     342                // shouldn't be here
     343                return 0;
     344        }
     345}
     346
     347CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) {
     348}
     349
     350CompoundStmtNode::CompoundStmtNode( string *name_) : StatementNode(*name_), first( 0 ), last( 0 ) {
     351}
     352
     353CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ): first( stmt ) {
     354        if ( first ) {
     355                last = ( StatementNode *)( stmt->get_last());
     356        } else {
     357                last = 0;
     358        }
     359}
     360
     361CompoundStmtNode::~CompoundStmtNode() {
     362        delete first;
     363}
     364
     365void CompoundStmtNode::add_statement( StatementNode *stmt ) {
     366        if ( stmt != 0 ) {
     367                last->set_link( stmt );
     368                last = ( StatementNode *)( stmt->get_link());
     369        }
     370}
     371
     372void CompoundStmtNode::print( ostream &os, int indent ) const {
     373        if ( first ) {
     374                first->printList( os, indent+2 );
     375        }
    409376}
    410377
    411378Statement *CompoundStmtNode::build() const {
    412 
    413   std::list<Label> labs;
    414   std::list<std::string> *labels = get_labels();
    415 
    416   if(labels != 0){
    417     std::back_insert_iterator< std::list<Label> > lab_it(labs);
    418     copy(labels->begin(), labels->end(), lab_it);
    419   }
    420 
    421   CompoundStmt *cs = new CompoundStmt( labs );
    422   buildList( first, cs->get_kids() );
    423   return cs;
    424 }
    425 
    426 void NullStmtNode::print(ostream &os, int indent) const {
    427   os << "\r" << string(indent, ' ') << "Null Statement:" << endl;
     379        std::list<Label> labs;
     380        std::list<std::string> *labels = get_labels();
     381
     382        if ( labels != 0 ) {
     383                std::back_insert_iterator< std::list<Label> > lab_it( labs );
     384                copy( labels->begin(), labels->end(), lab_it );
     385        }
     386
     387        CompoundStmt *cs = new CompoundStmt( labs );
     388        buildList( first, cs->get_kids() );
     389        return cs;
     390}
     391
     392void NullStmtNode::print( ostream &os, int indent ) const {
     393        os << "\r" << string( indent, ' ') << "Null Statement:" << endl;
    428394}
    429395
    430396Statement *NullStmtNode::build() const {
    431   return new NullStmt;
     397        return new NullStmt;
    432398}
    433399
    434400// Local Variables: //
    435 // mode: C++                //
    436 // compile-command: "gmake -f ../Makefile" //
     401// tab-width: 4 //
     402// mode: c++ //
     403// compile-command: "make install" //
    437404// End: //
  • translator/Parser/TypeData.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// TypeData.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:12:51 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:17:56 2015
     13// Update Count     : 4
     14//
     15
    116#include <cassert>
    217#include <algorithm>
     
    924#include "SynTree/Statement.h"
    1025
    11 
    1226TypeData::TypeData( Kind k ) : kind( k ), base( 0 ), forall( 0 ) {
    13     switch ( kind ) {
    14       case Unknown:
    15       case Pointer:
    16       case EnumConstant:
    17         // nothing else to initialize
    18         break;
    19       case Basic:
    20         basic = new Basic_t;
    21         break;
    22       case Array:
    23         array = new Array_t;
    24         array->dimension = 0;
    25         array->isVarLen = false;
    26         array->isStatic = false;
    27         break;
    28       case Function:
    29         function = new Function_t;
    30         function->params = 0;
    31         function->idList = 0;
    32         function->oldDeclList = 0;
    33         function->body = 0;
    34         function->hasBody = false;
    35         function->newStyle = false;
    36         break;
    37       case Aggregate:
    38         aggregate = new Aggregate_t;
    39         aggregate->params = 0;
    40         aggregate->actuals = 0;
    41         aggregate->members = 0;
    42         break;
    43       case AggregateInst:
    44         aggInst = new AggInst_t;
    45         aggInst->aggregate = 0;
    46         aggInst->params = 0;
    47         break;
    48       case Enum:
    49         enumeration = new Enumeration_t;
    50         enumeration->constants = 0;
    51         break;
    52       case Symbolic:
    53       case SymbolicInst:
    54         symbolic = new Symbolic_t;
    55         symbolic->params = 0;
    56         symbolic->actuals = 0;
    57         symbolic->assertions = 0;
    58         break;
    59       case Variable:
    60         variable = new Variable_t;
    61         variable->tyClass = DeclarationNode::Type;
    62         variable->assertions = 0;
    63         break;
    64       case Tuple:
    65         tuple = new Tuple_t;
    66         tuple->members = 0;
    67         break;
    68  
    69       case Typeof:
    70         typeexpr = new Typeof_t;
    71         typeexpr->expr = 0;
    72         break;
    73  
    74       case Attr:
    75         attr = new Attr_t;
    76         attr->expr = 0;
    77         attr->type = 0;
    78         break;
    79     }
     27        switch ( kind ) {
     28          case Unknown:
     29          case Pointer:
     30          case EnumConstant:
     31                // nothing else to initialize
     32                break;
     33          case Basic:
     34                basic = new Basic_t;
     35                break;
     36          case Array:
     37                array = new Array_t;
     38                array->dimension = 0;
     39                array->isVarLen = false;
     40                array->isStatic = false;
     41                break;
     42          case Function:
     43                function = new Function_t;
     44                function->params = 0;
     45                function->idList = 0;
     46                function->oldDeclList = 0;
     47                function->body = 0;
     48                function->hasBody = false;
     49                function->newStyle = false;
     50                break;
     51          case Aggregate:
     52                aggregate = new Aggregate_t;
     53                aggregate->params = 0;
     54                aggregate->actuals = 0;
     55                aggregate->members = 0;
     56                break;
     57          case AggregateInst:
     58                aggInst = new AggInst_t;
     59                aggInst->aggregate = 0;
     60                aggInst->params = 0;
     61                break;
     62          case Enum:
     63                enumeration = new Enumeration_t;
     64                enumeration->constants = 0;
     65                break;
     66          case Symbolic:
     67          case SymbolicInst:
     68                symbolic = new Symbolic_t;
     69                symbolic->params = 0;
     70                symbolic->actuals = 0;
     71                symbolic->assertions = 0;
     72                break;
     73          case Variable:
     74                variable = new Variable_t;
     75                variable->tyClass = DeclarationNode::Type;
     76                variable->assertions = 0;
     77                break;
     78          case Tuple:
     79                tuple = new Tuple_t;
     80                tuple->members = 0;
     81                break;
     82          case Typeof:
     83                typeexpr = new Typeof_t;
     84                typeexpr->expr = 0;
     85                break;
     86          case Attr:
     87                attr = new Attr_t;
     88                attr->expr = 0;
     89                attr->type = 0;
     90                break;
     91        }
    8092}
    8193
    8294TypeData::~TypeData() {
    83     delete base;
    84     delete forall;
    85 
    86     switch ( kind ) {
    87       case Unknown:
    88       case Pointer:
    89       case EnumConstant:
    90         // nothing to destroy
    91         break;
    92       case Basic:
    93         delete basic;
    94         break;
    95       case Array:
    96         delete array->dimension;
    97         delete array;
    98         break;
    99       case Function:
    100         delete function->params;
    101         delete function->idList;
    102         delete function->oldDeclList;
    103         delete function->body;
    104         delete function;
    105         break;
    106       case Aggregate:
    107         delete aggregate->params;
    108         delete aggregate->actuals;
    109         delete aggregate->members;
    110         delete aggregate;
    111         break;
    112       case AggregateInst:
    113         delete aggInst->aggregate;
    114         delete aggInst->params;
    115         delete aggInst;
    116         break;
    117       case Enum:
    118         delete enumeration->constants;
    119         delete enumeration;
    120         break;
    121       case Symbolic:
    122       case SymbolicInst:
    123         delete symbolic->params;
    124         delete symbolic->actuals;
    125         delete symbolic->assertions;
    126         delete symbolic;
    127         break;
    128       case Variable:
    129         delete variable->assertions;
    130         delete variable;
    131         break;
    132       case Tuple:
    133         delete tuple->members;
    134         delete tuple;
    135         break;
    136  
    137       case Typeof:
    138         delete typeexpr->expr;
    139         delete typeexpr;
    140         break;
    141  
    142       case Attr:
    143         delete attr->expr;
    144         delete attr->type;
    145         delete attr;
    146         break;
    147     }
     95        delete base;
     96        delete forall;
     97
     98        switch ( kind ) {
     99          case Unknown:
     100          case Pointer:
     101          case EnumConstant:
     102                // nothing to destroy
     103                break;
     104          case Basic:
     105                delete basic;
     106                break;
     107          case Array:
     108                delete array->dimension;
     109                delete array;
     110                break;
     111          case Function:
     112                delete function->params;
     113                delete function->idList;
     114                delete function->oldDeclList;
     115                delete function->body;
     116                delete function;
     117                break;
     118          case Aggregate:
     119                delete aggregate->params;
     120                delete aggregate->actuals;
     121                delete aggregate->members;
     122                delete aggregate;
     123                break;
     124          case AggregateInst:
     125                delete aggInst->aggregate;
     126                delete aggInst->params;
     127                delete aggInst;
     128                break;
     129          case Enum:
     130                delete enumeration->constants;
     131                delete enumeration;
     132                break;
     133          case Symbolic:
     134          case SymbolicInst:
     135                delete symbolic->params;
     136                delete symbolic->actuals;
     137                delete symbolic->assertions;
     138                delete symbolic;
     139                break;
     140          case Variable:
     141                delete variable->assertions;
     142                delete variable;
     143                break;
     144          case Tuple:
     145                delete tuple->members;
     146                delete tuple;
     147                break;
     148          case Typeof:
     149                delete typeexpr->expr;
     150                delete typeexpr;
     151                break;
     152          case Attr:
     153                delete attr->expr;
     154                delete attr->type;
     155                delete attr;
     156                break;
     157        }
    148158}
    149159
    150160TypeData *TypeData::clone() const {
    151     TypeData *newtype = new TypeData( kind );
    152     newtype->qualifiers = qualifiers;
    153     newtype->base = maybeClone( base );
    154     newtype->forall = maybeClone( forall );
    155 
    156     switch ( kind ) {
    157       case Unknown:
    158       case EnumConstant:
    159       case Pointer:
    160         // nothing else to copy
    161         break;
    162       case Basic:
    163         newtype->basic->typeSpec = basic->typeSpec;
    164         newtype->basic->modifiers = basic->modifiers;
    165         break;
    166       case Array:
    167         newtype->array->dimension = maybeClone( array->dimension );
    168         newtype->array->isVarLen = array->isVarLen;
    169         newtype->array->isStatic = array->isStatic;
    170         break;
    171       case Function:
    172         newtype->function->params = maybeClone( function->params );
    173         newtype->function->idList = maybeClone( function->idList );
    174         newtype->function->oldDeclList = maybeClone( function->oldDeclList );
    175         newtype->function->body = maybeClone( function->body );
    176         newtype->function->hasBody = function->hasBody;
    177         newtype->function->newStyle = function->newStyle;
    178         break;
    179       case Aggregate:
    180         newtype->aggregate->params = maybeClone( aggregate->params );
    181         newtype->aggregate->actuals = maybeClone( aggregate->actuals );
    182         newtype->aggregate->members = maybeClone( aggregate->members );
    183         newtype->aggregate->name = aggregate->name;
    184         newtype->aggregate->kind = aggregate->kind;
    185         break;
    186       case AggregateInst:
    187         newtype->aggInst->aggregate = maybeClone( aggInst->aggregate );
    188         newtype->aggInst->params = maybeClone( aggInst->params );
    189         break;
    190       case Enum:
    191         newtype->enumeration->name = enumeration->name;
    192         newtype->enumeration->constants = maybeClone( enumeration->constants );
    193         break;
    194       case Symbolic:
    195       case SymbolicInst:
    196         newtype->symbolic->params = maybeClone( symbolic->params );
    197         newtype->symbolic->actuals = maybeClone( symbolic->actuals );
    198         newtype->symbolic->assertions = maybeClone( symbolic->assertions );
    199         newtype->symbolic->isTypedef = symbolic->isTypedef;
    200         newtype->symbolic->name = symbolic->name;
    201         break;
    202       case Variable:
    203         newtype->variable->assertions = maybeClone( variable->assertions );
    204         newtype->variable->name = variable->name;
    205         newtype->variable->tyClass = variable->tyClass;
    206         break;
    207       case Tuple:
    208         newtype->tuple->members = maybeClone( tuple->members );
    209         break;
    210    
    211       case Typeof:
    212         newtype->typeexpr->expr = maybeClone( typeexpr->expr );
    213         break;
    214  
    215       case Attr:
    216         newtype->attr->expr = maybeClone( attr->expr );
    217         newtype->attr->type = maybeClone( attr->type );
    218         break;
    219     }
    220     return newtype;
     161        TypeData *newtype = new TypeData( kind );
     162        newtype->qualifiers = qualifiers;
     163        newtype->base = maybeClone( base );
     164        newtype->forall = maybeClone( forall );
     165
     166        switch ( kind ) {
     167          case Unknown:
     168          case EnumConstant:
     169          case Pointer:
     170                // nothing else to copy
     171                break;
     172          case Basic:
     173                newtype->basic->typeSpec = basic->typeSpec;
     174                newtype->basic->modifiers = basic->modifiers;
     175                break;
     176          case Array:
     177                newtype->array->dimension = maybeClone( array->dimension );
     178                newtype->array->isVarLen = array->isVarLen;
     179                newtype->array->isStatic = array->isStatic;
     180                break;
     181          case Function:
     182                newtype->function->params = maybeClone( function->params );
     183                newtype->function->idList = maybeClone( function->idList );
     184                newtype->function->oldDeclList = maybeClone( function->oldDeclList );
     185                newtype->function->body = maybeClone( function->body );
     186                newtype->function->hasBody = function->hasBody;
     187                newtype->function->newStyle = function->newStyle;
     188                break;
     189          case Aggregate:
     190                newtype->aggregate->params = maybeClone( aggregate->params );
     191                newtype->aggregate->actuals = maybeClone( aggregate->actuals );
     192                newtype->aggregate->members = maybeClone( aggregate->members );
     193                newtype->aggregate->name = aggregate->name;
     194                newtype->aggregate->kind = aggregate->kind;
     195                break;
     196          case AggregateInst:
     197                newtype->aggInst->aggregate = maybeClone( aggInst->aggregate );
     198                newtype->aggInst->params = maybeClone( aggInst->params );
     199                break;
     200          case Enum:
     201                newtype->enumeration->name = enumeration->name;
     202                newtype->enumeration->constants = maybeClone( enumeration->constants );
     203                break;
     204          case Symbolic:
     205          case SymbolicInst:
     206                newtype->symbolic->params = maybeClone( symbolic->params );
     207                newtype->symbolic->actuals = maybeClone( symbolic->actuals );
     208                newtype->symbolic->assertions = maybeClone( symbolic->assertions );
     209                newtype->symbolic->isTypedef = symbolic->isTypedef;
     210                newtype->symbolic->name = symbolic->name;
     211                break;
     212          case Variable:
     213                newtype->variable->assertions = maybeClone( variable->assertions );
     214                newtype->variable->name = variable->name;
     215                newtype->variable->tyClass = variable->tyClass;
     216                break;
     217          case Tuple:
     218                newtype->tuple->members = maybeClone( tuple->members );
     219                break;
     220          case Typeof:
     221                newtype->typeexpr->expr = maybeClone( typeexpr->expr );
     222                break;
     223          case Attr:
     224                newtype->attr->expr = maybeClone( attr->expr );
     225                newtype->attr->type = maybeClone( attr->type );
     226                break;
     227        }
     228        return newtype;
    221229}
    222230
    223231void TypeData::print( std::ostream &os, int indent ) const {
    224     using std::endl;
    225     using std::string;
    226 
    227     printEnums( qualifiers.begin(), qualifiers.end(), DeclarationNode::qualifierName, os );
    228 
    229     if ( forall ) {
    230         os << "forall " << endl;
    231         forall->printList( os, indent+4 );
    232     }
    233 
    234     switch ( kind ) {
    235       case Unknown:
    236         os << "entity of unknown type ";
    237         break;
    238       case Pointer:
    239         os << "pointer ";
    240         if ( base ) {
    241             os << "to ";
    242             base->print( os, indent );
    243         }
    244         break;
    245       case EnumConstant:
    246         os << "enumeration constant ";
    247         break;
    248       case Basic:
    249         printEnums( basic->modifiers.begin(), basic->modifiers.end(), DeclarationNode::modifierName, os );
    250         printEnums( basic->typeSpec.begin(), basic->typeSpec.end(), DeclarationNode::basicTypeName, os );
    251         break;
    252       case Array:
    253         if ( array->isStatic ) {
    254             os << "static ";
    255         }
    256         if ( array->dimension ) {
    257             os << "array of ";
    258             array->dimension->printOneLine( os, indent );
    259         } else if ( array->isVarLen ) {
    260             os << "variable-length array of ";
    261         } else {
    262             os << "open array of ";
    263         }
    264         if ( base ) {
    265             base->print( os, indent );
    266         }
    267         break;
    268       case Function:
    269         os << "function" << endl;
    270         if ( function->params ) {
    271             os << string( indent+2, ' ' ) << "with parameters " << endl;
    272             function->params->printList( os, indent+4 );
    273         } else {
    274             os << string( indent+2, ' ' ) << "with no parameters " << endl;
    275         }
    276         if ( function->idList ) {
    277             os << string( indent+2, ' ' ) << "with old-style identifier list " << endl;
    278             function->idList->printList( os, indent+4 );
    279         }
    280         if ( function->oldDeclList ) {
    281             os << string( indent+2, ' ' ) << "with old-style declaration list " << endl;
    282             function->oldDeclList->printList( os, indent+4 );
    283         }
    284         os << string( indent+2, ' ' ) << "returning ";
    285         if ( base ) {
    286             base->print( os, indent+4 );
    287         } else {
    288             os << "nothing ";
    289         }
    290         os << endl;
    291         if ( function->hasBody ) {
    292             os << string( indent+2, ' ' ) << "with body " << endl;
    293         }
    294         if ( function->body ) {
    295             function->body->printList( os, indent+2 );
    296         }
    297         break;
    298       case Aggregate:
    299         os << DeclarationNode::tyConName[ aggregate->kind ] << ' ' << aggregate->name << endl;
    300         if ( aggregate->params ) {
    301             os << string( indent+2, ' ' ) << "with type parameters " << endl;
    302             aggregate->params->printList( os, indent+4 );
    303         }
    304         if ( aggregate->actuals ) {
    305             os << string( indent+2, ' ' ) << "instantiated with actual parameters " << endl;
    306             aggregate->actuals->printList( os, indent+4 );
    307         }
    308         if ( aggregate->members ) {
    309             os << string( indent+2, ' ' ) << "with members " << endl;
    310             aggregate->members->printList( os, indent+4 );
     232        using std::endl;
     233        using std::string;
     234
     235        printEnums( qualifiers.begin(), qualifiers.end(), DeclarationNode::qualifierName, os );
     236
     237        if ( forall ) {
     238                os << "forall " << endl;
     239                forall->printList( os, indent+4 );
     240        }
     241
     242        switch ( kind ) {
     243          case Unknown:
     244                os << "entity of unknown type ";
     245                break;
     246          case Pointer:
     247                os << "pointer ";
     248                if ( base ) {
     249                        os << "to ";
     250                        base->print( os, indent );
     251                }
     252                break;
     253          case EnumConstant:
     254                os << "enumeration constant ";
     255                break;
     256          case Basic:
     257                printEnums( basic->modifiers.begin(), basic->modifiers.end(), DeclarationNode::modifierName, os );
     258                printEnums( basic->typeSpec.begin(), basic->typeSpec.end(), DeclarationNode::basicTypeName, os );
     259                break;
     260          case Array:
     261                if ( array->isStatic ) {
     262                        os << "static ";
     263                }
     264                if ( array->dimension ) {
     265                        os << "array of ";
     266                        array->dimension->printOneLine( os, indent );
     267                } else if ( array->isVarLen ) {
     268                        os << "variable-length array of ";
     269                } else {
     270                        os << "open array of ";
     271                }
     272                if ( base ) {
     273                        base->print( os, indent );
     274                }
     275                break;
     276          case Function:
     277                os << "function" << endl;
     278                if ( function->params ) {
     279                        os << string( indent+2, ' ' ) << "with parameters " << endl;
     280                        function->params->printList( os, indent+4 );
     281                } else {
     282                        os << string( indent+2, ' ' ) << "with no parameters " << endl;
     283                }
     284                if ( function->idList ) {
     285                        os << string( indent+2, ' ' ) << "with old-style identifier list " << endl;
     286                        function->idList->printList( os, indent+4 );
     287                }
     288                if ( function->oldDeclList ) {
     289                        os << string( indent+2, ' ' ) << "with old-style declaration list " << endl;
     290                        function->oldDeclList->printList( os, indent+4 );
     291                }
     292                os << string( indent+2, ' ' ) << "returning ";
     293                if ( base ) {
     294                        base->print( os, indent+4 );
     295                } else {
     296                        os << "nothing ";
     297                }
     298                os << endl;
     299                if ( function->hasBody ) {
     300                        os << string( indent+2, ' ' ) << "with body " << endl;
     301                }
     302                if ( function->body ) {
     303                        function->body->printList( os, indent+2 );
     304                }
     305                break;
     306          case Aggregate:
     307                os << DeclarationNode::tyConName[ aggregate->kind ] << ' ' << aggregate->name << endl;
     308                if ( aggregate->params ) {
     309                        os << string( indent+2, ' ' ) << "with type parameters " << endl;
     310                        aggregate->params->printList( os, indent+4 );
     311                }
     312                if ( aggregate->actuals ) {
     313                        os << string( indent+2, ' ' ) << "instantiated with actual parameters " << endl;
     314                        aggregate->actuals->printList( os, indent+4 );
     315                }
     316                if ( aggregate->members ) {
     317                        os << string( indent+2, ' ' ) << "with members " << endl;
     318                        aggregate->members->printList( os, indent+4 );
    311319///     } else {
    312320///       os << string( indent+2, ' ' ) << "with no members " << endl;
    313         }
    314         break;
    315       case AggregateInst:
    316         if ( aggInst->aggregate ) {
    317             os << "instance of " ;
    318             aggInst->aggregate->print( os, indent );
     321                }
     322                break;
     323          case AggregateInst:
     324                if ( aggInst->aggregate ) {
     325                        os << "instance of " ;
     326                        aggInst->aggregate->print( os, indent );
     327                } else {
     328                        os << "instance of an unspecified aggregate ";
     329                }
     330                if ( aggInst->params ) {
     331                        os << string( indent+2, ' ' ) << "with parameters " << endl;
     332                        aggInst->params->printList( os, indent+2 );
     333                }
     334                break;
     335          case Enum:
     336                os << "enumeration ";
     337                if ( enumeration->constants ) {
     338                        os << "with constants" << endl;
     339                        enumeration->constants->printList( os, indent+2 );
     340                }
     341                break;
     342          case SymbolicInst:
     343                os << "instance of type " << symbolic->name;
     344                if ( symbolic->actuals ) {
     345                        os << " with parameters" << endl;
     346                        symbolic->actuals->printList( os, indent + 2 );
     347                }
     348                break;
     349          case Symbolic:
     350                if ( symbolic->isTypedef ) {
     351                        os << "typedef definition ";
     352                } else {
     353                        os << "type definition ";
     354                }
     355                if ( symbolic->params ) {
     356                        os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
     357                        symbolic->params->printList( os, indent + 2 );
     358                }
     359                if ( symbolic->assertions ) {
     360                        os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
     361                        symbolic->assertions->printList( os, indent + 4 );
     362                        os << string( indent+2, ' ' );
     363                }
     364                if ( base ) {
     365                        os << "for ";
     366                        base->print( os, indent + 2 );
     367                }
     368                break;
     369          case Variable:
     370                os << DeclarationNode::typeClassName[ variable->tyClass ] << " variable ";
     371                if ( variable->assertions ) {
     372                        os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
     373                        variable->assertions->printList( os, indent + 4 );
     374                        os << string( indent+2, ' ' );
     375                }
     376                break;
     377          case Tuple:
     378                os << "tuple ";
     379                if ( tuple->members ) {
     380                        os << "with members " << endl;
     381                        tuple->members->printList( os, indent + 2 );
     382                }
     383                break;
     384          case Typeof:
     385                os << "type-of expression ";
     386                if ( typeexpr->expr ) {
     387                        typeexpr->expr->print( os, indent + 2 );
     388                }
     389                break;
     390          case Attr:
     391                os << "attribute type decl " << attr->name << " applied to ";
     392                if ( attr->expr ) {
     393                        attr->expr->print( os, indent + 2 );
     394                }
     395                if ( attr->type ) {
     396                        attr->type->print( os, indent + 2 );
     397                }
     398                break;
     399        }
     400}
     401
     402TypeData *TypeData::extractAggregate( bool toplevel ) const {
     403        TypeData *ret = 0;
     404
     405        switch ( kind ) {
     406          case Aggregate:
     407                if ( !toplevel && aggregate->members ) {
     408                        ret = clone();
     409                        ret->qualifiers.clear();
     410                }
     411                break;
     412          case Enum:
     413                if ( !toplevel && enumeration->constants ) {
     414                        ret = clone();
     415                        ret->qualifiers.clear();
     416                }
     417                break;
     418          case AggregateInst:
     419                if ( aggInst->aggregate ) {
     420                        ret = aggInst->aggregate->extractAggregate( false );
     421                }
     422                break;
     423          default:
     424                if ( base ) {
     425                        ret = base->extractAggregate( false );
     426                }
     427        }
     428        return ret;
     429}
     430
     431void buildForall( const DeclarationNode *firstNode, std::list< TypeDecl* > &outputList ) {
     432        buildList( firstNode, outputList );
     433        for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
     434                if ( (*i)->get_kind() == TypeDecl::Any ) {
     435                        FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     436                        assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
     437                        assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
     438                        assignType->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
     439                        (*i)->get_assertions().push_front( new FunctionDecl( "?=?", Declaration::NoStorageClass, LinkageSpec::Cforall, assignType, 0, false ) );
     440                }
     441        }
     442}
     443
     444Declaration *TypeData::buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init ) const {
     445        if ( kind == TypeData::Function ) {
     446                FunctionDecl *decl;
     447                if ( function->hasBody ) {
     448                        if ( function->body ) {
     449                                Statement *stmt = function->body->build();
     450                                CompoundStmt *body = dynamic_cast< CompoundStmt* >( stmt );
     451                                assert( body );
     452                                decl = new FunctionDecl( name, sc, linkage, buildFunction(), body, isInline );
     453                        } else {
     454                                // std::list<Label> ls;
     455                                decl = new FunctionDecl( name, sc, linkage, buildFunction(), new CompoundStmt( std::list<Label>() ), isInline );
     456                        }
     457                } else {
     458                        decl = new FunctionDecl( name, sc, linkage, buildFunction(), 0, isInline );
     459                }
     460                for ( DeclarationNode *cur = function->idList; cur != 0; cur = dynamic_cast< DeclarationNode* >( cur->get_link() ) ) {
     461                        if ( cur->get_name() != "" ) {
     462                                decl->get_oldIdents().insert( decl->get_oldIdents().end(), cur->get_name() );
     463                        }
     464                }
     465                buildList( function->oldDeclList, decl->get_oldDecls() );
     466                return decl;
     467        } else if ( kind == TypeData::Aggregate ) {
     468                return buildAggregate();
     469        } else if ( kind == TypeData::Enum ) {
     470                return buildEnum();
     471        } else if ( kind == TypeData::Symbolic ) {
     472                return buildSymbolic( name, sc );
     473        } else if ( kind == TypeData::Variable ) {
     474                return buildVariable();
    319475        } else {
    320             os << "instance of an unspecified aggregate ";
    321         }
    322         if ( aggInst->params ) {
    323             os << string( indent+2, ' ' ) << "with parameters " << endl;
    324             aggInst->params->printList( os, indent+2 );
    325         }
    326         break;
    327       case Enum:
    328         os << "enumeration ";
    329         if ( enumeration->constants ) {
    330             os << "with constants" << endl;
    331             enumeration->constants->printList( os, indent+2 );
    332         }
    333         break;
    334       case SymbolicInst:
    335         os << "instance of type " << symbolic->name;
    336         if ( symbolic->actuals ) {
    337             os << " with parameters" << endl;
    338             symbolic->actuals->printList( os, indent + 2 );
    339         }
    340         break;
    341       case Symbolic:
    342         if ( symbolic->isTypedef ) {
    343             os << "typedef definition ";
     476                if ( isInline ) {
     477                        throw SemanticError( "invalid inline specification in declaration of ", this );
     478                } else {
     479                        return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init );
     480                }
     481        }
     482        return 0;
     483}
     484
     485Type *TypeData::build() const {
     486        switch ( kind ) {
     487          case Unknown:
     488                // fill in implicit int
     489                return new BasicType( buildQualifiers(), BasicType::SignedInt );
     490          case Basic:
     491                return buildBasicType();
     492          case Pointer:
     493                return buildPointer();
     494          case Array:
     495                return buildArray();
     496          case Function:
     497                return buildFunction();
     498          case AggregateInst:
     499                return buildAggInst();
     500          case EnumConstant:
     501                // the name gets filled in later -- by SymTab::Validate
     502                return new EnumInstType( buildQualifiers(), "" );
     503          case SymbolicInst:
     504                return buildSymbolicInst();;
     505          case Tuple:
     506                return buildTuple();
     507          case Typeof:
     508                return buildTypeof();
     509          case Attr:
     510                return buildAttr();
     511          case Symbolic:
     512          case Enum:
     513          case Aggregate:
     514          case Variable:
     515                assert( false );
     516        }
     517
     518        return 0;
     519}
     520
     521Type::Qualifiers TypeData::buildQualifiers() const {
     522        Type::Qualifiers q;
     523        for ( std::list< DeclarationNode::Qualifier >::const_iterator i = qualifiers.begin(); i != qualifiers.end(); ++i ) {
     524                switch ( *i ) {
     525                  case DeclarationNode::Const:
     526                        q.isConst = true;
     527                        break;
     528                  case DeclarationNode::Volatile:
     529                        q.isVolatile = true;
     530                        break;
     531                  case DeclarationNode::Restrict:
     532                        q.isRestrict = true;
     533                        break;
     534                  case DeclarationNode::Lvalue:
     535                        q.isLvalue = true;
     536                        break;
     537                  case DeclarationNode::Atomic:
     538                        q.isAtomic = true;
     539                        break;
     540                  case DeclarationNode::Attribute:
     541                        q.isAttribute = true;
     542                        break;
     543                }
     544        }
     545        return q;
     546}
     547
     548Type *TypeData::buildBasicType() const {
     549        static const BasicType::Kind kindMap[] = { BasicType::Char, BasicType::SignedInt, BasicType::Float, BasicType::Double,
     550                                                                                           BasicType::Char /* void */, BasicType::Bool, BasicType::DoubleComplex,
     551                                                                                           BasicType::DoubleImaginary };
     552        bool init = false;
     553        bool sawDouble = false;
     554        bool sawSigned = false;
     555        BasicType::Kind ret;
     556
     557        for ( std::list< DeclarationNode::BasicType >::const_iterator i = basic->typeSpec.begin(); i != basic->typeSpec.end(); ++i ) {
     558                if ( !init ) {
     559                        init = true;
     560                        if ( *i == DeclarationNode::Void ) {
     561                                if ( basic->typeSpec.size() != 1 || !basic->modifiers.empty() ) {
     562                                        throw SemanticError( "invalid type specifier \"void\" in type: ", this );
     563                                } else {
     564                                        return new VoidType( buildQualifiers() );
     565                                }
     566                        } else {
     567                                ret = kindMap[ *i ];
     568                        }
     569                } else {
     570                        switch ( *i ) {
     571                          case DeclarationNode::Float:
     572                                if ( sawDouble ) {
     573                                        throw SemanticError( "invalid type specifier \"float\" in type: ", this );
     574                                } else {
     575                                        switch ( ret ) {
     576                                          case BasicType::DoubleComplex:
     577                                                ret = BasicType::FloatComplex;
     578                                                break;
     579                                          case BasicType::DoubleImaginary:
     580                                                ret = BasicType::FloatImaginary;
     581                                                break;
     582                                          default:
     583                                                throw SemanticError( "invalid type specifier \"float\" in type: ", this );
     584                                        }
     585                                }
     586                                break;
     587                          case DeclarationNode::Double:
     588                                if ( sawDouble ) {
     589                                        throw SemanticError( "duplicate type specifier \"double\" in type: ", this );
     590                                } else {
     591                                        switch ( ret ) {
     592                                          case BasicType::DoubleComplex:
     593                                          case BasicType::DoubleImaginary:
     594                                                break;
     595                                          default:
     596                                                throw SemanticError( "invalid type specifier \"double\" in type: ", this );
     597                                        }
     598                                }
     599                                break;
     600       
     601                          case DeclarationNode::Complex:
     602                                switch ( ret ) {
     603                                  case BasicType::Float:
     604                                        ret = BasicType::FloatComplex;
     605                                        break;
     606                                  case BasicType::Double:
     607                                        ret = BasicType::DoubleComplex;
     608                                        break;
     609                                  default:
     610                                        throw SemanticError( "invalid type specifier \"_Complex\" in type: ", this );
     611                                }
     612                                break;
     613                          case DeclarationNode::Imaginary:
     614                                switch ( ret ) {
     615                                  case BasicType::Float:
     616                                        ret = BasicType::FloatImaginary;
     617                                        break;
     618                                  case BasicType::Double:
     619                                        ret = BasicType::DoubleImaginary;
     620                                        break;
     621                                  default:
     622                                        throw SemanticError( "invalid type specifier \"_Imaginary\" in type: ", this );
     623                                }
     624                                break;
     625                          default:
     626                                throw SemanticError( std::string( "invalid type specifier \"" ) + DeclarationNode::basicTypeName[ *i ] + "\" in type: ", this );
     627                        }
     628                }
     629                if ( *i == DeclarationNode::Double ) {
     630                        sawDouble = true;
     631                }
     632        }
     633
     634        for ( std::list< DeclarationNode::Modifier >::const_iterator i = basic->modifiers.begin(); i != basic->modifiers.end(); ++i ) {
     635                switch ( *i ) {
     636                  case DeclarationNode::Long:
     637                        if ( !init ) {
     638                                init = true;
     639                                ret = BasicType::LongSignedInt;
     640                        } else {
     641                                switch ( ret ) {
     642                                  case BasicType::SignedInt:
     643                                        ret = BasicType::LongSignedInt;
     644                                        break;
     645                                  case BasicType::UnsignedInt:
     646                                        ret = BasicType::LongUnsignedInt;
     647                                        break;
     648                                  case BasicType::LongSignedInt:
     649                                        ret = BasicType::LongLongSignedInt;
     650                                        break;
     651                                  case BasicType::LongUnsignedInt:
     652                                        ret = BasicType::LongLongUnsignedInt;
     653                                        break;
     654                                  case BasicType::Double:
     655                                        ret = BasicType::LongDouble;
     656                                        break;
     657                                  case BasicType::DoubleComplex:
     658                                        ret = BasicType::LongDoubleComplex;
     659                                        break;
     660                                  case BasicType::DoubleImaginary:
     661                                        ret = BasicType::LongDoubleImaginary;
     662                                        break;
     663                                  default:
     664                                        throw SemanticError( "invalid type modifier \"long\" in type: ", this );
     665                                }
     666                        }
     667                        break;
     668                  case DeclarationNode::Short:
     669                        if ( !init ) {
     670                                init = true;
     671                                ret = BasicType::ShortSignedInt;
     672                        } else {
     673                                switch ( ret ) {
     674                                  case BasicType::SignedInt:
     675                                        ret = BasicType::ShortSignedInt;
     676                                        break;
     677                                  case BasicType::UnsignedInt:
     678                                        ret = BasicType::ShortUnsignedInt;
     679                                        break;
     680                                  default:
     681                                        throw SemanticError( "invalid type modifier \"short\" in type: ", this );
     682                                }
     683                        }
     684                        break;
     685                  case DeclarationNode::Signed:
     686                        if ( !init ) {
     687                                init = true;
     688                                ret = BasicType::SignedInt;
     689                        } else if ( sawSigned ) {
     690                                throw SemanticError( "duplicate type modifer \"signed\" in type: ", this );
     691                        } else {
     692                                switch ( ret ) {
     693                                  case BasicType::LongLongSignedInt:    // PAB
     694                                        ret = BasicType::LongLongUnsignedInt;
     695                                        break;
     696                                  case BasicType::LongSignedInt:
     697                                        ret = BasicType::LongUnsignedInt;
     698                                        break;
     699                                  case BasicType::SignedInt:
     700                                  case BasicType::ShortSignedInt:
     701                                        break;
     702                                  case BasicType::Char:
     703                                        ret = BasicType::SignedChar;
     704                                        break;
     705                                  default:
     706                                        throw SemanticError( "invalid type modifer \"signed\" in type: ", this );
     707                                }
     708                        }
     709                        break;
     710                  case DeclarationNode::Unsigned:
     711                        if ( !init ) {
     712                                init = true;
     713                                ret = BasicType::UnsignedInt;
     714                        } else if ( sawSigned ) {
     715                                throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
     716                        } else {
     717                                switch ( ret ) {
     718                                  case BasicType::LongLongSignedInt:    // PAB
     719                                        ret = BasicType::LongLongUnsignedInt;
     720                                        break;
     721                                  case BasicType::LongSignedInt:
     722                                        ret = BasicType::LongUnsignedInt;
     723                                        break;
     724                                  case BasicType::SignedInt:
     725                                        ret = BasicType::UnsignedInt;
     726                                        break;
     727                                  case BasicType::ShortSignedInt:
     728                                        ret = BasicType::ShortUnsignedInt;
     729                                        break;
     730                                  case BasicType::Char:
     731                                        ret = BasicType::UnsignedChar;
     732                                        break;
     733                                  default:
     734                                        throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
     735                                }
     736                        }
     737                        break;
     738                }
     739
     740                if ( *i == DeclarationNode::Signed ) {
     741                        sawSigned = true;
     742                }
     743        }
     744
     745        BasicType *bt;
     746        if ( !init ) {
     747                bt = new BasicType( buildQualifiers(), BasicType::SignedInt );
    344748        } else {
    345             os << "type definition ";
    346         }
    347         if ( symbolic->params ) {
    348             os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
    349             symbolic->params->printList( os, indent + 2 );
    350         }
    351         if ( symbolic->assertions ) {
    352             os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
    353             symbolic->assertions->printList( os, indent + 4 );
    354             os << string( indent+2, ' ' );
    355         }
     749                bt = new BasicType( buildQualifiers(), ret );
     750        }
     751        buildForall( forall, bt->get_forall() );
     752        return bt;
     753}
     754
     755
     756PointerType *TypeData::buildPointer() const {
     757        PointerType *pt;
    356758        if ( base ) {
    357             os << "for ";
    358             base->print( os, indent + 2 );
    359         }
    360         break;
    361       case Variable:
    362         os << DeclarationNode::typeClassName[ variable->tyClass ] << " variable ";
    363         if ( variable->assertions ) {
    364             os << endl << string( indent+2, ' ' ) << "with assertions" << endl;
    365             variable->assertions->printList( os, indent + 4 );
    366             os << string( indent+2, ' ' );
    367         }
    368         break;
    369       case Tuple:
    370         os << "tuple ";
    371         if ( tuple->members ) {
    372             os << "with members " << endl;
    373             tuple->members->printList( os, indent + 2 );
    374         }
    375         break;
    376    
    377       case Typeof:
    378         os << "type-of expression ";
    379         if ( typeexpr->expr ) {
    380             typeexpr->expr->print( os, indent + 2 );
    381         }
    382         break;
    383    
    384       case Attr:
    385         os << "attribute type decl " << attr->name << " applied to ";
    386         if ( attr->expr ) {
    387             attr->expr->print( os, indent + 2 );
    388         }
    389         if ( attr->type ) {
    390             attr->type->print( os, indent + 2 );
    391         }
    392         break;
    393     }
    394 }
    395 
    396 TypeData *TypeData::extractAggregate( bool toplevel ) const {
    397     TypeData *ret = 0;
    398 
    399     switch ( kind ) {
    400       case Aggregate:
    401         if ( !toplevel && aggregate->members ) {
    402             ret = clone();
    403             ret->qualifiers.clear();
    404         }
    405         break;
    406       case Enum:
    407         if ( !toplevel && enumeration->constants ) {
    408             ret = clone();
    409             ret->qualifiers.clear();
    410         }
    411         break;
    412       case AggregateInst:
    413         if ( aggInst->aggregate ) {
    414             ret = aggInst->aggregate->extractAggregate( false );
    415         }
    416         break;
    417       default:
     759                pt = new PointerType( buildQualifiers(), base->build() );
     760        } else {
     761                pt = new PointerType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     762        }
     763        buildForall( forall, pt->get_forall() );
     764        return pt;
     765}
     766
     767ArrayType *TypeData::buildArray() const {
     768        ArrayType *at;
    418769        if ( base ) {
    419             ret = base->extractAggregate( false );
    420         }
    421     }
    422     return ret;
    423 }
    424 
    425 void buildForall( const DeclarationNode *firstNode, std::list< TypeDecl* > &outputList ) {
    426  
    427     buildList( firstNode, outputList );
    428     for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
    429         if ( (*i)->get_kind() == TypeDecl::Any ) {
    430             FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    431             assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
    432             assignType->get_parameters().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
    433             assignType->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
    434             (*i)->get_assertions().push_front( new FunctionDecl( "?=?", Declaration::NoStorageClass, LinkageSpec::Cforall,  assignType, 0, false ) );
    435         }
    436     }
    437 }
    438 
    439 Declaration *TypeData::buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init ) const {
    440     if ( kind == TypeData::Function ) {
    441         FunctionDecl *decl;
    442         if ( function->hasBody ) {
    443             if ( function->body ) {
    444                 Statement *stmt = function->body->build();
    445                 CompoundStmt *body = dynamic_cast< CompoundStmt* >( stmt );
    446                 assert( body );
    447                 decl = new FunctionDecl( name, sc, linkage, buildFunction(), body, isInline );
    448             } else {
    449                 // std::list<Label> ls;
    450                 decl = new FunctionDecl( name, sc, linkage, buildFunction(), new CompoundStmt( std::list<Label>() ), isInline );
    451             }
     770                at = new ArrayType( buildQualifiers(), base->build(), maybeBuild< Expression >( array->dimension ),
     771                                                        array->isVarLen, array->isStatic );
    452772        } else {
    453             decl = new FunctionDecl( name, sc, linkage, buildFunction(), 0, isInline );
    454         }
    455         for ( DeclarationNode *cur = function->idList; cur != 0; cur = dynamic_cast< DeclarationNode* >( cur->get_link() ) ) {
    456             if ( cur->get_name() != "" ) {
    457                 decl->get_oldIdents().insert( decl->get_oldIdents().end(), cur->get_name() );
    458             }
    459         }
    460         buildList( function->oldDeclList, decl->get_oldDecls() );
    461         return decl;
    462     } else if ( kind == TypeData::Aggregate ) {
    463         return buildAggregate();
    464     } else if ( kind == TypeData::Enum ) {
    465         return buildEnum();
    466     } else if ( kind == TypeData::Symbolic ) {
    467         return buildSymbolic( name, sc );
    468     } else if ( kind == TypeData::Variable ) {
    469         return buildVariable();
    470     } else {
    471         if ( isInline ) {
    472             throw SemanticError( "invalid inline specification in declaration of ", this );
     773                at = new ArrayType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
     774                                                        maybeBuild< Expression >( array->dimension ), array->isVarLen, array->isStatic );
     775        }
     776        buildForall( forall, at->get_forall() );
     777        return at;
     778}
     779
     780FunctionType *TypeData::buildFunction() const {
     781        assert( kind == Function );
     782        bool hasEllipsis = function->params ? function->params->get_hasEllipsis() : true;
     783        if ( !function->params ) hasEllipsis = !function->newStyle;
     784        FunctionType *ft = new FunctionType( buildQualifiers(), hasEllipsis );
     785        buildList( function->params, ft->get_parameters() );
     786        buildForall( forall, ft->get_forall() );
     787        if ( base ) {
     788                switch ( base->kind ) {
     789                  case Tuple:
     790                        buildList( base->tuple->members, ft->get_returnVals() );
     791                        break;
     792                  default:
     793                        ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType* >( base->buildDecl( "", Declaration::NoStorageClass, 0, false, LinkageSpec::Cforall ) ) );
     794                }
    473795        } else {
    474             return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init );
    475         }
    476     }
    477     return 0;
    478 }
    479 
    480 Type *TypeData::build() const {
    481 
    482     switch ( kind ) {
    483       case Unknown:
    484         // fill in implicit int
    485         return new BasicType( buildQualifiers(), BasicType::SignedInt );
    486 
    487       case Basic:
    488         return buildBasicType();
    489 
    490       case Pointer:
    491         return buildPointer();
    492 
    493       case Array:
    494         return buildArray();
    495 
    496       case Function:
    497         return buildFunction();
    498 
    499       case AggregateInst:
    500         return buildAggInst();
    501 
    502       case EnumConstant:
    503         // the name gets filled in later -- by SymTab::Validate
    504         return new EnumInstType( buildQualifiers(), "" );
    505 
    506       case SymbolicInst:
    507         return buildSymbolicInst();;
    508 
    509       case Tuple:
    510         return buildTuple();
    511  
    512       case Typeof:
    513         return buildTypeof();
    514 
    515       case Attr:
    516         return buildAttr();
    517 
    518       case Symbolic:
    519       case Enum:
    520       case Aggregate:
    521       case Variable:
    522         assert( false );
    523     }
    524 
    525     return 0;
    526 }
    527 
    528 Type::Qualifiers TypeData::buildQualifiers() const {
    529     Type::Qualifiers q;
    530     for ( std::list< DeclarationNode::Qualifier >::const_iterator i = qualifiers.begin(); i != qualifiers.end(); ++i ) {
    531         switch ( *i ) {
    532           case DeclarationNode::Const:
    533             q.isConst = true;
    534             break;
    535           case DeclarationNode::Volatile:
    536             q.isVolatile = true;
    537             break;
    538           case DeclarationNode::Restrict:
    539             q.isRestrict = true;
    540             break;
    541           case DeclarationNode::Lvalue:
    542             q.isLvalue = true;
    543             break;
    544           case DeclarationNode::Atomic:
    545             q.isAtomic = true;
    546             break;
    547           case DeclarationNode::Attribute:
    548             q.isAttribute = true;
    549             break;
    550         }
    551     }
    552     return q;
    553 }
    554 
    555 Type *TypeData::buildBasicType() const {
    556     static const BasicType::Kind kindMap[] = { BasicType::Char, BasicType::SignedInt, BasicType::Float, BasicType::Double,
    557                                                BasicType::Char /* void */, BasicType::Bool, BasicType::DoubleComplex,
    558                                                BasicType::DoubleImaginary };
    559     bool init = false;
    560     bool sawDouble = false;
    561     bool sawSigned = false;
    562     BasicType::Kind ret;
    563 
    564     for ( std::list< DeclarationNode::BasicType >::const_iterator i = basic->typeSpec.begin(); i != basic->typeSpec.end(); ++i ) {
    565         if ( !init ) {
    566             init = true;
    567             if ( *i == DeclarationNode::Void ) {
    568                 if ( basic->typeSpec.size() != 1 || !basic->modifiers.empty() ) {
    569                     throw SemanticError( "invalid type specifier \"void\" in type: ", this );
    570                 } else {
    571                     return new VoidType( buildQualifiers() );
    572                 }
    573             } else {
    574                 ret = kindMap[ *i ];
    575             }
    576         } else {
    577             switch ( *i ) {
    578               case DeclarationNode::Float:
    579                 if ( sawDouble ) {
    580                     throw SemanticError( "invalid type specifier \"float\" in type: ", this );
    581                 } else {
    582                     switch ( ret ) {
    583                       case BasicType::DoubleComplex:
    584                         ret = BasicType::FloatComplex;
    585                         break;
    586                       case BasicType::DoubleImaginary:
    587                         ret = BasicType::FloatImaginary;
    588                         break;
    589                       default:
    590                         throw SemanticError( "invalid type specifier \"float\" in type: ", this );
    591                     }
    592                 }
    593                 break;
    594               case DeclarationNode::Double:
    595                 if ( sawDouble ) {
    596                     throw SemanticError( "duplicate type specifier \"double\" in type: ", this );
    597                 } else {
    598                     switch ( ret ) {
    599                       case BasicType::DoubleComplex:
    600                       case BasicType::DoubleImaginary:
    601                         break;
    602                       default:
    603                         throw SemanticError( "invalid type specifier \"double\" in type: ", this );
    604                     }
    605                 }
     796                ft->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 ) );
     797        }
     798        return ft;
     799}
     800
     801AggregateDecl *TypeData::buildAggregate() const {
     802        assert( kind == Aggregate );
     803        AggregateDecl *at;
     804        switch ( aggregate->kind ) {
     805          case DeclarationNode::Struct:
     806                at = new StructDecl( aggregate->name );
    606807                break;
    607808       
    608               case DeclarationNode::Complex:
    609                 switch ( ret ) {
    610                   case BasicType::Float:
    611                     ret = BasicType::FloatComplex;
    612                     break;
    613          
    614                   case BasicType::Double:
    615                     ret = BasicType::DoubleComplex;
    616                     break;
    617                   default:
    618                     throw SemanticError( "invalid type specifier \"_Complex\" in type: ", this );
    619                 }
    620                 break;
    621        
    622               case DeclarationNode::Imaginary:
    623                 switch ( ret ) {
    624                   case BasicType::Float:
    625                     ret = BasicType::FloatImaginary;
    626                     break;
    627          
    628                   case BasicType::Double:
    629                     ret = BasicType::DoubleImaginary;
    630                     break;
    631                   default:
    632                     throw SemanticError( "invalid type specifier \"_Imaginary\" in type: ", this );
    633                 }
    634                 break;
    635        
    636               default:
    637                 throw SemanticError( std::string( "invalid type specifier \"" ) + DeclarationNode::basicTypeName[ *i ] + "\" in type: ", this );
    638             }
    639         }
    640         if ( *i == DeclarationNode::Double ) {
    641             sawDouble = true;
    642         }
    643     }
    644 
    645     for ( std::list< DeclarationNode::Modifier >::const_iterator i = basic->modifiers.begin(); i != basic->modifiers.end(); ++i ) {
    646         switch ( *i ) {
    647           case DeclarationNode::Long:
    648             if ( !init ) {
    649                 init = true;
    650                 ret = BasicType::LongSignedInt;
    651             } else {
    652                 switch ( ret ) {
    653                   case BasicType::SignedInt:
    654                     ret = BasicType::LongSignedInt;
    655                     break;
    656                   case BasicType::UnsignedInt:
    657                     ret = BasicType::LongUnsignedInt;
    658                     break;
    659                   case BasicType::LongSignedInt:
    660                     ret = BasicType::LongLongSignedInt;
    661                     break;
    662                   case BasicType::LongUnsignedInt:
    663                     ret = BasicType::LongLongUnsignedInt;
    664                     break;
    665                   case BasicType::Double:
    666                     ret = BasicType::LongDouble;
    667                     break;
    668                   case BasicType::DoubleComplex:
    669                     ret = BasicType::LongDoubleComplex;
    670                     break;
    671                   case BasicType::DoubleImaginary:
    672                     ret = BasicType::LongDoubleImaginary;
    673                     break;
    674                   default:
    675                     throw SemanticError( "invalid type modifier \"long\" in type: ", this );
    676                 }
    677             }
    678             break;
    679           case DeclarationNode::Short:
    680             if ( !init ) {
    681                 init = true;
    682                 ret = BasicType::ShortSignedInt;
    683             } else {
    684                 switch ( ret ) {
    685                   case BasicType::SignedInt:
    686                     ret = BasicType::ShortSignedInt;
    687                     break;
    688                   case BasicType::UnsignedInt:
    689                     ret = BasicType::ShortUnsignedInt;
    690                     break;
    691                   default:
    692                     throw SemanticError( "invalid type modifier \"short\" in type: ", this );
    693                 }
    694             }
    695             break;
    696           case DeclarationNode::Signed:
    697             if ( !init ) {
    698                 init = true;
    699                 ret = BasicType::SignedInt;
    700             } else if ( sawSigned ) {
    701                 throw SemanticError( "duplicate type modifer \"signed\" in type: ", this );
    702             } else {
    703                 switch ( ret ) {
    704                   case BasicType::LongLongSignedInt:    // PAB
    705                     ret = BasicType::LongLongUnsignedInt;
    706                     break;
    707                   case BasicType::LongSignedInt:
    708                     ret = BasicType::LongUnsignedInt;
    709                     break;
    710                   case BasicType::SignedInt:
    711                   case BasicType::ShortSignedInt:
    712                     break;
    713                   case BasicType::Char:
    714                     ret = BasicType::SignedChar;
    715                     break;
    716                   default:
    717                     throw SemanticError( "invalid type modifer \"signed\" in type: ", this );
    718                 }
    719             }
    720             break;
    721           case DeclarationNode::Unsigned:
    722             if ( !init ) {
    723                 init = true;
    724                 ret = BasicType::UnsignedInt;
    725             } else if ( sawSigned ) {
    726                 throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
    727             } else {
    728                 switch ( ret ) {
    729                   case BasicType::LongLongSignedInt:    // PAB
    730                     ret = BasicType::LongLongUnsignedInt;
    731                     break;
    732                   case BasicType::LongSignedInt:
    733                     ret = BasicType::LongUnsignedInt;
    734                     break;
    735                   case BasicType::SignedInt:
    736                     ret = BasicType::UnsignedInt;
    737                     break;
    738                   case BasicType::ShortSignedInt:
    739                     ret = BasicType::ShortUnsignedInt;
    740                     break;
    741                   case BasicType::Char:
    742                     ret = BasicType::UnsignedChar;
    743                     break;
    744                   default:
    745                     throw SemanticError( "invalid type modifer \"unsigned\" in type: ", this );
    746                 }
    747             }
    748             break;
    749         }
    750 
    751         if ( *i == DeclarationNode::Signed ) {
    752             sawSigned = true;
    753         }
    754     }
    755 
    756     BasicType *bt;
    757     if ( !init ) {
    758         bt = new BasicType( buildQualifiers(), BasicType::SignedInt );
    759     } else {
    760         bt = new BasicType( buildQualifiers(), ret );
    761     }
    762     buildForall( forall, bt->get_forall() );
    763     return bt;
    764 }
    765 
    766 
    767 PointerType *TypeData::buildPointer() const {
    768     PointerType *pt;
    769     if ( base ) {
    770         pt = new PointerType( buildQualifiers(), base->build() );
    771     } else {
    772         pt = new PointerType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    773     }
    774     buildForall( forall, pt->get_forall() );
    775     return pt;
    776 }
    777 
    778 ArrayType *TypeData::buildArray() const {
    779  
    780     ArrayType *at;
    781     if ( base ) {
    782         at = new ArrayType( buildQualifiers(), base->build(), maybeBuild< Expression >( array->dimension ),
    783                             array->isVarLen, array->isStatic );
    784     } else {
    785         at = new ArrayType( buildQualifiers(), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
    786                             maybeBuild< Expression >( array->dimension ), array->isVarLen, array->isStatic );
    787     }
    788     buildForall( forall, at->get_forall() );
    789     return at;
    790 }
    791 
    792 FunctionType *TypeData::buildFunction() const {
    793     assert( kind == Function );
    794     bool hasEllipsis = function->params ? function->params->get_hasEllipsis() : true;
    795     if ( !function->params ) hasEllipsis = !function->newStyle;
    796     FunctionType *ft = new FunctionType( buildQualifiers(), hasEllipsis );
    797     buildList( function->params, ft->get_parameters() );
    798     buildForall( forall, ft->get_forall() );
    799     if ( base ) {
    800         switch ( base->kind ) {
    801           case Tuple:
    802             buildList( base->tuple->members, ft->get_returnVals() );
    803             break;
     809          case DeclarationNode::Union:
     810                at = new UnionDecl( aggregate->name );
     811                break;
     812       
     813          case DeclarationNode::Context:
     814                at = new ContextDecl( aggregate->name );
     815                break;
     816       
    804817          default:
    805             ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType* >( base->buildDecl( "", Declaration::NoStorageClass, 0, false, LinkageSpec::Cforall ) ) );
    806         }
    807     } else {
    808         ft->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 ) );
    809     }
    810     return ft;
    811 }
    812 
    813 AggregateDecl *TypeData::buildAggregate() const {
    814     assert( kind == Aggregate );
    815     AggregateDecl *at;
    816     switch ( aggregate->kind ) {
    817       case DeclarationNode::Struct:
    818         at = new StructDecl( aggregate->name );
    819         break;
    820    
    821       case DeclarationNode::Union:
    822         at = new UnionDecl( aggregate->name );
    823         break;
    824    
    825       case DeclarationNode::Context:
    826         at = new ContextDecl( aggregate->name );
    827         break;
    828    
    829       default:
    830         assert( false );
    831     }
    832  
    833     buildList( aggregate->params, at->get_parameters() );
    834     buildList( aggregate->members, at->get_members() );
    835 
    836     return at;
     818                assert( false );
     819        }
     820        buildList( aggregate->params, at->get_parameters() );
     821        buildList( aggregate->members, at->get_members() );
     822
     823        return at;
    837824}
    838825
     
    850837
    851838ReferenceToType *TypeData::buildAggInst() const {
    852     assert( kind == AggregateInst );
    853     std::string name;
    854 
    855     ReferenceToType *ret;
    856     if ( aggInst->aggregate->kind == Enum ) {
    857         ret = new EnumInstType( buildQualifiers(), aggInst->aggregate->enumeration->name );
    858     } else {
    859         assert( aggInst->aggregate->kind == Aggregate );
    860         switch ( aggInst->aggregate->aggregate->kind ) {
    861           case DeclarationNode::Struct:
    862             ret = new StructInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
    863             break;
    864           case DeclarationNode::Union:
    865             ret = new UnionInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
    866             break;
    867           case DeclarationNode::Context:
    868             ret = new ContextInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
    869             break;
    870           default:
    871             assert( false );
    872         }
    873     }
    874     buildList( aggInst->params, ret->get_parameters() );
    875     buildForall( forall, ret->get_forall() );
    876     return ret;
     839        assert( kind == AggregateInst );
     840        std::string name;
     841
     842        ReferenceToType *ret;
     843        if ( aggInst->aggregate->kind == Enum ) {
     844                ret = new EnumInstType( buildQualifiers(), aggInst->aggregate->enumeration->name );
     845        } else {
     846                assert( aggInst->aggregate->kind == Aggregate );
     847                switch ( aggInst->aggregate->aggregate->kind ) {
     848                  case DeclarationNode::Struct:
     849                        ret = new StructInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
     850                        break;
     851                  case DeclarationNode::Union:
     852                        ret = new UnionInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
     853                        break;
     854                  case DeclarationNode::Context:
     855                        ret = new ContextInstType( buildQualifiers(), aggInst->aggregate->aggregate->name );
     856                        break;
     857                  default:
     858                        assert( false );
     859                }
     860        }
     861        buildList( aggInst->params, ret->get_parameters() );
     862        buildForall( forall, ret->get_forall() );
     863        return ret;
    877864}
    878865
    879866NamedTypeDecl *TypeData::buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const {
    880     assert( kind == Symbolic );
    881     NamedTypeDecl *ret;
    882     if ( symbolic->isTypedef ) {
    883         ret = new TypedefDecl( name, sc, maybeBuild< Type >( base ) );
    884     } else {
    885         ret = new TypeDecl( name, sc, maybeBuild< Type >( base ), TypeDecl::Any );
    886     }
    887     buildList( symbolic->params, ret->get_parameters() );
    888     buildList( symbolic->assertions, ret->get_assertions() );
    889     return ret;
     867        assert( kind == Symbolic );
     868        NamedTypeDecl *ret;
     869        if ( symbolic->isTypedef ) {
     870                ret = new TypedefDecl( name, sc, maybeBuild< Type >( base ) );
     871        } else {
     872                ret = new TypeDecl( name, sc, maybeBuild< Type >( base ), TypeDecl::Any );
     873        }
     874        buildList( symbolic->params, ret->get_parameters() );
     875        buildList( symbolic->assertions, ret->get_assertions() );
     876        return ret;
    890877}
    891878
    892879TypeDecl *TypeData::buildVariable() const {
    893     assert( kind == Variable );
    894     static const TypeDecl::Kind kindMap[] = { TypeDecl::Any, TypeDecl::Ftype, TypeDecl::Dtype };
    895 
    896     TypeDecl *ret = new TypeDecl( variable->name, Declaration::NoStorageClass, 0, kindMap[ variable->tyClass ] );
    897     buildList( variable->assertions, ret->get_assertions() );
    898    
    899     return ret;
     880        assert( kind == Variable );
     881        static const TypeDecl::Kind kindMap[] = { TypeDecl::Any, TypeDecl::Ftype, TypeDecl::Dtype };
     882
     883        TypeDecl *ret = new TypeDecl( variable->name, Declaration::NoStorageClass, 0, kindMap[ variable->tyClass ] );
     884        buildList( variable->assertions, ret->get_assertions() );
     885       
     886        return ret;
    900887}
    901888
    902889EnumDecl *TypeData::buildEnum() const {
    903     assert( kind == Enum );
    904     EnumDecl *ret = new EnumDecl( enumeration->name );
    905     buildList( enumeration->constants, ret->get_members() );
    906 
    907     return ret;
     890        assert( kind == Enum );
     891        EnumDecl *ret = new EnumDecl( enumeration->name );
     892        buildList( enumeration->constants, ret->get_members() );
     893
     894        return ret;
    908895}
    909896
    910897TypeInstType *TypeData::buildSymbolicInst() const {
    911     assert( kind == SymbolicInst );
    912 
    913 
    914     TypeInstType *ret = new TypeInstType( buildQualifiers(), symbolic->name, false );
    915     buildList( symbolic->actuals, ret->get_parameters() );
    916     buildForall( forall, ret->get_forall() );
    917 
    918     return ret;
     898        assert( kind == SymbolicInst );
     899        TypeInstType *ret = new TypeInstType( buildQualifiers(), symbolic->name, false );
     900        buildList( symbolic->actuals, ret->get_parameters() );
     901        buildForall( forall, ret->get_forall() );
     902
     903        return ret;
    919904}
    920905
    921906TupleType *TypeData::buildTuple() const {
    922     assert( kind == Tuple );
    923 
    924 
    925     TupleType *ret = new TupleType( buildQualifiers() );
    926     buildTypeList( tuple->members, ret->get_types() );
    927     buildForall( forall, ret->get_forall() );
    928 
    929     return ret;
     907        assert( kind == Tuple );
     908        TupleType *ret = new TupleType( buildQualifiers() );
     909        buildTypeList( tuple->members, ret->get_types() );
     910        buildForall( forall, ret->get_forall() );
     911
     912        return ret;
    930913}
    931914
    932915TypeofType *TypeData::buildTypeof() const {
    933     assert( kind == Typeof );
    934     assert( typeexpr );
    935     assert( typeexpr->expr );
    936     TypeofType *ret = new TypeofType( buildQualifiers(), typeexpr->expr->build() );
    937 
    938     return ret;
     916        assert( kind == Typeof );
     917        assert( typeexpr );
     918        assert( typeexpr->expr );
     919        TypeofType *ret = new TypeofType( buildQualifiers(), typeexpr->expr->build() );
     920
     921        return ret;
    939922}
    940923
    941924AttrType *TypeData::buildAttr() const {
    942     assert( kind == Attr );
    943     assert( attr );
    944     AttrType *ret;
    945     if ( attr->expr ) {
    946         ret = new AttrType( buildQualifiers(), attr->name, attr->expr->build() );
    947     } else {
    948         assert( attr->type );
    949         ret = new AttrType( buildQualifiers(), attr->name, attr->type->buildType() );
    950     }
    951 
    952     return ret;
    953 }
     925        assert( kind == Attr );
     926        assert( attr );
     927        AttrType *ret;
     928        if ( attr->expr ) {
     929                ret = new AttrType( buildQualifiers(), attr->name, attr->expr->build() );
     930        } else {
     931                assert( attr->type );
     932                ret = new AttrType( buildQualifiers(), attr->name, attr->type->buildType() );
     933        }
     934
     935        return ret;
     936}
     937
     938// Local Variables: //
     939// tab-width: 4 //
     940// mode: c++ //
     941// compile-command: "make install" //
     942// End: //
  • translator/Parser/TypeData.h

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// TypeData.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:18:36 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:20:00 2015
     13// Update Count     : 2
     14//
     15
    116#ifndef TYPEDATA_H
    217#define TYPEDATA_H
     
    823
    924struct TypeData {
    10     enum Kind { Unknown, Basic, Pointer, Array, Function, Aggregate, AggregateInst,
    11                 Enum, EnumConstant, Symbolic, SymbolicInst, Variable, Tuple, Typeof, Attr } kind;
     25        enum Kind { Unknown, Basic, Pointer, Array, Function, Aggregate, AggregateInst,
     26                                Enum, EnumConstant, Symbolic, SymbolicInst, Variable, Tuple, Typeof, Attr } kind;
    1227
    13     TypeData( Kind k = Unknown );
    14     ~TypeData();
    15     void print( std::ostream &, int indent = 0 ) const;
    16     TypeData *clone() const;
     28        TypeData( Kind k = Unknown );
     29        ~TypeData();
     30        void print( std::ostream &, int indent = 0 ) const;
     31        TypeData *clone() const;
    1732
    18     Type *build() const;
    19     FunctionType *buildFunction() const;
     33        Type *build() const;
     34        FunctionType *buildFunction() const;
    2035
    21     TypeData *base;
    22     std::list< DeclarationNode::Qualifier > qualifiers;
    23     DeclarationNode *forall;
     36        TypeData *base;
     37        std::list< DeclarationNode::Qualifier > qualifiers;
     38        DeclarationNode *forall;
    2439
    25     struct Basic_t {
    26         std::list< DeclarationNode::BasicType > typeSpec;
    27         std::list< DeclarationNode::Modifier > modifiers;
    28     };
     40        struct Basic_t {
     41                std::list< DeclarationNode::BasicType > typeSpec;
     42                std::list< DeclarationNode::Modifier > modifiers;
     43        };
    2944
    30     struct Aggregate_t {
    31         DeclarationNode::TyCon kind;
    32         std::string name;
    33         DeclarationNode *params;
    34         ExpressionNode *actuals;                        // holds actual parameters later applied to AggInst
    35         DeclarationNode *members;
    36     };
     45        struct Aggregate_t {
     46                DeclarationNode::TyCon kind;
     47                std::string name;
     48                DeclarationNode *params;
     49                ExpressionNode *actuals;                                                // holds actual parameters later applied to AggInst
     50                DeclarationNode *members;
     51        };
    3752
    38     struct AggInst_t {
    39         TypeData *aggregate;
    40         ExpressionNode *params;
    41     };
     53        struct AggInst_t {
     54                TypeData *aggregate;
     55                ExpressionNode *params;
     56        };
    4257
    43     struct Array_t {
    44         ExpressionNode *dimension;
    45         bool isVarLen;
    46         bool isStatic;
    47     };
     58        struct Array_t {
     59                ExpressionNode *dimension;
     60                bool isVarLen;
     61                bool isStatic;
     62        };
    4863
    49     struct Enumeration_t {
    50         std::string name;
    51         DeclarationNode *constants;
    52     };
     64        struct Enumeration_t {
     65                std::string name;
     66                DeclarationNode *constants;
     67        };
    5368
    54     struct Function_t {
    55         DeclarationNode *params;
    56         DeclarationNode *idList;                        // old-style
    57         DeclarationNode *oldDeclList;
    58         StatementNode *body;
    59         bool hasBody;
    60         bool newStyle;
    61     };
     69        struct Function_t {
     70                DeclarationNode *params;
     71                DeclarationNode *idList;                                                // old-style
     72                DeclarationNode *oldDeclList;
     73                StatementNode *body;
     74                bool hasBody;
     75                bool newStyle;
     76        };
    6277
    63     struct Symbolic_t {
    64         std::string name;
    65         bool isTypedef;
    66         DeclarationNode *params;
    67         ExpressionNode *actuals;
    68         DeclarationNode *assertions;
    69     };
     78        struct Symbolic_t {
     79                std::string name;
     80                bool isTypedef;
     81                DeclarationNode *params;
     82                ExpressionNode *actuals;
     83                DeclarationNode *assertions;
     84        };
    7085
    71     struct Variable_t {
    72         DeclarationNode::TypeClass tyClass;
    73         std::string name;
    74         DeclarationNode *assertions;
    75     };
     86        struct Variable_t {
     87                DeclarationNode::TypeClass tyClass;
     88                std::string name;
     89                DeclarationNode *assertions;
     90        };
    7691
    77     struct Tuple_t {
    78         DeclarationNode *members;
    79     };
     92        struct Tuple_t {
     93                DeclarationNode *members;
     94        };
    8095 
    81     struct Typeof_t {
    82         ExpressionNode *expr;
    83     };
     96        struct Typeof_t {
     97                ExpressionNode *expr;
     98        };
    8499
    85     struct Attr_t {
    86         std::string name;
    87         ExpressionNode *expr;
    88         DeclarationNode *type;
    89     };
     100        struct Attr_t {
     101                std::string name;
     102                ExpressionNode *expr;
     103                DeclarationNode *type;
     104        };
    90105
    91     union {
    92         Basic_t *basic;
    93         Aggregate_t *aggregate;
    94         AggInst_t *aggInst;
    95         Array_t *array;
    96         Enumeration_t *enumeration;
    97         Function_t *function;
    98         Symbolic_t *symbolic;
    99         Variable_t *variable;
    100         Tuple_t *tuple;
    101         Typeof_t *typeexpr;
    102         Attr_t *attr;
    103     };
     106        union {
     107                Basic_t *basic;
     108                Aggregate_t *aggregate;
     109                AggInst_t *aggInst;
     110                Array_t *array;
     111                Enumeration_t *enumeration;
     112                Function_t *function;
     113                Symbolic_t *symbolic;
     114                Variable_t *variable;
     115                Tuple_t *tuple;
     116                Typeof_t *typeexpr;
     117                Attr_t *attr;
     118        };
    104119
    105     TypeData *extractAggregate( bool toplevel = true ) const;
    106     // helper function for DeclNodeImpl::build
    107     Declaration * buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init = 0 ) const;
    108     // helper functions for build()
    109     Type::Qualifiers buildQualifiers() const;
    110     Type *buildBasicType() const;
    111     PointerType * buildPointer() const;
    112     ArrayType * buildArray() const;
    113     AggregateDecl * buildAggregate() const;
    114     ReferenceToType * buildAggInst() const;
    115     NamedTypeDecl * buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const;
    116     TypeDecl* buildVariable() const;
    117     EnumDecl* buildEnum() const;
    118     TypeInstType * buildSymbolicInst() const;
    119     TupleType * buildTuple() const;
    120     TypeofType * buildTypeof() const;
    121     AttrType * buildAttr() const;
     120        TypeData *extractAggregate( bool toplevel = true ) const;
     121        // helper function for DeclNodeImpl::build
     122        Declaration * buildDecl( std::string name, Declaration::StorageClass sc, Expression *bitfieldWidth, bool isInline, LinkageSpec::Type linkage, Initializer *init = 0 ) const;
     123        // helper functions for build()
     124        Type::Qualifiers buildQualifiers() const;
     125        Type *buildBasicType() const;
     126        PointerType * buildPointer() const;
     127        ArrayType * buildArray() const;
     128        AggregateDecl * buildAggregate() const;
     129        ReferenceToType * buildAggInst() const;
     130        NamedTypeDecl * buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const;
     131        TypeDecl* buildVariable() const;
     132        EnumDecl* buildEnum() const;
     133        TypeInstType * buildSymbolicInst() const;
     134        TupleType * buildTuple() const;
     135        TypeofType * buildTypeof() const;
     136        AttrType * buildAttr() const;
    122137};
    123138
    124139#endif // TYPEDATA_H
     140
     141// Local Variables: //
     142// tab-width: 4 //
     143// mode: c++ //
     144// compile-command: "make install" //
     145// End: //
  • translator/Parser/TypedefTable.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// TypedefTable.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:20:13 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:24:03 2015
     13// Update Count     : 2
     14//
     15
    116#include <map>
    217#include <list>
     
    722#if 0
    823#include <iostream>
    9 #  define debugPrint(x) cerr << x
     24#define debugPrint(x ) cerr << x
    1025#else
    11 #  define debugPrint(x)
     26#define debugPrint( x )
    1227#endif
    1328
    14 TypedefTable::TypedefTable() : currentScope(0) {}
     29TypedefTable::TypedefTable() : currentScope( 0 ) {}
    1530
    16 bool TypedefTable::isKind(string identifier, kind_t kind) const {
    17     tableType::const_iterator id_pos = table.find(identifier);
    18     if (id_pos == table.end()) {
    19         return true;
    20     } else {
    21         return (*((*id_pos).second.begin())).kind == kind;
    22     }
     31bool TypedefTable::isKind( string identifier, kind_t kind ) const {
     32        tableType::const_iterator id_pos = table.find( identifier );
     33        if ( id_pos == table.end()) {
     34                return true;
     35        } else {
     36                return (*((*id_pos ).second.begin())).kind == kind;
     37        }
    2338}
    2439
    25 bool TypedefTable::isIdentifier(string identifier) const {
    26     return isKind(identifier, ID);
     40bool TypedefTable::isIdentifier( string identifier ) const {
     41        return isKind( identifier, ID );
    2742}
    2843
    29 bool TypedefTable::isTypedef(string identifier) const {
    30     return isKind(identifier, TD);
     44bool TypedefTable::isTypedef( string identifier ) const {
     45        return isKind( identifier, TD );
    3146}
    3247
    33 bool TypedefTable::isTypegen(string identifier) const {
    34     return isKind(identifier, TG);
     48bool TypedefTable::isTypegen( string identifier ) const {
     49        return isKind( identifier, TG );
    3550}
    3651
    37 void TypedefTable::addToScope(const std::string &identifier, kind_t kind, int scope) {
    38     if ( currentContext != "" && scope == contextScope ) {
    39         DeferredEntry entry = { identifier, kind };
    40         contexts[currentContext].push_back( entry );
    41     } else {
    42         debugPrint( "Adding " << identifier << " as type " << kind << " scope " << scope << " from scope " << currentScope << endl );
    43         Entry newEntry = { scope, kind };
    44         tableType::iterator curPos = table.find(identifier);
    45         if (curPos == table.end()) {
    46             list<Entry> newList;
    47             newList.push_front(newEntry);
    48             table[identifier] = newList;
     52void TypedefTable::addToScope( const std::string &identifier, kind_t kind, int scope ) {
     53        if ( currentContext != "" && scope == contextScope ) {
     54                DeferredEntry entry = { identifier, kind };
     55                contexts[currentContext].push_back( entry );
    4956        } else {
    50             list<Entry>::iterator listPos = (*curPos).second.begin();
    51             while( listPos != (*curPos).second.end() && listPos->scope > scope ) {
    52                 listPos++;
    53             }
    54             (*curPos).second.insert(listPos, newEntry);
     57                debugPrint( "Adding " << identifier << " as type " << kind << " scope " << scope << " from scope " << currentScope << endl );
     58                Entry newEntry = { scope, kind };
     59                tableType::iterator curPos = table.find( identifier );
     60                if ( curPos == table.end()) {
     61                        list<Entry> newList;
     62                        newList.push_front( newEntry );
     63                        table[identifier] = newList;
     64                } else {
     65                        list<Entry>::iterator listPos = (*curPos ).second.begin();
     66                        while( listPos != (*curPos ).second.end() && listPos->scope > scope ) {
     67                                listPos++;
     68                        }
     69                        (*curPos ).second.insert( listPos, newEntry );
     70                }
    5571        }
    56     }
    5772}
    5873
    59 void TypedefTable::addToCurrentScope(const std::string &identifier, kind_t kind) {
    60     addToScope( identifier, kind, currentScope );
     74void TypedefTable::addToCurrentScope( const std::string &identifier, kind_t kind ) {
     75        addToScope( identifier, kind, currentScope );
    6176}
    6277
    63 void TypedefTable::addToCurrentScope(kind_t kind) {
    64     addToCurrentScope( nextIdentifiers.top(), kind );
     78void TypedefTable::addToCurrentScope( kind_t kind ) {
     79        addToCurrentScope( nextIdentifiers.top(), kind );
    6580}
    6681
    67 void TypedefTable::addToEnclosingScope(const std::string &identifier, kind_t kind) {
    68     assert( currentScope >= 1 );
    69     addToScope( identifier, kind, currentScope - 1 );
     82void TypedefTable::addToEnclosingScope( const std::string &identifier, kind_t kind ) {
     83        assert( currentScope >= 1 );
     84        addToScope( identifier, kind, currentScope - 1 );
    7085}
    7186
    72 void TypedefTable::addToEnclosingScope(kind_t kind) {
    73     addToEnclosingScope( nextIdentifiers.top(), kind );
     87void TypedefTable::addToEnclosingScope( kind_t kind ) {
     88        addToEnclosingScope( nextIdentifiers.top(), kind );
    7489}
    7590
    76 void TypedefTable::addToEnclosingScope2(const std::string &identifier, kind_t kind) {
    77     assert( currentScope >= 2 );
    78     addToScope( identifier, kind, currentScope - 2 );
     91void TypedefTable::addToEnclosingScope2( const std::string &identifier, kind_t kind ) {
     92        assert( currentScope >= 2 );
     93        addToScope( identifier, kind, currentScope - 2 );
    7994}
    8095
    81 void TypedefTable::addToEnclosingScope2(kind_t kind) {
    82     addToEnclosingScope2( nextIdentifiers.top(), kind );
     96void TypedefTable::addToEnclosingScope2( kind_t kind ) {
     97        addToEnclosingScope2( nextIdentifiers.top(), kind );
    8398}
    8499
    85100void TypedefTable::setNextIdentifier( const std::string &identifier ) {
    86     nextIdentifiers.top() = identifier;
     101        nextIdentifiers.top() = identifier;
    87102}
    88103
    89104void TypedefTable::openContext( std::string contextName ) {
    90     map< string, deferListType >::iterator i = contexts.find( contextName );
    91     if ( i != contexts.end() ) {
    92         deferListType &entries = i->second;
    93         for (deferListType::iterator i = entries.begin(); i != entries.end(); i++) {
    94             addToEnclosingScope( i->identifier, i->kind );
     105        map< string, deferListType >::iterator i = contexts.find( contextName );
     106        if ( i != contexts.end() ) {
     107                deferListType &entries = i->second;
     108                for ( deferListType::iterator i = entries.begin(); i != entries.end(); i++) {
     109                        addToEnclosingScope( i->identifier, i->kind );
     110                }
    95111        }
    96     }
    97112}
    98113
    99 void TypedefTable::enterScope(void) {
    100     currentScope += 1;
    101     deferListStack.push( deferListType() );
    102     nextIdentifiers.push( "" );
    103     debugPrint( "Entering scope " << currentScope << ", nextIdentifiers size is " << nextIdentifiers.size() << endl );
     114void TypedefTable::enterScope( void ) {
     115        currentScope += 1;
     116        deferListStack.push( deferListType() );
     117        nextIdentifiers.push( "" );
     118        debugPrint( "Entering scope " << currentScope << ", nextIdentifiers size is " << nextIdentifiers.size() << endl );
    104119}
    105120
    106 void TypedefTable::leaveScope(void) {
    107     debugPrint( "Leaving scope " << currentScope << endl );
    108     for (tableType::iterator i = table.begin(); i != table.end(); ) {
    109         list<Entry> &declList = (*i).second;
    110         while (!declList.empty() && declList.front().scope == currentScope) {
    111             declList.pop_front();
     121void TypedefTable::leaveScope( void ) {
     122        debugPrint( "Leaving scope " << currentScope << endl );
     123        for ( tableType::iterator i = table.begin(); i != table.end(); ) {
     124                list<Entry> &declList = (*i ).second;
     125                while (!declList.empty() && declList.front().scope == currentScope ) {
     126                        declList.pop_front();
     127                }
     128                if ( declList.empty() ) {                       // standard idom for erasing during traversal
     129                        table.erase( i++ );
     130                } else ++i;
    112131        }
    113         if ( declList.empty() ) {                       // standard idom for erasing during traversal
    114             table.erase( i++ );
    115         } else ++i;
    116     }
    117     currentScope -= 1;
    118     for (deferListType::iterator i = deferListStack.top().begin(); i != deferListStack.top().end(); i++) {
    119         addToCurrentScope( i->identifier, i->kind );
    120     }
    121     deferListStack.pop();
    122     debugPrint( "nextIdentifiers size is " << nextIdentifiers.size() << " top is " << nextIdentifiers.top() << endl );
    123     nextIdentifiers.pop();
     132        currentScope -= 1;
     133        for ( deferListType::iterator i = deferListStack.top().begin(); i != deferListStack.top().end(); i++) {
     134                addToCurrentScope( i->identifier, i->kind );
     135        }
     136        deferListStack.pop();
     137        debugPrint( "nextIdentifiers size is " << nextIdentifiers.size() << " top is " << nextIdentifiers.top() << endl );
     138        nextIdentifiers.pop();
    124139}
    125140
    126141void TypedefTable::enterContext( std::string contextName ) {
    127     currentContext = contextName;
    128     contextScope = currentScope;
     142        currentContext = contextName;
     143        contextScope = currentScope;
    129144}
    130145
    131 void TypedefTable::leaveContext(void) {
    132     currentContext = "";
     146void TypedefTable::leaveContext( void ) {
     147        currentContext = "";
    133148}
    134149
    135 void TypedefTable::print(void) const {
    136     for (tableType::const_iterator i = table.begin(); i != table.end(); i++) {
    137         debugPrint( (*i).first << ": " );
    138         list<Entry> declList = (*i).second;
    139         for (list<Entry>::const_iterator j = declList.begin(); j != declList.end(); j++) {
    140             debugPrint( "(" << (*j).scope << " " << (*j).kind << ") " );
     150void TypedefTable::print( void ) const {
     151        for ( tableType::const_iterator i = table.begin(); i != table.end(); i++) {
     152                debugPrint( (*i ).first << ": " );
     153                list<Entry> declList = (*i ).second;
     154                for ( list<Entry>::const_iterator j = declList.begin(); j != declList.end(); j++ ) {
     155                        debugPrint( "(" << (*j ).scope << " " << (*j).kind << ") " );
     156                }
     157                debugPrint( endl );
    141158        }
    142         debugPrint( endl );
    143     }
    144159}
     160
     161// Local Variables: //
     162// tab-width: 4 //
     163// mode: c++ //
     164// compile-command: "make install" //
     165// End: //
  • translator/Parser/TypedefTable.h

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// TypedefTable.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:24:36 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:25:59 2015
     13// Update Count     : 3
     14//
     15
    116#ifndef TYPEDEFTABLE_H
    217#define TYPEDEFTABLE_H
     
    924class TypedefTable {
    1025  public:
    11     enum kind_t { ID, TD, TG };
     26        enum kind_t { ID, TD, TG };
    1227  private:
    13     struct Entry {
    14         int scope;
    15         kind_t kind;
    16     };
    17    
    18     struct DeferredEntry {
    19         std::string identifier;
    20         kind_t kind;
    21     };
     28        struct Entry {
     29                int scope;
     30                kind_t kind;
     31        };
     32       
     33        struct DeferredEntry {
     34                std::string identifier;
     35                kind_t kind;
     36        };
    2237
    23     typedef std::map<std::string, std::list<Entry> > tableType;
    24     tableType table;
     38        typedef std::map<std::string, std::list<Entry> > tableType;
     39        tableType table;
    2540
    26     int currentScope;
    27     std::string currentContext;
    28     int contextScope;
    29    
    30     typedef std::list< DeferredEntry > deferListType;
    31     std::stack< deferListType > deferListStack;
    32     std::map< std::string, deferListType > contexts;
    33    
    34     std::stack< std::string > nextIdentifiers;
     41        int currentScope;
     42        std::string currentContext;
     43        int contextScope;
     44       
     45        typedef std::list< DeferredEntry > deferListType;
     46        std::stack< deferListType > deferListStack;
     47        std::map< std::string, deferListType > contexts;
     48       
     49        std::stack< std::string > nextIdentifiers;
    3550
    36     bool isKind( std::string identifier, kind_t kind ) const;
    37     void addToScope( const std::string &identifier, kind_t kind, int scope );
     51        bool isKind( std::string identifier, kind_t kind ) const;
     52        void addToScope( const std::string &identifier, kind_t kind, int scope );
    3853  public:
    39     TypedefTable();
     54        TypedefTable();
    4055
    41     bool isIdentifier( std::string identifier ) const;
    42     bool isTypedef( std::string identifier ) const;
    43     bool isTypegen( std::string identifier ) const;
    44    
    45     // "addToCurrentScope" adds the identifier/type pair to the current scope This does less than you think it does,
    46     // since each declaration is within its own scope.  Mostly useful for type parameters.
    47     void addToCurrentScope( const std::string &identifier, kind_t kind );
    48     void addToCurrentScope( kind_t kind );              // use nextIdentifiers.top()
     56        bool isIdentifier( std::string identifier ) const;
     57        bool isTypedef( std::string identifier ) const;
     58        bool isTypegen( std::string identifier ) const;
     59       
     60        // "addToCurrentScope" adds the identifier/type pair to the current scope This does less than you think it does,
     61        // since each declaration is within its own scope.  Mostly useful for type parameters.
     62        void addToCurrentScope( const std::string &identifier, kind_t kind );
     63        void addToCurrentScope( kind_t kind );          // use nextIdentifiers.top()
    4964
    50     // "addToEnclosingScope" adds the identifier/type pair to the scope that encloses the current one.  This is the
    51     // right way to handle type and typedef names
    52     void addToEnclosingScope( const std::string &identifier, kind_t kind );
    53     void addToEnclosingScope( kind_t kind );            // use nextIdentifiers.top()
    54    
    55     // "addToEnclosingScope2" adds the identifier/type pair to the scope that encloses the scope enclosing the the
    56     // current one.  This is the right way to handle assertion names
    57     void addToEnclosingScope2( const std::string &identifier, kind_t kind );
    58     void addToEnclosingScope2( kind_t kind );           // use nextIdentifiers.top()
    59    
    60     // set the next identifier to be used by an "add" operation without an identifier parameter within the current scope
    61     void setNextIdentifier( const std::string &identifier );
    62    
    63     // dump the definitions from a pre-defined context into the current scope
    64     void openContext( std::string contextName );
    65    
    66     void enterScope( void );
    67     void leaveScope( void );
    68     void enterContext( std::string contextName );
    69     void leaveContext( void );
     65        // "addToEnclosingScope" adds the identifier/type pair to the scope that encloses the current one.  This is the
     66        // right way to handle type and typedef names
     67        void addToEnclosingScope( const std::string &identifier, kind_t kind );
     68        void addToEnclosingScope( kind_t kind );                // use nextIdentifiers.top()
     69       
     70        // "addToEnclosingScope2" adds the identifier/type pair to the scope that encloses the scope enclosing the the
     71        // current one.  This is the right way to handle assertion names
     72        void addToEnclosingScope2( const std::string &identifier, kind_t kind );
     73        void addToEnclosingScope2( kind_t kind );               // use nextIdentifiers.top()
     74       
     75        // set the next identifier to be used by an "add" operation without an identifier parameter within the current scope
     76        void setNextIdentifier( const std::string &identifier );
     77       
     78        // dump the definitions from a pre-defined context into the current scope
     79        void openContext( std::string contextName );
     80       
     81        void enterScope();
     82        void leaveScope();
     83        void enterContext( std::string contextName );
     84        void leaveContext();
    7085
    71     void print( void ) const;
     86        void print() const;
    7287};
    7388
    7489#endif // TYPEDEFTABLE_H
     90
     91// Local Variables: //
     92// tab-width: 4 //
     93// mode: c++ //
     94// compile-command: "make install" //
     95// End: //
  • translator/Parser/cfa.y

    rb8508a2 rb87a5ed  
    1 //                              -*- Mode: C++ -*-
    2 //
    3 // CForall Grammar Version 1.0, Copyright (C) Peter A. Buhr 2001
    4 //
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
    57// cfa.y --
    68//
     
    810// Created On       : Sat Sep  1 20:22:55 2001
    911// Last Modified By : Peter A. Buhr
    10 // Last Modified On : Tue May 12 17:24:53 2015
    11 // Update Count     : 963
     12// Last Modified On : Sat May 16 11:55:39 2015
     13// Update Count     : 975
    1214//
    1315
    14 // This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on the C
    15 // grammar by James A. Roskind, specifically parts of DECLARATIONS and EXTERNAL DEFINITIONS.  While parts have been
    16 // copied, important changes have been made in all sections; these changes are sufficient to constitute a new grammar.
    17 // In particular, this grammar attempts to be more syntactically precise, i.e., it parses less incorrect language syntax
    18 // that must be subsequently rejected by semantic checks.  Nevertheless, there are still several semantic checks
    19 // required and many are noted in the grammar. Finally, the grammar is extended with GCC and CFA language extensions.
    20 
    21 // Acknowledgments to Richard Bilson, Glen Ditchfield, and Rodolfo Gabriel Esteves who all helped when I got stuck with
    22 // the grammar.
     16// This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on
     17// the C grammar by James A. Roskind, specifically parts of DECLARATIONS and EXTERNAL DEFINITIONS.  While
     18// parts have been copied, important changes have been made in all sections; these changes are sufficient to
     19// constitute a new grammar.  In particular, this grammar attempts to be more syntactically precise, i.e., it
     20// parses less incorrect language syntax that must be subsequently rejected by semantic checks.  Nevertheless,
     21// there are still several semantic checks required and many are noted in the grammar. Finally, the grammar is
     22// extended with GCC and CFA language extensions.
     23
     24// Acknowledgments to Richard Bilson, Glen Ditchfield, and Rodolfo Gabriel Esteves who all helped when I got
     25// stuck with the grammar.
    2326
    2427// The root language for this grammar is ANSI99/11 C. All of ANSI99/11 is parsed, except for:
     
    2629// 1. designation with '=' (use ':' instead)
    2730//
    28 // Most of the syntactic extensions from ANSI90 to ANSI11 C are marked with the comment "C99/C11". This grammar also has
    29 // two levels of extensions. The first extensions cover most of the GCC C extensions, except for:
     31// Most of the syntactic extensions from ANSI90 to ANSI11 C are marked with the comment "C99/C11". This
     32// grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions, except for:
    3033//
    3134// 1. nested functions
     
    3437// 4. attributes not allowed in parenthesis of declarator
    3538//
    36 // All of the syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall
    37 // (CFA), which fixes several of C's outstanding problems and extends C with many modern language concepts. All of the
    38 // syntactic extensions for CFA C are marked with the comment "CFA". As noted above, there is one unreconcileable
    39 // parsing problem between C99 and CFA with respect to designators; this is discussed in detail before the "designation"
    40 // grammar rule.
     39// All of the syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for
     40// Cforall (CFA), which fixes several of C's outstanding problems and extends C with many modern language
     41// concepts. All of the syntactic extensions for CFA C are marked with the comment "CFA". As noted above,
     42// there is one unreconcileable parsing problem between C99 and CFA with respect to designators; this is
     43// discussed in detail before the "designation" grammar rule.
    4144
    4245%{
    43 #define YYDEBUG_LEXER_TEXT (yylval)                     // lexer loads this up each time
    44 #define YYDEBUG 1                                       // get the pretty debugging code to compile
     46#define YYDEBUG_LEXER_TEXT (yylval)                                             // lexer loads this up each time
     47#define YYDEBUG 1                                                                               // get the pretty debugging code to compile
    4548
    4649#undef __GNUC_MINOR__
     
    5356#include "LinkageSpec.h"
    5457
    55 DeclarationNode *theTree = 0;                           // the resulting parse tree
     58DeclarationNode *theTree = 0;                                                   // the resulting parse tree
    5659LinkageSpec::Type linkage = LinkageSpec::Cforall;
    5760std::stack< LinkageSpec::Type > linkageStack;
     
    6467%token TYPEDEF
    6568%token AUTO EXTERN REGISTER STATIC
    66 %token INLINE                                           // C99
    67 %token FORTRAN                                          // C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
     69%token INLINE                                                                                   // C99
     70%token FORTRAN                                                                                  // C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
    6871%token CONST VOLATILE
    69 %token RESTRICT                                         // C99
    70 %token FORALL LVALUE                                    // CFA
     72%token RESTRICT                                                                                 // C99
     73%token FORALL LVALUE                                                                    // CFA
    7174%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
    72 %token BOOL COMPLEX IMAGINARY                           // C99
    73 %token TYPEOF LABEL                                     // GCC
     75%token BOOL COMPLEX IMAGINARY                                                   // C99
     76%token TYPEOF LABEL                                                                             // GCC
    7477%token ENUM STRUCT UNION
    75 %token TYPE FTYPE DTYPE CONTEXT                         // CFA
     78%token TYPE FTYPE DTYPE CONTEXT                                                 // CFA
    7679%token SIZEOF
    77 %token ATTRIBUTE EXTENSION                              // GCC
     80%token ATTRIBUTE EXTENSION                                                              // GCC
    7881%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
    79 %token CHOOSE FALLTHRU TRY CATCH FINALLY THROW          // CFA
    80 %token ASM                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
     82%token CHOOSE FALLTHRU TRY CATCH FINALLY THROW                  // CFA
     83%token ASM                                                                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
    8184%token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATICASSERT THREADLOCAL // C11
    8285
    8386// names and constants: lexer differentiates between identifier and typedef names
    84 %token<tok> IDENTIFIER          QUOTED_IDENTIFIER       TYPEDEFname             TYPEGENname
    85 %token<tok> ATTR_IDENTIFIER     ATTR_TYPEDEFname        ATTR_TYPEGENname
    86 %token<tok> INTEGERconstant     FLOATINGconstant        CHARACTERconstant       STRINGliteral
    87 %token<tok> ZERO                ONE                     // CFA
     87%token<tok> IDENTIFIER                  QUOTED_IDENTIFIER               TYPEDEFname                             TYPEGENname
     88%token<tok> ATTR_IDENTIFIER             ATTR_TYPEDEFname                ATTR_TYPEGENname
     89%token<tok> INTEGERconstant             FLOATINGconstant                CHARACTERconstant               STRINGliteral
     90%token<tok> ZERO                                ONE                                             // CFA
    8891
    8992// multi-character operators
    90 %token ARROW                    /* ->                           */
    91 %token ICR DECR                 /* ++   --                      */
    92 %token LS RS                    /* <<   >>                      */
    93 %token LE GE EQ NE              /* <=   >=      ==      !=      */
    94 %token ANDAND OROR              /* &&   ||                      */
    95 %token ELLIPSIS                 /* ...                          */
    96 
    97 %token MULTassign       DIVassign       MODassign       /* *=   /=      %=      */
    98 %token PLUSassign       MINUSassign                     /* +=   -=              */
    99 %token LSassign         RSassign                        /* <<=  >>=             */
    100 %token ANDassign        ERassign        ORassign        /* &=   ^=      |=      */
     93%token ARROW                                                                                    // ->
     94%token ICR DECR                                                                                 // ++   --
     95%token LS RS                                                                                    // <<   >>
     96%token LE GE EQ NE                                                                              // <=   >=      ==      !=
     97%token ANDAND OROR                                                                              // &&   ||
     98%token ELLIPSIS                                                                                 // ...
     99
     100%token MULTassign       DIVassign       MODassign                               // *=   /=      %=/
     101%token PLUSassign       MINUSassign                                                     // +=   -=
     102%token LSassign         RSassign                                                        // <<=  >>=
     103%token ANDassign        ERassign        ORassign                                // &=   ^=      |=
    101104
    102105// Types declaration
    103106%union
    104107{
    105     Token tok;
    106     ParseNode *pn;
    107     ExpressionNode *en;
    108     DeclarationNode *decl;
    109     DeclarationNode::TyCon aggKey;
    110     DeclarationNode::TypeClass tclass;
    111     StatementNode *sn;
    112     ConstantNode *constant;
    113     InitializerNode *in;
     108        Token tok;
     109        ParseNode *pn;
     110        ExpressionNode *en;
     111        DeclarationNode *decl;
     112        DeclarationNode::TyCon aggKey;
     113        DeclarationNode::TypeClass tclass;
     114        StatementNode *sn;
     115        ConstantNode *constant;
     116        InitializerNode *in;
    114117}
    115118
     
    120123// expressions
    121124%type<constant> constant
    122 %type<en> tuple                         tuple_expression_list
    123 %type<en> unary_operator                assignment_operator
    124 %type<en> primary_expression            postfix_expression              unary_expression
    125 %type<en> cast_expression               multiplicative_expression       additive_expression     shift_expression
    126 %type<en> relational_expression         equality_expression             AND_expression          exclusive_OR_expression
    127 %type<en> inclusive_OR_expression       logical_AND_expression          logical_OR_expression   conditional_expression
    128 %type<en> constant_expression           assignment_expression           assignment_expression_opt
    129 %type<en> comma_expression              comma_expression_opt
    130 %type<en> argument_expression_list      argument_expression             for_control_expression  assignment_opt
     125%type<en> tuple                                                 tuple_expression_list
     126%type<en> unary_operator                                assignment_operator
     127%type<en> primary_expression                    postfix_expression                      unary_expression
     128%type<en> cast_expression                               multiplicative_expression       additive_expression                     shift_expression
     129%type<en> relational_expression                 equality_expression                     AND_expression                          exclusive_OR_expression
     130%type<en> inclusive_OR_expression               logical_AND_expression          logical_OR_expression           conditional_expression
     131%type<en> constant_expression                   assignment_expression           assignment_expression_opt
     132%type<en> comma_expression                              comma_expression_opt
     133%type<en> argument_expression_list              argument_expression                     for_control_expression          assignment_opt
    131134%type<en> subrange
    132135
    133136// statements
    134 %type<sn> labeled_statement     compound_statement      expression_statement    selection_statement
    135 %type<sn> iteration_statement   jump_statement          exception_statement     asm_statement
    136 %type<sn> fall_through_opt      fall_through
    137 %type<sn> statement             statement_list
    138 %type<sn> block_item_list       block_item
     137%type<sn> labeled_statement                             compound_statement                      expression_statement            selection_statement
     138%type<sn> iteration_statement                   jump_statement                          exception_statement                     asm_statement
     139%type<sn> fall_through_opt                              fall_through
     140%type<sn> statement                                             statement_list
     141%type<sn> block_item_list                               block_item
    139142%type<sn> case_clause
    140 %type<en> case_value            case_value_list
    141 %type<sn> case_label            case_label_list
    142 %type<sn> switch_clause_list_opt switch_clause_list     choose_clause_list_opt  choose_clause_list
    143 %type<pn> handler_list          handler_clause          finally_clause
     143%type<en> case_value                                    case_value_list
     144%type<sn> case_label                                    case_label_list
     145%type<sn> switch_clause_list_opt                switch_clause_list                      choose_clause_list_opt          choose_clause_list
     146%type<pn> handler_list                                  handler_clause                          finally_clause
    144147
    145148// declarations
     
    232235
    233236
    234 // Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string is
    235 // ambiguous:
    236 // .---------.                  matches IF '(' comma_expression ')' statement
     237// Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string
     238// is ambiguous:
     239// .---------.                          matches IF '(' comma_expression ')' statement
    237240// if ( C ) S1 else S2
    238 // `-----------------'  matches IF '(' comma_expression ')' statement ELSE statement */
     241// `-----------------'          matches IF '(' comma_expression ')' statement ELSE statement */
    239242
    240243%nonassoc THEN  // rule precedence for IF '(' comma_expression ')' statement
    241244%nonassoc ELSE  // token precedence for start of else clause in IF statement
    242245
    243 %start translation_unit                                 // parse-tree root
     246%start translation_unit                                                                 // parse-tree root
    244247
    245248%%
    246249//************************* Namespace Management ********************************
    247250
    248 // The grammar in the ANSI C standard is not strictly context-free, since it relies upon the distinct terminal symbols
    249 // "identifier" and "TYPEDEFname" that are lexically identical.  While it is possible to write a purely context-free
    250 // grammar, such a grammar would obscure the relationship between syntactic and semantic constructs.  Hence, this
    251 // grammar uses the ANSI style.
    252 //
    253 // Cforall compounds this problem by introducing type names local to the scope of a declaration (for instance, those
    254 // introduced through "forall" qualifiers), and by introducing "type generators" -- parametrized types.  This latter
    255 // type name creates a third class of identifiers that must be distinguished by the scanner.
    256 //
    257 // Since the scanner cannot distinguish among the different classes of identifiers without some context information, it
    258 // accesses a data structure (the TypedefTable) to allow classification of an identifier that it has just read.
    259 // Semantic actions during the parser update this data structure when the class of identifiers change.
    260 //
    261 // Because the Cforall language is block-scoped, there is the possibility that an identifier can change its class in a
    262 // local scope; it must revert to its original class at the end of the block.  Since type names can be local to a
    263 // particular declaration, each declaration is itself a scope.  This requires distinguishing between type names that are
    264 // local to the current declaration scope and those that persist past the end of the declaration (i.e., names defined in
    265 // "typedef" or "type" declarations).
    266 //
    267 // The non-terminals "push" and "pop" derive the empty string; their only use is to denote the opening and closing of
    268 // scopes.  Every push must have a matching pop, although it is regrettable the matching pairs do not always occur
    269 // within the same rule.  These non-terminals may appear in more contexts than strictly necessary from a semantic point
    270 // of view.  Unfortunately, these extra rules are necessary to prevent parsing conflicts -- the parser may not have
    271 // enough context and look-ahead information to decide whether a new scope is necessary, so the effect of these extra
    272 // rules is to open a new scope unconditionally.  As the grammar evolves, it may be neccesary to add or move around
    273 // "push" and "pop" nonterminals to resolve conflicts of this sort.
     251// The grammar in the ANSI C standard is not strictly context-free, since it relies upon the distinct terminal
     252// symbols "identifier" and "TYPEDEFname" that are lexically identical.  While it is possible to write a
     253// purely context-free grammar, such a grammar would obscure the relationship between syntactic and semantic
     254// constructs.  Hence, this grammar uses the ANSI style.
     255//
     256// Cforall compounds this problem by introducing type names local to the scope of a declaration (for instance,
     257// those introduced through "forall" qualifiers), and by introducing "type generators" -- parametrized types.
     258// This latter type name creates a third class of identifiers that must be distinguished by the scanner.
     259//
     260// Since the scanner cannot distinguish among the different classes of identifiers without some context
     261// information, it accesses a data structure (the TypedefTable) to allow classification of an identifier that
     262// it has just read.  Semantic actions during the parser update this data structure when the class of
     263// identifiers change.
     264//
     265// Because the Cforall language is block-scoped, there is the possibility that an identifier can change its
     266// class in a local scope; it must revert to its original class at the end of the block.  Since type names can
     267// be local to a particular declaration, each declaration is itself a scope.  This requires distinguishing
     268// between type names that are local to the current declaration scope and those that persist past the end of
     269// the declaration (i.e., names defined in "typedef" or "type" declarations).
     270//
     271// The non-terminals "push" and "pop" derive the empty string; their only use is to denote the opening and
     272// closing of scopes.  Every push must have a matching pop, although it is regrettable the matching pairs do
     273// not always occur within the same rule.  These non-terminals may appear in more contexts than strictly
     274// necessary from a semantic point of view.  Unfortunately, these extra rules are necessary to prevent parsing
     275// conflicts -- the parser may not have enough context and look-ahead information to decide whether a new
     276// scope is necessary, so the effect of these extra rules is to open a new scope unconditionally.  As the
     277// grammar evolves, it may be neccesary to add or move around "push" and "pop" nonterminals to resolve
     278// conflicts of this sort.
    274279
    275280push:
    276                 {
    277                     typedefTable.enterScope();
    278                 }
    279         ;
     281                                {
     282                                        typedefTable.enterScope();
     283                                }
     284                ;
    280285
    281286pop:
    282                 {
    283                     typedefTable.leaveScope();
    284                 }
    285         ;
     287                                {
     288                                        typedefTable.leaveScope();
     289                                }
     290                ;
    286291
    287292//************************* CONSTANTS ********************************
    288293
    289294constant:
    290                 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration
    291                 // constant".
    292         INTEGERconstant                                 { $$ = new ConstantNode(ConstantNode::Integer,  $1); }
    293         | FLOATINGconstant                              { $$ = new ConstantNode(ConstantNode::Float,    $1); }
    294         | CHARACTERconstant                             { $$ = new ConstantNode(ConstantNode::Character, $1); }
    295         ;
     295                                // ENUMERATIONconstant is not included here; it is treated as a variable with type
     296                                // "enumeration constant".
     297                INTEGERconstant                                                                 { $$ = new ConstantNode(ConstantNode::Integer, $1); }
     298                | FLOATINGconstant                                                              { $$ = new ConstantNode(ConstantNode::Float, $1); }
     299                | CHARACTERconstant                                                             { $$ = new ConstantNode(ConstantNode::Character, $1); }
     300                ;
    296301
    297302identifier:
    298         IDENTIFIER
    299         | ATTR_IDENTIFIER                               // CFA
    300         | zero_one                                      // CFA
    301         ;
     303                IDENTIFIER
     304                | ATTR_IDENTIFIER                                                               // CFA
     305                | zero_one                                                                              // CFA
     306                ;
    302307
    303308no_01_identifier:
    304         IDENTIFIER
    305         | ATTR_IDENTIFIER                               // CFA
    306         ;
     309                IDENTIFIER
     310                | ATTR_IDENTIFIER                                                               // CFA
     311                ;
    307312
    308313no_attr_identifier:
    309         IDENTIFIER
    310         ;
    311 
    312 zero_one:                                               // CFA
    313         ZERO
    314         | ONE
    315         ;
    316 
    317 string_literal_list:                                    // juxtaposed strings are concatenated
    318         STRINGliteral                                   { $$ = new ConstantNode(ConstantNode::String, $1); }
    319         | string_literal_list STRINGliteral             { $$ = $1->append( $2 ); }
    320         ;
     314                IDENTIFIER
     315                ;
     316
     317zero_one:                                                                                               // CFA
     318                ZERO
     319                | ONE
     320                ;
     321
     322string_literal_list:                                                                    // juxtaposed strings are concatenated
     323                STRINGliteral                                                                   { $$ = new ConstantNode(ConstantNode::String, $1); }
     324                | string_literal_list STRINGliteral                             { $$ = $1->append( $2 ); }
     325                ;
    321326
    322327//************************* EXPRESSIONS ********************************
    323328
    324329primary_expression:
    325         IDENTIFIER                                      // typedef name cannot be used as a variable name
    326                 { $$ = new VarRefNode($1); }
    327         | zero_one
    328                 { $$ = new VarRefNode($1); }
    329         | constant
    330                 { $$ = $1; }
    331         | string_literal_list
    332                 { $$ = $1; }
    333         | '(' comma_expression ')'
    334                 { $$ = $2; }
    335         | '(' compound_statement ')'                    // GCC, lambda expression
    336                 { $$ = new ValofExprNode($2); }
    337         ;
     330                IDENTIFIER                                                                              // typedef name cannot be used as a variable name
     331                                { $$ = new VarRefNode($1); }
     332                | zero_one
     333                                { $$ = new VarRefNode($1); }
     334                | constant
     335                                { $$ = $1; }
     336                | string_literal_list
     337                                { $$ = $1; }
     338                | '(' comma_expression ')'
     339                                { $$ = $2; }
     340                | '(' compound_statement ')'                                    // GCC, lambda expression
     341                                { $$ = new ValofExprNode($2); }
     342                ;
    338343
    339344postfix_expression:
    340         primary_expression
    341         | postfix_expression '[' push assignment_expression pop ']'
    342                 // CFA, comma_expression disallowed in the context because it results in a commom user error:
    343                 // subscripting a matrix with x[i,j] instead of x[i][j]. While this change is not backwards
    344                 // compatible, there seems to be little advantage to this feature and many disadvantages. It is
    345                 // possible to write x[(i,j)] in CFA, which is equivalent to the old x[i,j].
    346                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Index), $1, $4); }
    347         | postfix_expression '(' argument_expression_list ')'
    348                 { $$ = new CompositeExprNode($1, $3); }
    349         | postfix_expression '.' no_attr_identifier
    350                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), $1, new VarRefNode($3)); }
    351         | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
    352         | postfix_expression ARROW no_attr_identifier
    353                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), $1, new VarRefNode($3)); }
    354         | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
    355         | postfix_expression ICR
    356                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::IncrPost), $1); }
    357         | postfix_expression DECR
    358                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::DecrPost), $1); }
    359                 // GCC has priority: cast_expression
    360         | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99
    361                 { $$ = 0; }
    362         ;
     345                primary_expression
     346                | postfix_expression '[' push assignment_expression pop ']'
     347                                // CFA, comma_expression disallowed in the context because it results in a commom user error:
     348                                // subscripting a matrix with x[i,j] instead of x[i][j]. While this change is not backwards
     349                                // compatible, there seems to be little advantage to this feature and many disadvantages. It
     350                                // is possible to write x[(i,j)] in CFA, which is equivalent to the old x[i,j].
     351                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Index), $1, $4); }
     352                | postfix_expression '(' argument_expression_list ')'
     353                                { $$ = new CompositeExprNode($1, $3); }
     354                | postfix_expression '.' no_attr_identifier
     355                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), $1, new VarRefNode($3)); }
     356                | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
     357                | postfix_expression ARROW no_attr_identifier
     358                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), $1, new VarRefNode($3)); }
     359                | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
     360                | postfix_expression ICR
     361                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::IncrPost), $1); }
     362                | postfix_expression DECR
     363                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::DecrPost), $1); }
     364                                // GCC has priority: cast_expression
     365                | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99
     366                                { $$ = 0; }
     367                ;
    363368
    364369argument_expression_list:
    365         argument_expression
    366         | argument_expression_list ',' argument_expression
    367                                                         { $$ = (ExpressionNode *)($1->set_link($3)); }
    368         ;
     370                argument_expression
     371                | argument_expression_list ',' argument_expression
     372                                { $$ = (ExpressionNode *)($1->set_link($3)); }
     373                ;
    369374
    370375argument_expression:
    371         // empty
    372                 { $$ = 0; }                             // use default argument
    373         | assignment_expression
    374         | no_attr_identifier ':' assignment_expression
    375                                                         { $$ = $3->set_asArgName($1); }
    376                 // Only a list of no_attr_identifier_or_typedef_name is allowed in this context. However, there is
    377                 // insufficient look ahead to distinguish between this list of parameter names and a tuple, so the
    378                 // tuple form must be used with an appropriate semantic check.
    379         | '[' push assignment_expression pop ']' ':' assignment_expression
    380                                                         { $$ = $7->set_asArgName($3); }
    381         | '[' push assignment_expression ',' tuple_expression_list pop ']' ':' assignment_expression
    382                                                         { $$ = $9->set_asArgName(new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 )))); }
    383         ;
    384 
    385 field_list:                                             // CFA, tuple field selector
    386         field
    387         | field_list ',' field                          { $$ = (ExpressionNode *)$1->set_link( $3 ); }
    388         ;
    389 
    390 field:                                                  // CFA, tuple field selector
    391         no_attr_identifier
    392                                                         { $$ = new VarRefNode( $1 ); }
    393         | no_attr_identifier '.' field
    394                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $3); }
    395         | no_attr_identifier '.' '[' push field_list pop ']'
    396                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $5); }
    397         | no_attr_identifier ARROW field
    398                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $3); }
    399         | no_attr_identifier ARROW '[' push field_list pop ']'
    400                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $5); }
    401         ;
     376                // empty
     377                                { $$ = 0; }                                                             // use default argument
     378                | assignment_expression
     379                | no_attr_identifier ':' assignment_expression
     380                                { $$ = $3->set_asArgName($1); }
     381                                // Only a list of no_attr_identifier_or_typedef_name is allowed in this context. However,
     382                                // there is insufficient look ahead to distinguish between this list of parameter names and a
     383                                // tuple, so the tuple form must be used with an appropriate semantic check.
     384                | '[' push assignment_expression pop ']' ':' assignment_expression
     385                                { $$ = $7->set_asArgName($3); }
     386                | '[' push assignment_expression ',' tuple_expression_list pop ']' ':' assignment_expression
     387                                { $$ = $9->set_asArgName(new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 )))); }
     388                ;
     389
     390field_list:                                                                                             // CFA, tuple field selector
     391                field
     392                | field_list ',' field                                                  { $$ = (ExpressionNode *)$1->set_link( $3 ); }
     393                ;
     394
     395field:                                                                                                  // CFA, tuple field selector
     396                no_attr_identifier
     397                                { $$ = new VarRefNode( $1 ); }
     398                | no_attr_identifier '.' field
     399                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $3); }
     400                | no_attr_identifier '.' '[' push field_list pop ']'
     401                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $5); }
     402                | no_attr_identifier ARROW field
     403                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $3); }
     404                | no_attr_identifier ARROW '[' push field_list pop ']'
     405                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $5); }
     406                ;
    402407
    403408unary_expression:
    404         postfix_expression
    405         | ICR unary_expression
    406                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Incr), $2); }
    407         | DECR unary_expression
    408                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Decr), $2); }
    409         | EXTENSION cast_expression                     // GCC
    410                 { $$ = $2; }
    411         | unary_operator cast_expression
    412                 { $$ = new CompositeExprNode($1, $2); }
    413         | '!' cast_expression
    414                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neg), $2); }
    415         | '*' cast_expression                           // CFA
    416                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PointTo), $2); }
    417                 // '*' is is separated from unary_operator because of shift/reduce conflict in:
    418                 //      { * X; } // dereference X
    419                 //      { * int X; } // CFA declaration of pointer to int
    420                 // '&' must be moved here if C++ reference variables are supported.
    421         | SIZEOF unary_expression
    422                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), $2); }
    423         | SIZEOF '(' type_name_no_function ')'
    424                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), new TypeValueNode($3)); }
    425         | ATTR_IDENTIFIER
    426                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1)); }
    427         | ATTR_IDENTIFIER '(' type_name ')'
    428                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), new TypeValueNode($3)); }
    429         | ATTR_IDENTIFIER '(' argument_expression ')'
    430                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), $3); }
    431         | ALIGNOF unary_expression                      // GCC, variable alignment
    432                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), $2); }
    433         | ALIGNOF '(' type_name_no_function ')'         // GCC, type alignment
    434                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), new TypeValueNode($3)); }
    435         | ANDAND no_attr_identifier                     // GCC, address of label
    436                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LabelAddress), new VarRefNode($2, true)); }
    437         ;
     409                postfix_expression
     410                | ICR unary_expression
     411                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Incr), $2); }
     412                | DECR unary_expression
     413                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Decr), $2); }
     414                | EXTENSION cast_expression                                             // GCC
     415                                { $$ = $2; }
     416                | unary_operator cast_expression
     417                                { $$ = new CompositeExprNode($1, $2); }
     418                | '!' cast_expression
     419                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neg), $2); }
     420                | '*' cast_expression                                                   // CFA
     421                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PointTo), $2); }
     422                                // '*' is is separated from unary_operator because of shift/reduce conflict in:
     423                                //              { * X; } // dereference X
     424                                //              { * int X; } // CFA declaration of pointer to int
     425                                // '&' must be moved here if C++ reference variables are supported.
     426                | SIZEOF unary_expression
     427                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), $2); }
     428                | SIZEOF '(' type_name_no_function ')'
     429                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), new TypeValueNode($3)); }
     430                | ATTR_IDENTIFIER
     431                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1)); }
     432                | ATTR_IDENTIFIER '(' type_name ')'
     433                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), new TypeValueNode($3)); }
     434                | ATTR_IDENTIFIER '(' argument_expression ')'
     435                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), $3); }
     436                | ALIGNOF unary_expression                                              // GCC, variable alignment
     437                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), $2); }
     438                | ALIGNOF '(' type_name_no_function ')'                 // GCC, type alignment
     439                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), new TypeValueNode($3)); }
     440                | ANDAND no_attr_identifier                                             // GCC, address of label
     441                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LabelAddress), new VarRefNode($2, true)); }
     442                ;
    438443
    439444unary_operator:
    440         '&'                                             { $$ = new OperatorNode(OperatorNode::AddressOf); }
    441         | '+'                                           { $$ = new OperatorNode(OperatorNode::UnPlus); }
    442         | '-'                                           { $$ = new OperatorNode(OperatorNode::UnMinus); }
    443         | '~'                                           { $$ = new OperatorNode(OperatorNode::BitNeg); }
    444         ;
     445                '&'                                                                                             { $$ = new OperatorNode(OperatorNode::AddressOf); }
     446                | '+'                                                                                   { $$ = new OperatorNode(OperatorNode::UnPlus); }
     447                | '-'                                                                                   { $$ = new OperatorNode(OperatorNode::UnMinus); }
     448                | '~'                                                                                   { $$ = new OperatorNode(OperatorNode::BitNeg); }
     449                ;
    445450
    446451cast_expression:
    447         unary_expression
    448         | '(' type_name_no_function ')' cast_expression
    449                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
    450         | '(' type_name_no_function ')' tuple
    451                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
    452         ;
     452                unary_expression
     453                | '(' type_name_no_function ')' cast_expression
     454                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
     455                | '(' type_name_no_function ')' tuple
     456                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
     457                ;
    453458
    454459multiplicative_expression:
    455         cast_expression
    456         | multiplicative_expression '*' cast_expression
    457                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mul),$1,$3); }
    458         | multiplicative_expression '/' cast_expression
    459                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Div),$1,$3); }
    460         | multiplicative_expression '%' cast_expression
    461                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mod),$1,$3); }
    462         ;
     460                cast_expression
     461                | multiplicative_expression '*' cast_expression
     462                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mul),$1,$3); }
     463                | multiplicative_expression '/' cast_expression
     464                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Div),$1,$3); }
     465                | multiplicative_expression '%' cast_expression
     466                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mod),$1,$3); }
     467                ;
    463468
    464469additive_expression:
    465         multiplicative_expression
    466         | additive_expression '+' multiplicative_expression
    467                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Plus),$1,$3); }
    468         | additive_expression '-' multiplicative_expression
    469                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Minus),$1,$3); }
    470         ;
     470                multiplicative_expression
     471                | additive_expression '+' multiplicative_expression
     472                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Plus),$1,$3); }
     473                | additive_expression '-' multiplicative_expression
     474                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Minus),$1,$3); }
     475                ;
    471476
    472477shift_expression:
    473         additive_expression
    474         | shift_expression LS additive_expression
    475                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LShift),$1,$3); }
    476         | shift_expression RS additive_expression
    477                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::RShift),$1,$3); }
    478         ;
     478                additive_expression
     479                | shift_expression LS additive_expression
     480                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LShift),$1,$3); }
     481                | shift_expression RS additive_expression
     482                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::RShift),$1,$3); }
     483                ;
    479484
    480485relational_expression:
    481         shift_expression
    482         | relational_expression '<' shift_expression
    483                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LThan),$1,$3); }
    484         | relational_expression '>' shift_expression
    485                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GThan),$1,$3); }
    486         | relational_expression LE shift_expression
    487                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LEThan),$1,$3); }
    488         | relational_expression GE shift_expression
    489                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GEThan),$1,$3); }
    490         ;
     486                shift_expression
     487                | relational_expression '<' shift_expression
     488                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LThan),$1,$3); }
     489                | relational_expression '>' shift_expression
     490                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GThan),$1,$3); }
     491                | relational_expression LE shift_expression
     492                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LEThan),$1,$3); }
     493                | relational_expression GE shift_expression
     494                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GEThan),$1,$3); }
     495                ;
    491496
    492497equality_expression:
    493         relational_expression
    494         | equality_expression EQ relational_expression
    495                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Eq), $1, $3); }
    496         | equality_expression NE relational_expression
    497                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neq), $1, $3); }
    498         ;
     498                relational_expression
     499                | equality_expression EQ relational_expression
     500                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Eq), $1, $3); }
     501                | equality_expression NE relational_expression
     502                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neq), $1, $3); }
     503                ;
    499504
    500505AND_expression:
    501         equality_expression
    502         | AND_expression '&' equality_expression
    503                                                 { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::BitAnd), $1, $3); }
    504         ;
     506                equality_expression
     507                | AND_expression '&' equality_expression
     508                                { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::BitAnd), $1, $3); }
     509                ;
    505510
    506511exclusive_OR_expression:
    507         AND_expression
    508         | exclusive_OR_expression '^' AND_expression
    509                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Xor), $1, $3); }
    510         ;
     512                AND_expression
     513                | exclusive_OR_expression '^' AND_expression
     514                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Xor), $1, $3); }
     515                ;
    511516
    512517inclusive_OR_expression:
    513         exclusive_OR_expression
    514         | inclusive_OR_expression '|' exclusive_OR_expression
    515                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::BitOr), $1, $3); }
    516         ;
     518                exclusive_OR_expression
     519                | inclusive_OR_expression '|' exclusive_OR_expression
     520                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::BitOr), $1, $3); }
     521                ;
    517522
    518523logical_AND_expression:
    519         inclusive_OR_expression
    520         | logical_AND_expression ANDAND inclusive_OR_expression
    521                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::And), $1, $3); }
    522         ;
     524                inclusive_OR_expression
     525                | logical_AND_expression ANDAND inclusive_OR_expression
     526                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::And), $1, $3); }
     527                ;
    523528
    524529logical_OR_expression:
    525         logical_AND_expression
    526         | logical_OR_expression OROR logical_AND_expression
    527                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Or), $1, $3); }
    528         ;
     530                logical_AND_expression
     531                | logical_OR_expression OROR logical_AND_expression
     532                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Or), $1, $3); }
     533                ;
    529534
    530535conditional_expression:
    531         logical_OR_expression
    532         | logical_OR_expression '?' comma_expression ':' conditional_expression
    533                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond),
    534                                                                        (ExpressionNode *)mkList((*$1,*$3,*$5))); }
    535         | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
    536                                                 { $$=new CompositeExprNode(new OperatorNode(OperatorNode::NCond),$1,$4); }
    537         | logical_OR_expression '?' comma_expression ':' tuple // CFA, tuple expression
    538                                                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond),
    539                                                                        (ExpressionNode *)mkList(( *$1, *$3, *$5 ))); }
    540         ;
     536                logical_OR_expression
     537                | logical_OR_expression '?' comma_expression ':' conditional_expression
     538                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond), (ExpressionNode *)mkList((*$1,*$3,*$5))); }
     539                | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
     540                                { $$=new CompositeExprNode(new OperatorNode(OperatorNode::NCond),$1,$4); }
     541                | logical_OR_expression '?' comma_expression ':' tuple // CFA, tuple expression
     542                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond), (ExpressionNode *)mkList(( *$1, *$3, *$5 ))); }
     543                ;
    541544
    542545constant_expression:
    543         conditional_expression
    544         ;
     546                conditional_expression
     547                ;
    545548
    546549assignment_expression:
    547                 // CFA, assignment is separated from assignment_operator to ensure no assignment operations for tuples
    548         conditional_expression
    549         | unary_expression '=' assignment_expression
    550                                                         { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::Assign), $1, $3); }
    551         | unary_expression assignment_operator assignment_expression
    552                                                         { $$ =new CompositeExprNode($2, $1, $3); }
    553         | tuple assignment_opt                          // CFA, tuple expression
    554                 {
    555                   if ( $2 == 0 ) {
    556                     $$ = $1;
    557                   } else {
    558                     $$ = new CompositeExprNode( new OperatorNode( OperatorNode::Assign ), $1, $2 );
    559                   }
    560                 }
    561         ;
     550                                // CFA, assignment is separated from assignment_operator to ensure no assignment operations
     551                                // for tuples
     552                conditional_expression
     553                | unary_expression '=' assignment_expression
     554                                { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::Assign), $1, $3); }
     555                | unary_expression assignment_operator assignment_expression
     556                                { $$ =new CompositeExprNode($2, $1, $3); }
     557                | tuple assignment_opt                                                  // CFA, tuple expression
     558                                { $$ = ($2 == 0) ? $1 : new CompositeExprNode( new OperatorNode( OperatorNode::Assign ), $1, $2 ); }
     559                ;
    562560
    563561assignment_expression_opt:
    564         // empty
    565                 { $$ = new NullExprNode; }
    566         | assignment_expression
    567         ;
    568 
    569 tuple:                                                  // CFA, tuple
    570                 // CFA, one assignment_expression is factored out of comma_expression to eliminate a shift/reduce
    571                 // conflict with comma_expression in new_identifier_parameter_array and new_abstract_array
    572         '[' push pop ']'
    573                 { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ) ); }
    574         | '[' push assignment_expression pop ']'
    575                 { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), $3 ); }
    576         | '[' push ',' tuple_expression_list pop ']'
    577                 { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(new NullExprNode)->set_link( $4 ) ); }
    578         | '[' push assignment_expression ',' tuple_expression_list pop ']'
    579                 { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 ) ) ); }
    580         ;
     562                // empty
     563                                { $$ = new NullExprNode; }
     564                | assignment_expression
     565                ;
     566
     567tuple:                                                                                                  // CFA, tuple
     568                                // CFA, one assignment_expression is factored out of comma_expression to eliminate a
     569                                // shift/reduce conflict with comma_expression in new_identifier_parameter_array and
     570                                // new_abstract_array
     571                '[' push pop ']'
     572                                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ) ); }
     573                | '[' push assignment_expression pop ']'
     574                                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), $3 ); }
     575                | '[' push ',' tuple_expression_list pop ']'
     576                                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(new NullExprNode)->set_link( $4 ) ); }
     577                | '[' push assignment_expression ',' tuple_expression_list pop ']'
     578                                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 ) ) ); }
     579                ;
    581580
    582581tuple_expression_list:
    583         assignment_expression_opt
    584         | tuple_expression_list ',' assignment_expression_opt
    585                 { $$ = (ExpressionNode *)$1->set_link( $3 ); }
    586         ;
     582                assignment_expression_opt
     583                | tuple_expression_list ',' assignment_expression_opt
     584                                { $$ = (ExpressionNode *)$1->set_link( $3 ); }
     585                ;
    587586
    588587assignment_operator:
    589         MULTassign                                      { $$ = new OperatorNode(OperatorNode::MulAssn);  }
    590         | DIVassign                                     { $$ = new OperatorNode(OperatorNode::DivAssn);  }
    591         | MODassign                                     { $$ = new OperatorNode(OperatorNode::ModAssn);  }
    592         | PLUSassign                                    { $$ = new OperatorNode(OperatorNode::PlusAssn); }
    593         | MINUSassign                                   { $$ = new OperatorNode(OperatorNode::MinusAssn); }
    594         | LSassign                                      { $$ = new OperatorNode(OperatorNode::LSAssn);    }
    595         | RSassign                                      { $$ = new OperatorNode(OperatorNode::RSAssn);    }
    596         | ANDassign                                     { $$ = new OperatorNode(OperatorNode::AndAssn);  }
    597         | ERassign                                      { $$ = new OperatorNode(OperatorNode::ERAssn);    }
    598         | ORassign                                      { $$ = new OperatorNode(OperatorNode::OrAssn);    }
    599         ;
     588                MULTassign                                                                              { $$ = new OperatorNode(OperatorNode::MulAssn); }
     589                | DIVassign                                                                             { $$ = new OperatorNode(OperatorNode::DivAssn); }
     590                | MODassign                                                                             { $$ = new OperatorNode(OperatorNode::ModAssn); }
     591                | PLUSassign                                                                    { $$ = new OperatorNode(OperatorNode::PlusAssn); }
     592                | MINUSassign                                                                   { $$ = new OperatorNode(OperatorNode::MinusAssn); }
     593                | LSassign                                                                              { $$ = new OperatorNode(OperatorNode::LSAssn); }
     594                | RSassign                                                                              { $$ = new OperatorNode(OperatorNode::RSAssn); }
     595                | ANDassign                                                                             { $$ = new OperatorNode(OperatorNode::AndAssn); }
     596                | ERassign                                                                              { $$ = new OperatorNode(OperatorNode::ERAssn); }
     597                | ORassign                                                                              { $$ = new OperatorNode(OperatorNode::OrAssn); }
     598                ;
    600599
    601600comma_expression:
    602         assignment_expression
    603         | comma_expression ',' assignment_expression    // { $$ = (ExpressionNode *)$1->add_to_list($3); }
    604                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Comma),$1,$3); }
    605         ;
     601                assignment_expression
     602                | comma_expression ',' assignment_expression    // { $$ = (ExpressionNode *)$1->add_to_list($3); }
     603                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Comma),$1,$3); }
     604                ;
    606605
    607606comma_expression_opt:
    608         // empty
    609                 { $$ = 0; }
    610         | comma_expression
    611         ;
     607                // empty
     608                                { $$ = 0; }
     609                | comma_expression
     610                ;
    612611
    613612//*************************** STATEMENTS *******************************
    614613
    615614statement:
    616         labeled_statement
    617         | compound_statement
    618         | expression_statement                          { $$ = $1; }
    619         | selection_statement
    620         | iteration_statement
    621         | jump_statement
    622         | exception_statement
    623         | asm_statement
    624         ;
     615                labeled_statement
     616                | compound_statement
     617                | expression_statement                                                  { $$ = $1; }
     618                | selection_statement
     619                | iteration_statement
     620                | jump_statement
     621                | exception_statement
     622                | asm_statement
     623                ;
    625624
    626625labeled_statement:
    627         no_attr_identifier ':' attribute_list_opt statement
    628                 { $$ = $4->add_label($1);}
    629         ;
     626                no_attr_identifier ':' attribute_list_opt statement
     627                                { $$ = $4->add_label($1);}
     628                ;
    630629
    631630compound_statement:
    632         '{' '}'
    633                 { $$ = new CompoundStmtNode( (StatementNode *)0 ); }
    634         | '{'
    635                 // Two scopes are necessary because the block itself has a scope, but every declaration within the block
    636                 // also requires its own scope
    637           push push
    638           label_declaration_opt                         // GCC, local labels
    639           block_item_list pop '}'                       // C99, intermix declarations and statements
    640                 { $$ = new CompoundStmtNode( $5 ); }
    641         ;
    642 
    643 block_item_list:                                        // C99
    644         block_item
    645         | block_item_list push block_item
    646                 { if ($1 != 0) { $1->set_link($3); $$ = $1; } }
    647         ;
     631                '{' '}'
     632                                { $$ = new CompoundStmtNode( (StatementNode *)0 ); }
     633                | '{'
     634                                // Two scopes are necessary because the block itself has a scope, but every declaration within
     635                                // the block also requires its own scope
     636                  push push
     637                  label_declaration_opt                                                 // GCC, local labels
     638                  block_item_list pop '}'                                               // C99, intermix declarations and statements
     639                                { $$ = new CompoundStmtNode( $5 ); }
     640                ;
     641
     642block_item_list:                                                                                // C99
     643                block_item
     644                | block_item_list push block_item
     645                                { if ($1 != 0) { $1->set_link($3); $$ = $1; } }
     646                ;
    648647
    649648block_item:
    650         declaration                                     // CFA, new & old style declarations
    651                 { $$ = new StatementNode( $1 ); }
    652         | EXTENSION declaration                         // GCC
    653                 { $$ = new StatementNode( $2 ); }
    654         | statement pop
    655         ;
     649                declaration                                                                             // CFA, new & old style declarations
     650                                { $$ = new StatementNode( $1 ); }
     651                | EXTENSION declaration                                                 // GCC
     652                                { $$ = new StatementNode( $2 ); }
     653                | statement pop
     654                ;
    656655
    657656statement_list:
    658         statement
    659         | statement_list statement
    660                 { if ($1 != 0) { $1->set_link($2); $$ = $1; } }
    661         ;
     657                statement
     658                | statement_list statement
     659                                { if ($1 != 0) { $1->set_link($2); $$ = $1; } }
     660                ;
    662661
    663662expression_statement:
    664         comma_expression_opt ';'
    665                 { $$ = new StatementNode(StatementNode::Exp, $1, 0); }
    666         ;
     663                comma_expression_opt ';'
     664                                { $$ = new StatementNode(StatementNode::Exp, $1, 0); }
     665                ;
    667666
    668667selection_statement:
    669         IF '(' comma_expression ')' statement           %prec THEN
    670                 // explicitly deal with the shift/reduce conflict on if/else
    671                 { $$ = new StatementNode(StatementNode::If, $3, $5); }
    672         | IF '(' comma_expression ')' statement ELSE statement
    673                 { $$ = new StatementNode(StatementNode::If, $3, (StatementNode *)mkList((*$5, *$7)) ); }
    674         | SWITCH '(' comma_expression ')' case_clause   // CFA
    675                 { $$ = new StatementNode(StatementNode::Switch, $3, $5); }
    676         | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
    677                 { $$ = new StatementNode(StatementNode::Switch, $3, $8); /* xxx */ }
    678                 // The semantics of the declaration list is changed to include any associated initialization, which is
    679                 // performed *before* the transfer to the appropriate case clause.  Statements after the initial
    680                 // declaration list can never be executed, and therefore, are removed from the grammar even though C
    681                 // allows it.
    682         | CHOOSE '(' comma_expression ')' case_clause   // CFA
    683                 { $$ = new StatementNode(StatementNode::Choose, $3, $5); }
    684         | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt choose_clause_list_opt '}' // CFA
    685                 { $$ = new StatementNode(StatementNode::Choose, $3, $8); }
    686         ;
    687 
    688 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
    689 // clause allows a list of values and subranges.
    690 
    691 case_value:                                             // CFA
    692         constant_expression                     { $$ = $1; }
    693         | constant_expression ELLIPSIS constant_expression // GCC, subrange
    694                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range),$1,$3); }
    695         | subrange                                      // CFA, subrange
    696         ;
    697 
    698 case_value_list:                                        // CFA
    699         case_value
    700         | case_value_list ',' case_value
    701                 { $$ = new CompositeExprNode(new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(tupleContents($1))->set_link($3) ); }
    702         ;
    703 
    704 case_label:                                             // CFA
    705         CASE case_value_list ':'                { $$ = new StatementNode(StatementNode::Case, $2, 0); }
    706         | DEFAULT ':'                           {  $$ = new StatementNode(StatementNode::Default);    }
    707                 // A semantic check is required to ensure only one default clause per switch/choose statement.
    708         ;
    709 
    710 case_label_list:                                        // CFA
    711         case_label
    712         | case_label_list case_label            { $$ = (StatementNode *)($1->set_link($2)); }
    713         ;
    714 
    715 case_clause:                                            // CFA
    716         case_label_list statement               { $$ = $1->append_last_case($2); }
    717         ;
    718 
    719 switch_clause_list_opt:                                 // CFA
    720         // empty
    721                 { $$ = 0; }
    722         | switch_clause_list
    723         ;
    724 
    725 switch_clause_list:                                     // CFA
    726         case_label_list statement_list
    727                                                 { $$ = $1->append_last_case($2); }
    728         | switch_clause_list case_label_list statement_list
    729                                                 { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
    730         ;
    731 
    732 choose_clause_list_opt:                                 // CFA
    733         // empty
    734                 { $$ = 0; }
    735         | choose_clause_list
    736         ;
    737 
    738 choose_clause_list:                                     // CFA
    739         case_label_list fall_through
    740                 { $$ = $1->append_last_case($2); }
    741         | case_label_list statement_list fall_through_opt
    742                 { $$ = $1->append_last_case((StatementNode *)mkList((*$2,*$3))); }
    743         | choose_clause_list case_label_list fall_through
    744                 { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
    745         | choose_clause_list case_label_list statement_list fall_through_opt
    746                 { $$ = (StatementNode *)($1->set_link($2->append_last_case((StatementNode *)mkList((*$3,*$4))))); }
    747         ;
    748 
    749 fall_through_opt:                                       // CFA
    750         // empty
    751                 { $$ = 0; }
    752         | fall_through
    753         ;
    754 
    755 fall_through:                                           // CFA
    756         FALLTHRU                                { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
    757         | FALLTHRU ';'                          { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
    758         ;
     668                IF '(' comma_expression ')' statement                           %prec THEN
     669                                // explicitly deal with the shift/reduce conflict on if/else
     670                                { $$ = new StatementNode(StatementNode::If, $3, $5); }
     671                | IF '(' comma_expression ')' statement ELSE statement
     672                                { $$ = new StatementNode(StatementNode::If, $3, (StatementNode *)mkList((*$5, *$7)) ); }
     673                | SWITCH '(' comma_expression ')' case_clause   // CFA
     674                                { $$ = new StatementNode(StatementNode::Switch, $3, $5); }
     675                | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
     676                                { $$ = new StatementNode(StatementNode::Switch, $3, $8); /* xxx */ }
     677                                // The semantics of the declaration list is changed to include any associated initialization,
     678                                // which is performed *before* the transfer to the appropriate case clause.  Statements after
     679                                // the initial declaration list can never be executed, and therefore, are removed from the
     680                                // grammar even though C allows it.
     681                | CHOOSE '(' comma_expression ')' case_clause   // CFA
     682                                { $$ = new StatementNode(StatementNode::Choose, $3, $5); }
     683                | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt choose_clause_list_opt '}' // CFA
     684                                { $$ = new StatementNode(StatementNode::Choose, $3, $8); }
     685                ;
     686
     687// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a
     688// case clause allows a list of values and subranges.
     689
     690case_value:                                                                                             // CFA
     691                constant_expression                                                             { $$ = $1; }
     692                | constant_expression ELLIPSIS constant_expression // GCC, subrange
     693                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range),$1,$3); }
     694                | subrange                                                                              // CFA, subrange
     695                ;
     696
     697case_value_list:                                                                                // CFA
     698                case_value
     699                | case_value_list ',' case_value
     700                                { $$ = new CompositeExprNode(new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(tupleContents($1))->set_link($3) ); }
     701                ;
     702
     703case_label:                                                                                             // CFA
     704                CASE case_value_list ':'                                                { $$ = new StatementNode(StatementNode::Case, $2, 0); }
     705                | DEFAULT ':'                                                               { $$ = new StatementNode(StatementNode::Default); }
     706                                // A semantic check is required to ensure only one default clause per switch/choose statement.
     707                ;
     708
     709case_label_list:                                                                                // CFA
     710                case_label
     711                | case_label_list case_label                                    { $$ = (StatementNode *)($1->set_link($2)); }
     712                ;
     713
     714case_clause:                                                                                    // CFA
     715                case_label_list statement                                               { $$ = $1->append_last_case($2); }
     716                ;
     717
     718switch_clause_list_opt:                                                                 // CFA
     719                // empty
     720                                { $$ = 0; }
     721                | switch_clause_list
     722                ;
     723
     724switch_clause_list:                                                                             // CFA
     725                case_label_list statement_list
     726                                { $$ = $1->append_last_case($2); }
     727                | switch_clause_list case_label_list statement_list
     728                                { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
     729                ;
     730
     731choose_clause_list_opt:                                                                 // CFA
     732                // empty
     733                                { $$ = 0; }
     734                | choose_clause_list
     735                ;
     736
     737choose_clause_list:                                                                             // CFA
     738                case_label_list fall_through
     739                                { $$ = $1->append_last_case($2); }
     740                | case_label_list statement_list fall_through_opt
     741                                { $$ = $1->append_last_case((StatementNode *)mkList((*$2,*$3))); }
     742                | choose_clause_list case_label_list fall_through
     743                                { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
     744                | choose_clause_list case_label_list statement_list fall_through_opt
     745                                { $$ = (StatementNode *)($1->set_link($2->append_last_case((StatementNode *)mkList((*$3,*$4))))); }
     746                ;
     747
     748fall_through_opt:                                                                               // CFA
     749                // empty
     750                                { $$ = 0; }
     751                | fall_through
     752                ;
     753
     754fall_through:                                                                                   // CFA
     755                FALLTHRU                                                                                { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
     756                | FALLTHRU ';'                                                                  { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
     757                ;
    759758
    760759iteration_statement:
    761         WHILE '(' comma_expression ')' statement
    762                                                 { $$ = new StatementNode(StatementNode::While, $3, $5); }
    763         | DO statement WHILE '(' comma_expression ')' ';'
    764                                                 { $$ = new StatementNode(StatementNode::Do, $5, $2); }
    765         | FOR '(' push for_control_expression ')' statement
    766                                                 { $$ = new StatementNode(StatementNode::For, $4, $6); }
    767         ;
     760                WHILE '(' comma_expression ')' statement
     761                                { $$ = new StatementNode(StatementNode::While, $3, $5); }
     762                | DO statement WHILE '(' comma_expression ')' ';'
     763                                { $$ = new StatementNode(StatementNode::Do, $5, $2); }
     764                | FOR '(' push for_control_expression ')' statement
     765                                { $$ = new StatementNode(StatementNode::For, $4, $6); }
     766                ;
    768767
    769768for_control_expression:
    770         comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
    771                                                 { $$ = new ForCtlExprNode($1, $4, $6); }
    772         | declaration comma_expression_opt ';' comma_expression_opt // C99
    773                 // Like C++, the loop index can be declared local to the loop.
    774                                                 { $$ = new ForCtlExprNode($1, $2, $4); }
    775         ;
     769                comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
     770                                { $$ = new ForCtlExprNode($1, $4, $6); }
     771                | declaration comma_expression_opt ';' comma_expression_opt // C99
     772                                // Like C++, the loop index can be declared local to the loop.
     773                                { $$ = new ForCtlExprNode($1, $2, $4); }
     774                ;
    776775
    777776jump_statement:
    778         GOTO no_attr_identifier ';'
    779                                                 { $$ = new StatementNode(StatementNode::Goto, $2); }
    780         | GOTO '*' comma_expression ';'         // GCC, computed goto
    781                 // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; =>
    782                 // goto *(i+3); whereas normal operator precedence yields goto (*i)+3;
    783                                                 { $$ = new StatementNode(StatementNode::Goto, $3); }
    784         | CONTINUE ';'
    785                 // A semantic check is required to ensure this statement appears only in the body of an iteration
    786                 // statement.
    787                                                 { $$ = new StatementNode(StatementNode::Continue, 0, 0); }
    788         | CONTINUE no_attr_identifier ';'       // CFA, multi-level continue
    789                 // A semantic check is required to ensure this statement appears only in the body of an iteration
    790                 // statement, and the target of the transfer appears only at the start of an iteration statement.
    791                                                 { $$ = new StatementNode(StatementNode::Continue, $2); }
    792         | BREAK ';'
    793                 // A semantic check is required to ensure this statement appears only in the body of an iteration
    794                 // statement.
    795                                                 { $$ = new StatementNode(StatementNode::Break, 0, 0); }
    796         | BREAK no_attr_identifier ';'          // CFA, multi-level exit
    797                 // A semantic check is required to ensure this statement appears only in the body of an iteration
    798                 // statement, and the target of the transfer appears only at the start of an iteration statement.
    799                                                 { $$ = new StatementNode(StatementNode::Break, $2 ); }
    800         | RETURN comma_expression_opt ';'
    801                                                 { $$ = new StatementNode(StatementNode::Return, $2, 0); }
    802         | THROW assignment_expression ';'
    803                                                 { $$ = new StatementNode(StatementNode::Throw, $2, 0); }
    804         | THROW ';'
    805                                                 { $$ = new StatementNode(StatementNode::Throw, 0, 0); }
    806         ;
     777                GOTO no_attr_identifier ';'
     778                                { $$ = new StatementNode(StatementNode::Goto, $2); }
     779                | GOTO '*' comma_expression ';'                         // GCC, computed goto
     780                                // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto
     781                                // *i+3; => goto *(i+3); whereas normal operator precedence yields goto (*i)+3;
     782                                { $$ = new StatementNode(StatementNode::Goto, $3); }
     783                | CONTINUE ';'
     784                                // A semantic check is required to ensure this statement appears only in the body of an
     785                                // iteration statement.
     786                                { $$ = new StatementNode(StatementNode::Continue, 0, 0); }
     787                | CONTINUE no_attr_identifier ';'               // CFA, multi-level continue
     788                                // A semantic check is required to ensure this statement appears only in the body of an
     789                                // iteration statement, and the target of the transfer appears only at the start of an
     790                                // iteration statement.
     791                                { $$ = new StatementNode(StatementNode::Continue, $2); }
     792                | BREAK ';'
     793                                // A semantic check is required to ensure this statement appears only in the body of an
     794                                // iteration statement.
     795                                { $$ = new StatementNode(StatementNode::Break, 0, 0); }
     796                | BREAK no_attr_identifier ';'                          // CFA, multi-level exit
     797                                // A semantic check is required to ensure this statement appears only in the body of an
     798                                // iteration statement, and the target of the transfer appears only at the start of an
     799                                // iteration statement.
     800                                { $$ = new StatementNode(StatementNode::Break, $2 ); }
     801                | RETURN comma_expression_opt ';'
     802                                { $$ = new StatementNode(StatementNode::Return, $2, 0); }
     803                | THROW assignment_expression ';'
     804                                { $$ = new StatementNode(StatementNode::Throw, $2, 0); }
     805                | THROW ';'
     806                                { $$ = new StatementNode(StatementNode::Throw, 0, 0); }
     807                ;
    807808
    808809exception_statement:
    809         TRY compound_statement handler_list
    810                              { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
    811         | TRY compound_statement finally_clause
    812                              { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
    813         | TRY compound_statement handler_list finally_clause
    814                              {
    815                                $3->set_link($4);
    816                                $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3))));
    817                              }
    818         ;
     810                TRY compound_statement handler_list
     811                                { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
     812                | TRY compound_statement finally_clause
     813                                { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
     814                | TRY compound_statement handler_list finally_clause
     815                                {
     816                                        $3->set_link($4);
     817                                        $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3))));
     818                                }
     819                ;
    819820
    820821handler_list:
    821                 // There must be at least one catch clause
    822         handler_clause
    823                 // ISO/IEC 9899:1999 Section 15.3(6) If present, a "..." handler shall be the last handler for its try
    824                 // block.
    825         | CATCH '(' ELLIPSIS ')' compound_statement
    826                                                 { $$ = StatementNode::newCatchStmt( 0, $5, true ); }
    827         | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
    828                                                 { $$ = $1->set_link( StatementNode::newCatchStmt( 0, $6, true ) ); }
    829         ;
     822                                // There must be at least one catch clause
     823                handler_clause
     824                                // ISO/IEC 9899:1999 Section 15.3(6) If present, a "..." handler shall be the last handler for
     825                                // its try block.
     826                | CATCH '(' ELLIPSIS ')' compound_statement
     827                                { $$ = StatementNode::newCatchStmt( 0, $5, true ); }
     828                | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
     829                                { $$ = $1->set_link( StatementNode::newCatchStmt( 0, $6, true ) ); }
     830                ;
    830831
    831832handler_clause:
    832         CATCH '(' push push exception_declaration pop ')' compound_statement pop
    833                                                 { $$ = StatementNode::newCatchStmt($5, $8); }
    834         | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
    835                                                 { $$ = $1->set_link( StatementNode::newCatchStmt($6, $9) );  }
    836         ;
     833                CATCH '(' push push exception_declaration pop ')' compound_statement pop
     834                                { $$ = StatementNode::newCatchStmt($5, $8); }
     835                | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
     836                                { $$ = $1->set_link( StatementNode::newCatchStmt($6, $9) ); }
     837                ;
    837838
    838839finally_clause:
    839         FINALLY compound_statement
    840                                                 { $$ = new StatementNode(StatementNode::Finally, 0, $2);
    841                                                   std::cout << "Just created a finally node" << std::endl;
    842                                                 }
    843         ;
     840                FINALLY compound_statement
     841                                { $$ = new StatementNode(StatementNode::Finally, 0, $2);
     842                                        std::cout << "Just created a finally node" << std::endl;
     843                                }
     844                ;
    844845
    845846exception_declaration:
    846                 // A semantic check is required to ensure type_specifier does not create a new type, e.g.:
    847                 //
    848                 //      catch ( struct { int i; } x ) ...
    849                 //
    850                 // This new type cannot catch any thrown type because of name equivalence among types.
    851         type_specifier
    852         | type_specifier declarator
    853                 {
    854                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    855                     $$ = $2->addType( $1 );
    856                 }
    857         | type_specifier variable_abstract_declarator
    858                 $$ = $2->addType( $1 ); }
    859         | new_abstract_declarator_tuple no_attr_identifier // CFA
    860                 {
    861                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    862                     $$ = $1->addName( $2 );
    863                 }
    864         | new_abstract_declarator_tuple                 // CFA
    865         ;
     847                                // A semantic check is required to ensure type_specifier does not create a new type, e.g.:
     848                                //
     849                                //              catch ( struct { int i; } x ) ...
     850                                //
     851                                // This new type cannot catch any thrown type because of name equivalence among types.
     852                type_specifier
     853                | type_specifier declarator
     854                                {
     855                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     856                                        $$ = $2->addType( $1 );
     857                                }
     858                | type_specifier variable_abstract_declarator
     859                                { $$ = $2->addType( $1 ); }
     860                | new_abstract_declarator_tuple no_attr_identifier // CFA
     861                                {
     862                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     863                                        $$ = $1->addName( $2 );
     864                                }
     865                | new_abstract_declarator_tuple                                 // CFA
     866                ;
    866867
    867868asm_statement:
    868         ASM type_qualifier_list_opt '(' constant_expression ')' ';'
    869                                                 { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
    870         | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ')' ';' // remaining GCC
    871                                                 { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
    872         | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ')' ';'
    873                                                 { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
    874         | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ':'
    875                         asm_clobbers_list ')' ';'
    876                                                 { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
    877         ;
    878 
    879 asm_operands_opt:                                       // GCC
    880         // empty
    881         | asm_operands_list
    882         ;
    883 
    884 asm_operands_list:                                      // GCC
    885         asm_operand
    886         | asm_operands_list ',' asm_operand
    887         ;
    888 
    889 asm_operand:                                            // GCC
    890         STRINGliteral '(' constant_expression ')'       {}
    891         ;
    892 
    893 asm_clobbers_list:                                      // GCC
    894         STRINGliteral                           {}
    895         | asm_clobbers_list ',' STRINGliteral
    896         ;
     869                ASM type_qualifier_list_opt '(' constant_expression ')' ';'
     870                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
     871                | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ')' ';' // remaining GCC
     872                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
     873                | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ')' ';'
     874                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
     875                | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ':'
     876                                                asm_clobbers_list ')' ';'
     877                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
     878                ;
     879
     880asm_operands_opt:                                                                               // GCC
     881                // empty
     882                | asm_operands_list
     883                ;
     884
     885asm_operands_list:                                                                              // GCC
     886                asm_operand
     887                | asm_operands_list ',' asm_operand
     888                ;
     889
     890asm_operand:                                                                                    // GCC
     891                STRINGliteral '(' constant_expression ')'               {}
     892                ;
     893
     894asm_clobbers_list:                                                                              // GCC
     895                STRINGliteral                                                                   {}
     896                | asm_clobbers_list ',' STRINGliteral
     897                ;
    897898
    898899//******************************* DECLARATIONS *********************************
    899900
    900 declaration_list_opt:                                   // used at beginning of switch statement
    901         pop
    902                 { $$ = 0; }
    903         | declaration_list
    904         ;
     901declaration_list_opt:                                                                   // used at beginning of switch statement
     902                pop
     903                                { $$ = 0; }
     904                | declaration_list
     905                ;
    905906
    906907declaration_list:
    907         declaration
    908         | declaration_list push declaration
    909                 { $$ = $1->appendList( $3 ); }
    910         ;
    911 
    912 old_declaration_list_opt:                               // used to declare parameter types in K&R style functions
    913         pop
    914                 { $$ = 0; }
    915         | old_declaration_list
    916         ;
     908                declaration
     909                | declaration_list push declaration
     910                                { $$ = $1->appendList( $3 ); }
     911                ;
     912
     913old_declaration_list_opt:                                                               // used to declare parameter types in K&R style functions
     914                pop
     915                                { $$ = 0; }
     916                | old_declaration_list
     917                ;
    917918
    918919old_declaration_list:
    919         old_declaration
    920         | old_declaration_list push old_declaration
    921                 { $$ = $1->appendList( $3 ); }
    922         ;
    923 
    924 label_declaration_opt:                                  // GCC, local label
    925         // empty
    926         | label_declaration_list
    927         ;
    928 
    929 label_declaration_list:                                 // GCC, local label
    930         LABEL label_list ';'
    931         | label_declaration_list LABEL label_list ';'
    932         ;
    933 
    934 label_list:                                             // GCC, local label
    935         no_attr_identifier_or_typedef_name              {}
    936         | label_list ',' no_attr_identifier_or_typedef_name {}
    937         ;
    938 
    939 declaration:                                            // CFA, new & old style declarations
    940         new_declaration
    941         | old_declaration
    942         ;
    943 
    944 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
    945 // declarations. CFA declarations use the same declaration tokens as in C; however, CFA places declaration modifiers to
    946 // the left of the base type, while C declarations place modifiers to the right of the base type. CFA declaration
    947 // modifiers are interpreted from left to right and the entire type specification is distributed across all variables in
    948 // the declaration list (as in Pascal).  ANSI C and the new CFA declarations may appear together in the same program
    949 // block, but cannot be mixed within a specific declaration.
    950 //
    951 //          CFA             C
    952 //      [10] int x;     int x[10];      // array of 10 integers
    953 //      [10] * char y;  char *y[10];    // array of 10 pointers to char
    954 
    955 new_declaration:                                        // CFA
    956         new_variable_declaration pop ';'
    957         | new_typedef_declaration pop ';'
    958         | new_function_declaration pop ';'
    959         | type_declaring_list pop ';'
    960         | context_specifier pop ';'
    961         ;
    962 
    963 new_variable_declaration:                               // CFA
    964         new_variable_specifier initializer_opt
    965                 {
    966                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    967                         $$ = $1;
    968                 }
    969         | declaration_qualifier_list new_variable_specifier initializer_opt
    970                 // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is necessary to
    971                 // preclude them as a type_qualifier cannot appear in that context.
    972                 {
    973                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    974                         $$ = $2->addQualifiers( $1 );
    975                 }
    976         | new_variable_declaration pop ',' push identifier_or_typedef_name initializer_opt
    977                 {
    978                         typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
    979                         $$ = $1->appendList( $1->cloneType( $5 ) );
    980                 }
    981         ;
    982 
    983 new_variable_specifier:                                 // CFA
    984                 // A semantic check is required to ensure asm_name only appears on declarations with implicit or
    985                 // explicit static storage-class
    986         new_abstract_declarator_no_tuple identifier_or_typedef_name asm_name_opt
    987                 {
    988                         typedefTable.setNextIdentifier( *$2 );
    989                         $$ = $1->addName( $2 );
    990                 }
    991         | new_abstract_tuple identifier_or_typedef_name asm_name_opt
    992                 {
    993                         typedefTable.setNextIdentifier( *$2 );
    994                         $$ = $1->addName( $2 );
    995                 }
    996         | type_qualifier_list new_abstract_tuple identifier_or_typedef_name asm_name_opt
    997                 {
    998                         typedefTable.setNextIdentifier( *$3 );
    999                         $$ = $2->addQualifiers( $1 )->addName( $3 );
    1000                 }
    1001         ;
    1002 
    1003 new_function_declaration:                               // CFA
    1004         new_function_specifier
    1005                 {
    1006                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    1007                         $$ = $1;
    1008                 }
    1009         | declaration_qualifier_list new_function_specifier
    1010                 // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is necessary to
    1011                 // preclude them as a type_qualifier cannot appear in this context.
    1012                 {
    1013                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    1014                         $$ = $2->addQualifiers( $1 );
    1015                 }
    1016         | new_function_declaration pop ',' push identifier_or_typedef_name
    1017                 {
    1018                         typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
    1019                         $$ = $1->appendList( $1->cloneType( $5 ) );
    1020                 }
    1021         ;
    1022 
    1023 new_function_specifier:                                 // CFA
    1024         '[' push pop ']' identifier '(' push new_parameter_type_list_opt pop ')'
    1025                 {
    1026                         typedefTable.setNextIdentifier( *($5) );
    1027                         $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    1028                 }
    1029         | '[' push pop ']' TYPEDEFname '(' push new_parameter_type_list_opt pop ')'
    1030                 {
    1031                         typedefTable.setNextIdentifier( *($5) );
    1032                         $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
    1033                 }
    1034                 /* identifier_or_typedef_name must be broken apart because of the sequence:
    1035 
    1036                    '[' ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
    1037                    '[' ']' type_specifier
    1038 
    1039                    type_specifier can resolve to just TYPEDEFname (e.g. typedef int T; int f( T );). Therefore
    1040                    this must be flattened to allow lookahead to the '(' without having to reduce
    1041                    identifier_or_typedef_name. */
    1042         | new_abstract_tuple identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
    1043                 /* To obtain LR(1), this rule must be factored out from function return type (see
    1044                    new_abstract_declarator). */
    1045                 {
    1046                         $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
    1047                 }
    1048         | new_function_return identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
    1049                 {
    1050                         $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
    1051                 }
    1052         ;
    1053 
    1054 new_function_return:                                    // CFA
    1055         '[' push new_parameter_list pop ']'
    1056                 { $$ = DeclarationNode::newTuple( $3 ); }
    1057         | '[' push new_parameter_list pop ',' push new_abstract_parameter_list pop ']'
    1058                 /* To obtain LR(1), the last new_abstract_parameter_list is added into this flattened rule to
    1059                    lookahead to the ']'. */
    1060                 { $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
    1061         ;
    1062 
    1063 new_typedef_declaration:                                // CFA
    1064         TYPEDEF new_variable_specifier
    1065                 {
    1066                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1067                         $$ = $2->addTypedef();
    1068                 }
    1069         | TYPEDEF new_function_specifier
    1070                 {
    1071                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1072                         $$ = $2->addTypedef();
    1073                 }
    1074         | new_typedef_declaration pop ',' push no_attr_identifier
    1075                 {
    1076                         typedefTable.addToEnclosingScope( *$5, TypedefTable::TD);
    1077                         $$ = $1->appendList( $1->cloneType( $5 ) );
    1078                 }
    1079         ;
    1080 
    1081 /* Traditionally typedef is part of storage-class specifier for syntactic convenience only. Here, it is
    1082    factored out as a separate form of declaration, which syntactically precludes storage-class specifiers and
    1083    initialization. */
     920                old_declaration
     921                | old_declaration_list push old_declaration
     922                                { $$ = $1->appendList( $3 ); }
     923                ;
     924
     925label_declaration_opt:                                                                  // GCC, local label
     926                // empty
     927                | label_declaration_list
     928                ;
     929
     930label_declaration_list:                                                                 // GCC, local label
     931                LABEL label_list ';'
     932                | label_declaration_list LABEL label_list ';'
     933                ;
     934
     935label_list:                                                                                             // GCC, local label
     936                no_attr_identifier_or_typedef_name                              {}
     937                | label_list ',' no_attr_identifier_or_typedef_name {}
     938                ;
     939
     940declaration:                                                                                    // CFA, new & old style declarations
     941                new_declaration
     942                | old_declaration
     943                ;
     944
     945// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and
     946// function declarations. CFA declarations use the same declaration tokens as in C; however, CFA places
     947// declaration modifiers to the left of the base type, while C declarations place modifiers to the right of
     948// the base type. CFA declaration modifiers are interpreted from left to right and the entire type
     949// specification is distributed across all variables in the declaration list (as in Pascal).  ANSI C and the
     950// new CFA declarations may appear together in the same program block, but cannot be mixed within a specific
     951// declaration.
     952//
     953//                      CFA                                     C
     954//              [10] int x;                     int x[10];              // array of 10 integers
     955//              [10] * char y;          char *y[10];    // array of 10 pointers to char
     956
     957new_declaration:                                                                                // CFA
     958                new_variable_declaration pop ';'
     959                | new_typedef_declaration pop ';'
     960                | new_function_declaration pop ';'
     961                | type_declaring_list pop ';'
     962                | context_specifier pop ';'
     963                ;
     964
     965new_variable_declaration:                                                               // CFA
     966                new_variable_specifier initializer_opt
     967                                {
     968                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     969                                        $$ = $1;
     970                                }
     971                | declaration_qualifier_list new_variable_specifier initializer_opt
     972                                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
     973                                // necessary to preclude them as a type_qualifier cannot appear in that context.
     974                                {
     975                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     976                                        $$ = $2->addQualifiers( $1 );
     977                                }
     978                | new_variable_declaration pop ',' push identifier_or_typedef_name initializer_opt
     979                                {
     980                                        typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
     981                                        $$ = $1->appendList( $1->cloneType( $5 ) );
     982                                }
     983                ;
     984
     985new_variable_specifier:                                                                 // CFA
     986                                // A semantic check is required to ensure asm_name only appears on declarations with implicit
     987                                // or explicit static storage-class
     988                new_abstract_declarator_no_tuple identifier_or_typedef_name asm_name_opt
     989                                {
     990                                        typedefTable.setNextIdentifier( *$2 );
     991                                        $$ = $1->addName( $2 );
     992                                }
     993                | new_abstract_tuple identifier_or_typedef_name asm_name_opt
     994                                {
     995                                        typedefTable.setNextIdentifier( *$2 );
     996                                        $$ = $1->addName( $2 );
     997                                }
     998                | type_qualifier_list new_abstract_tuple identifier_or_typedef_name asm_name_opt
     999                                {
     1000                                        typedefTable.setNextIdentifier( *$3 );
     1001                                        $$ = $2->addQualifiers( $1 )->addName( $3 );
     1002                                }
     1003                ;
     1004
     1005new_function_declaration:                                                               // CFA
     1006                new_function_specifier
     1007                                {
     1008                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1009                                        $$ = $1;
     1010                                }
     1011                | declaration_qualifier_list new_function_specifier
     1012                                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
     1013                                // necessary to preclude them as a type_qualifier cannot appear in this context.
     1014                                {
     1015                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1016                                        $$ = $2->addQualifiers( $1 );
     1017                                }
     1018                | new_function_declaration pop ',' push identifier_or_typedef_name
     1019                                {
     1020                                        typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
     1021                                        $$ = $1->appendList( $1->cloneType( $5 ) );
     1022                                }
     1023                ;
     1024
     1025new_function_specifier:                                                                 // CFA
     1026                '[' push pop ']' identifier '(' push new_parameter_type_list_opt pop ')'
     1027                                {
     1028                                        typedefTable.setNextIdentifier( *($5) );
     1029                                        $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
     1030                                }
     1031                | '[' push pop ']' TYPEDEFname '(' push new_parameter_type_list_opt pop ')'
     1032                                {
     1033                                        typedefTable.setNextIdentifier( *($5) );
     1034                                        $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
     1035                                }
     1036                                // identifier_or_typedef_name must be broken apart because of the sequence:
     1037                                //
     1038                                //   '[' ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
     1039                                //   '[' ']' type_specifier
     1040                                //
     1041                                // type_specifier can resolve to just TYPEDEFname (e.g. typedef int T; int f( T );). Therefore
     1042                                // this must be flattened to allow lookahead to the '(' without having to reduce
     1043                                // identifier_or_typedef_name.
     1044                | new_abstract_tuple identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
     1045                                // To obtain LR(1), this rule must be factored out from function return type (see
     1046                                //   new_abstract_declarator).
     1047                                {
     1048                                        $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
     1049                                }
     1050                | new_function_return identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
     1051                                {
     1052                                        $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
     1053                                }
     1054                ;
     1055
     1056new_function_return:                                                                    // CFA
     1057                '[' push new_parameter_list pop ']'
     1058                                { $$ = DeclarationNode::newTuple( $3 ); }
     1059                | '[' push new_parameter_list pop ',' push new_abstract_parameter_list pop ']'
     1060                                // To obtain LR(1), the last new_abstract_parameter_list is added into this flattened rule to
     1061                                // lookahead to the ']'.
     1062                                { $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
     1063                ;
     1064
     1065new_typedef_declaration:                                                                // CFA
     1066                TYPEDEF new_variable_specifier
     1067                                {
     1068                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1069                                        $$ = $2->addTypedef();
     1070                                }
     1071                | TYPEDEF new_function_specifier
     1072                                {
     1073                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1074                                        $$ = $2->addTypedef();
     1075                                }
     1076                | new_typedef_declaration pop ',' push no_attr_identifier
     1077                                {
     1078                                        typedefTable.addToEnclosingScope( *$5, TypedefTable::TD);
     1079                                        $$ = $1->appendList( $1->cloneType( $5 ) );
     1080                                }
     1081                ;
     1082
     1083// Traditionally typedef is part of storage-class specifier for syntactic convenience only. Here, it is
     1084// factored out as a separate form of declaration, which syntactically precludes storage-class specifiers and
     1085// initialization.
    10841086
    10851087typedef_declaration:
    1086         TYPEDEF type_specifier declarator
    1087                 {
    1088                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1089                         $$ = $3->addType( $2 )->addTypedef();
    1090                 }
    1091         | typedef_declaration pop ',' push declarator
    1092                 {
    1093                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1094                         $$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
    1095                 }
    1096         | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2)
    1097                 {
    1098                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1099                         $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
    1100                 }
    1101         | type_specifier TYPEDEF declarator
    1102                 {
    1103                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1104                         $$ = $3->addType( $1 )->addTypedef();
    1105                 }
    1106         | type_specifier TYPEDEF type_qualifier_list declarator
    1107                 {
    1108                         typedefTable.addToEnclosingScope( TypedefTable::TD);
    1109                         $$ = $4->addQualifiers($1)->addTypedef()->addType($1);
    1110                 }
    1111         ;
    1112 
    1113 typedef_expression:                                     // GCC, naming expression type
    1114         TYPEDEF no_attr_identifier '=' assignment_expression
    1115                 {
    1116                         typedefTable.addToEnclosingScope(*($2), TypedefTable::TD);
    1117                         $$ = DeclarationNode::newName( 0 ); // XXX
    1118                 }
    1119         | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
    1120                 {
    1121                         typedefTable.addToEnclosingScope(*($5), TypedefTable::TD);
    1122                         $$ = DeclarationNode::newName( 0 ); // XXX
    1123                 }
    1124         ;
     1088                TYPEDEF type_specifier declarator
     1089                                {
     1090                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1091                                        $$ = $3->addType( $2 )->addTypedef();
     1092                                }
     1093                | typedef_declaration pop ',' push declarator
     1094                                {
     1095                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1096                                        $$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
     1097                                }
     1098                | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2)
     1099                                {
     1100                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1101                                        $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
     1102                                }
     1103                | type_specifier TYPEDEF declarator
     1104                                {
     1105                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1106                                        $$ = $3->addType( $1 )->addTypedef();
     1107                                }
     1108                | type_specifier TYPEDEF type_qualifier_list declarator
     1109                                {
     1110                                        typedefTable.addToEnclosingScope( TypedefTable::TD);
     1111                                        $$ = $4->addQualifiers($1)->addTypedef()->addType($1);
     1112                                }
     1113                ;
     1114
     1115typedef_expression:                                                                             // GCC, naming expression type
     1116                TYPEDEF no_attr_identifier '=' assignment_expression
     1117                                {
     1118                                        typedefTable.addToEnclosingScope(*($2), TypedefTable::TD);
     1119                                        $$ = DeclarationNode::newName( 0 ); // XXX
     1120                                }
     1121                | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
     1122                                {
     1123                                        typedefTable.addToEnclosingScope(*($5), TypedefTable::TD);
     1124                                        $$ = DeclarationNode::newName( 0 ); // XXX
     1125                                }
     1126                ;
    11251127
    11261128old_declaration:
    1127         declaring_list pop ';'
    1128         | typedef_declaration pop ';'
    1129         | typedef_expression pop ';'                    // GCC, naming expression type
    1130         | sue_declaration_specifier pop ';'
    1131         ;
     1129                declaring_list pop ';'
     1130                | typedef_declaration pop ';'
     1131                | typedef_expression pop ';'                                    // GCC, naming expression type
     1132                | sue_declaration_specifier pop ';'
     1133                ;
    11321134
    11331135declaring_list:
    1134                 /* A semantic check is required to ensure asm_name only appears on declarations with implicit
    1135                    or explicit static storage-class */
    1136         declaration_specifier declarator asm_name_opt initializer_opt
    1137                 {
    1138                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    1139                         $$ = ($2->addType( $1 ))->addInitializer($4);
    1140                 }
    1141         | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    1142                 {
    1143                         typedefTable.addToEnclosingScope( TypedefTable::ID );
    1144                         $$ = $1->appendList( $1->cloneBaseType( $4->addInitializer($6) ) );
    1145                 }
    1146         ;
    1147 
    1148 declaration_specifier:                                  // type specifier + storage class
    1149         basic_declaration_specifier
    1150         | sue_declaration_specifier
    1151         | typedef_declaration_specifier
    1152         | typegen_declaration_specifier
    1153         ;
    1154 
    1155 type_specifier:                                         // declaration specifier - storage class
    1156         basic_type_specifier
    1157         | sue_type_specifier
    1158         | typedef_type_specifier
    1159         | typegen_type_specifier
    1160         ;
    1161 
    1162 type_qualifier_list_opt:                                // GCC, used in asm_statement
    1163         // empty
    1164                 { $$ = 0; }
    1165         | type_qualifier_list
    1166         ;
     1136                                // A semantic check is required to ensure asm_name only appears on declarations with implicit
     1137                                // or explicit static storage-class
     1138                declaration_specifier declarator asm_name_opt initializer_opt
     1139                                {
     1140                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1141                                        $$ = ($2->addType( $1 ))->addInitializer($4);
     1142                                }
     1143                | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
     1144                                {
     1145                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1146                                        $$ = $1->appendList( $1->cloneBaseType( $4->addInitializer($6) ) );
     1147                                }
     1148                ;
     1149
     1150declaration_specifier:                                                                  // type specifier + storage class
     1151                basic_declaration_specifier
     1152                | sue_declaration_specifier
     1153                | typedef_declaration_specifier
     1154                | typegen_declaration_specifier
     1155                ;
     1156
     1157type_specifier:                                                                                 // declaration specifier - storage class
     1158                basic_type_specifier
     1159                | sue_type_specifier
     1160                | typedef_type_specifier
     1161                | typegen_type_specifier
     1162                ;
     1163
     1164type_qualifier_list_opt:                                                                // GCC, used in asm_statement
     1165                // empty
     1166                                { $$ = 0; }
     1167                | type_qualifier_list
     1168                ;
    11671169
    11681170type_qualifier_list:
    1169                 /* A semantic check is necessary to ensure a type qualifier is appropriate for the kind of
    1170                   declaration.
    1171 
    1172                   ISO/IEC 9899:1999 Section 6.7.3(4) : If the same qualifier appears more than once in the
    1173                   same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is
    1174                    the same as if it appeared only once. */
    1175         type_qualifier
    1176         | type_qualifier_list type_qualifier
    1177                 { $$ = $1->addQualifiers( $2 ); }
    1178         ;
     1171                                // A semantic check is necessary to ensure a type qualifier is appropriate for the kind of
     1172                                // declaration.
     1173                                //
     1174                                // ISO/IEC 9899:1999 Section 6.7.3(4) : If the same qualifier appears more than once in the
     1175                                // same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is
     1176                                // the same as if it appeared only once.
     1177                type_qualifier
     1178                | type_qualifier_list type_qualifier
     1179                                { $$ = $1->addQualifiers( $2 ); }
     1180                ;
    11791181
    11801182type_qualifier:
    1181         type_qualifier_name
    1182         | attribute
    1183                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); }
    1184         ;
     1183                type_qualifier_name
     1184                | attribute
     1185                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); }
     1186                ;
    11851187
    11861188type_qualifier_name:
    1187         CONST
    1188                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }
    1189         | RESTRICT
    1190                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
    1191         | VOLATILE
    1192                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
    1193         | LVALUE                                        // CFA
    1194                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
    1195         | ATOMIC
    1196                 { $$ = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }
    1197         | FORALL '('
    1198                 {
    1199                         typedefTable.enterScope();
    1200                 }
    1201           type_parameter_list ')'                       // CFA
    1202                 {
    1203                         typedefTable.leaveScope();
    1204                         $$ = DeclarationNode::newForall( $4 );
    1205                 }
    1206         ;
     1189                CONST
     1190                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }
     1191                | RESTRICT
     1192                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
     1193                | VOLATILE
     1194                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
     1195                | LVALUE                                                                                // CFA
     1196                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
     1197                | ATOMIC
     1198                                { $$ = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }
     1199                | FORALL '('
     1200                                {
     1201                                        typedefTable.enterScope();
     1202                                }
     1203                  type_parameter_list ')'                                               // CFA
     1204                                {
     1205                                        typedefTable.leaveScope();
     1206                                        $$ = DeclarationNode::newForall( $4 );
     1207                                }
     1208                ;
    12071209
    12081210declaration_qualifier_list:
    1209         storage_class_list
    1210         | type_qualifier_list storage_class_list        // remaining OBSOLESCENT (see 2)
    1211                 { $$ = $1->addQualifiers( $2 ); }
    1212         | declaration_qualifier_list type_qualifier_list storage_class_list
    1213                 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
    1214         ;
     1211                storage_class_list
     1212                | type_qualifier_list storage_class_list                // remaining OBSOLESCENT (see 2)
     1213                                { $$ = $1->addQualifiers( $2 ); }
     1214                | declaration_qualifier_list type_qualifier_list storage_class_list
     1215                                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
     1216                ;
    12151217
    12161218storage_class_list:
    1217                 /* A semantic check is necessary to ensure a storage class is appropriate for the kind of
    1218                   declaration and that only one of each is specified, except for inline, which can appear
    1219                   with the others.
    1220 
    1221                   ISO/IEC 9899:1999 Section 6.7.1(2) : At most, one storage-class specifier may be given in
    1222                    the declaration specifiers in a declaration. */
    1223         storage_class
    1224         | storage_class_list storage_class
    1225                 { $$ = $1->addQualifiers( $2 ); }
    1226         ;
     1219                                // A semantic check is necessary to ensure a storage class is appropriate for the kind of
     1220                                // declaration and that only one of each is specified, except for inline, which can appear
     1221                                // with the others.
     1222                                //
     1223                                // ISO/IEC 9899:1999 Section 6.7.1(2) : At most, one storage-class specifier may be given in
     1224                                // the declaration specifiers in a declaration.
     1225                storage_class
     1226                | storage_class_list storage_class
     1227                                { $$ = $1->addQualifiers( $2 ); }
     1228                ;
    12271229
    12281230storage_class:
    1229         storage_class_name
    1230         ;
     1231                storage_class_name
     1232                ;
    12311233
    12321234storage_class_name:
    1233         EXTERN
    1234                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
    1235         | STATIC
    1236                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
    1237         | AUTO
    1238                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
    1239         | REGISTER
    1240                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
    1241         | INLINE                                        // C99
    1242                 // INLINE is essentially a storage class specifier for functions, and hence, belongs here.
    1243                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }
    1244         | FORTRAN                                       // C99
    1245                 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Fortran ); }
    1246         ;
     1235                EXTERN
     1236                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
     1237                | STATIC
     1238                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
     1239                | AUTO
     1240                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
     1241                | REGISTER
     1242                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
     1243                | INLINE                                                                                // C99
     1244                                // INLINE is essentially a storage class specifier for functions, and hence, belongs here.
     1245                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }
     1246                | FORTRAN                                                                               // C99
     1247                                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Fortran ); }
     1248                ;
    12471249
    12481250basic_type_name:
    1249         CHAR
    1250                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
    1251         | DOUBLE
    1252                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
    1253         | FLOAT
    1254                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
    1255         | INT
    1256                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
    1257         | LONG
    1258                 { $$ = DeclarationNode::newModifier( DeclarationNode::Long ); }
    1259         | SHORT
    1260                 { $$ = DeclarationNode::newModifier( DeclarationNode::Short ); }
    1261         | SIGNED
    1262                 { $$ = DeclarationNode::newModifier( DeclarationNode::Signed ); }
    1263         | UNSIGNED
    1264                 { $$ = DeclarationNode::newModifier( DeclarationNode::Unsigned ); }
    1265         | VOID
    1266                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
    1267         | BOOL                                          // C99
    1268                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
    1269         | COMPLEX                                       // C99
    1270                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }
    1271         | IMAGINARY                                     // C99
    1272                 { $$ = DeclarationNode::newBasicType( DeclarationNode::Imaginary ); }
    1273         ;
     1251                CHAR
     1252                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
     1253                | DOUBLE
     1254                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
     1255                | FLOAT
     1256                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
     1257                | INT
     1258                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
     1259                | LONG
     1260                                { $$ = DeclarationNode::newModifier( DeclarationNode::Long ); }
     1261                | SHORT
     1262                                { $$ = DeclarationNode::newModifier( DeclarationNode::Short ); }
     1263                | SIGNED
     1264                                { $$ = DeclarationNode::newModifier( DeclarationNode::Signed ); }
     1265                | UNSIGNED
     1266                                { $$ = DeclarationNode::newModifier( DeclarationNode::Unsigned ); }
     1267                | VOID
     1268                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     1269                | BOOL                                                                                  // C99
     1270                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
     1271                | COMPLEX                                                                               // C99
     1272                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }
     1273                | IMAGINARY                                                                             // C99
     1274                                { $$ = DeclarationNode::newBasicType( DeclarationNode::Imaginary ); }
     1275                ;
    12741276
    12751277basic_declaration_specifier:
    1276                 // A semantic check is necessary for conflicting storage classes.
    1277         basic_type_specifier
    1278         | declaration_qualifier_list basic_type_specifier
    1279                 { $$ = $2->addQualifiers( $1 ); }
    1280         | basic_declaration_specifier storage_class     // remaining OBSOLESCENT (see 2)
    1281                 { $$ = $1->addQualifiers( $2 ); }
    1282         | basic_declaration_specifier storage_class type_qualifier_list
    1283                 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
    1284         | basic_declaration_specifier storage_class basic_type_specifier
    1285                 { $$ = $3->addQualifiers( $2 )->addType( $1 ); }
    1286         ;
     1278                                // A semantic check is necessary for conflicting storage classes.
     1279                basic_type_specifier
     1280                | declaration_qualifier_list basic_type_specifier
     1281                                { $$ = $2->addQualifiers( $1 ); }
     1282                | basic_declaration_specifier storage_class             // remaining OBSOLESCENT (see 2)
     1283                                { $$ = $1->addQualifiers( $2 ); }
     1284                | basic_declaration_specifier storage_class type_qualifier_list
     1285                                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
     1286                | basic_declaration_specifier storage_class basic_type_specifier
     1287                                { $$ = $3->addQualifiers( $2 )->addType( $1 ); }
     1288                ;
    12871289
    12881290basic_type_specifier:
    1289         direct_type_name
    1290         | type_qualifier_list_opt indirect_type_name type_qualifier_list_opt
    1291                 { $$ = $2->addQualifiers( $1 )->addQualifiers( $3 ); }
    1292         ;
     1291                direct_type_name
     1292                | type_qualifier_list_opt indirect_type_name type_qualifier_list_opt
     1293                                { $$ = $2->addQualifiers( $1 )->addQualifiers( $3 ); }
     1294                ;
    12931295
    12941296direct_type_name:
    1295                 // A semantic check is necessary for conflicting type qualifiers.
    1296         basic_type_name
    1297         | type_qualifier_list basic_type_name
    1298                 { $$ = $2->addQualifiers( $1 ); }
    1299         | direct_type_name type_qualifier
    1300                 { $$ = $1->addQualifiers( $2 ); }
    1301         | direct_type_name basic_type_name
    1302                 { $$ = $1->addType( $2 ); }
    1303         ;
     1297                                // A semantic check is necessary for conflicting type qualifiers.
     1298                basic_type_name
     1299                | type_qualifier_list basic_type_name
     1300                                { $$ = $2->addQualifiers( $1 ); }
     1301                | direct_type_name type_qualifier
     1302                                { $$ = $1->addQualifiers( $2 ); }
     1303                | direct_type_name basic_type_name
     1304                                { $$ = $1->addType( $2 ); }
     1305                ;
    13041306
    13051307indirect_type_name:
    1306         TYPEOF '(' type_name ')'                        // GCC: typeof(x) y;
    1307                 { $$ = $3; }
    1308         | TYPEOF '(' comma_expression ')'               // GCC: typeof(a+b) y;
    1309                 { $$ = DeclarationNode::newTypeof( $3 ); }
    1310         | ATTR_TYPEGENname '(' type_name ')'            // CFA: e.g., @type(x) y;
    1311                 { $$ = DeclarationNode::newAttr( $1, $3 ); }
    1312         | ATTR_TYPEGENname '(' comma_expression ')'     // CFA: e.g., @type(a+b) y;
    1313                 { $$ = DeclarationNode::newAttr( $1, $3 ); }
    1314         ;
     1308                TYPEOF '(' type_name ')'                                                // GCC: typeof(x) y;
     1309                                { $$ = $3; }
     1310                | TYPEOF '(' comma_expression ')'                               // GCC: typeof(a+b) y;
     1311                                { $$ = DeclarationNode::newTypeof( $3 ); }
     1312                | ATTR_TYPEGENname '(' type_name ')'                    // CFA: e.g., @type(x) y;
     1313                                { $$ = DeclarationNode::newAttr( $1, $3 ); }
     1314                | ATTR_TYPEGENname '(' comma_expression ')'             // CFA: e.g., @type(a+b) y;
     1315                                { $$ = DeclarationNode::newAttr( $1, $3 ); }
     1316                ;
    13151317
    13161318sue_declaration_specifier:
    1317         sue_type_specifier
    1318         | declaration_qualifier_list sue_type_specifier
    1319                 { $$ = $2->addQualifiers( $1 ); }
    1320         | sue_declaration_specifier storage_class       // remaining OBSOLESCENT (see 2)
    1321                 { $$ = $1->addQualifiers( $2 ); }
    1322         | sue_declaration_specifier storage_class type_qualifier_list
    1323                 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
    1324         ;
     1319                sue_type_specifier
     1320                | declaration_qualifier_list sue_type_specifier
     1321                                { $$ = $2->addQualifiers( $1 ); }
     1322                | sue_declaration_specifier storage_class               // remaining OBSOLESCENT (see 2)
     1323                                { $$ = $1->addQualifiers( $2 ); }
     1324                | sue_declaration_specifier storage_class type_qualifier_list
     1325                                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
     1326                ;
    13251327
    13261328sue_type_specifier:
    1327         elaborated_type_name                            // struct, union, enum
    1328         | type_qualifier_list elaborated_type_name
    1329                 { $$ = $2->addQualifiers( $1 ); }
    1330         | sue_type_specifier type_qualifier
    1331                 { $$ = $1->addQualifiers( $2 ); }
    1332         ;
     1329                elaborated_type_name                                                    // struct, union, enum
     1330                | type_qualifier_list elaborated_type_name
     1331                                { $$ = $2->addQualifiers( $1 ); }
     1332                | sue_type_specifier type_qualifier
     1333                                { $$ = $1->addQualifiers( $2 ); }
     1334                ;
    13331335
    13341336typedef_declaration_specifier:
    1335         typedef_type_specifier
    1336         | declaration_qualifier_list typedef_type_specifier
    1337                 { $$ = $2->addQualifiers( $1 ); }
    1338         | typedef_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
    1339                 { $$ = $1->addQualifiers( $2 ); }
    1340         | typedef_declaration_specifier storage_class type_qualifier_list
    1341                 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
    1342         ;
    1343 
    1344 typedef_type_specifier:                                 // typedef types
    1345         TYPEDEFname
    1346                 { $$ = DeclarationNode::newFromTypedef( $1 ); }
    1347         | type_qualifier_list TYPEDEFname
    1348                 { $$ = DeclarationNode::newFromTypedef( $2 )->addQualifiers( $1 ); }
    1349         | typedef_type_specifier type_qualifier
    1350                 { $$ = $1->addQualifiers( $2 ); }
    1351         ;
     1337                typedef_type_specifier
     1338                | declaration_qualifier_list typedef_type_specifier
     1339                                { $$ = $2->addQualifiers( $1 ); }
     1340                | typedef_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
     1341                                { $$ = $1->addQualifiers( $2 ); }
     1342                | typedef_declaration_specifier storage_class type_qualifier_list
     1343                                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
     1344                ;
     1345
     1346typedef_type_specifier:                                                                 // typedef types
     1347                TYPEDEFname
     1348                                { $$ = DeclarationNode::newFromTypedef( $1 ); }
     1349                | type_qualifier_list TYPEDEFname
     1350                                { $$ = DeclarationNode::newFromTypedef( $2 )->addQualifiers( $1 ); }
     1351                | typedef_type_specifier type_qualifier
     1352                                { $$ = $1->addQualifiers( $2 ); }
     1353                ;
    13521354
    13531355elaborated_type_name:
    1354         aggregate_name
    1355         | enum_name
    1356         ;
     1356                aggregate_name
     1357                | enum_name
     1358                ;
    13571359
    13581360aggregate_name:
    1359         aggregate_key '{' field_declaration_list '}'
    1360                 { $$ = DeclarationNode::newAggregate( $1, 0, 0, 0, $3 ); }
    1361         | aggregate_key no_attr_identifier_or_typedef_name
    1362                 { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, 0 ); }
    1363         | aggregate_key no_attr_identifier_or_typedef_name '{' field_declaration_list '}'
    1364                 { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, $4 ); }
    1365         | aggregate_key '(' push type_parameter_list pop ')' '{' field_declaration_list '}' // CFA
    1366                 { $$ = DeclarationNode::newAggregate( $1, 0, $4, 0, $8 ); }
    1367         | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name // CFA
    1368                 { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, 0 ); }
    1369         | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
    1370                 { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, $9 ); }
    1371         | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' '{' field_declaration_list '}' // CFA
    1372                 { $$ = DeclarationNode::newAggregate( $1, 0, $4, $8, $11 ); }
    1373         | aggregate_key '(' push type_name_list pop ')' no_attr_identifier_or_typedef_name // CFA
    1374                 // push and pop are only to prevent S/R conflicts
    1375                 { $$ = DeclarationNode::newAggregate( $1, $7, 0, $4, 0 ); }
    1376         | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
    1377                 { $$ = DeclarationNode::newAggregate( $1, $10, $4, $8, $12 ); }
    1378         ;
     1361                aggregate_key '{' field_declaration_list '}'
     1362                                { $$ = DeclarationNode::newAggregate( $1, 0, 0, 0, $3 ); }
     1363                | aggregate_key no_attr_identifier_or_typedef_name
     1364                                { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, 0 ); }
     1365                | aggregate_key no_attr_identifier_or_typedef_name '{' field_declaration_list '}'
     1366                                { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, $4 ); }
     1367                | aggregate_key '(' push type_parameter_list pop ')' '{' field_declaration_list '}' // CFA
     1368                                { $$ = DeclarationNode::newAggregate( $1, 0, $4, 0, $8 ); }
     1369                | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name // CFA
     1370                                { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, 0 ); }
     1371                | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
     1372                                { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, $9 ); }
     1373                | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' '{' field_declaration_list '}' // CFA
     1374                                { $$ = DeclarationNode::newAggregate( $1, 0, $4, $8, $11 ); }
     1375                | aggregate_key '(' push type_name_list pop ')' no_attr_identifier_or_typedef_name // CFA
     1376                                // push and pop are only to prevent S/R conflicts
     1377                                { $$ = DeclarationNode::newAggregate( $1, $7, 0, $4, 0 ); }
     1378                | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
     1379                                { $$ = DeclarationNode::newAggregate( $1, $10, $4, $8, $12 ); }
     1380                ;
    13791381
    13801382aggregate_key:
    1381         STRUCT attribute_list_opt
    1382                 { $$ = DeclarationNode::Struct; }
    1383         | UNION attribute_list_opt
    1384                 { $$ = DeclarationNode::Union; }
    1385         ;
     1383                STRUCT attribute_list_opt
     1384                                { $$ = DeclarationNode::Struct; }
     1385                | UNION attribute_list_opt
     1386                                { $$ = DeclarationNode::Union; }
     1387                ;
    13861388
    13871389field_declaration_list:
    1388         field_declaration
    1389                 { $$ = $1; }
    1390         | field_declaration_list field_declaration
    1391                 { $$ = $1->appendList( $2 ); }
    1392         ;
     1390                field_declaration
     1391                                { $$ = $1; }
     1392                | field_declaration_list field_declaration
     1393                                { $$ = $1->appendList( $2 ); }
     1394                ;
    13931395
    13941396field_declaration:
    1395         new_field_declaring_list ';'                    // CFA, new style field declaration
    1396         | EXTENSION new_field_declaring_list ';'        // GCC
    1397                 { $$ = $2; }
    1398         | field_declaring_list ';'
    1399         | EXTENSION field_declaring_list ';'            // GCC
    1400                 { $$ = $2; }
    1401         ;
    1402 
    1403 new_field_declaring_list:                               // CFA, new style field declaration
    1404         new_abstract_declarator_tuple                   // CFA, no field name
    1405         | new_abstract_declarator_tuple no_attr_identifier_or_typedef_name
    1406                 { $$ = $1->addName( $2 ); }
    1407         | new_field_declaring_list ',' no_attr_identifier_or_typedef_name
    1408                 { $$ = $1->appendList( $1->cloneType( $3 ) ); }
    1409         | new_field_declaring_list ','                  // CFA, no field name
    1410                 { $$ = $1->appendList( $1->cloneType( 0 ) ); }
    1411         ;
     1397                new_field_declaring_list ';'                                    // CFA, new style field declaration
     1398                | EXTENSION new_field_declaring_list ';'                // GCC
     1399                                { $$ = $2; }
     1400                | field_declaring_list ';'
     1401                | EXTENSION field_declaring_list ';'                    // GCC
     1402                                { $$ = $2; }
     1403                ;
     1404
     1405new_field_declaring_list:                                                               // CFA, new style field declaration
     1406                new_abstract_declarator_tuple                                   // CFA, no field name
     1407                | new_abstract_declarator_tuple no_attr_identifier_or_typedef_name
     1408                                { $$ = $1->addName( $2 ); }
     1409                | new_field_declaring_list ',' no_attr_identifier_or_typedef_name
     1410                                { $$ = $1->appendList( $1->cloneType( $3 ) ); }
     1411                | new_field_declaring_list ','                                  // CFA, no field name
     1412                                { $$ = $1->appendList( $1->cloneType( 0 ) ); }
     1413                ;
    14121414
    14131415field_declaring_list:
    1414         type_specifier field_declarator
    1415                 { $$ = $2->addType( $1 ); }
    1416         | field_declaring_list ',' attribute_list_opt field_declarator
    1417                 { $$ = $1->appendList( $1->cloneBaseType( $4 ) ); }
    1418         ;
     1416                type_specifier field_declarator
     1417                                { $$ = $2->addType( $1 ); }
     1418                | field_declaring_list ',' attribute_list_opt field_declarator
     1419                                { $$ = $1->appendList( $1->cloneBaseType( $4 ) ); }
     1420                ;
    14191421
    14201422field_declarator:
    1421         // empty
    1422                 { $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
    1423         | bit_subrange_size                             // no field name
    1424                 { $$ = DeclarationNode::newBitfield( $1 ); }
    1425         | variable_declarator bit_subrange_size_opt
    1426                 // A semantic check is required to ensure bit_subrange only appears on base type int.
    1427                 { $$ = $1->addBitfield( $2 ); }
    1428         | typedef_redeclarator bit_subrange_size_opt
    1429                 // A semantic check is required to ensure bit_subrange only appears on base type int.
    1430                 { $$ = $1->addBitfield( $2 ); }
    1431         | variable_abstract_declarator                  // CFA, no field name
    1432         ;
     1423                // empty
     1424                                { $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
     1425                | bit_subrange_size                                                             // no field name
     1426                                { $$ = DeclarationNode::newBitfield( $1 ); }
     1427                | variable_declarator bit_subrange_size_opt
     1428                                // A semantic check is required to ensure bit_subrange only appears on base type int.
     1429                                { $$ = $1->addBitfield( $2 ); }
     1430                | typedef_redeclarator bit_subrange_size_opt
     1431                                // A semantic check is required to ensure bit_subrange only appears on base type int.
     1432                                { $$ = $1->addBitfield( $2 ); }
     1433                | variable_abstract_declarator                                  // CFA, no field name
     1434                ;
    14331435
    14341436bit_subrange_size_opt:
    1435         // empty
    1436                 { $$ = 0; }
    1437         | bit_subrange_size
    1438                 { $$ = $1; }
    1439         ;
     1437                // empty
     1438                                { $$ = 0; }
     1439                | bit_subrange_size
     1440                                { $$ = $1; }
     1441                ;
    14401442
    14411443bit_subrange_size:
    1442         ':' constant_expression
    1443                 { $$ = $2; }
    1444         ;
     1444                ':' constant_expression
     1445                                { $$ = $2; }
     1446                ;
    14451447
    14461448enum_key:
    1447         ENUM attribute_list_opt
    1448         ;
     1449                ENUM attribute_list_opt
     1450                ;
    14491451
    14501452enum_name:
    1451         enum_key '{' enumerator_list comma_opt '}'
    1452                 { $$ = DeclarationNode::newEnum( 0, $3 ); }
    1453         | enum_key no_attr_identifier_or_typedef_name '{' enumerator_list comma_opt '}'
    1454                 { $$ = DeclarationNode::newEnum( $2, $4 ); }
    1455         | enum_key no_attr_identifier_or_typedef_name
    1456                 { $$ = DeclarationNode::newEnum( $2, 0 ); }
    1457         ;
     1453                enum_key '{' enumerator_list comma_opt '}'
     1454                                { $$ = DeclarationNode::newEnum( 0, $3 ); }
     1455                | enum_key no_attr_identifier_or_typedef_name '{' enumerator_list comma_opt '}'
     1456                                { $$ = DeclarationNode::newEnum( $2, $4 ); }
     1457                | enum_key no_attr_identifier_or_typedef_name
     1458                                { $$ = DeclarationNode::newEnum( $2, 0 ); }
     1459                ;
    14581460
    14591461enumerator_list:
    1460         no_attr_identifier_or_typedef_name enumerator_value_opt
    1461                 { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
    1462         | enumerator_list ',' no_attr_identifier_or_typedef_name enumerator_value_opt
    1463                 { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
    1464         ;
     1462                no_attr_identifier_or_typedef_name enumerator_value_opt
     1463                                { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
     1464                | enumerator_list ',' no_attr_identifier_or_typedef_name enumerator_value_opt
     1465                                { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
     1466                ;
    14651467
    14661468enumerator_value_opt:
    1467         // empty
    1468                 { $$ = 0; }
    1469         | '=' constant_expression
    1470                 { $$ = $2; }
    1471         ;
     1469                // empty
     1470                                { $$ = 0; }
     1471                | '=' constant_expression
     1472                                { $$ = $2; }
     1473                ;
    14721474
    14731475// Minimum of one parameter after which ellipsis is allowed only at the end.
    14741476
    1475 new_parameter_type_list_opt:                            // CFA
    1476         // empty
    1477                 { $$ = 0; }
    1478         | new_parameter_type_list
    1479         ;
    1480 
    1481 new_parameter_type_list:                                // CFA, abstract + real
    1482         new_abstract_parameter_list
    1483         | new_parameter_list
    1484         | new_parameter_list pop ',' push new_abstract_parameter_list
    1485                 { $$ = $1->appendList( $5 ); }
    1486         | new_abstract_parameter_list pop ',' push ELLIPSIS
    1487                 { $$ = $1->addVarArgs(); }
    1488         | new_parameter_list pop ',' push ELLIPSIS
    1489                 { $$ = $1->addVarArgs(); }
    1490         ;
    1491 
    1492 new_parameter_list:                                     // CFA
    1493                 // To obtain LR(1) between new_parameter_list and new_abstract_tuple, the last
    1494                 // new_abstract_parameter_list is factored out from new_parameter_list, flattening the rules
    1495                 // to get lookahead to the ']'.
    1496         new_parameter_declaration
    1497         | new_abstract_parameter_list pop ',' push new_parameter_declaration
    1498                 { $$ = $1->appendList( $5 ); }
    1499         | new_parameter_list pop ',' push new_parameter_declaration
    1500                 { $$ = $1->appendList( $5 ); }
    1501         | new_parameter_list pop ',' push new_abstract_parameter_list pop ',' push new_parameter_declaration
    1502                 { $$ = $1->appendList( $5 )->appendList( $9 ); }
    1503         ;
    1504 
    1505 new_abstract_parameter_list:                            // CFA, new & old style abstract
    1506         new_abstract_parameter_declaration
    1507         | new_abstract_parameter_list pop ',' push new_abstract_parameter_declaration
    1508                 { $$ = $1->appendList( $5 ); }
    1509         ;
     1477new_parameter_type_list_opt:                                                    // CFA
     1478                // empty
     1479                                { $$ = 0; }
     1480                | new_parameter_type_list
     1481                ;
     1482
     1483new_parameter_type_list:                                                                // CFA, abstract + real
     1484                new_abstract_parameter_list
     1485                | new_parameter_list
     1486                | new_parameter_list pop ',' push new_abstract_parameter_list
     1487                                { $$ = $1->appendList( $5 ); }
     1488                | new_abstract_parameter_list pop ',' push ELLIPSIS
     1489                                { $$ = $1->addVarArgs(); }
     1490                | new_parameter_list pop ',' push ELLIPSIS
     1491                                { $$ = $1->addVarArgs(); }
     1492                ;
     1493
     1494new_parameter_list:                                                                             // CFA
     1495                                // To obtain LR(1) between new_parameter_list and new_abstract_tuple, the last
     1496                                // new_abstract_parameter_list is factored out from new_parameter_list, flattening the rules
     1497                                // to get lookahead to the ']'.
     1498                new_parameter_declaration
     1499                | new_abstract_parameter_list pop ',' push new_parameter_declaration
     1500                                { $$ = $1->appendList( $5 ); }
     1501                | new_parameter_list pop ',' push new_parameter_declaration
     1502                                { $$ = $1->appendList( $5 ); }
     1503                | new_parameter_list pop ',' push new_abstract_parameter_list pop ',' push new_parameter_declaration
     1504                                { $$ = $1->appendList( $5 )->appendList( $9 ); }
     1505                ;
     1506
     1507new_abstract_parameter_list:                                                    // CFA, new & old style abstract
     1508                new_abstract_parameter_declaration
     1509                | new_abstract_parameter_list pop ',' push new_abstract_parameter_declaration
     1510                                { $$ = $1->appendList( $5 ); }
     1511                ;
    15101512
    15111513parameter_type_list_opt:
    1512         // empty
    1513                 { $$ = 0; }
    1514         | parameter_type_list
    1515         ;
     1514                // empty
     1515                                { $$ = 0; }
     1516                | parameter_type_list
     1517                ;
    15161518
    15171519parameter_type_list:
    1518         parameter_list
    1519         | parameter_list pop ',' push ELLIPSIS
    1520                 { $$ = $1->addVarArgs(); }
    1521         ;
    1522 
    1523 parameter_list:                                         // abstract + real
    1524         abstract_parameter_declaration
    1525         | parameter_declaration
    1526         | parameter_list pop ',' push abstract_parameter_declaration
    1527                 { $$ = $1->appendList( $5 ); }
    1528         | parameter_list pop ',' push parameter_declaration
    1529                 { $$ = $1->appendList( $5 ); }
    1530         ;
     1520                parameter_list
     1521                | parameter_list pop ',' push ELLIPSIS
     1522                                { $$ = $1->addVarArgs(); }
     1523                ;
     1524
     1525parameter_list:                                                                                 // abstract + real
     1526                abstract_parameter_declaration
     1527                | parameter_declaration
     1528                | parameter_list pop ',' push abstract_parameter_declaration
     1529                                { $$ = $1->appendList( $5 ); }
     1530                | parameter_list pop ',' push parameter_declaration
     1531                                { $$ = $1->appendList( $5 ); }
     1532                ;
    15311533
    15321534// Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different
     
    15341536// function prototypes.
    15351537
    1536 new_parameter_declaration:                              // CFA, new & old style parameter declaration
    1537         parameter_declaration
    1538         | new_identifier_parameter_declarator_no_tuple identifier_or_typedef_name assignment_opt
    1539                 { $$ = $1->addName( $2 ); }
    1540         | new_abstract_tuple identifier_or_typedef_name assignment_opt
    1541                 // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
    1542                 { $$ = $1->addName( $2 ); }
    1543         | type_qualifier_list new_abstract_tuple identifier_or_typedef_name assignment_opt
    1544                 { $$ = $2->addName( $3 )->addQualifiers( $1 ); }
    1545         | new_function_specifier
    1546         ;
    1547 
    1548 new_abstract_parameter_declaration:                     // CFA, new & old style parameter declaration
    1549         abstract_parameter_declaration
    1550         | new_identifier_parameter_declarator_no_tuple
    1551         | new_abstract_tuple
    1552                 // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
    1553         | type_qualifier_list new_abstract_tuple
    1554                 { $$ = $2->addQualifiers( $1 ); }
    1555         | new_abstract_function
    1556         ;
     1538new_parameter_declaration:                                                              // CFA, new & old style parameter declaration
     1539                parameter_declaration
     1540                | new_identifier_parameter_declarator_no_tuple identifier_or_typedef_name assignment_opt
     1541                                { $$ = $1->addName( $2 ); }
     1542                | new_abstract_tuple identifier_or_typedef_name assignment_opt
     1543                                // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
     1544                                { $$ = $1->addName( $2 ); }
     1545                | type_qualifier_list new_abstract_tuple identifier_or_typedef_name assignment_opt
     1546                                { $$ = $2->addName( $3 )->addQualifiers( $1 ); }
     1547                | new_function_specifier
     1548                ;
     1549
     1550new_abstract_parameter_declaration:                                             // CFA, new & old style parameter declaration
     1551                abstract_parameter_declaration
     1552                | new_identifier_parameter_declarator_no_tuple
     1553                | new_abstract_tuple
     1554                                // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
     1555                | type_qualifier_list new_abstract_tuple
     1556                                { $$ = $2->addQualifiers( $1 ); }
     1557                | new_abstract_function
     1558                ;
    15571559
    15581560parameter_declaration:
    1559         declaration_specifier identifier_parameter_declarator assignment_opt
    1560                 {
    1561                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1562                     $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
    1563                 }
    1564         | declaration_specifier typedef_parameter_redeclarator assignment_opt
    1565                 {
    1566                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1567                     $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
    1568                 }
    1569         ;
     1561                declaration_specifier identifier_parameter_declarator assignment_opt
     1562                                {
     1563                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1564                                        $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
     1565                                }
     1566                | declaration_specifier typedef_parameter_redeclarator assignment_opt
     1567                                {
     1568                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1569                                        $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
     1570                                }
     1571                ;
    15701572
    15711573abstract_parameter_declaration:
    1572         declaration_specifier
    1573         | declaration_specifier abstract_parameter_declarator
    1574                 { $$ = $2->addType( $1 ); }
    1575         ;
     1574                declaration_specifier
     1575                | declaration_specifier abstract_parameter_declarator
     1576                                { $$ = $2->addType( $1 ); }
     1577                ;
    15761578
    15771579// ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
     
    15791581// based only on identifiers.  The ANSI-style parameter-list can redefine a typedef name.
    15801582
    1581 identifier_list:                                        // K&R-style parameter list => no types
    1582         no_attr_identifier
    1583                 { $$ = DeclarationNode::newName( $1 ); }
    1584         | identifier_list ',' no_attr_identifier
    1585                 { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
    1586         ;
     1583identifier_list:                                                                                // K&R-style parameter list => no types
     1584                no_attr_identifier
     1585                                { $$ = DeclarationNode::newName( $1 ); }
     1586                | identifier_list ',' no_attr_identifier
     1587                                { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
     1588                ;
    15871589
    15881590identifier_or_typedef_name:
    1589         identifier
    1590         | TYPEDEFname
    1591         | TYPEGENname
    1592         ;
     1591                identifier
     1592                | TYPEDEFname
     1593                | TYPEGENname
     1594                ;
    15931595
    15941596no_01_identifier_or_typedef_name:
    1595         no_01_identifier
    1596         | TYPEDEFname
    1597         | TYPEGENname
    1598         ;
     1597                no_01_identifier
     1598                | TYPEDEFname
     1599                | TYPEGENname
     1600                ;
    15991601
    16001602no_attr_identifier_or_typedef_name:
    1601         no_attr_identifier
    1602         | TYPEDEFname
    1603         | TYPEGENname
    1604         ;
    1605 
    1606 type_name_no_function:                                  // sizeof, alignof, cast (constructor)
    1607         new_abstract_declarator_tuple                   // CFA
    1608         | type_specifier
    1609         | type_specifier variable_abstract_declarator
    1610                 { $$ = $2->addType( $1 ); }
    1611         ;
    1612 
    1613 type_name:                                              // typeof, assertion
    1614         new_abstract_declarator_tuple                   // CFA
    1615         | new_abstract_function                         // CFA
    1616         | type_specifier
    1617         | type_specifier abstract_declarator
    1618                 { $$ = $2->addType( $1 ); }
    1619         ;
     1603                no_attr_identifier
     1604                | TYPEDEFname
     1605                | TYPEGENname
     1606                ;
     1607
     1608type_name_no_function:                                                                  // sizeof, alignof, cast (constructor)
     1609                new_abstract_declarator_tuple                                   // CFA
     1610                | type_specifier
     1611                | type_specifier variable_abstract_declarator
     1612                                { $$ = $2->addType( $1 ); }
     1613                ;
     1614
     1615type_name:                                                                                              // typeof, assertion
     1616                new_abstract_declarator_tuple                                   // CFA
     1617                | new_abstract_function                                                 // CFA
     1618                | type_specifier
     1619                | type_specifier abstract_declarator
     1620                                { $$ = $2->addType( $1 ); }
     1621                ;
    16201622
    16211623initializer_opt:
    1622         /* empty */                                     { $$ = 0; }
    1623         | '=' initializer                               { $$ = $2; }
    1624         ;
     1624                // empty
     1625                                { $$ = 0; }
     1626                | '=' initializer                                                               { $$ = $2; }
     1627                ;
    16251628
    16261629initializer:
    1627         assignment_expression                           { $$ = new InitializerNode($1); }
    1628         | '{' initializer_list comma_opt '}'            { $$ = new InitializerNode($2, true); }
    1629         ;
     1630                assignment_expression                                                   { $$ = new InitializerNode($1); }
     1631                | '{' initializer_list comma_opt '}'                    { $$ = new InitializerNode($2, true); }
     1632                ;
    16301633
    16311634initializer_list:
    1632         initializer
    1633         | designation initializer                       { $$ = $2->set_designators( $1 ); }
    1634         | initializer_list ',' initializer              { $$ = (InitializerNode *)( $1->set_link($3) ); }
    1635         | initializer_list ',' designation initializer
    1636                                                         { $$ = (InitializerNode *)( $1->set_link( $4->set_designators($3) ) ); }
    1637         ;
    1638 
    1639 // There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem
    1640 // is use of '=' to separator the designator from the initializer value, as in:
    1641 //
    1642 //      int x[10] = { [1] = 3 };
     1635                initializer
     1636                | designation initializer                                               { $$ = $2->set_designators( $1 ); }
     1637                | initializer_list ',' initializer                              { $$ = (InitializerNode *)( $1->set_link($3) ); }
     1638                | initializer_list ',' designation initializer
     1639                                { $$ = (InitializerNode *)( $1->set_link( $4->set_designators($3) ) ); }
     1640                ;
     1641
     1642// There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem is
     1643// use of '=' to separator the designator from the initializer value, as in:
     1644//
     1645//              int x[10] = { [1] = 3 };
    16431646//
    16441647// The string "[1] = 3" can be parsed as a designator assignment or a tuple assignment.  To disambiguate this
     
    16481651
    16491652designation:
    1650         designator_list ':'                             // C99, CFA uses ":" instead of "="
    1651         | no_attr_identifier_or_typedef_name ':'        // GCC, field name
    1652                                                         { $$ = new VarRefNode( $1 ); }
    1653         ;
    1654 
    1655 designator_list:                                        // C99
    1656         designator
    1657         | designator_list designator                    { $$ = (ExpressionNode *)($1->set_link( $2 )); }
    1658         ;
     1653                designator_list ':'                                                             // C99, CFA uses ":" instead of "="
     1654                | no_attr_identifier_or_typedef_name ':'                // GCC, field name
     1655                                                { $$ = new VarRefNode( $1 ); }
     1656                ;
     1657
     1658designator_list:                                                                                // C99
     1659                designator
     1660                | designator_list designator                                            { $$ = (ExpressionNode *)($1->set_link( $2 )); }
     1661                ;
    16591662
    16601663designator:
    1661         '.' no_attr_identifier_or_typedef_name          // C99, field name
    1662                                                         { $$ = new VarRefNode( $2 ); }
    1663         | '[' push assignment_expression pop ']'        // C99, single array element
    1664                 /* assignment_expression used instead of constant_expression because of shift/reduce conflicts
    1665                    with tuple. */
    1666                                                         { $$ = $3; }
    1667         | '[' push subrange pop ']'                     // CFA, multiple array elements
    1668                                                         { $$ = $3; }
    1669         | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    1670                                                         { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $3, $5); }
    1671         | '.' '[' push field_list pop ']'               // CFA, tuple field selector
    1672                                                         { $$ = $4; }
    1673         ;
     1664                '.' no_attr_identifier_or_typedef_name                  // C99, field name
     1665                                { $$ = new VarRefNode( $2 ); }
     1666                | '[' push assignment_expression pop ']'                // C99, single array element
     1667                                // assignment_expression used instead of constant_expression because of shift/reduce conflicts
     1668                                // with tuple.
     1669                                { $$ = $3; }
     1670                | '[' push subrange pop ']'                                             // CFA, multiple array elements
     1671                                { $$ = $3; }
     1672                | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
     1673                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $3, $5); }
     1674                | '.' '[' push field_list pop ']'                               // CFA, tuple field selector
     1675                                { $$ = $4; }
     1676                ;
    16741677
    16751678// The CFA type system is based on parametric polymorphism, the ability to declare functions with type
     
    16921695//     to declare requirements on type arguments of polymorphic functions.
    16931696
    1694 typegen_declaration_specifier:                          // CFA
    1695         typegen_type_specifier
    1696         | declaration_qualifier_list typegen_type_specifier
    1697                 { $$ = $2->addQualifiers( $1 ); }
    1698         | typegen_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
    1699                 { $$ = $1->addQualifiers( $2 ); }
    1700         | typegen_declaration_specifier storage_class type_qualifier_list
    1701                 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
    1702         ;
    1703 
    1704 typegen_type_specifier:                                 // CFA
    1705         TYPEGENname '(' type_name_list ')'
    1706                 { $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
    1707         | type_qualifier_list TYPEGENname '(' type_name_list ')'
    1708                 { $$ = DeclarationNode::newFromTypeGen( $2, $4 )->addQualifiers( $1 ); }
    1709         | typegen_type_specifier type_qualifier
    1710                 { $$ = $1->addQualifiers( $2 ); }
    1711         ;
    1712 
    1713 type_parameter_list:                                    // CFA
    1714         type_parameter assignment_opt
    1715         | type_parameter_list ',' type_parameter assignment_opt
    1716                 { $$ = $1->appendList( $3 ); }
    1717         ;
    1718 
    1719 type_parameter:                                         // CFA
    1720         type_class no_attr_identifier_or_typedef_name
    1721                 { typedefTable.addToEnclosingScope(*($2), TypedefTable::TD); }
    1722           assertion_list_opt
    1723                 { $$ = DeclarationNode::newTypeParam( $1, $2 )->addAssertions( $4 ); }
    1724         | type_specifier identifier_parameter_declarator
    1725         ;
    1726 
    1727 type_class:                                             // CFA
    1728         TYPE
    1729                 { $$ = DeclarationNode::Type; }
    1730         | DTYPE
    1731                 { $$ = DeclarationNode::Ftype; }
    1732         | FTYPE
    1733                 { $$ = DeclarationNode::Dtype; }
    1734         ;
    1735 
    1736 assertion_list_opt:                                     // CFA
    1737         // empty
    1738                 { $$ = 0; }
    1739         | assertion_list_opt assertion
    1740                 { $$ = $1 == 0 ? $2 : $1->appendList( $2 ); }
    1741         ;
    1742 
    1743 assertion:                                              // CFA
    1744         '|' no_attr_identifier_or_typedef_name '(' type_name_list ')'
    1745                 {
    1746                     typedefTable.openContext( *($2) );
    1747                     $$ = DeclarationNode::newContextUse( $2, $4 );
    1748                 }
    1749         | '|' '{' push context_declaration_list '}'
    1750                 { $$ = $4; }
    1751         | '|' '(' push type_parameter_list pop ')' '{' push context_declaration_list '}' '(' type_name_list ')'
    1752                 { $$ = 0; }
    1753         ;
    1754 
    1755 type_name_list:                                         // CFA
    1756         type_name
    1757                 { $$ = new TypeValueNode( $1 ); }
    1758         | assignment_expression
    1759         | type_name_list ',' type_name
    1760                 { $$ = (ExpressionNode *)($1->set_link(new TypeValueNode( $3 ))); }
    1761         | type_name_list ',' assignment_expression
    1762                 { $$ = (ExpressionNode *)($1->set_link($3)); }
    1763         ;
    1764 
    1765 type_declaring_list:                                    // CFA
    1766         TYPE type_declarator
    1767                 { $$ = $2; }
    1768         | storage_class_list TYPE type_declarator
    1769                 { $$ = $3->addQualifiers( $1 ); }
    1770         | type_declaring_list ',' type_declarator
    1771                 { $$ = $1->appendList( $3->copyStorageClasses( $1 ) ); }
    1772         ;
    1773 
    1774 type_declarator:                                        // CFA
    1775         type_declarator_name assertion_list_opt
    1776                 { $$ = $1->addAssertions( $2 ); }
    1777         | type_declarator_name assertion_list_opt '=' type_name
    1778                 { $$ = $1->addAssertions( $2 )->addType( $4 ); }
    1779         ;
    1780 
    1781 type_declarator_name:                                   // CFA
    1782         no_attr_identifier_or_typedef_name
    1783                 {
    1784                     typedefTable.addToEnclosingScope(*($1), TypedefTable::TD);
    1785                     $$ = DeclarationNode::newTypeDecl( $1, 0 );
    1786                 }
    1787         | no_01_identifier_or_typedef_name '(' push type_parameter_list pop ')'
    1788                 {
    1789                     typedefTable.addToEnclosingScope(*($1), TypedefTable::TG);
    1790                     $$ = DeclarationNode::newTypeDecl( $1, $4 );
    1791                 }
    1792         ;
    1793 
    1794 context_specifier:                                      // CFA
    1795         CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{' '}'
    1796                 {
    1797                     typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
    1798                     $$ = DeclarationNode::newContext( $2, $5, 0 );
    1799                 }
    1800         | CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{'
    1801                 {
    1802                     typedefTable.enterContext( *($2) );
    1803                     typedefTable.enterScope();
    1804                 }
    1805           context_declaration_list '}'
    1806                 {
    1807                     typedefTable.leaveContext();
    1808                     typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
    1809                     $$ = DeclarationNode::newContext( $2, $5, $10 );
    1810                 }
    1811         ;
    1812 
    1813 context_declaration_list:                               // CFA
    1814         context_declaration
    1815         | context_declaration_list push context_declaration
    1816                 { $$ = $1->appendList( $3 ); }
    1817         ;
    1818 
    1819 context_declaration:                                    // CFA
    1820         new_context_declaring_list pop ';'
    1821         | context_declaring_list pop ';'
    1822         ;
    1823 
    1824 new_context_declaring_list:                             // CFA
    1825         new_variable_specifier
    1826                 {
    1827                     typedefTable.addToEnclosingScope2( TypedefTable::ID );
    1828                     $$ = $1;
    1829                 }
    1830         | new_function_specifier
    1831                 {
    1832                     typedefTable.addToEnclosingScope2( TypedefTable::ID );
    1833                     $$ = $1;
    1834                 }
    1835         | new_context_declaring_list pop ',' push identifier_or_typedef_name
    1836                 {
    1837                     typedefTable.addToEnclosingScope2( *($5), TypedefTable::ID );
    1838                     $$ = $1->appendList( $1->cloneType( $5 ) );
    1839                 }
    1840         ;
    1841 
    1842 context_declaring_list:                                 // CFA
    1843         type_specifier declarator
    1844                 {
    1845                     typedefTable.addToEnclosingScope2( TypedefTable::ID );
    1846                     $$ = $2->addType( $1 );
    1847                 }
    1848         | context_declaring_list pop ',' push declarator
    1849                 {
    1850                     typedefTable.addToEnclosingScope2( TypedefTable::ID );
    1851                     $$ = $1->appendList( $1->cloneBaseType( $5 ) );
    1852                 }
    1853         ;
     1697typegen_declaration_specifier:                                                  // CFA
     1698                typegen_type_specifier
     1699                | declaration_qualifier_list typegen_type_specifier
     1700                                { $$ = $2->addQualifiers( $1 ); }
     1701                | typegen_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
     1702                                { $$ = $1->addQualifiers( $2 ); }
     1703                | typegen_declaration_specifier storage_class type_qualifier_list
     1704                                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
     1705                ;
     1706
     1707typegen_type_specifier:                                                                 // CFA
     1708                TYPEGENname '(' type_name_list ')'
     1709                                { $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
     1710                | type_qualifier_list TYPEGENname '(' type_name_list ')'
     1711                                { $$ = DeclarationNode::newFromTypeGen( $2, $4 )->addQualifiers( $1 ); }
     1712                | typegen_type_specifier type_qualifier
     1713                                { $$ = $1->addQualifiers( $2 ); }
     1714                ;
     1715
     1716type_parameter_list:                                                                    // CFA
     1717                type_parameter assignment_opt
     1718                | type_parameter_list ',' type_parameter assignment_opt
     1719                                { $$ = $1->appendList( $3 ); }
     1720                ;
     1721
     1722type_parameter:                                                                                 // CFA
     1723                type_class no_attr_identifier_or_typedef_name
     1724                                { typedefTable.addToEnclosingScope(*($2), TypedefTable::TD); }
     1725                  assertion_list_opt
     1726                                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addAssertions( $4 ); }
     1727                | type_specifier identifier_parameter_declarator
     1728                ;
     1729
     1730type_class:                                                                                             // CFA
     1731                TYPE
     1732                                { $$ = DeclarationNode::Type; }
     1733                | DTYPE
     1734                                { $$ = DeclarationNode::Ftype; }
     1735                | FTYPE
     1736                                { $$ = DeclarationNode::Dtype; }
     1737                ;
     1738
     1739assertion_list_opt:                                                                             // CFA
     1740                // empty
     1741                                { $$ = 0; }
     1742                | assertion_list_opt assertion
     1743                                { $$ = $1 == 0 ? $2 : $1->appendList( $2 ); }
     1744                ;
     1745
     1746assertion:                                                                                              // CFA
     1747                '|' no_attr_identifier_or_typedef_name '(' type_name_list ')'
     1748                                {
     1749                                        typedefTable.openContext( *($2) );
     1750                                        $$ = DeclarationNode::newContextUse( $2, $4 );
     1751                                }
     1752                | '|' '{' push context_declaration_list '}'
     1753                                { $$ = $4; }
     1754                | '|' '(' push type_parameter_list pop ')' '{' push context_declaration_list '}' '(' type_name_list ')'
     1755                                { $$ = 0; }
     1756                ;
     1757
     1758type_name_list:                                                                                 // CFA
     1759                type_name
     1760                                { $$ = new TypeValueNode( $1 ); }
     1761                | assignment_expression
     1762                | type_name_list ',' type_name
     1763                                { $$ = (ExpressionNode *)($1->set_link(new TypeValueNode( $3 ))); }
     1764                | type_name_list ',' assignment_expression
     1765                                { $$ = (ExpressionNode *)($1->set_link($3)); }
     1766                ;
     1767
     1768type_declaring_list:                                                                    // CFA
     1769                TYPE type_declarator
     1770                                { $$ = $2; }
     1771                | storage_class_list TYPE type_declarator
     1772                                { $$ = $3->addQualifiers( $1 ); }
     1773                | type_declaring_list ',' type_declarator
     1774                                { $$ = $1->appendList( $3->copyStorageClasses( $1 ) ); }
     1775                ;
     1776
     1777type_declarator:                                                                                // CFA
     1778                type_declarator_name assertion_list_opt
     1779                                { $$ = $1->addAssertions( $2 ); }
     1780                | type_declarator_name assertion_list_opt '=' type_name
     1781                                { $$ = $1->addAssertions( $2 )->addType( $4 ); }
     1782                ;
     1783
     1784type_declarator_name:                                                                   // CFA
     1785                no_attr_identifier_or_typedef_name
     1786                                {
     1787                                        typedefTable.addToEnclosingScope(*($1), TypedefTable::TD);
     1788                                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
     1789                                }
     1790                | no_01_identifier_or_typedef_name '(' push type_parameter_list pop ')'
     1791                                {
     1792                                        typedefTable.addToEnclosingScope(*($1), TypedefTable::TG);
     1793                                        $$ = DeclarationNode::newTypeDecl( $1, $4 );
     1794                                }
     1795                ;
     1796
     1797context_specifier:                                                                              // CFA
     1798                CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{' '}'
     1799                                {
     1800                                        typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
     1801                                        $$ = DeclarationNode::newContext( $2, $5, 0 );
     1802                                }
     1803                | CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{'
     1804                                {
     1805                                        typedefTable.enterContext( *($2) );
     1806                                        typedefTable.enterScope();
     1807                                }
     1808                  context_declaration_list '}'
     1809                                {
     1810                                        typedefTable.leaveContext();
     1811                                        typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
     1812                                        $$ = DeclarationNode::newContext( $2, $5, $10 );
     1813                                }
     1814                ;
     1815
     1816context_declaration_list:                                                               // CFA
     1817                context_declaration
     1818                | context_declaration_list push context_declaration
     1819                                { $$ = $1->appendList( $3 ); }
     1820                ;
     1821
     1822context_declaration:                                                                    // CFA
     1823                new_context_declaring_list pop ';'
     1824                | context_declaring_list pop ';'
     1825                ;
     1826
     1827new_context_declaring_list:                                                             // CFA
     1828                new_variable_specifier
     1829                                {
     1830                                        typedefTable.addToEnclosingScope2( TypedefTable::ID );
     1831                                        $$ = $1;
     1832                                }
     1833                | new_function_specifier
     1834                                {
     1835                                        typedefTable.addToEnclosingScope2( TypedefTable::ID );
     1836                                        $$ = $1;
     1837                                }
     1838                | new_context_declaring_list pop ',' push identifier_or_typedef_name
     1839                                {
     1840                                        typedefTable.addToEnclosingScope2( *($5), TypedefTable::ID );
     1841                                        $$ = $1->appendList( $1->cloneType( $5 ) );
     1842                                }
     1843                ;
     1844
     1845context_declaring_list:                                                                 // CFA
     1846                type_specifier declarator
     1847                                {
     1848                                        typedefTable.addToEnclosingScope2( TypedefTable::ID );
     1849                                        $$ = $2->addType( $1 );
     1850                                }
     1851                | context_declaring_list pop ',' push declarator
     1852                                {
     1853                                        typedefTable.addToEnclosingScope2( TypedefTable::ID );
     1854                                        $$ = $1->appendList( $1->cloneBaseType( $5 ) );
     1855                                }
     1856                ;
    18541857
    18551858//***************************** EXTERNAL DEFINITIONS *****************************
    18561859
    18571860translation_unit:
    1858         // empty
    1859                 {}                                      // empty input file
    1860         | external_definition_list
    1861                 {
    1862                   if ( theTree ) {
    1863                     theTree->appendList( $1 );
    1864                   } else {
    1865                     theTree = $1;
    1866                   }
    1867                 }
    1868         ;
     1861                // empty
     1862                                {}                                                                              // empty input file
     1863                | external_definition_list
     1864                                {
     1865                                        if ( theTree ) {
     1866                                                theTree->appendList( $1 );
     1867                                        } else {
     1868                                                theTree = $1;
     1869                                        }
     1870                                }
     1871                ;
    18691872
    18701873external_definition_list:
    1871         external_definition
    1872         | external_definition_list push external_definition
    1873                 {
    1874                     if ( $1 ) {
    1875                         $$ = $1->appendList( $3 );
    1876                     } else {
    1877                         $$ = $3;
    1878                     }
    1879                 }
    1880         ;
     1874                external_definition
     1875                | external_definition_list push external_definition
     1876                                { $$ = ($1 != NULL ) ? $1->appendList( $3 ) : $3; }
     1877                ;
    18811878
    18821879external_definition_list_opt:
    1883         // empty
    1884                 { $$ = 0; }
    1885         | external_definition_list
    1886         ;
     1880                // empty
     1881                                { $$ = 0; }
     1882                | external_definition_list
     1883                ;
    18871884
    18881885external_definition:
    1889         declaration
    1890         | function_definition
    1891         | asm_statement                                 // GCC, global assembler statement
    1892                 {}
    1893         | EXTERN STRINGliteral
    1894                 {
    1895                   linkageStack.push( linkage );
    1896                   linkage = LinkageSpec::fromString( *$2 );
    1897                 }
    1898           '{' external_definition_list_opt '}'          // C++-style linkage specifier
    1899                 {
    1900                   linkage = linkageStack.top();
    1901                   linkageStack.pop();
    1902                   $$ = $5;
    1903                 }
    1904         | EXTENSION external_definition
    1905                 { $$ = $2; }
    1906         ;
     1886                declaration
     1887                | function_definition
     1888                | asm_statement                                                                 // GCC, global assembler statement
     1889                                {}
     1890                | EXTERN STRINGliteral
     1891                                {
     1892                                        linkageStack.push( linkage );
     1893                                        linkage = LinkageSpec::fromString( *$2 );
     1894                                }
     1895                  '{' external_definition_list_opt '}'                  // C++-style linkage specifier
     1896                                {
     1897                                        linkage = linkageStack.top();
     1898                                        linkageStack.pop();
     1899                                        $$ = $5;
     1900                                }
     1901                | EXTENSION external_definition
     1902                                { $$ = $2; }
     1903                ;
    19071904
    19081905function_definition:
    1909         new_function_specifier compound_statement       // CFA
    1910                 {
    1911                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1912                     typedefTable.leaveScope();
    1913                     $$ = $1->addFunctionBody( $2 );
    1914                 }
    1915         | declaration_qualifier_list new_function_specifier compound_statement // CFA
    1916                 // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
    1917                 // necessary to preclude them as a type_qualifier cannot appear in this context.
    1918                 {
    1919                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1920                     typedefTable.leaveScope();
    1921                     $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
    1922                 }
    1923 
    1924         | declaration_specifier function_declarator compound_statement
    1925                 {
    1926                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1927                     typedefTable.leaveScope();
    1928                     $$ = $2->addFunctionBody( $3 )->addType( $1 );
    1929                 }
    1930 
    1931                 // These rules are a concession to the "implicit int" type_specifier because there is a
    1932                 // significant amount of code with functions missing a type-specifier on the return type.
    1933                 // Parsing is possible because function_definition does not appear in the context of an
    1934                 // expression (nested functions would preclude this concession). A function prototype
    1935                 // declaration must still have a type_specifier. OBSOLESCENT (see 1)
    1936         | function_declarator compound_statement
    1937                 {
    1938                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1939                     typedefTable.leaveScope();
    1940                     $$ = $1->addFunctionBody( $2 );
    1941                 }
    1942         | type_qualifier_list function_declarator compound_statement
    1943                 {
    1944                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1945                     typedefTable.leaveScope();
    1946                     $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
    1947                 }
    1948         | declaration_qualifier_list function_declarator compound_statement
    1949                 {
    1950                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1951                     typedefTable.leaveScope();
    1952                     $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
    1953                 }
    1954         | declaration_qualifier_list type_qualifier_list function_declarator compound_statement
    1955                 {
    1956                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1957                     typedefTable.leaveScope();
    1958                     $$ = $3->addFunctionBody( $4 )->addQualifiers( $2 )->addQualifiers( $1 );
    1959                 }
    1960 
    1961                 // Old-style K&R function definition, OBSOLESCENT (see 4)
    1962         | declaration_specifier old_function_declarator push old_declaration_list_opt compound_statement
    1963                 {
    1964                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1965                     typedefTable.leaveScope();
    1966                     $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addType( $1 );
    1967                 }
    1968         | old_function_declarator push old_declaration_list_opt compound_statement
    1969                 {
    1970                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1971                     typedefTable.leaveScope();
    1972                     $$ = $1->addOldDeclList( $3 )->addFunctionBody( $4 );
    1973                 }
    1974         | type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
    1975                 {
    1976                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1977                     typedefTable.leaveScope();
    1978                     $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
    1979                 }
    1980 
    1981                 // Old-style K&R function definition with "implicit int" type_specifier, OBSOLESCENT (see 4)
    1982         | declaration_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
    1983                 {
    1984                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1985                     typedefTable.leaveScope();
    1986                     $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
    1987                 }
    1988         | declaration_qualifier_list type_qualifier_list old_function_declarator push old_declaration_list_opt
    1989                         compound_statement
    1990                 {
    1991                     typedefTable.addToEnclosingScope( TypedefTable::ID );
    1992                     typedefTable.leaveScope();
    1993                     $$ = $3->addOldDeclList( $5 )->addFunctionBody( $6 )->addQualifiers( $2 )->addQualifiers( $1 );
    1994                 }
    1995         ;
     1906                new_function_specifier compound_statement               // CFA
     1907                                {
     1908                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1909                                        typedefTable.leaveScope();
     1910                                        $$ = $1->addFunctionBody( $2 );
     1911                                }
     1912                | declaration_qualifier_list new_function_specifier compound_statement // CFA
     1913                                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
     1914                                // necessary to preclude them as a type_qualifier cannot appear in this context.
     1915                                {
     1916                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1917                                        typedefTable.leaveScope();
     1918                                        $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
     1919                                }
     1920
     1921                | declaration_specifier function_declarator compound_statement
     1922                                {
     1923                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1924                                        typedefTable.leaveScope();
     1925                                        $$ = $2->addFunctionBody( $3 )->addType( $1 );
     1926                                }
     1927
     1928                                // These rules are a concession to the "implicit int" type_specifier because there is a
     1929                                // significant amount of code with functions missing a type-specifier on the return type.
     1930                                // Parsing is possible because function_definition does not appear in the context of an
     1931                                // expression (nested functions would preclude this concession). A function prototype
     1932                                // declaration must still have a type_specifier. OBSOLESCENT (see 1)
     1933                | function_declarator compound_statement
     1934                                {
     1935                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1936                                        typedefTable.leaveScope();
     1937                                        $$ = $1->addFunctionBody( $2 );
     1938                                }
     1939                | type_qualifier_list function_declarator compound_statement
     1940                                {
     1941                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1942                                        typedefTable.leaveScope();
     1943                                        $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
     1944                                }
     1945                | declaration_qualifier_list function_declarator compound_statement
     1946                                {
     1947                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1948                                        typedefTable.leaveScope();
     1949                                        $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
     1950                                }
     1951                | declaration_qualifier_list type_qualifier_list function_declarator compound_statement
     1952                                {
     1953                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1954                                        typedefTable.leaveScope();
     1955                                        $$ = $3->addFunctionBody( $4 )->addQualifiers( $2 )->addQualifiers( $1 );
     1956                                }
     1957
     1958                                // Old-style K&R function definition, OBSOLESCENT (see 4)
     1959                | declaration_specifier old_function_declarator push old_declaration_list_opt compound_statement
     1960                                {
     1961                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1962                                        typedefTable.leaveScope();
     1963                                        $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addType( $1 );
     1964                                }
     1965                | old_function_declarator push old_declaration_list_opt compound_statement
     1966                                {
     1967                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1968                                        typedefTable.leaveScope();
     1969                                        $$ = $1->addOldDeclList( $3 )->addFunctionBody( $4 );
     1970                                }
     1971                | type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
     1972                                {
     1973                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1974                                        typedefTable.leaveScope();
     1975                                        $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
     1976                                }
     1977
     1978                                // Old-style K&R function definition with "implicit int" type_specifier, OBSOLESCENT (see 4)
     1979                | declaration_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
     1980                                {
     1981                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1982                                        typedefTable.leaveScope();
     1983                                        $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
     1984                                }
     1985                | declaration_qualifier_list type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
     1986                                {
     1987                                        typedefTable.addToEnclosingScope( TypedefTable::ID );
     1988                                        typedefTable.leaveScope();
     1989                                        $$ = $3->addOldDeclList( $5 )->addFunctionBody( $6 )->addQualifiers( $2 )->addQualifiers( $1 );
     1990                                }
     1991                ;
    19961992
    19971993declarator:
    1998         variable_declarator
    1999         | function_declarator
    2000         | typedef_redeclarator
    2001         ;
     1994                variable_declarator
     1995                | function_declarator
     1996                | typedef_redeclarator
     1997                ;
    20021998
    20031999subrange:
    2004         constant_expression '~' constant_expression     // CFA, integer subrange
    2005                 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $1, $3); }
    2006         ;
    2007 
    2008 asm_name_opt:                                           // GCC
    2009         // empty
    2010         | ASM '(' string_literal_list ')' attribute_list_opt
    2011         ;
    2012 
    2013 attribute_list_opt:                                     // GCC
    2014         // empty
    2015         | attribute_list
    2016         ;
    2017 
    2018 attribute_list:                                         // GCC
    2019         attribute
    2020         | attribute_list attribute
    2021         ;
    2022 
    2023 attribute:                                              // GCC
    2024         ATTRIBUTE '(' '(' attribute_parameter_list ')' ')'
    2025         ;
    2026 
    2027 attribute_parameter_list:                               // GCC
    2028         attrib
    2029         | attribute_parameter_list ',' attrib
    2030         ;
    2031 
    2032 attrib:                                                 // GCC
    2033         // empty
    2034         | any_word
    2035         | any_word '(' comma_expression_opt ')'
    2036         ;
    2037 
    2038 any_word:                                               // GCC
    2039         identifier_or_typedef_name {}
    2040         | storage_class_name {}
    2041         | basic_type_name {}
    2042         | type_qualifier {}
    2043         ;
     2000                constant_expression '~' constant_expression             // CFA, integer subrange
     2001                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $1, $3); }
     2002                ;
     2003
     2004asm_name_opt:                                                                                   // GCC
     2005                // empty
     2006                | ASM '(' string_literal_list ')' attribute_list_opt
     2007                ;
     2008
     2009attribute_list_opt:                                                                             // GCC
     2010                // empty
     2011                | attribute_list
     2012                ;
     2013
     2014attribute_list:                                                                                 // GCC
     2015                attribute
     2016                | attribute_list attribute
     2017                ;
     2018
     2019attribute:                                                                                              // GCC
     2020                ATTRIBUTE '(' '(' attribute_parameter_list ')' ')'
     2021                ;
     2022
     2023attribute_parameter_list:                                                               // GCC
     2024                attrib
     2025                | attribute_parameter_list ',' attrib
     2026                ;
     2027
     2028attrib:                                                                                                 // GCC
     2029                // empty
     2030                | any_word
     2031                | any_word '(' comma_expression_opt ')'
     2032                ;
     2033
     2034any_word:                                                                                               // GCC
     2035                identifier_or_typedef_name {}
     2036                | storage_class_name {}
     2037                | basic_type_name {}
     2038                | type_qualifier {}
     2039                ;
    20442040
    20452041// ============================================================================
     
    20482044// in an expression, as in:
    20492045//
    2050 //      int (*f())[10] { ... };
    2051 //      ... (*f())[3] += 1;     // definition mimics usage
     2046//              int (*f())[10] { ... };
     2047//              ... (*f())[3] += 1;             // definition mimics usage
    20522048//
    20532049// Because these patterns are highly recursive, changes at a lower level in the recursion require copying some
     
    20602056// declarators to define a variable or function prototype, e.g.:
    20612057//
    2062 //      valid declaration       invalid definition
    2063 //      -----------------       ------------------
    2064 //      int f;                  int f {}
    2065 //      int *f;                 int *f {}
    2066 //      int f[10];              int f[10] {}
    2067 //      int (*f)(int);          int (*f)(int) {}
     2058//              valid declaration               invalid definition
     2059//              -----------------               ------------------
     2060//              int f;                                          int f {}
     2061//              int *f;                                         int *f {}
     2062//              int f[10];                              int f[10] {}
     2063//              int (*f)(int);                          int (*f)(int) {}
    20682064//
    20692065// To preclude this syntactic anomaly requires separating the grammar rules for variable and function
     
    20752071
    20762072variable_declarator:
    2077         paren_identifier attribute_list_opt
    2078         | variable_ptr
    2079         | variable_array attribute_list_opt
    2080         | variable_function attribute_list_opt
    2081         ;
     2073                paren_identifier attribute_list_opt
     2074                | variable_ptr
     2075                | variable_array attribute_list_opt
     2076                | variable_function attribute_list_opt
     2077                ;
    20822078
    20832079paren_identifier:
    2084         identifier
    2085                 {
    2086                     typedefTable.setNextIdentifier( *($1) );
    2087                     $$ = DeclarationNode::newName( $1 );
    2088                 }
    2089         | '(' paren_identifier ')'                      // redundant parenthesis
    2090                 { $$ = $2; }
    2091         ;
     2080                identifier
     2081                                {
     2082                                        typedefTable.setNextIdentifier( *($1) );
     2083                                        $$ = DeclarationNode::newName( $1 );
     2084                                }
     2085                | '(' paren_identifier ')'                                              // redundant parenthesis
     2086                                { $$ = $2; }
     2087                ;
    20922088
    20932089variable_ptr:
    2094         '*' variable_declarator
    2095                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2096         | '*' type_qualifier_list variable_declarator
    2097                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2098         | '(' variable_ptr ')'
    2099                 { $$ = $2; }
    2100         ;
     2090                '*' variable_declarator
     2091                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2092                | '*' type_qualifier_list variable_declarator
     2093                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2094                | '(' variable_ptr ')'
     2095                                { $$ = $2; }
     2096                ;
    21012097
    21022098variable_array:
    2103         paren_identifier array_dimension
    2104                 { $$ = $1->addArray( $2 ); }
    2105         | '(' variable_ptr ')' array_dimension
    2106                 { $$ = $2->addArray( $4 ); }
    2107         | '(' variable_array ')' multi_array_dimension  // redundant parenthesis
    2108                 { $$ = $2->addArray( $4 ); }
    2109         | '(' variable_array ')'                        // redundant parenthesis
    2110                 { $$ = $2; }
    2111         ;
     2099                paren_identifier array_dimension
     2100                                { $$ = $1->addArray( $2 ); }
     2101                | '(' variable_ptr ')' array_dimension
     2102                                { $$ = $2->addArray( $4 ); }
     2103                | '(' variable_array ')' multi_array_dimension  // redundant parenthesis
     2104                                { $$ = $2->addArray( $4 ); }
     2105                | '(' variable_array ')'                                                // redundant parenthesis
     2106                                { $$ = $2; }
     2107                ;
    21122108
    21132109variable_function:
    2114         '(' variable_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2115                 { $$ = $2->addParamList( $6 ); }
    2116         | '(' variable_function ')'                     // redundant parenthesis
    2117                 { $$ = $2; }
    2118         ;
     2110                '(' variable_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2111                                { $$ = $2->addParamList( $6 ); }
     2112                | '(' variable_function ')'                                             // redundant parenthesis
     2113                                { $$ = $2; }
     2114                ;
    21192115
    21202116// This pattern parses a function declarator that is not redefining a typedef name. Because functions cannot
     
    21242120
    21252121function_declarator:
    2126         function_no_ptr attribute_list_opt
    2127         | function_ptr
    2128         | function_array attribute_list_opt
    2129         ;
     2122                function_no_ptr attribute_list_opt
     2123                | function_ptr
     2124                | function_array attribute_list_opt
     2125                ;
    21302126
    21312127function_no_ptr:
    2132         paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2133                 { $$ = $1->addParamList( $4 ); }
    2134         | '(' function_ptr ')' '(' push parameter_type_list_opt pop ')'
    2135                 { $$ = $2->addParamList( $6 ); }
    2136         | '(' function_no_ptr ')'                       // redundant parenthesis
    2137                 { $$ = $2; }
    2138         ;
     2128                paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2129                                { $$ = $1->addParamList( $4 ); }
     2130                | '(' function_ptr ')' '(' push parameter_type_list_opt pop ')'
     2131                                { $$ = $2->addParamList( $6 ); }
     2132                | '(' function_no_ptr ')'                                               // redundant parenthesis
     2133                                { $$ = $2; }
     2134                ;
    21392135
    21402136function_ptr:
    2141         '*' function_declarator
    2142                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2143         | '*' type_qualifier_list function_declarator
    2144                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2145         | '(' function_ptr ')'
    2146                 { $$ = $2; }
    2147         ;
     2137                '*' function_declarator
     2138                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2139                | '*' type_qualifier_list function_declarator
     2140                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2141                | '(' function_ptr ')'
     2142                                { $$ = $2; }
     2143                ;
    21482144
    21492145function_array:
    2150         '(' function_ptr ')' array_dimension
    2151                 { $$ = $2->addArray( $4 ); }
    2152         | '(' function_array ')' multi_array_dimension  // redundant parenthesis
    2153                 { $$ = $2->addArray( $4 ); }
    2154         | '(' function_array ')'                        // redundant parenthesis
    2155                 { $$ = $2; }
    2156         ;
     2146                '(' function_ptr ')' array_dimension
     2147                                { $$ = $2->addArray( $4 ); }
     2148                | '(' function_array ')' multi_array_dimension  // redundant parenthesis
     2149                                { $$ = $2->addArray( $4 ); }
     2150                | '(' function_array ')'                                                // redundant parenthesis
     2151                                { $$ = $2; }
     2152                ;
    21572153
    21582154// This pattern parses an old-style K&R function declarator (OBSOLESCENT, see 4) that is not redefining a
     
    21612157
    21622158old_function_declarator:
    2163         old_function_no_ptr
    2164         | old_function_ptr
    2165         | old_function_array
    2166         ;
     2159                old_function_no_ptr
     2160                | old_function_ptr
     2161                | old_function_array
     2162                ;
    21672163
    21682164old_function_no_ptr:
    2169         paren_identifier '(' identifier_list ')'        // function_declarator handles empty parameter
    2170                 { $$ = $1->addIdList( $3 ); }
    2171         | '(' old_function_ptr ')' '(' identifier_list ')'
    2172                 { $$ = $2->addIdList( $5 ); }
    2173         | '(' old_function_no_ptr ')'                   // redundant parenthesis
    2174                 { $$ = $2; }
    2175         ;
     2165                paren_identifier '(' identifier_list ')'                // function_declarator handles empty parameter
     2166                                { $$ = $1->addIdList( $3 ); }
     2167                | '(' old_function_ptr ')' '(' identifier_list ')'
     2168                                { $$ = $2->addIdList( $5 ); }
     2169                | '(' old_function_no_ptr ')'                                   // redundant parenthesis
     2170                                { $$ = $2; }
     2171                ;
    21762172
    21772173old_function_ptr:
    2178         '*' old_function_declarator
    2179                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2180         | '*' type_qualifier_list old_function_declarator
    2181                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2182         | '(' old_function_ptr ')'
    2183                 { $$ = $2; }
    2184         ;
     2174                '*' old_function_declarator
     2175                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2176                | '*' type_qualifier_list old_function_declarator
     2177                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2178                | '(' old_function_ptr ')'
     2179                                { $$ = $2; }
     2180                ;
    21852181
    21862182old_function_array:
    2187         '(' old_function_ptr ')' array_dimension
    2188                 { $$ = $2->addArray( $4 ); }
    2189         | '(' old_function_array ')' multi_array_dimension // redundant parenthesis
    2190                 { $$ = $2->addArray( $4 ); }
    2191         | '(' old_function_array ')'                    // redundant parenthesis
    2192                 { $$ = $2; }
    2193         ;
     2183                '(' old_function_ptr ')' array_dimension
     2184                                { $$ = $2->addArray( $4 ); }
     2185                | '(' old_function_array ')' multi_array_dimension // redundant parenthesis
     2186                                { $$ = $2->addArray( $4 ); }
     2187                | '(' old_function_array ')'                                    // redundant parenthesis
     2188                                { $$ = $2; }
     2189                ;
    21942190
    21952191// This pattern parses a declaration for a variable or function prototype that redefines a typedef name, e.g.:
    21962192//
    2197 //      typedef int foo;
    2198 //      {
    2199 //         int foo; // redefine typedef name in new scope
    2200 //      }
     2193//              typedef int foo;
     2194//              {
     2195//                 int foo; // redefine typedef name in new scope
     2196//              }
    22012197//
    22022198// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
     
    22042200
    22052201typedef_redeclarator:
    2206         paren_typedef attribute_list_opt
    2207         | typedef_ptr
    2208         | typedef_array attribute_list_opt
    2209         | typedef_function attribute_list_opt
    2210         ;
     2202                paren_typedef attribute_list_opt
     2203                | typedef_ptr
     2204                | typedef_array attribute_list_opt
     2205                | typedef_function attribute_list_opt
     2206                ;
    22112207
    22122208paren_typedef:
    2213         TYPEDEFname
    2214                 {
    2215                 typedefTable.setNextIdentifier( *($1) );
    2216                 $$ = DeclarationNode::newName( $1 );
    2217                 }
    2218         | '(' paren_typedef ')'
    2219                 { $$ = $2; }
    2220         ;
     2209                TYPEDEFname
     2210                                {
     2211                                typedefTable.setNextIdentifier( *($1) );
     2212                                $$ = DeclarationNode::newName( $1 );
     2213                                }
     2214                | '(' paren_typedef ')'
     2215                                { $$ = $2; }
     2216                ;
    22212217
    22222218typedef_ptr:
    2223         '*' typedef_redeclarator
    2224                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2225         | '*' type_qualifier_list typedef_redeclarator
    2226                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2227         | '(' typedef_ptr ')'
    2228                 { $$ = $2; }
    2229         ;
     2219                '*' typedef_redeclarator
     2220                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2221                | '*' type_qualifier_list typedef_redeclarator
     2222                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2223                | '(' typedef_ptr ')'
     2224                                { $$ = $2; }
     2225                ;
    22302226
    22312227typedef_array:
    2232         paren_typedef array_dimension
    2233                 { $$ = $1->addArray( $2 ); }
    2234         | '(' typedef_ptr ')' array_dimension
    2235                 { $$ = $2->addArray( $4 ); }
    2236         | '(' typedef_array ')' multi_array_dimension   // redundant parenthesis
    2237                 { $$ = $2->addArray( $4 ); }
    2238         | '(' typedef_array ')'                         // redundant parenthesis
    2239                 { $$ = $2; }
    2240         ;
     2228                paren_typedef array_dimension
     2229                                { $$ = $1->addArray( $2 ); }
     2230                | '(' typedef_ptr ')' array_dimension
     2231                                { $$ = $2->addArray( $4 ); }
     2232                | '(' typedef_array ')' multi_array_dimension   // redundant parenthesis
     2233                                { $$ = $2->addArray( $4 ); }
     2234                | '(' typedef_array ')'                                                 // redundant parenthesis
     2235                                { $$ = $2; }
     2236                ;
    22412237
    22422238typedef_function:
    2243         paren_typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2244                 { $$ = $1->addParamList( $4 ); }
    2245         | '(' typedef_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2246                 { $$ = $2->addParamList( $6 ); }
    2247         | '(' typedef_function ')'                      // redundant parenthesis
    2248                 { $$ = $2; }
    2249         ;
     2239                paren_typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2240                                { $$ = $1->addParamList( $4 ); }
     2241                | '(' typedef_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2242                                { $$ = $2->addParamList( $6 ); }
     2243                | '(' typedef_function ')'                                              // redundant parenthesis
     2244                                { $$ = $2; }
     2245                ;
    22502246
    22512247// This pattern parses a declaration for a parameter variable or function prototype that is not redefining a
     
    22552251
    22562252identifier_parameter_declarator:
    2257         paren_identifier attribute_list_opt
    2258         | identifier_parameter_ptr
    2259         | identifier_parameter_array attribute_list_opt
    2260         | identifier_parameter_function attribute_list_opt
    2261         ;
     2253                paren_identifier attribute_list_opt
     2254                | identifier_parameter_ptr
     2255                | identifier_parameter_array attribute_list_opt
     2256                | identifier_parameter_function attribute_list_opt
     2257                ;
    22622258
    22632259identifier_parameter_ptr:
    2264         '*' identifier_parameter_declarator
    2265                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2266         | '*' type_qualifier_list identifier_parameter_declarator
    2267                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2268         | '(' identifier_parameter_ptr ')'
    2269                 { $$ = $2; }
    2270         ;
     2260                '*' identifier_parameter_declarator
     2261                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2262                | '*' type_qualifier_list identifier_parameter_declarator
     2263                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2264                | '(' identifier_parameter_ptr ')'
     2265                                { $$ = $2; }
     2266                ;
    22712267
    22722268identifier_parameter_array:
    2273         paren_identifier array_parameter_dimension
    2274                 { $$ = $1->addArray( $2 ); }
    2275         | '(' identifier_parameter_ptr ')' array_dimension
    2276                 { $$ = $2->addArray( $4 ); }
    2277         | '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis
    2278                 { $$ = $2->addArray( $4 ); }
    2279         | '(' identifier_parameter_array ')'            // redundant parenthesis
    2280                 { $$ = $2; }
    2281         ;
     2269                paren_identifier array_parameter_dimension
     2270                                { $$ = $1->addArray( $2 ); }
     2271                | '(' identifier_parameter_ptr ')' array_dimension
     2272                                { $$ = $2->addArray( $4 ); }
     2273                | '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis
     2274                                { $$ = $2->addArray( $4 ); }
     2275                | '(' identifier_parameter_array ')'                    // redundant parenthesis
     2276                                { $$ = $2; }
     2277                ;
    22822278
    22832279identifier_parameter_function:
    2284         paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2285                 { $$ = $1->addParamList( $4 ); }
    2286         | '(' identifier_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2287                 { $$ = $2->addParamList( $6 ); }
    2288         | '(' identifier_parameter_function ')'         // redundant parenthesis
    2289                 { $$ = $2; }
    2290         ;
    2291 
    2292 // This pattern parses a declaration for a parameter variable or function prototype that is redefining a typedef name,
    2293 // e.g.:
    2294 //
    2295 //      typedef int foo;
    2296 //      int f( int foo ); // redefine typedef name in new scope
    2297 //
    2298 // and allows the C99 array options, which can only appear in a parameter list.  In addition, the pattern handles the
    2299 // special meaning of parenthesis around a typedef name:
    2300 //
    2301 //      ISO/IEC 9899:1999 Section 6.7.5.3(11) : "In a parameter declaration, a single typedef name in
    2302 //      parentheses is taken to be an abstract declarator that specifies a function with a single parameter,
    2303 //      not as redundant parentheses around the identifier."
     2280                paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2281                                { $$ = $1->addParamList( $4 ); }
     2282                | '(' identifier_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2283                                { $$ = $2->addParamList( $6 ); }
     2284                | '(' identifier_parameter_function ')'                 // redundant parenthesis
     2285                                { $$ = $2; }
     2286                ;
     2287
     2288// This pattern parses a declaration for a parameter variable or function prototype that is redefining a
     2289// typedef name, e.g.:
     2290//
     2291//              typedef int foo;
     2292//              int f( int foo ); // redefine typedef name in new scope
     2293//
     2294// and allows the C99 array options, which can only appear in a parameter list.  In addition, the pattern
     2295// handles the special meaning of parenthesis around a typedef name:
     2296//
     2297//              ISO/IEC 9899:1999 Section 6.7.5.3(11) : "In a parameter declaration, a single typedef name in
     2298//              parentheses is taken to be an abstract declarator that specifies a function with a single parameter,
     2299//              not as redundant parentheses around the identifier."
    23042300//
    23052301// which precludes the following cases:
    23062302//
    2307 //      typedef float T;
    2308 //      int f( int ( T [5] ) );                 // see abstract_parameter_declarator
    2309 //      int g( int ( T ( int ) ) );             // see abstract_parameter_declarator
    2310 //      int f( int f1( T a[5] ) );              // see identifier_parameter_declarator
    2311 //      int g( int g1( T g2( int p ) ) );       // see identifier_parameter_declarator
    2312 //
    2313 // In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type list, and
    2314 // not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes declaring an array of
    2315 // functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to arrays and
    2316 // functions.
     2303//              typedef float T;
     2304//              int f( int ( T [5] ) );                                         // see abstract_parameter_declarator
     2305//              int g( int ( T ( int ) ) );                             // see abstract_parameter_declarator
     2306//              int f( int f1( T a[5] ) );                              // see identifier_parameter_declarator
     2307//              int g( int g1( T g2( int p ) ) );               // see identifier_parameter_declarator
     2308//
     2309// In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type
     2310// list, and not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes
     2311// declaring an array of functions versus a pointer to an array of functions, and returning arrays and
     2312// functions versus pointers to arrays and functions.
    23172313
    23182314typedef_parameter_redeclarator:
    2319         typedef attribute_list_opt
    2320         | typedef_parameter_ptr
    2321         | typedef_parameter_array attribute_list_opt
    2322         | typedef_parameter_function attribute_list_opt
    2323         ;
     2315                typedef attribute_list_opt
     2316                | typedef_parameter_ptr
     2317                | typedef_parameter_array attribute_list_opt
     2318                | typedef_parameter_function attribute_list_opt
     2319                ;
    23242320
    23252321typedef:
    2326         TYPEDEFname
    2327                 {
    2328                     typedefTable.setNextIdentifier( *($1) );
    2329                     $$ = DeclarationNode::newName( $1 );
    2330                 }
    2331         ;
     2322                TYPEDEFname
     2323                                {
     2324                                        typedefTable.setNextIdentifier( *($1) );
     2325                                        $$ = DeclarationNode::newName( $1 );
     2326                                }
     2327                ;
    23322328
    23332329typedef_parameter_ptr:
    2334         '*' typedef_parameter_redeclarator
    2335                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2336         | '*' type_qualifier_list typedef_parameter_redeclarator
    2337                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2338         | '(' typedef_parameter_ptr ')'
    2339                 { $$ = $2; }
    2340         ;
     2330                '*' typedef_parameter_redeclarator
     2331                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2332                | '*' type_qualifier_list typedef_parameter_redeclarator
     2333                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2334                | '(' typedef_parameter_ptr ')'
     2335                                { $$ = $2; }
     2336                ;
    23412337
    23422338typedef_parameter_array:
    2343         typedef array_parameter_dimension
    2344                 { $$ = $1->addArray( $2 ); }
    2345         | '(' typedef_parameter_ptr ')' array_parameter_dimension
    2346                 { $$ = $2->addArray( $4 ); }
    2347         ;
     2339                typedef array_parameter_dimension
     2340                                { $$ = $1->addArray( $2 ); }
     2341                | '(' typedef_parameter_ptr ')' array_parameter_dimension
     2342                                { $$ = $2->addArray( $4 ); }
     2343                ;
    23482344
    23492345typedef_parameter_function:
    2350         typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2351                 { $$ = $1->addParamList( $4 ); }
    2352         | '(' typedef_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2353                 { $$ = $2->addParamList( $6 ); }
    2354         ;
    2355 
    2356 // This pattern parses a declaration of an abstract variable or function prototype, i.e., there is no identifier to
    2357 // which the type applies, e.g.:
    2358 //
    2359 //      sizeof( int );
    2360 //      sizeof( int [10] );
    2361 //
    2362 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
    2363 // and functions versus pointers to arrays and functions.
     2346                typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2347                                { $$ = $1->addParamList( $4 ); }
     2348                | '(' typedef_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2349                                { $$ = $2->addParamList( $6 ); }
     2350                ;
     2351
     2352// This pattern parses a declaration of an abstract variable or function prototype, i.e., there is no
     2353// identifier to which the type applies, e.g.:
     2354//
     2355//              sizeof( int );
     2356//              sizeof( int [10] );
     2357//
     2358// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
     2359// returning arrays and functions versus pointers to arrays and functions.
    23642360
    23652361abstract_declarator:
    2366         abstract_ptr
    2367         | abstract_array attribute_list_opt
    2368         | abstract_function attribute_list_opt
    2369         ;
     2362                abstract_ptr
     2363                | abstract_array attribute_list_opt
     2364                | abstract_function attribute_list_opt
     2365                ;
    23702366
    23712367abstract_ptr:
    2372         '*'
    2373                 { $$ = DeclarationNode::newPointer( 0 ); }
    2374         | '*' type_qualifier_list
    2375                 { $$ = DeclarationNode::newPointer( $2 ); }
    2376         | '*' abstract_declarator
    2377                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2378         | '*' type_qualifier_list abstract_declarator
    2379                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2380         | '(' abstract_ptr ')'
    2381                 { $$ = $2; }
    2382         ;
     2368                '*'
     2369                                { $$ = DeclarationNode::newPointer( 0 ); }
     2370                | '*' type_qualifier_list
     2371                                { $$ = DeclarationNode::newPointer( $2 ); }
     2372                | '*' abstract_declarator
     2373                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2374                | '*' type_qualifier_list abstract_declarator
     2375                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2376                | '(' abstract_ptr ')'
     2377                                { $$ = $2; }
     2378                ;
    23832379
    23842380abstract_array:
    2385         array_dimension
    2386         | '(' abstract_ptr ')' array_dimension
    2387                 { $$ = $2->addArray( $4 ); }
    2388         | '(' abstract_array ')' multi_array_dimension  // redundant parenthesis
    2389                 { $$ = $2->addArray( $4 ); }
    2390         | '(' abstract_array ')'                        // redundant parenthesis
    2391                 { $$ = $2; }
    2392         ;
     2381                array_dimension
     2382                | '(' abstract_ptr ')' array_dimension
     2383                                { $$ = $2->addArray( $4 ); }
     2384                | '(' abstract_array ')' multi_array_dimension  // redundant parenthesis
     2385                                { $$ = $2->addArray( $4 ); }
     2386                | '(' abstract_array ')'                                                // redundant parenthesis
     2387                                { $$ = $2; }
     2388                ;
    23932389
    23942390abstract_function:
    2395         '(' push parameter_type_list_opt pop ')'        // empty parameter list OBSOLESCENT (see 3)
    2396                 { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
    2397         | '(' abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2398                 { $$ = $2->addParamList( $6 ); }
    2399         | '(' abstract_function ')'                     // redundant parenthesis
    2400                 { $$ = $2; }
    2401         ;
     2391                '(' push parameter_type_list_opt pop ')'                // empty parameter list OBSOLESCENT (see 3)
     2392                                { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
     2393                | '(' abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2394                                { $$ = $2->addParamList( $6 ); }
     2395                | '(' abstract_function ')'                                             // redundant parenthesis
     2396                                { $$ = $2; }
     2397                ;
    24022398
    24032399array_dimension:
    2404                 // Only the first dimension can be empty.
    2405         '[' push pop ']'
    2406                 { $$ = DeclarationNode::newArray( 0, 0, false ); }
    2407         | '[' push pop ']' multi_array_dimension
    2408                 { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $5 ); }
    2409         | multi_array_dimension
    2410         ;
     2400                                // Only the first dimension can be empty.
     2401                '[' push pop ']'
     2402                                { $$ = DeclarationNode::newArray( 0, 0, false ); }
     2403                | '[' push pop ']' multi_array_dimension
     2404                                { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $5 ); }
     2405                | multi_array_dimension
     2406                ;
    24112407
    24122408multi_array_dimension:
    2413         '[' push assignment_expression pop ']'
    2414                 { $$ = DeclarationNode::newArray( $3, 0, false ); }
    2415         | '[' push '*' pop ']'                          // C99
    2416                 { $$ = DeclarationNode::newVarArray( 0 ); }
    2417         | multi_array_dimension '[' push assignment_expression pop ']'
    2418                 { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
    2419         | multi_array_dimension '[' push '*' pop ']'    // C99
    2420                 { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
    2421         ;
     2409                '[' push assignment_expression pop ']'
     2410                                { $$ = DeclarationNode::newArray( $3, 0, false ); }
     2411                | '[' push '*' pop ']'                                                          // C99
     2412                                { $$ = DeclarationNode::newVarArray( 0 ); }
     2413                | multi_array_dimension '[' push assignment_expression pop ']'
     2414                                { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
     2415                | multi_array_dimension '[' push '*' pop ']'            // C99
     2416                                { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
     2417                ;
    24222418
    24232419// This pattern parses a declaration of a parameter abstract variable or function prototype, i.e., there is no
    24242420// identifier to which the type applies, e.g.:
    24252421//
    2426 //      int f( int );           // abstract variable parameter; no parameter name specified
    2427 //      int f( int (int) );     // abstract function-prototype parameter; no parameter name specified
    2428 //
    2429 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
    2430 // and functions versus pointers to arrays and functions. */
     2422//              int f( int );                   // abstract variable parameter; no parameter name specified
     2423//              int f( int (int) );             // abstract function-prototype parameter; no parameter name specified
     2424//
     2425// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
     2426// returning arrays and functions versus pointers to arrays and functions.
    24312427
    24322428abstract_parameter_declarator:
    2433         abstract_parameter_ptr
    2434         | abstract_parameter_array attribute_list_opt
    2435         | abstract_parameter_function attribute_list_opt
    2436         ;
     2429                abstract_parameter_ptr
     2430                | abstract_parameter_array attribute_list_opt
     2431                | abstract_parameter_function attribute_list_opt
     2432                ;
    24372433
    24382434abstract_parameter_ptr:
    2439         '*'
    2440                 { $$ = DeclarationNode::newPointer( 0 ); }
    2441         | '*' type_qualifier_list
    2442                 { $$ = DeclarationNode::newPointer( $2 ); }
    2443         | '*' abstract_parameter_declarator
    2444                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2445         | '*' type_qualifier_list abstract_parameter_declarator
    2446                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2447         | '(' abstract_parameter_ptr ')'
    2448                 { $$ = $2; }
    2449         ;
     2435                '*'
     2436                                { $$ = DeclarationNode::newPointer( 0 ); }
     2437                | '*' type_qualifier_list
     2438                                { $$ = DeclarationNode::newPointer( $2 ); }
     2439                | '*' abstract_parameter_declarator
     2440                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2441                | '*' type_qualifier_list abstract_parameter_declarator
     2442                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2443                | '(' abstract_parameter_ptr ')'
     2444                                { $$ = $2; }
     2445                ;
    24502446
    24512447abstract_parameter_array:
    2452         array_parameter_dimension
    2453         | '(' abstract_parameter_ptr ')' array_parameter_dimension
    2454                 { $$ = $2->addArray( $4 ); }
    2455         | '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis
    2456                 { $$ = $2->addArray( $4 ); }
    2457         | '(' abstract_parameter_array ')'              // redundant parenthesis
    2458                 { $$ = $2; }
    2459         ;
     2448                array_parameter_dimension
     2449                | '(' abstract_parameter_ptr ')' array_parameter_dimension
     2450                                { $$ = $2->addArray( $4 ); }
     2451                | '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis
     2452                                { $$ = $2->addArray( $4 ); }
     2453                | '(' abstract_parameter_array ')'                              // redundant parenthesis
     2454                                { $$ = $2; }
     2455                ;
    24602456
    24612457abstract_parameter_function:
    2462         '(' push parameter_type_list_opt pop ')'        // empty parameter list OBSOLESCENT (see 3)
    2463                 { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
    2464         | '(' abstract_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2465                 { $$ = $2->addParamList( $6 ); }
    2466         | '(' abstract_parameter_function ')'           // redundant parenthesis
    2467                 { $$ = $2; }
    2468         ;
     2458                '(' push parameter_type_list_opt pop ')'                // empty parameter list OBSOLESCENT (see 3)
     2459                                { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
     2460                | '(' abstract_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2461                                { $$ = $2->addParamList( $6 ); }
     2462                | '(' abstract_parameter_function ')'                   // redundant parenthesis
     2463                                { $$ = $2; }
     2464                ;
    24692465
    24702466array_parameter_dimension:
    2471                 // Only the first dimension can be empty or have qualifiers.
    2472         array_parameter_1st_dimension
    2473         | array_parameter_1st_dimension multi_array_dimension
    2474                 { $$ = $1->addArray( $2 ); }
    2475         | multi_array_dimension
    2476         ;
     2467                                // Only the first dimension can be empty or have qualifiers.
     2468                array_parameter_1st_dimension
     2469                | array_parameter_1st_dimension multi_array_dimension
     2470                                { $$ = $1->addArray( $2 ); }
     2471                | multi_array_dimension
     2472                ;
    24772473
    24782474// The declaration of an array parameter has additional syntax over arrays in normal variable declarations:
    24792475//
    2480 //      ISO/IEC 9899:1999 Section 6.7.5.2(1) : "The optional type qualifiers and the keyword static shall appear only in
    2481 //      a declaration of a function parameter with an array type, and then only in the outermost array type derivation."
     2476//              ISO/IEC 9899:1999 Section 6.7.5.2(1) : "The optional type qualifiers and the keyword static shall
     2477//              appear only in a declaration of a function parameter with an array type, and then only in the
     2478//              outermost array type derivation."
    24822479
    24832480array_parameter_1st_dimension:
    2484         '[' push pop ']'
    2485                 { $$ = DeclarationNode::newArray( 0, 0, false ); }
    2486         // multi_array_dimension handles the '[' '*' ']' case
    2487         | '[' push type_qualifier_list '*' pop ']'      // remaining C99
    2488                 { $$ = DeclarationNode::newVarArray( $3 ); }
    2489         | '[' push type_qualifier_list pop ']'
    2490                 { $$ = DeclarationNode::newArray( 0, $3, false ); }
    2491         // multi_array_dimension handles the '[' assignment_expression ']' case
    2492         | '[' push type_qualifier_list assignment_expression pop ']'
    2493                 { $$ = DeclarationNode::newArray( $4, $3, false ); }
    2494         | '[' push STATIC type_qualifier_list_opt assignment_expression pop ']'
    2495                 { $$ = DeclarationNode::newArray( $5, $4, true ); }
    2496         | '[' push type_qualifier_list STATIC assignment_expression pop ']'
    2497                 { $$ = DeclarationNode::newArray( $5, $3, true ); }
    2498         ;
    2499 
    2500 // This pattern parses a declaration of an abstract variable, i.e., there is no identifier to which the type applies,
    2501 // e.g.:
    2502 //
    2503 //      sizeof( int ); // abstract variable; no identifier name specified
    2504 //
    2505 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
    2506 // and functions versus pointers to arrays and functions. */
     2481                '[' push pop ']'
     2482                                { $$ = DeclarationNode::newArray( 0, 0, false ); }
     2483                // multi_array_dimension handles the '[' '*' ']' case
     2484                | '[' push type_qualifier_list '*' pop ']'              // remaining C99
     2485                                { $$ = DeclarationNode::newVarArray( $3 ); }
     2486                | '[' push type_qualifier_list pop ']'
     2487                                { $$ = DeclarationNode::newArray( 0, $3, false ); }
     2488                // multi_array_dimension handles the '[' assignment_expression ']' case
     2489                | '[' push type_qualifier_list assignment_expression pop ']'
     2490                                { $$ = DeclarationNode::newArray( $4, $3, false ); }
     2491                | '[' push STATIC type_qualifier_list_opt assignment_expression pop ']'
     2492                                { $$ = DeclarationNode::newArray( $5, $4, true ); }
     2493                | '[' push type_qualifier_list STATIC assignment_expression pop ']'
     2494                                { $$ = DeclarationNode::newArray( $5, $3, true ); }
     2495                ;
     2496
     2497// This pattern parses a declaration of an abstract variable, i.e., there is no identifier to which the type
     2498// applies, e.g.:
     2499//
     2500//              sizeof( int ); // abstract variable; no identifier name specified
     2501//
     2502// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
     2503// returning arrays and functions versus pointers to arrays and functions.
    25072504
    25082505variable_abstract_declarator:
    2509         variable_abstract_ptr
    2510         | variable_abstract_array attribute_list_opt
    2511         | variable_abstract_function attribute_list_opt
    2512         ;
     2506                variable_abstract_ptr
     2507                | variable_abstract_array attribute_list_opt
     2508                | variable_abstract_function attribute_list_opt
     2509                ;
    25132510
    25142511variable_abstract_ptr:
    2515         '*'
    2516                 { $$ = DeclarationNode::newPointer( 0 ); }
    2517         | '*' type_qualifier_list
    2518                 { $$ = DeclarationNode::newPointer( $2 ); }
    2519         | '*' variable_abstract_declarator
    2520                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
    2521         | '*' type_qualifier_list variable_abstract_declarator
    2522                 { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
    2523         | '(' variable_abstract_ptr ')'
    2524                 { $$ = $2; }
    2525         ;
     2512                '*'
     2513                                { $$ = DeclarationNode::newPointer( 0 ); }
     2514                | '*' type_qualifier_list
     2515                                { $$ = DeclarationNode::newPointer( $2 ); }
     2516                | '*' variable_abstract_declarator
     2517                                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
     2518                | '*' type_qualifier_list variable_abstract_declarator
     2519                                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
     2520                | '(' variable_abstract_ptr ')'
     2521                                { $$ = $2; }
     2522                ;
    25262523
    25272524variable_abstract_array:
    2528         array_dimension
    2529         | '(' variable_abstract_ptr ')' array_dimension
    2530                 { $$ = $2->addArray( $4 ); }
    2531         | '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis
    2532                 { $$ = $2->addArray( $4 ); }
    2533         | '(' variable_abstract_array ')'               // redundant parenthesis
    2534                 { $$ = $2; }
    2535         ;
     2525                array_dimension
     2526                | '(' variable_abstract_ptr ')' array_dimension
     2527                                { $$ = $2->addArray( $4 ); }
     2528                | '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis
     2529                                { $$ = $2->addArray( $4 ); }
     2530                | '(' variable_abstract_array ')'                               // redundant parenthesis
     2531                                { $$ = $2; }
     2532                ;
    25362533
    25372534variable_abstract_function:
    2538         '(' variable_abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    2539                 { $$ = $2->addParamList( $6 ); }
    2540         | '(' variable_abstract_function ')'            // redundant parenthesis
    2541                 { $$ = $2; }
    2542         ;
    2543 
    2544 // This pattern parses a new-style declaration for a parameter variable or function prototype that is either an
    2545 // identifier or typedef name and allows the C99 array options, which can only appear in a parameter list.
    2546 
    2547 new_identifier_parameter_declarator_tuple:              // CFA
    2548         new_identifier_parameter_declarator_no_tuple
    2549         | new_abstract_tuple
    2550         | type_qualifier_list new_abstract_tuple
    2551                 { $$ = $2->addQualifiers( $1 ); }
    2552         ;
    2553 
    2554 new_identifier_parameter_declarator_no_tuple:           // CFA
    2555         new_identifier_parameter_ptr
    2556         | new_identifier_parameter_array
    2557         ;
    2558 
    2559 new_identifier_parameter_ptr:                           // CFA
    2560         '*' type_specifier
    2561                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2562         | type_qualifier_list '*' type_specifier
    2563                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2564         | '*' new_abstract_function
    2565                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2566         | type_qualifier_list '*' new_abstract_function
    2567                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2568         | '*' new_identifier_parameter_declarator_tuple
    2569                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2570         | type_qualifier_list '*' new_identifier_parameter_declarator_tuple
    2571                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2572         ;
    2573 
    2574 new_identifier_parameter_array:                         // CFA
    2575                 // Only the first dimension can be empty or have qualifiers. Empty dimension must be factored out due to
    2576                 // shift/reduce conflict with new-style empty (void) function return type. */
    2577         '[' push pop ']' type_specifier
    2578                 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2579         | new_array_parameter_1st_dimension type_specifier
    2580                 { $$ = $2->addNewArray( $1 ); }
    2581         | '[' push pop ']' multi_array_dimension type_specifier
    2582                 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2583         | new_array_parameter_1st_dimension multi_array_dimension type_specifier
    2584                 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
    2585         | multi_array_dimension type_specifier
    2586                 { $$ = $2->addNewArray( $1 ); }
    2587         | '[' push pop ']' new_identifier_parameter_ptr
    2588                 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2589         | new_array_parameter_1st_dimension new_identifier_parameter_ptr
    2590                 { $$ = $2->addNewArray( $1 ); }
    2591         | '[' push pop ']' multi_array_dimension new_identifier_parameter_ptr
    2592                 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2593         | new_array_parameter_1st_dimension multi_array_dimension new_identifier_parameter_ptr
    2594                 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
    2595         | multi_array_dimension new_identifier_parameter_ptr
    2596                 { $$ = $2->addNewArray( $1 ); }
    2597         ;
     2535                '(' variable_abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     2536                                { $$ = $2->addParamList( $6 ); }
     2537                | '(' variable_abstract_function ')'                    // redundant parenthesis
     2538                                { $$ = $2; }
     2539                ;
     2540
     2541// This pattern parses a new-style declaration for a parameter variable or function prototype that is either
     2542// an identifier or typedef name and allows the C99 array options, which can only appear in a parameter list.
     2543
     2544new_identifier_parameter_declarator_tuple:                              // CFA
     2545                new_identifier_parameter_declarator_no_tuple
     2546                | new_abstract_tuple
     2547                | type_qualifier_list new_abstract_tuple
     2548                                { $$ = $2->addQualifiers( $1 ); }
     2549                ;
     2550
     2551new_identifier_parameter_declarator_no_tuple:                   // CFA
     2552                new_identifier_parameter_ptr
     2553                | new_identifier_parameter_array
     2554                ;
     2555
     2556new_identifier_parameter_ptr:                                                   // CFA
     2557                '*' type_specifier
     2558                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2559                | type_qualifier_list '*' type_specifier
     2560                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2561                | '*' new_abstract_function
     2562                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2563                | type_qualifier_list '*' new_abstract_function
     2564                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2565                | '*' new_identifier_parameter_declarator_tuple
     2566                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2567                | type_qualifier_list '*' new_identifier_parameter_declarator_tuple
     2568                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2569                ;
     2570
     2571new_identifier_parameter_array:                                                 // CFA
     2572                                // Only the first dimension can be empty or have qualifiers. Empty dimension must be factored
     2573                                // out due to shift/reduce conflict with new-style empty (void) function return type.
     2574                '[' push pop ']' type_specifier
     2575                                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2576                | new_array_parameter_1st_dimension type_specifier
     2577                                { $$ = $2->addNewArray( $1 ); }
     2578                | '[' push pop ']' multi_array_dimension type_specifier
     2579                                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2580                | new_array_parameter_1st_dimension multi_array_dimension type_specifier
     2581                                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     2582                | multi_array_dimension type_specifier
     2583                                { $$ = $2->addNewArray( $1 ); }
     2584                | '[' push pop ']' new_identifier_parameter_ptr
     2585                                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2586                | new_array_parameter_1st_dimension new_identifier_parameter_ptr
     2587                                { $$ = $2->addNewArray( $1 ); }
     2588                | '[' push pop ']' multi_array_dimension new_identifier_parameter_ptr
     2589                                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2590                | new_array_parameter_1st_dimension multi_array_dimension new_identifier_parameter_ptr
     2591                                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     2592                | multi_array_dimension new_identifier_parameter_ptr
     2593                                { $$ = $2->addNewArray( $1 ); }
     2594                ;
    25982595
    25992596new_array_parameter_1st_dimension:
    2600         '[' push type_qualifier_list '*' pop ']'        // remaining C99
    2601                 { $$ = DeclarationNode::newVarArray( $3 ); }
    2602         | '[' push type_qualifier_list assignment_expression pop ']'
    2603                 { $$ = DeclarationNode::newArray( $4, $3, false ); }
    2604         | '[' push declaration_qualifier_list assignment_expression pop ']'
    2605                 // declaration_qualifier_list must be used because of shift/reduce conflict with assignment_expression,
    2606                 // so a semantic check is necessary to preclude them as a type_qualifier cannot appear in this
    2607                 // context.
    2608                 { $$ = DeclarationNode::newArray( $4, $3, true ); }
    2609         | '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']'
    2610                 { $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); }
    2611         ;
    2612 
    2613 // This pattern parses a new-style declaration of an abstract variable or function prototype, i.e., there is no
    2614 // identifier to which the type applies, e.g.:
    2615 //
    2616 //      [int] f( int );         // abstract variable parameter; no parameter name specified
    2617 //      [int] f( [int] (int) ); // abstract function-prototype parameter; no parameter name specified
     2597                '[' push type_qualifier_list '*' pop ']'                // remaining C99
     2598                                { $$ = DeclarationNode::newVarArray( $3 ); }
     2599                | '[' push type_qualifier_list assignment_expression pop ']'
     2600                                { $$ = DeclarationNode::newArray( $4, $3, false ); }
     2601                | '[' push declaration_qualifier_list assignment_expression pop ']'
     2602                                // declaration_qualifier_list must be used because of shift/reduce conflict with
     2603                                // assignment_expression, so a semantic check is necessary to preclude them as a
     2604                                // type_qualifier cannot appear in this context.
     2605                                { $$ = DeclarationNode::newArray( $4, $3, true ); }
     2606                | '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']'
     2607                                { $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); }
     2608                ;
     2609
     2610// This pattern parses a new-style declaration of an abstract variable or function prototype, i.e., there is
     2611// no identifier to which the type applies, e.g.:
     2612//
     2613//              [int] f( int );                         // abstract variable parameter; no parameter name specified
     2614//              [int] f( [int] (int) );         // abstract function-prototype parameter; no parameter name specified
    26182615//
    26192616// These rules need LR(3):
    26202617//
    2621 //      new_abstract_tuple identifier_or_typedef_name
    2622 //      '[' new_parameter_list ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
     2618//              new_abstract_tuple identifier_or_typedef_name
     2619//              '[' new_parameter_list ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
    26232620//
    26242621// since a function return type can be syntactically identical to a tuple type:
    26252622//
    2626 //      [int, int] t;
    2627 //      [int, int] f( int );
     2623//              [int, int] t;
     2624//              [int, int] f( int );
    26282625//
    26292626// Therefore, it is necessary to look at the token after identifier_or_typedef_name to know when to reduce
    2630 // new_abstract_tuple. To make this LR(1), several rules have to be flattened (lengthened) to allow the necessary
    2631 // lookahead. To accomplish this, new_abstract_declarator has an entry point without tuple, and tuple declarations are
    2632 // duplicated when appearing with new_function_specifier.
    2633 
    2634 new_abstract_declarator_tuple:                          // CFA
    2635         new_abstract_tuple
    2636         | type_qualifier_list new_abstract_tuple
    2637                 { $$ = $2->addQualifiers( $1 ); }
    2638         | new_abstract_declarator_no_tuple
    2639         ;
    2640 
    2641 new_abstract_declarator_no_tuple:                       // CFA
    2642         new_abstract_ptr
    2643         | new_abstract_array
    2644         ;
    2645 
    2646 new_abstract_ptr:                                       // CFA
    2647         '*' type_specifier
    2648                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2649         | type_qualifier_list '*' type_specifier
    2650                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2651         | '*' new_abstract_function
    2652                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2653         | type_qualifier_list '*' new_abstract_function
    2654                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2655         | '*' new_abstract_declarator_tuple
    2656                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
    2657         | type_qualifier_list '*' new_abstract_declarator_tuple
    2658                 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
    2659         ;
    2660 
    2661 new_abstract_array:                                     // CFA
    2662                 // Only the first dimension can be empty. Empty dimension must be factored out due to shift/reduce
    2663                 // conflict with empty (void) function return type.
    2664         '[' push pop ']' type_specifier
    2665                 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2666         | '[' push pop ']' multi_array_dimension type_specifier
    2667                 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2668         | multi_array_dimension type_specifier
    2669                 { $$ = $2->addNewArray( $1 ); }
    2670         | '[' push pop ']' new_abstract_ptr
    2671                 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2672         | '[' push pop ']' multi_array_dimension new_abstract_ptr
    2673                 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
    2674         | multi_array_dimension new_abstract_ptr
    2675                 { $$ = $2->addNewArray( $1 ); }
    2676         ;
    2677 
    2678 new_abstract_tuple:                                     // CFA
    2679         '[' push new_abstract_parameter_list pop ']'
    2680                 { $$ = DeclarationNode::newTuple( $3 ); }
    2681         ;
    2682 
    2683 new_abstract_function:                                  // CFA
    2684         '[' push pop ']' '(' new_parameter_type_list_opt ')'
    2685                 { $$ = DeclarationNode::newFunction( 0, DeclarationNode::newTuple( 0 ), $6, 0 ); }
    2686         | new_abstract_tuple '(' push new_parameter_type_list_opt pop ')'
    2687                 { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
    2688         | new_function_return '(' push new_parameter_type_list_opt pop ')'
    2689                 { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
    2690         ;
    2691 
    2692 // 1) ISO/IEC 9899:1999 Section 6.7.2(2) : "At least one type specifier shall be given in the declaration specifiers in
    2693 //    each declaration, and in the specifier-qualifier list in each structure declaration and type name."
    2694 //
    2695 // 2) ISO/IEC 9899:1999 Section 6.11.5(1) : "The placement of a storage-class specifier other than at the beginning of
    2696 //    the declaration specifiers in a declaration is an obsolescent feature."
     2627// new_abstract_tuple. To make this LR(1), several rules have to be flattened (lengthened) to allow the
     2628// necessary lookahead. To accomplish this, new_abstract_declarator has an entry point without tuple, and
     2629// tuple declarations are duplicated when appearing with new_function_specifier.
     2630
     2631new_abstract_declarator_tuple:                                                  // CFA
     2632                new_abstract_tuple
     2633                | type_qualifier_list new_abstract_tuple
     2634                                { $$ = $2->addQualifiers( $1 ); }
     2635                | new_abstract_declarator_no_tuple
     2636                ;
     2637
     2638new_abstract_declarator_no_tuple:                                               // CFA
     2639                new_abstract_ptr
     2640                | new_abstract_array
     2641                ;
     2642
     2643new_abstract_ptr:                                                                               // CFA
     2644                '*' type_specifier
     2645                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2646                | type_qualifier_list '*' type_specifier
     2647                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2648                | '*' new_abstract_function
     2649                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2650                | type_qualifier_list '*' new_abstract_function
     2651                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2652                | '*' new_abstract_declarator_tuple
     2653                                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     2654                | type_qualifier_list '*' new_abstract_declarator_tuple
     2655                                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
     2656                ;
     2657
     2658new_abstract_array:                                                                             // CFA
     2659                                // Only the first dimension can be empty. Empty dimension must be factored out due to
     2660                                // shift/reduce conflict with empty (void) function return type.
     2661                '[' push pop ']' type_specifier
     2662                                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2663                | '[' push pop ']' multi_array_dimension type_specifier
     2664                                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2665                | multi_array_dimension type_specifier
     2666                                { $$ = $2->addNewArray( $1 ); }
     2667                | '[' push pop ']' new_abstract_ptr
     2668                                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2669                | '[' push pop ']' multi_array_dimension new_abstract_ptr
     2670                                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     2671                | multi_array_dimension new_abstract_ptr
     2672                                { $$ = $2->addNewArray( $1 ); }
     2673                ;
     2674
     2675new_abstract_tuple:                                                                             // CFA
     2676                '[' push new_abstract_parameter_list pop ']'
     2677                                { $$ = DeclarationNode::newTuple( $3 ); }
     2678                ;
     2679
     2680new_abstract_function:                                                                  // CFA
     2681                '[' push pop ']' '(' new_parameter_type_list_opt ')'
     2682                                { $$ = DeclarationNode::newFunction( 0, DeclarationNode::newTuple( 0 ), $6, 0 ); }
     2683                | new_abstract_tuple '(' push new_parameter_type_list_opt pop ')'
     2684                                { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
     2685                | new_function_return '(' push new_parameter_type_list_opt pop ')'
     2686                                { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
     2687                ;
     2688
     2689// 1) ISO/IEC 9899:1999 Section 6.7.2(2) : "At least one type specifier shall be given in the declaration
     2690//    specifiers in each declaration, and in the specifier-qualifier list in each structure declaration and
     2691//    type name."
     2692//
     2693// 2) ISO/IEC 9899:1999 Section 6.11.5(1) : "The placement of a storage-class specifier other than at the
     2694//    beginning of the declaration specifiers in a declaration is an obsolescent feature."
    26972695//
    26982696// 3) ISO/IEC 9899:1999 Section 6.11.6(1) : "The use of function declarators with empty parentheses (not
    26992697//    prototype-format parameter type declarators) is an obsolescent feature."
    27002698//
    2701 // 4) ISO/IEC 9899:1999 Section 6.11.7(1) : "The use of function definitions with separate parameter identifier and
    2702 //    declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
     2699// 4) ISO/IEC 9899:1999 Section 6.11.7(1) : "The use of function definitions with separate parameter
     2700//    identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an
     2701//    obsolescent feature.
    27032702
    27042703//************************* MISCELLANEOUS ********************************
    27052704
    2706 comma_opt:                                              // redundant comma
    2707         // empty
    2708         | ','
    2709         ;
     2705comma_opt:                                                                                              // redundant comma
     2706                // empty
     2707                | ','
     2708                ;
    27102709
    27112710assignment_opt:
    2712         // empty
    2713                 { $$ = 0; }
    2714         | '=' assignment_expression
    2715                 { $$ = $2; }
    2716         ;
     2711                // empty
     2712                                { $$ = 0; }
     2713                | '=' assignment_expression
     2714                                { $$ = $2; }
     2715                ;
    27172716
    27182717%%
     
    27202719
    27212720void yyerror( char *string ) {
    2722     using std::cout;
    2723     using std::endl;
    2724     cout << "Error ";
    2725     if ( yyfilename ) {
    2726         cout << "in file " << yyfilename << " ";
    2727     }
    2728     cout << "at line " << yylineno << " reading token \"" << *(yylval.tok.str) << "\"" << endl;
     2721        using std::cout;
     2722        using std::endl;
     2723        cout << "Error ";
     2724        if ( yyfilename ) {
     2725                cout << "in file " << yyfilename << " ";
     2726        }
     2727        cout << "at line " << yylineno << " reading token \"" << *(yylval.tok.str) << "\"" << endl;
    27292728}
    27302729
    27312730// Local Variables: //
    27322731// fill-column: 110 //
     2732// tab-width: 4 //
     2733// mode: c++ //
    27332734// compile-command: "make install" //
    27342735// End: //
  • translator/Parser/lex.h

    rb8508a2 rb87a5ed  
    1 /*
    2  * This file is part of the Cforall project
    3  *
    4  * $Id: lex.h,v 1.2 2003/11/07 19:45:31 rcbilson Exp $
    5  *
    6  * Prototypes that enable Roskind's c5.y to compile with g++
    7  * Richard Bilson       5 Jan 2001
    8  *
    9  */
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// lex.h --
     8//
     9// Author           : Peter A. Buhr
     10// Created On       : Sat Sep 22 08:58:10 2001
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 12:18:48 2015
     13// Update Count     : 334
     14//
    1015
    1116#ifndef PARSER_LEX_H
     
    1419int yylex();
    1520void yyerror(char *);
    16 extern "C" {
    17 #include <malloc.h>
    18 }
    1921
    20 /* External declarations for information sharing between lexer and scanner */
     22// External declarations for information sharing between lexer and scanner
    2123#include "TypedefTable.h"
    2224extern TypedefTable typedefTable;
    2325
    24 /* current location in the input */
     26// current location in the input
    2527extern int yylineno;
    2628extern char *yyfilename;
    2729
    28 struct Location
    29 {
    30   char *file;
    31   int line;
     30struct Location {
     31    char *file;
     32    int line;
    3233};
    3334
    34 class Token
    35 {
    36 public:
    37   std::string *str;
    38   Location loc;
     35class Token {
     36  public:
     37    std::string *str;
     38    Location loc;
    3939
    40   operator std::string *() { return str; }
     40    operator std::string *() { return str; }
    4141};
    4242
    43 #endif // ifndef PARSER_LEX_H
     43#endif // PARSER_LEX_H
     44
     45// Local Variables: //
     46// fill-column: 110 //
     47// tab-width: 4 //
     48// mode: c++ //
     49// compile-command: "make install" //
     50// End: //
  • translator/Parser/lex.l

    rb8508a2 rb87a5ed  
    1 /*                               -*- Mode: C -*-
    2  *
    3  * CForall Lexer Version 1.0, Copyright (C) Peter A. Buhr 2001 -- Permission is granted to copy this
    4  *      grammar and to use it within software systems.  THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT
    5  *      ANY EXPRESS OR IMPLIED WARRANTIES.
     1/*
     2 * Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3 *
     4 * The contents of this file are covered under the licence agreement in the
     5 * file "LICENCE" distributed with Cforall.
    66 *
    77 * lex.l --
     
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Wed Jan 21 08:43:59 2015
    13  * Update Count     : 320
     12 * Last Modified On : Sat May 16 12:14:18 2015
     13 * Update Count     : 330
    1414 */
    1515
     
    1717
    1818%{
    19 // This lexer assumes the program has been preprocessed by cpp. Hence, all user level preprocessor
    20 // directive have been performed and removed from the source. The only exceptions are preprocessor
    21 // directives passed to the compiler (e.g., line-number directives) and C/C++ style comments, which
    22 // are ignored.
     19// This lexer assumes the program has been preprocessed by cpp. Hence, all user level preprocessor directive
     20// have been performed and removed from the source. The only exceptions are preprocessor directives passed to
     21// the compiler (e.g., line-number directives) and C/C++ style comments, which are ignored.
    2322
    2423//**************************** Includes and Defines ****************************
     
    2827#include "lex.h"
    2928#include "ParseNode.h"
    30 #include "cfa.tab.h" // YACC generated definitions based on C++ grammar
     29#include "cfa.tab.h"                                                                    // YACC generated definitions based on C++ grammar
    3130
    3231char *yyfilename;
    33 std::string *strtext;                                   // accumulate parts of character and string constant value
    34 
    35 #define WHITE_RETURN(x)                                 // do nothing
     32std::string *strtext;                                                                   // accumulate parts of character and string constant value
     33
     34#define WHITE_RETURN(x)                                                                 // do nothing
    3635#define NEWLINE_RETURN()        WHITE_RETURN('\n')
    3736#define RETURN_VAL(x)           yylval.tok.str = new std::string(yytext); \
    38                                 yylval.tok.loc.file = yyfilename; \
    39                                 yylval.tok.loc.line = yylineno; \
    40                                 return(x)
     37                                        yylval.tok.loc.file = yyfilename; \
     38                                        yylval.tok.loc.line = yylineno; \
     39                                        return(x)
    4140#define RETURN_STR(x)           yylval.tok.str = strtext; \
    42                                 yylval.tok.loc.file = yyfilename; \
    43                                 yylval.tok.loc.line = yylineno; \
    44                                 return(x)
    45 
    46 #define KEYWORD_RETURN(x)       RETURN_VAL(x)           // keyword
     41                                        yylval.tok.loc.file = yyfilename; \
     42                                        yylval.tok.loc.line = yylineno; \
     43                                        return(x)
     44
     45#define KEYWORD_RETURN(x)       RETURN_VAL(x)                           // keyword
    4746#define IDENTIFIER_RETURN()     RETURN_VAL((typedefTable.isIdentifier(yytext) ? IDENTIFIER : typedefTable.isTypedef(yytext) ? TYPEDEFname : TYPEGENname))
    4847//#define ATTRIBUTE_RETURN()    RETURN_VAL((typedefTable.isIdentifier(yytext) ? ATTR_IDENTIFIER : typedefTable.isTypedef(yytext) ? ATTR_TYPEDEFname : ATTR_TYPEGENname))
    4948#define ATTRIBUTE_RETURN()      RETURN_VAL(ATTR_IDENTIFIER)
    5049
    51 #define ASCIIOP_RETURN()        RETURN_VAL((int)yytext[0]) // single character operator
    52 #define NAMEDOP_RETURN(x)       RETURN_VAL(x)           // multichar operator, with a name
     50#define ASCIIOP_RETURN()        RETURN_VAL((int)yytext[0])      // single character operator
     51#define NAMEDOP_RETURN(x)       RETURN_VAL(x)                           // multichar operator, with a name
    5352
    5453#define NUMERIC_RETURN(x)       rm_underscore(); RETURN_VAL(x) // numeric constant
    5554
    5655void rm_underscore() {
    57     // remove underscores in numeric constant
    58     int j = 0;
    59     for ( int i = 0; yytext[i] != '\0'; i += 1 ) {
    60         if ( yytext[i] != '_' ) {
    61             yytext[j] = yytext[i];
    62             j += 1;
    63         } // if
    64     } // for
    65     yyleng = j;
    66     yytext[yyleng] = '\0';
     56        // remove underscores in numeric constant
     57        int j = 0;
     58        for ( int i = 0; yytext[i] != '\0'; i += 1 ) {
     59                if ( yytext[i] != '_' ) {
     60                        yytext[j] = yytext[i];
     61                        j += 1;
     62                } // if
     63        } // for
     64        yyleng = j;
     65        yytext[yyleng] = '\0';
    6766}
    6867
     
    7574universal_char "\\"((u"_"?{hex_quad})|(U"_"?{hex_quad}{2}))
    7675
    77         // identifier, GCC: $ in identifier
     76                                // identifier, GCC: $ in identifier
    7877identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})*
    7978
    80         // quoted identifier
     79                                // quoted identifier
    8180quoted_identifier "`"{identifier}"`"
    8281
    83         // attribute identifier, GCC: $ in identifier
     82                                // attribute identifier, GCC: $ in identifier
    8483attr_identifier "@"{identifier}
    8584
    86         // numeric constants, CFA: '_' in constant
     85                                // numeric constants, CFA: '_' in constant
    8786hex_quad {hex}("_"?{hex}){3}
    8887integer_suffix "_"?(([uU][lL]?)|([uU]("ll"|"LL")?)|([lL][uU]?)|("ll"|"LL")[uU]?)
     
    109108hex_floating_constant {hex_prefix}(({hex_fractional_constant}{binary_exponent})|({hex_digits}{binary_exponent})){floating_suffix}?
    110109
    111         // character escape sequence, GCC: \e => esc character
     110                                // character escape sequence, GCC: \e => esc character
    112111simple_escape "\\"[abefnrtv'"?\\]
    113         // ' stop highlighting
     112                                // ' stop highlighting
    114113octal_escape "\\"{octal}("_"?{octal}){0,2}
    115114hex_escape "\\""x""_"?{hex_digits}
    116115escape_seq {simple_escape}|{octal_escape}|{hex_escape}|{universal_char}
    117116
    118         // display/white-space characters
     117                                // display/white-space characters
    119118h_tab [\011]
    120119form_feed [\014]
     
    123122h_white [ ]|{h_tab}
    124123
    125         // operators
     124                                // operators
    126125op_unary_only "~"|"!"
    127126op_unary_binary "+"|"-"|"*"
     
    140139
    141140%%
    142         /* line directives */
     141                                   /* line directives */
    143142^{h_white}*"#"{h_white}*[0-9]+{h_white}*["][^"\n]+["][^\n]*"\n" {
    144143        /* " stop highlighting */
     
    150149        begin_string = strchr( end_num, '"' );
    151150        if ( begin_string ) {
    152             end_string = strchr( begin_string + 1, '"' );
    153             if ( end_string ) {
    154                 length = end_string - begin_string - 1;
    155                 filename = new char[ length + 1 ];
    156                 memcpy( filename, begin_string + 1, length );
    157                 filename[ length ] = '\0';
    158                 //std::cout << "file " << filename << " line " << lineno << std::endl;
    159                 yylineno = lineno;
    160                 yyfilename = filename;
    161             }
    162         }
     151                end_string = strchr( begin_string + 1, '"' );
     152                if ( end_string ) {
     153                        length = end_string - begin_string - 1;
     154                        filename = new char[ length + 1 ];
     155                        memcpy( filename, begin_string + 1, length );
     156                        filename[ length ] = '\0';
     157                        //std::cout << "file " << filename << " line " << lineno << std::endl;
     158                        yylineno = lineno;
     159                        yyfilename = filename;
     160                } // if
     161        } // if
    163162}
    164163
    165         /* ignore preprocessor directives (for now) */
     164                                /* ignore preprocessor directives (for now) */
    166165^{h_white}*"#"[^\n]*"\n" ;
    167166
    168         /* ignore C style comments */
     167                                /* ignore C style comments */
    169168"/*"                    { BEGIN COMMENT; }
    170169<COMMENT>.|\n           ;
    171170<COMMENT>"*/"           { BEGIN 0; }
    172171
    173         /* ignore C++ style comments */
     172                                /* ignore C++ style comments */
    174173"//"[^\n]*"\n"          ;
    175174
    176         /* ignore whitespace */
     175                                /* ignore whitespace */
    177176{h_white}+              { WHITE_RETURN(' '); }
    178177({v_tab}|{c_return}|{form_feed})+ { WHITE_RETURN(' '); }
    179178({h_white}|{v_tab}|{c_return}|{form_feed})*"\n" { NEWLINE_RETURN(); }
    180179
    181         /* keywords */
    182 _Alignas                { KEYWORD_RETURN(ALIGNAS); }    // C11
    183 _Alignof                { KEYWORD_RETURN(ALIGNOF); }    // C11
    184 __alignof               { KEYWORD_RETURN(ALIGNOF); }    // GCC
    185 __alignof__             { KEYWORD_RETURN(ALIGNOF); }    // GCC
    186 asm                     { KEYWORD_RETURN(ASM); }
    187 __asm                   { KEYWORD_RETURN(ASM); }        // GCC
    188 __asm__                 { KEYWORD_RETURN(ASM); }        // GCC
    189 _Atomic                 { KEYWORD_RETURN(ATOMIC); }     // C11
    190 __attribute             { KEYWORD_RETURN(ATTRIBUTE); }  // GCC
    191 __attribute__           { KEYWORD_RETURN(ATTRIBUTE); }  // GCC
     180                                /* keywords */
     181_Alignas                { KEYWORD_RETURN(ALIGNAS); }                    // C11
     182_Alignof                { KEYWORD_RETURN(ALIGNOF); }                    // C11
     183__alignof               { KEYWORD_RETURN(ALIGNOF); }                    // GCC
     184__alignof__             { KEYWORD_RETURN(ALIGNOF); }                    // GCC
     185asm                             { KEYWORD_RETURN(ASM); }
     186__asm                   { KEYWORD_RETURN(ASM); }                                // GCC
     187__asm__                 { KEYWORD_RETURN(ASM); }                                // GCC
     188_Atomic                 { KEYWORD_RETURN(ATOMIC); }                             // C11
     189__attribute             { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
     190__attribute__   { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
    192191auto                    { KEYWORD_RETURN(AUTO); }
    193 _Bool                   { KEYWORD_RETURN(BOOL); }       // C99
     192_Bool                   { KEYWORD_RETURN(BOOL); }                               // C99
    194193break                   { KEYWORD_RETURN(BREAK); }
    195194case                    { KEYWORD_RETURN(CASE); }
    196 catch                   { KEYWORD_RETURN(CATCH); }      // CFA
     195catch                   { KEYWORD_RETURN(CATCH); }                              // CFA
    197196char                    { KEYWORD_RETURN(CHAR); }
    198 choose                  { KEYWORD_RETURN(CHOOSE); }     // CFA
    199 _Complex                { KEYWORD_RETURN(COMPLEX); }    // C99
    200 __complex               { KEYWORD_RETURN(COMPLEX); }    // GCC
    201 __complex__             { KEYWORD_RETURN(COMPLEX); }    // GCC
     197choose                  { KEYWORD_RETURN(CHOOSE); }                             // CFA
     198_Complex                { KEYWORD_RETURN(COMPLEX); }                    // C99
     199__complex               { KEYWORD_RETURN(COMPLEX); }                    // GCC
     200__complex__             { KEYWORD_RETURN(COMPLEX); }                    // GCC
    202201const                   { KEYWORD_RETURN(CONST); }
    203 __const                 { KEYWORD_RETURN(CONST); }      // GCC
    204 __const__               { KEYWORD_RETURN(CONST); }      // GCC
    205 context                 { KEYWORD_RETURN(CONTEXT); }    // CFA
     202__const                 { KEYWORD_RETURN(CONST); }                              // GCC
     203__const__               { KEYWORD_RETURN(CONST); }                              // GCC
     204context                 { KEYWORD_RETURN(CONTEXT); }                    // CFA
    206205continue                { KEYWORD_RETURN(CONTINUE); }
    207206default                 { KEYWORD_RETURN(DEFAULT); }
    208 do                      { KEYWORD_RETURN(DO); }
     207do                              { KEYWORD_RETURN(DO); }
    209208double                  { KEYWORD_RETURN(DOUBLE); }
    210 dtype                   { KEYWORD_RETURN(DTYPE); }      // CFA
     209dtype                   { KEYWORD_RETURN(DTYPE); }                              // CFA
    211210else                    { KEYWORD_RETURN(ELSE); }
    212211enum                    { KEYWORD_RETURN(ENUM); }
    213 __extension__           { KEYWORD_RETURN(EXTENSION); }  // GCC
     212__extension__   { KEYWORD_RETURN(EXTENSION); }                  // GCC
    214213extern                  { KEYWORD_RETURN(EXTERN); }
    215 fallthru                { KEYWORD_RETURN(FALLTHRU); }   // CFA
    216 finally                 { KEYWORD_RETURN(FINALLY); }    // CFA
     214fallthru                { KEYWORD_RETURN(FALLTHRU); }                   // CFA
     215finally                 { KEYWORD_RETURN(FINALLY); }                    // CFA
    217216float                   { KEYWORD_RETURN(FLOAT); }
    218 __float128              { KEYWORD_RETURN(FLOAT); }      // GCC
    219 for                     { KEYWORD_RETURN(FOR); }
    220 forall                  { KEYWORD_RETURN(FORALL); }     // CFA
     217__float128              { KEYWORD_RETURN(FLOAT); }                              // GCC
     218for                             { KEYWORD_RETURN(FOR); }
     219forall                  { KEYWORD_RETURN(FORALL); }                             // CFA
    221220fortran                 { KEYWORD_RETURN(FORTRAN); }
    222 ftype                   { KEYWORD_RETURN(FTYPE); }      // CFA
    223 _Generic                { KEYWORD_RETURN(GENERIC); }    // C11
     221ftype                   { KEYWORD_RETURN(FTYPE); }                              // CFA
     222_Generic                { KEYWORD_RETURN(GENERIC); }                    // C11
    224223goto                    { KEYWORD_RETURN(GOTO); }
    225 if                      { KEYWORD_RETURN(IF); }
    226 _Imaginary              { KEYWORD_RETURN(IMAGINARY); }  // C99
    227 __imag                  { KEYWORD_RETURN(IMAGINARY); }  // GCC
    228 __imag__                { KEYWORD_RETURN(IMAGINARY); }  // GCC
    229 inline                  { KEYWORD_RETURN(INLINE); }     // C99
    230 __inline                { KEYWORD_RETURN(INLINE); }     // GCC
    231 __inline__              { KEYWORD_RETURN(INLINE); }     // GCC
    232 int                     { KEYWORD_RETURN(INT); }
    233 __int128                { KEYWORD_RETURN(INT); }        // GCC
    234 __label__               { KEYWORD_RETURN(LABEL); }      // GCC
     224if                              { KEYWORD_RETURN(IF); }
     225_Imaginary              { KEYWORD_RETURN(IMAGINARY); }                  // C99
     226__imag                  { KEYWORD_RETURN(IMAGINARY); }                  // GCC
     227__imag__                { KEYWORD_RETURN(IMAGINARY); }                  // GCC
     228inline                  { KEYWORD_RETURN(INLINE); }                             // C99
     229__inline                { KEYWORD_RETURN(INLINE); }                             // GCC
     230__inline__              { KEYWORD_RETURN(INLINE); }                             // GCC
     231int                             { KEYWORD_RETURN(INT); }
     232__int128                { KEYWORD_RETURN(INT); }                                // GCC
     233__label__               { KEYWORD_RETURN(LABEL); }                              // GCC
    235234long                    { KEYWORD_RETURN(LONG); }
    236 lvalue                  { KEYWORD_RETURN(LVALUE); }     // CFA
    237 _Noreturn               { KEYWORD_RETURN(NORETURN); }   // C11
     235lvalue                  { KEYWORD_RETURN(LVALUE); }                             // CFA
     236_Noreturn               { KEYWORD_RETURN(NORETURN); }                   // C11
    238237register                { KEYWORD_RETURN(REGISTER); }
    239 restrict                { KEYWORD_RETURN(RESTRICT); }   // C99
    240 __restrict              { KEYWORD_RETURN(RESTRICT); }   // GCC
    241 __restrict__            { KEYWORD_RETURN(RESTRICT); }   // GCC
     238restrict                { KEYWORD_RETURN(RESTRICT); }                   // C99
     239__restrict              { KEYWORD_RETURN(RESTRICT); }                   // GCC
     240__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    242241return                  { KEYWORD_RETURN(RETURN); }
    243242short                   { KEYWORD_RETURN(SHORT); }
    244243signed                  { KEYWORD_RETURN(SIGNED); }
    245 __signed                { KEYWORD_RETURN(SIGNED); }     // GCC
    246 __signed__              { KEYWORD_RETURN(SIGNED); }     // GCC
     244__signed                { KEYWORD_RETURN(SIGNED); }                             // GCC
     245__signed__              { KEYWORD_RETURN(SIGNED); }                             // GCC
    247246sizeof                  { KEYWORD_RETURN(SIZEOF); }
    248247static                  { KEYWORD_RETURN(STATIC); }
    249 _Static_assert          { KEYWORD_RETURN(STATICASSERT); } // C11
     248_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
    250249struct                  { KEYWORD_RETURN(STRUCT); }
    251250switch                  { KEYWORD_RETURN(SWITCH); }
    252 _Thread_local           { KEYWORD_RETURN(THREADLOCAL); } // C11
    253 throw                   { KEYWORD_RETURN(THROW); }      // CFA
    254 try                     { KEYWORD_RETURN(TRY); }        // CFA
    255 type                    { KEYWORD_RETURN(TYPE); }       // CFA
     251_Thread_local   { KEYWORD_RETURN(THREADLOCAL); }                // C11
     252throw                   { KEYWORD_RETURN(THROW); }                              // CFA
     253try                             { KEYWORD_RETURN(TRY); }                                // CFA
     254type                    { KEYWORD_RETURN(TYPE); }                               // CFA
    256255typedef                 { KEYWORD_RETURN(TYPEDEF); }
    257 typeof                  { KEYWORD_RETURN(TYPEOF); }     // GCC
    258 __typeof                { KEYWORD_RETURN(TYPEOF); }     // GCC
    259 __typeof__              { KEYWORD_RETURN(TYPEOF); }     // GCC
     256typeof                  { KEYWORD_RETURN(TYPEOF); }                             // GCC
     257__typeof                { KEYWORD_RETURN(TYPEOF); }                             // GCC
     258__typeof__              { KEYWORD_RETURN(TYPEOF); }                             // GCC
    260259union                   { KEYWORD_RETURN(UNION); }
    261260unsigned                { KEYWORD_RETURN(UNSIGNED); }
    262261void                    { KEYWORD_RETURN(VOID); }
    263262volatile                { KEYWORD_RETURN(VOLATILE); }
    264 __volatile              { KEYWORD_RETURN(VOLATILE); }   // GCC
    265 __volatile__            { KEYWORD_RETURN(VOLATILE); }   // GCC
     263__volatile              { KEYWORD_RETURN(VOLATILE); }                   // GCC
     264__volatile__    { KEYWORD_RETURN(VOLATILE); }                   // GCC
    266265while                   { KEYWORD_RETURN(WHILE); }
    267266
    268         /* identifier */
    269 {identifier}            { IDENTIFIER_RETURN(); }
    270 {attr_identifier}       { ATTRIBUTE_RETURN(); }
     267                                /* identifier */
     268{identifier}    { IDENTIFIER_RETURN(); }
     269{attr_identifier} { ATTRIBUTE_RETURN(); }
    271270"`"                     { BEGIN BKQUOTE; }
    272 <BKQUOTE>{identifier}   { IDENTIFIER_RETURN(); }
    273 <BKQUOTE>"`"            { BEGIN 0; }
    274 
    275         /* numeric constants */
    276 "0"                     { NUMERIC_RETURN(ZERO); }       // CFA
    277 "1"                     { NUMERIC_RETURN(ONE); }        // CFA
     271<BKQUOTE>{identifier} { IDENTIFIER_RETURN(); }
     272<BKQUOTE>"`"    { BEGIN 0; }
     273
     274                                /* numeric constants */
     275"0"                             { NUMERIC_RETURN(ZERO); }                               // CFA
     276"1"                             { NUMERIC_RETURN(ONE); }                                // CFA
    278277{decimal_constant}      { NUMERIC_RETURN(INTEGERconstant); }
    279278{octal_constant}        { NUMERIC_RETURN(INTEGERconstant); }
     
    282281{hex_floating_constant} { NUMERIC_RETURN(FLOATINGconstant); }
    283282
    284         /* character constant, allows empty value */
     283                                /* character constant, allows empty value */
    285284"L"?"_"?[']             { BEGIN QUOTE; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); }
    286 <QUOTE>[^'\\\n]*        { *strtext += std::string( yytext ); }
    287 <QUOTE>['\n]            { BEGIN 0; *strtext += std::string( yytext); RETURN_STR(CHARACTERconstant); }
    288         /* ' stop highlighting */
    289 
    290         /* string constant */
     285<QUOTE>[^'\\\n]* { *strtext += std::string( yytext ); }
     286<QUOTE>['\n]    { BEGIN 0; *strtext += std::string( yytext); RETURN_STR(CHARACTERconstant); }
     287                                /* ' stop highlighting */
     288
     289                                /* string constant */
    291290"L"?"_"?["]             { BEGIN STRING; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); }
    292 <STRING>[^"\\\n]*       { *strtext += std::string( yytext ); }
    293 <STRING>["\n]           { BEGIN 0; *strtext += std::string( yytext); RETURN_STR(STRINGliteral); }
    294         /* " stop highlighting */
     291<STRING>[^"\\\n]* { *strtext += std::string( yytext ); }
     292<STRING>["\n]   { BEGIN 0; *strtext += std::string( yytext); RETURN_STR(STRINGliteral); }
     293                                /* " stop highlighting */
    295294
    296295<QUOTE,STRING>{escape_seq} { rm_underscore(); *strtext += std::string( yytext ); }
    297296<QUOTE,STRING>[\\]      { *strtext += std::string( yytext ); } // unknown escape character
    298297
    299         /* punctuation */
    300 "["                     { ASCIIOP_RETURN(); }
    301 "]"                     { ASCIIOP_RETURN(); }
    302 "("                     { ASCIIOP_RETURN(); }
    303 ")"                     { ASCIIOP_RETURN(); }
    304 "{"                     { ASCIIOP_RETURN(); }
    305 "}"                     { ASCIIOP_RETURN(); }
    306 ","                     { ASCIIOP_RETURN(); }           // also operator
    307 ":"                     { ASCIIOP_RETURN(); }
    308 ";"                     { ASCIIOP_RETURN(); }
    309 "."                     { ASCIIOP_RETURN(); }           // also operator
     298                                /* punctuation */
     299"["                             { ASCIIOP_RETURN(); }
     300"]"                             { ASCIIOP_RETURN(); }
     301"("                             { ASCIIOP_RETURN(); }
     302")"                             { ASCIIOP_RETURN(); }
     303"{"                             { ASCIIOP_RETURN(); }
     304"}"                             { ASCIIOP_RETURN(); }
     305","                             { ASCIIOP_RETURN(); }                                   // also operator
     306":"                             { ASCIIOP_RETURN(); }
     307";"                             { ASCIIOP_RETURN(); }
     308"."                             { ASCIIOP_RETURN(); }                                   // also operator
    310309"..."                   { NAMEDOP_RETURN(ELLIPSIS); }
    311310
    312         /* alternative C99 brackets, "<:" & "<:<:" handled by preprocessor */
     311                                /* alternative C99 brackets, "<:" & "<:<:" handled by preprocessor */
    313312"<:"                    { RETURN_VAL('['); }
    314313":>"                    { RETURN_VAL(']'); }
     
    316315"%>"                    { RETURN_VAL('}'); }
    317316
    318         /* operators */
    319 "!"                     { ASCIIOP_RETURN(); }
    320 "+"                     { ASCIIOP_RETURN(); }
    321 "-"                     { ASCIIOP_RETURN(); }
    322 "*"                     { ASCIIOP_RETURN(); }
    323 "/"                     { ASCIIOP_RETURN(); }
    324 "%"                     { ASCIIOP_RETURN(); }
    325 "^"                     { ASCIIOP_RETURN(); }
    326 "~"                     { ASCIIOP_RETURN(); }
    327 "&"                     { ASCIIOP_RETURN(); }
    328 "|"                     { ASCIIOP_RETURN(); }
    329 "<"                     { ASCIIOP_RETURN(); }
    330 ">"                     { ASCIIOP_RETURN(); }
    331 "="                     { ASCIIOP_RETURN(); }
    332 "?"                     { ASCIIOP_RETURN(); }
     317                                /* operators */
     318"!"                             { ASCIIOP_RETURN(); }
     319"+"                             { ASCIIOP_RETURN(); }
     320"-"                             { ASCIIOP_RETURN(); }
     321"*"                             { ASCIIOP_RETURN(); }
     322"/"                             { ASCIIOP_RETURN(); }
     323"%"                             { ASCIIOP_RETURN(); }
     324"^"                             { ASCIIOP_RETURN(); }
     325"~"                             { ASCIIOP_RETURN(); }
     326"&"                             { ASCIIOP_RETURN(); }
     327"|"                             { ASCIIOP_RETURN(); }
     328"<"                             { ASCIIOP_RETURN(); }
     329">"                             { ASCIIOP_RETURN(); }
     330"="                             { ASCIIOP_RETURN(); }
     331"?"                             { ASCIIOP_RETURN(); }
    333332
    334333"++"                    { NAMEDOP_RETURN(ICR); }
     
    354353">>="                   { NAMEDOP_RETURN(RSassign); }
    355354
    356         /* CFA, operator identifier */
    357 {op_unary}"?"           { IDENTIFIER_RETURN(); }        // unary
     355                                /* CFA, operator identifier */
     356{op_unary}"?"   { IDENTIFIER_RETURN(); }                                // unary
    358357"?"({op_unary_pre_post}|"()"|"[?]") { IDENTIFIER_RETURN(); }
    359 "?"{op_binary_over}"?"  { IDENTIFIER_RETURN(); }        // binary
     358"?"{op_binary_over}"?"  { IDENTIFIER_RETURN(); }                // binary
    360359        /*
    361           This rule handles ambiguous cases with operator identifiers, e.g., "int *?*?()", where the
    362           string "*?*?"  can be lexed as "*"/"?*?" or "*?"/"*?". Since it is common practise to put
    363           a unary operator juxtaposed to an identifier, e.g., "*i", users will be annoyed if they
    364           cannot do this with respect to operator identifiers. Even with this special hack, there
    365           are 5 general cases that cannot be handled. The first case is for the function-call
    366           identifier "?()":
     360          This rule handles ambiguous cases with operator identifiers, e.g., "int *?*?()", where the string "*?*?"
     361          can be lexed as "*"/"?*?" or "*?"/"*?". Since it is common practise to put a unary operator juxtaposed
     362          to an identifier, e.g., "*i", users will be annoyed if they cannot do this with respect to operator
     363          identifiers. Even with this special hack, there are 5 general cases that cannot be handled. The first
     364          case is for the function-call identifier "?()":
    367365
    368366          int * ?()();  // declaration: space required after '*'
    369367          * ?()();      // expression: space required after '*'
    370368
    371           Without the space, the string "*?()" is ambiguous without N character look ahead; it
    372           requires scanning ahead to determine if there is a '(', which is the start of an
    373           argument/parameter list.
     369          Without the space, the string "*?()" is ambiguous without N character look ahead; it requires scanning
     370          ahead to determine if there is a '(', which is the start of an argument/parameter list.
    374371
    375372          The 4 remaining cases occur in expressions:
     
    380377          i?--i:0;              // space required after '?'
    381378
    382           In the first two cases, the string "i++?" is ambiguous, where this string can be lexed as
    383           "i"/"++?" or "i++"/"?"; it requires scanning ahead to determine if there is a '(', which
    384           is the start of an argument list.  In the second two cases, the string "?++x" is
    385           ambiguous, where this string can be lexed as "?++"/"x" or "?"/"++x"; it requires scanning
    386           ahead to determine if there is a '(', which is the start of an argument list.
     379          In the first two cases, the string "i++?" is ambiguous, where this string can be lexed as "i"/"++?" or
     380          "i++"/"?"; it requires scanning ahead to determine if there is a '(', which is the start of an argument
     381          list.  In the second two cases, the string "?++x" is ambiguous, where this string can be lexed as
     382          "?++"/"x" or "?"/"++x"; it requires scanning ahead to determine if there is a '(', which is the start of
     383          an argument list.
    387384        */
    388385{op_unary}"?"(({op_unary_pre_post}|"[?]")|({op_binary_over}"?")) {
    389                             // 1 or 2 character unary operator ?
    390                             int i = yytext[1] == '?' ? 1 : 2;
    391                             yyless( i );                // put back characters up to first '?'
    392                             if ( i > 1 ) {
    393                                 NAMEDOP_RETURN( yytext[0] == '+' ? ICR : DECR );
    394                             } else {
    395                                 ASCIIOP_RETURN();
    396                             } // if
    397                         }
    398 
    399         /* unknown characters */
     386        // 1 or 2 character unary operator ?
     387        int i = yytext[1] == '?' ? 1 : 2;
     388        yyless( i );            // put back characters up to first '?'
     389        if ( i > 1 ) {
     390                NAMEDOP_RETURN( yytext[0] == '+' ? ICR : DECR );
     391        } else {
     392                ASCIIOP_RETURN();
     393        } // if
     394}
     395
     396                                /* unknown characters */
    400397.                       { printf("unknown character(s):\"%s\" on line %d\n", yytext, yylineno); }
    401398
    402399%%
    403400
    404 
    405 // Local Variables:
    406 // fill-column: 100
    407 // compile-command: "make"
    408 // End:
     401// Local Variables: //
     402// fill-column: 110 //
     403// tab-width: 4 //
     404// mode: c++ //
     405// compile-command: "make install" //
     406// End: //
  • translator/Parser/module.mk

    rb8508a2 rb87a5ed  
    1 ###
    2 ### This file is part of the Cforall project
    3 ###
    4 ### $Id: module.mk,v 1.12 2005/08/30 19:11:40 rcbilson Exp $
    5 ###
     1######################### -*- Mode: Makefile-Gmake -*- ########################
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## module.mk --
     9##
     10## Author           : Peter A. Buhr
     11## Created On       : Sat May 16 15:29:09 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat May 16 15:29:50 2015
     14## Update Count     : 1
     15###############################################################################
    616
    717YACC=bison
  • translator/Parser/parseutility.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// parseutility.cc --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:30:39 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:31:33 2015
     13// Update Count     : 2
     14//
     15
    116#include "parseutility.h"
    217#include "SynTree/Type.h"
    318#include "SynTree/Expression.h"
    419
     20Expression *notZeroExpr( Expression *orig ) {
     21        UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
     22        comparison->get_args().push_back( orig );
     23        comparison->get_args().push_back( new NameExpr( "0" ) );
     24        return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     25}
    526
    6 Expression *notZeroExpr( Expression *orig ) {
    7       UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
    8       comparison->get_args().push_back( orig );
    9       comparison->get_args().push_back( new NameExpr( "0" ) );
    10       return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    11 }
     27// Local Variables: //
     28// tab-width: 4 //
     29// mode: c++ //
     30// compile-command: "make install" //
     31// End: //
  • translator/Parser/parseutility.h

    rb8508a2 rb87a5ed  
    1 #ifndef PARSER_PARSEUTILITY_H
    2 #define PARSER_PARSEUTILITY_H
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// parseutility.h --
     8//
     9// Author           : Rodolfo G. Esteves
     10// Created On       : Sat May 16 15:31:46 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 15:32:58 2015
     13// Update Count     : 2
     14//
     15
     16#ifndef PARSEUTILITY_H
     17#define PARSEUTILITY_H
    318
    419#include "SynTree/SynTree.h"
     
    621Expression *notZeroExpr( Expression *orig );
    722
    8 #endif // PARSER_PARSEUTILITY_H
     23#endif // PARSEUTILITY_H
     24
     25// Local Variables: //
     26// tab-width: 4 //
     27// mode: c++ //
     28// compile-command: "make install" //
     29// End: //
  • translator/ResolvExpr/AlternativeFinder.cc

    rb8508a2 rb87a5ed  
    2525#include "utility.h"
    2626
    27 extern bool resolveVerbose;
    28 #define PRINT( text ) if ( resolveVerbose ) { text }
     27extern bool resolvep;
     28#define PRINT( text ) if ( resolvep ) { text }
    2929//#define DEBUG_COST
    3030
  • translator/examples/Makefile.in

    rb8508a2 rb87a5ed  
     1######################### -*- Mode: Makefile-Gmake -*- ########################
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## Makefile.in --
     9##
     10## Author           : Peter A. Buhr
     11## Created On       : Sat May 16 11:34:24 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Sat May 16 11:35:25 2015
     14## Update Count     : 2
     15###############################################################################
     16
    117CC := @CFA_BINDIR@/cfa
    2 CFLAGS = -g -Wall -Wunused-function -MMD
     18CFLAGS = -g -Wall -Wno-unused-function -MMD
    319MAKEFILE_NAME = ${firstword ${MAKEFILE_LIST}}   # makefile name
    420
  • translator/main.cc

    rb8508a2 rb87a5ed  
     1//
     2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     3//
     4// The contents of this file are covered under the licence agreement in the
     5// file "LICENCE" distributed with Cforall.
     6//
     7// main.cc --
     8//
     9// Author           : Peter A. Buhr
     10// Created On       : Fri May 15 23:12:02 2015
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 07:42:27 2015
     13// Update Count     : 8
     14//
     15
    116#include <iostream>
    217#include <fstream>
    3 #include <iterator>
    4 #include <algorithm>
     18#include <cstdlib>
    519#include <cstdio>
     20#include <getopt.h>
    621#include "Parser/Parser.h"
    722#include "Parser/ParseNode.h"
     
    3146#include "SemanticError.h"
    3247#include "UnimplementedError.h"
    33 #include "utility.h"
    3448
    3549#include "../config.h"
     
    3751using namespace std;
    3852
    39 extern "C"{
    40 #include <unistd.h>
    41 } // extern
    42 
    43 FILE *open_prelude();
    44 FILE *open_builtins();
    45 bool beVerbose = false;
    46 bool resolveVerbose = false;
     53bool
     54        astp = false,
     55        exprp = false,
     56        expraltp = false,
     57        grammarp = false,
     58        libcfap = false,
     59        resolvep = false,                                                                       // used in AlternativeFinder
     60        symtabp = false,
     61        parsep = false,
     62        validp = false,
     63        preludep = true,
     64        protop = false,
     65        codegenp = false,
     66        errorp = false;
     67
     68enum { Ast, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Prototypes, Resolver, Symbol, Parse, };
     69
     70static struct option long_opts[] = {
     71        { "ast", no_argument, 0, Ast },
     72        { "expr", no_argument, 0, Expr },
     73        { "expralt", no_argument, 0, ExprAlt },
     74        { "grammar", no_argument, 0, Grammar },
     75        { "libcfa", no_argument, 0, LibCFA },
     76        { "nopreamble", no_argument, 0, Nopreamble },
     77        { "prototypes", no_argument, 0, Prototypes },
     78        { "resolver", no_argument, 0, Resolver },
     79        { "symbol", no_argument, 0, Symbol },
     80        { "parse", no_argument, 0, Parse },
     81        { 0, 0, 0, 0 }
     82};
    4783
    4884int main( int argc, char *argv[] ) {
    49     bool debugp = false, treep = false, astp = false, manglep = false, symtabp = false, validp = false;
    50     bool preludep = true, protop = false, libp = false;
    51     bool exprp = false, codegenp = false, errorp = false;
    52     int c;
    53     FILE *input, *prelude, *builtins;
    54     std::ostream *output = &std::cout;
    55 
    56     opterr = 0;
    57 
    58     std::list< Declaration* > translationUnit;
    59    
    60     while ( (c = getopt( argc, argv, "dtsgmvxcenprlDyz:" )) != -1 ) {
    61         switch (c) {
    62           case 'd':
    63             // bison debugging info
    64             debugp = true;
    65             break;
    66           case 't':
    67             // dump parse tree
    68             treep = true;
    69             break;
    70           case 's':
    71             // dump AST
    72             astp = true;
    73             break;
    74           case 'g':
    75             // print alternatives for expressions
    76             manglep = true;
    77             break;
    78           case 'm':
    79             // print symbol table events
    80             symtabp = true;
    81             break;
    82           case 'r':
    83             // print resolver steps
    84             resolveVerbose = true;
    85             break;
    86           case 'x':
    87             // dump AST after decl validation pass
    88             validp = true;
    89             break;
    90           case 'e':
    91             // dump AST after expression analysis
    92             exprp = true;
    93             break;
    94           case 'z':
    95             codegenp = true;
    96             break;
    97           case 'y':
    98             errorp = true;
    99             break;
    100           case 'n':
    101             // don't read preamble
    102             preludep = false;
    103             break;
    104           case 'p':
    105             // generate prototypes for preamble functions
    106             protop = true;
    107             break;
    108           case 'l':
    109             // generate libcfa.c
    110             libp = true;
    111             break;
    112           case 'v':
    113             // verbose
    114             beVerbose = true;
    115             break;
    116           case 'D':
    117             // ignore -Dxxx
    118             break;
    119           case '?':
    120             cout << "Unknown option: '" << (char)optopt << "'" << endl;
    121             exit(1);
    122           default:
    123             abort();
    124         } // switch
    125     } // while
    126 
    127     try {
    128         if ( optind < argc ) {
    129             input = fopen( argv[ optind ], "r" );
    130             if ( ! input ) {
    131                 std::cout << "Error: can't open " << argv[optind] << std::endl;
    132                 exit( 1 );
    133             } // if
    134             optind++;
    135         } else {
    136             input = stdin;
    137         } // if
    138 
    139         if ( optind < argc ) {
    140             output = new ofstream( argv[ optind ] );
    141         } // if
    142    
    143         Parser::get_parser().set_debug( debugp );
    144    
    145         if ( preludep ) {
    146             // include gcc builtins
    147             builtins = open_builtins();
    148             if ( !builtins ) {
    149                 std::cout << "Error: can't open builtins" << std::endl;
    150                 exit( 1 );
    151             } // if
    152      
    153             Parser::get_parser().set_linkage( LinkageSpec::Compiler );
    154             Parser::get_parser().parse( builtins );
    155    
    156             if ( Parser::get_parser().get_parseStatus() != 0 ) {
    157                 return Parser::get_parser().get_parseStatus();
    158             } // if
    159             fclose( builtins );
    160 
    161             // include cfa prelude
    162             if ( libp ) {
    163                 prelude = input;
    164             } else {
    165                 prelude = open_prelude();
    166             } // if
    167             if ( !prelude ) {
    168                 std::cout << "Error: can't open prelude" << std::endl;
    169                 exit( 1 );
    170             } // if
    171      
    172             Parser::get_parser().set_linkage( LinkageSpec::Intrinsic );
    173             Parser::get_parser().parse( prelude );
    174    
    175             if ( Parser::get_parser().get_parseStatus() != 0 ) {
    176                 return Parser::get_parser().get_parseStatus();
    177             } // if
    178             fclose( prelude );
    179         } // if
    180    
    181         if ( libp ) {
    182             std::list< Declaration* > translationUnit;
    183             buildList( Parser::get_parser().get_parseTree(), translationUnit );
    184             Parser::get_parser().freeTree();
    185             SymTab::validate( translationUnit, false );
    186             CodeGen::fixNames( translationUnit );
    187             LibCfa::makeLibCfa( translationUnit );
    188             ResolvExpr::resolve( translationUnit );
    189             GenPoly::convertLvalue( translationUnit );
    190             GenPoly::box( translationUnit );
    191             CodeGen::generate( translationUnit, *output, true );
    192             if ( output != &std::cout ) {
    193                 delete output;
    194             } // if
    195             return 0;
    196         } // if
    197    
    198         Parser::get_parser().set_linkage( LinkageSpec::Cforall );
     85        FILE *input;
     86        std::ostream *output = &std::cout;
     87        int long_index;
     88        std::list< Declaration* > translationUnit;
     89
     90        opterr = 0;                                                                                     // prevent getopt from printing error messages
     91       
     92        int c;
     93        while ( (c = getopt_long( argc, argv, "aefglnpqrsxyzD:", long_opts, &long_index )) != -1 ) {
     94                switch ( c ) {
     95                  case Ast:
     96                  case 'a':                                                                             // dump AST
     97                        astp = true;
     98                        break;
     99                  case Expr:
     100                  case 'e':                                                                             // dump AST after expression analysis
     101                        exprp = true;
     102                        break;
     103                  case ExprAlt:
     104                  case 'f':                                                                             // print alternatives for expressions
     105                        expraltp = true;
     106                        break;
     107                  case Grammar:
     108                  case 'g':                                                                             // bison debugging info (grammar rules)
     109                        grammarp = true;
     110                        break;
     111                  case LibCFA:
     112                  case 'l':                                                                             // generate libcfa.c
     113                        libcfap = true;
     114                        break;
     115                  case Nopreamble:
     116                  case 'n':                                                                             // do not read preamble
     117                        preludep = false;
     118                        break;
     119                  case Prototypes:
     120                  case 'p':                                                                             // generate prototypes for preamble functions
     121                        protop = true;
     122                        break;
     123                  case Parse:
     124                  case 'q':                                                                             // dump parse tree
     125                        parsep = true;
     126                        break;
     127                  case Resolver:
     128                  case 'r':                                                                             // print resolver steps
     129                        resolvep = true;
     130                        break;
     131                  case Symbol:
     132                  case 's':                                                                             // print symbol table events
     133                        symtabp = true;
     134                        break;
     135                  case 'x':                                                                             // dump AST after decl validation pass
     136                        validp = true;
     137                        break;
     138                  case 'y':
     139                        errorp = true;
     140                        break;
     141                  case 'z':
     142                        codegenp = true;
     143                        break;
     144                  case 'D':                                                                             // ignore -Dxxx
     145                        break;
     146                  case '?':
     147                        cout << "Unknown option: '" << (char)optopt << "'" << endl;
     148                        exit(1);
     149                  default:
     150                        abort();
     151                } // switch
     152        } // while
     153
     154        try {
     155                if ( optind < argc ) {
     156                        input = fopen( argv[ optind ], "r" );
     157                        if ( ! input ) {
     158                                std::cout << "Error: can't open " << argv[optind] << std::endl;
     159                                exit( 1 );
     160                        } // if
     161                        optind += 1;
     162                } else {
     163                        input = stdin;
     164                } // if
     165
     166                if ( optind < argc ) {
     167                        output = new ofstream( argv[ optind ] );
     168                } // if
     169       
     170                Parser::get_parser().set_debug( grammarp );
     171       
     172                if ( preludep ) {                                                               // include gcc builtins
     173                        FILE *builtins = fopen( CFA_LIBDIR "/builtins.cf", "r" );
     174                        if ( builtins == NULL ) {
     175                                std::cout << "Error: can't open builtins" << std::endl;
     176                                exit( 1 );
     177                        } // if
     178         
     179                        Parser::get_parser().set_linkage( LinkageSpec::Compiler );
     180                        Parser::get_parser().parse( builtins );
     181       
     182                        if ( Parser::get_parser().get_parseStatus() != 0 ) {
     183                                return Parser::get_parser().get_parseStatus();
     184                        } // if
     185                        fclose( builtins );
     186
     187                        FILE *prelude;
     188                        if ( libcfap ) {                                                        // include cfa prelude
     189                                prelude = input;
     190                        } else {
     191                                prelude = fopen( CFA_LIBDIR "/prelude.cf", "r" );
     192                        } // if
     193                        if ( prelude == NULL ) {
     194                                std::cout << "Error: can't open prelude" << std::endl;
     195                                exit( 1 );
     196                        } // if
     197         
     198                        Parser::get_parser().set_linkage( LinkageSpec::Intrinsic );
     199                        Parser::get_parser().parse( prelude );
     200       
     201                        if ( Parser::get_parser().get_parseStatus() != 0 ) {
     202                                return Parser::get_parser().get_parseStatus();
     203                        } // if
     204                        fclose( prelude );
     205                } // if
     206       
     207                if ( libcfap ) {
     208                        std::list< Declaration* > translationUnit;
     209                        buildList( Parser::get_parser().get_parseTree(), translationUnit );
     210                        Parser::get_parser().freeTree();
     211                        SymTab::validate( translationUnit, false );
     212                        CodeGen::fixNames( translationUnit );
     213                        LibCfa::makeLibCfa( translationUnit );
     214                        ResolvExpr::resolve( translationUnit );
     215                        GenPoly::convertLvalue( translationUnit );
     216                        GenPoly::box( translationUnit );
     217                        CodeGen::generate( translationUnit, *output, true );
     218                        if ( output != &std::cout ) {
     219                                delete output;
     220                        } // if
     221                        return 0;
     222                } // if
     223       
     224                Parser::get_parser().set_linkage( LinkageSpec::Cforall );
    199225 
    200         Parser::get_parser().parse( input );
    201         if ( debugp || Parser::get_parser().get_parseStatus() != 0 ) {
    202             return Parser::get_parser().get_parseStatus();
    203         } // if
    204         fclose( input );
     226                Parser::get_parser().parse( input );
     227                if ( grammarp || Parser::get_parser().get_parseStatus() != 0 ) {
     228                        return Parser::get_parser().get_parseStatus();
     229                } // if
     230                fclose( input );
    205231 
    206         if ( treep ) {
    207             Parser::get_parser().get_parseTree()->printList( std::cout );
    208             Parser::get_parser().freeTree();
    209             return 0;
    210         } // if
    211 
    212         buildList( Parser::get_parser().get_parseTree(), translationUnit );
    213 
    214         Parser::get_parser().freeTree();
    215         if ( astp ) {
    216             printAll( translationUnit, std::cout );
    217             return 0;
    218         } // if
    219 
    220         if ( manglep ) {
    221             SymTab::validate( translationUnit, false );
    222             ResolvExpr::AlternativePrinter printer( std::cout );
    223             acceptAll( translationUnit, printer );
    224             return 0;
    225         } // if
    226 
    227         if ( symtabp ) {
    228             SymTab::validate( translationUnit, true );
    229             return 0;
    230         } // if
    231 
    232         if ( validp ) {
    233             SymTab::validate( translationUnit, false );
    234             printAll( translationUnit, std::cout );
    235             return 0;
    236         } // if
    237 
    238         if ( exprp ) {
    239             InitTweak::tweak( translationUnit );
    240             SymTab::validate( translationUnit, false );
    241             ControlStruct::mutate( translationUnit );
    242             CodeGen::fixNames( translationUnit );
    243             ResolvExpr::resolve( translationUnit );
    244             printAll( translationUnit, std::cout );
    245             return 0;
    246         } // if
    247 
    248         if ( codegenp ) {
    249             // print the tree right before code generation
    250             cerr << "tweak" << endl;
    251             InitTweak::tweak( translationUnit );
    252             cerr << "validate" << endl;
    253             SymTab::validate( translationUnit, false );
    254             cerr << "mutate" << endl;
    255             ControlStruct::mutate( translationUnit );
    256             cerr << "fixNames" << endl;
    257             CodeGen::fixNames( translationUnit );
    258             cerr << "resolve" << endl;
    259             ResolvExpr::resolve( translationUnit );
    260             cerr << "copyParams" << endl;
    261             GenPoly::copyParams( translationUnit );
    262             cerr << "convertSpecializations" << endl;
    263             GenPoly::convertSpecializations( translationUnit );
    264             cerr << "convertLvalue" << endl;
    265             GenPoly::convertLvalue( translationUnit );
    266             cerr << "box" << endl;
    267             GenPoly::box( translationUnit );
    268             if ( errorp ) {
    269                 printAll( translationUnit, std::cout );
    270             }
    271             return 0;
    272         } // if
    273 
    274         // add the assignment statement after the
    275         // initialization of a type parameter
    276         InitTweak::tweak( translationUnit );
    277 
    278         //std::cerr << "before validate" << std::endl;
    279         SymTab::validate( translationUnit, false );
    280         //Try::visit( translationUnit );
    281         //Tuples::mutate( translationUnit );
    282         //InitTweak::mutate( translationUnit );
    283         //std::cerr << "before mutate" << std::endl;
    284         ControlStruct::mutate( translationUnit );
    285         //std::cerr << "before fixNames" << std::endl;
    286         CodeGen::fixNames( translationUnit );
    287         //std::cerr << "before resolve" << std::endl;
    288         ResolvExpr::resolve( translationUnit );
    289         //Tuples::checkFunctions( translationUnit );
    290         //      std::cerr << "Finished tuple checkfunctions" << std::endl;
    291         //printAll( translationUnit, std::cerr );
    292         //std::cerr << "before copyParams" << std::endl;
    293         GenPoly::copyParams( translationUnit );
    294         //std::cerr << "before convertSpecializations" << std::endl;
    295         GenPoly::convertSpecializations( translationUnit );
    296         //std::cerr << "before convertLvalue" << std::endl;
    297         GenPoly::convertLvalue( translationUnit );
    298         //std::cerr << "before box" << std::endl;
    299         GenPoly::box( translationUnit );
    300         //Tuples::mutate( translationUnit );
    301 
    302         CodeGen::generate( translationUnit, *output, protop );
    303 
    304         if ( output != &std::cout ) {
    305             delete output;
    306         } // if
    307 
    308     } catch ( SemanticError &e ) {
    309         if ( errorp ) {
    310            printAll( translationUnit, std::cout );
    311         }
    312         e.print( cout );
    313         if ( output != &std::cout ) {
    314             delete output;
    315         } // if
    316         return 1;
    317     } catch ( UnimplementedError &e ) {
    318         std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl;
    319         if ( output != &std::cout ) {
    320             delete output;
    321         } // if
    322         return 1;
    323     } catch ( CompilerError &e ) {
    324         std::cerr << "Compiler Error: " << e.get_what() << std::endl;
    325         std::cerr << "(please report bugs to " << std::endl;
    326         if ( output != &std::cout ) {
    327             delete output;
    328         } // if
    329         return 1;
    330     } // try
    331 
    332     return 0;
     232                if ( parsep ) {
     233                        Parser::get_parser().get_parseTree()->printList( std::cout );
     234                        Parser::get_parser().freeTree();
     235                        return 0;
     236                } // if
     237
     238                buildList( Parser::get_parser().get_parseTree(), translationUnit );
     239
     240                Parser::get_parser().freeTree();
     241                if ( astp ) {
     242                        printAll( translationUnit, std::cout );
     243                        return 0;
     244                } // if
     245
     246                if ( expraltp ) {
     247                        SymTab::validate( translationUnit, false );
     248                        ResolvExpr::AlternativePrinter printer( std::cout );
     249                        acceptAll( translationUnit, printer );
     250                        return 0;
     251                } // if
     252
     253                if ( symtabp ) {
     254                        SymTab::validate( translationUnit, true );
     255                        return 0;
     256                } // if
     257
     258                if ( validp ) {
     259                        SymTab::validate( translationUnit, false );
     260                        printAll( translationUnit, std::cout );
     261                        return 0;
     262                } // if
     263
     264                if ( exprp ) {
     265                        InitTweak::tweak( translationUnit );
     266                        SymTab::validate( translationUnit, false );
     267                        ControlStruct::mutate( translationUnit );
     268                        CodeGen::fixNames( translationUnit );
     269                        ResolvExpr::resolve( translationUnit );
     270                        printAll( translationUnit, std::cout );
     271                        return 0;
     272                } // if
     273
     274                if ( codegenp ) {
     275                        // print the tree right before code generation
     276                        cerr << "tweak" << endl;
     277                        InitTweak::tweak( translationUnit );
     278                        cerr << "validate" << endl;
     279                        SymTab::validate( translationUnit, false );
     280                        cerr << "mutate" << endl;
     281                        ControlStruct::mutate( translationUnit );
     282                        cerr << "fixNames" << endl;
     283                        CodeGen::fixNames( translationUnit );
     284                        cerr << "resolve" << endl;
     285                        ResolvExpr::resolve( translationUnit );
     286                        cerr << "copyParams" << endl;
     287                        GenPoly::copyParams( translationUnit );
     288                        cerr << "convertSpecializations" << endl;
     289                        GenPoly::convertSpecializations( translationUnit );
     290                        cerr << "convertLvalue" << endl;
     291                        GenPoly::convertLvalue( translationUnit );
     292                        cerr << "box" << endl;
     293                        GenPoly::box( translationUnit );
     294                        if ( errorp ) {
     295                                printAll( translationUnit, std::cout );
     296                        }
     297                        return 0;
     298                } // if
     299
     300                // add the assignment statement after the
     301                // initialization of a type parameter
     302                InitTweak::tweak( translationUnit );
     303
     304                //std::cerr << "before validate" << std::endl;
     305                SymTab::validate( translationUnit, false );
     306                //Try::visit( translationUnit );
     307                //Tuples::mutate( translationUnit );
     308                //InitTweak::mutate( translationUnit );
     309                //std::cerr << "before mutate" << std::endl;
     310                ControlStruct::mutate( translationUnit );
     311                //std::cerr << "before fixNames" << std::endl;
     312                CodeGen::fixNames( translationUnit );
     313                //std::cerr << "before resolve" << std::endl;
     314                ResolvExpr::resolve( translationUnit );
     315                //Tuples::checkFunctions( translationUnit );
     316                //        std::cerr << "Finished tuple checkfunctions" << std::endl;
     317                //printAll( translationUnit, std::cerr );
     318                //std::cerr << "before copyParams" << std::endl;
     319                GenPoly::copyParams( translationUnit );
     320                //std::cerr << "before convertSpecializations" << std::endl;
     321                GenPoly::convertSpecializations( translationUnit );
     322                //std::cerr << "before convertLvalue" << std::endl;
     323                GenPoly::convertLvalue( translationUnit );
     324                //std::cerr << "before box" << std::endl;
     325                GenPoly::box( translationUnit );
     326                //Tuples::mutate( translationUnit );
     327
     328                CodeGen::generate( translationUnit, *output, protop );
     329
     330                if ( output != &std::cout ) {
     331                        delete output;
     332                } // if
     333
     334        } catch ( SemanticError &e ) {
     335                if ( errorp ) {
     336                        printAll( translationUnit, std::cout );
     337                }
     338                e.print( cout );
     339                if ( output != &std::cout ) {
     340                        delete output;
     341                } // if
     342                return 1;
     343        } catch ( UnimplementedError &e ) {
     344                std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl;
     345                if ( output != &std::cout ) {
     346                        delete output;
     347                } // if
     348                return 1;
     349        } catch ( CompilerError &e ) {
     350                std::cerr << "Compiler Error: " << e.get_what() << std::endl;
     351                std::cerr << "(please report bugs to " << std::endl;
     352                if ( output != &std::cout ) {
     353                        delete output;
     354                } // if
     355                return 1;
     356        } // try
     357
     358        return 0;
    333359} // main
    334360
    335 FILE *open_prelude() {
    336     FILE *ret;
    337 
    338     const string name("prelude.cf"),
    339         full_name = string(CFA_LIBDIR) + "/" + name;
    340 
    341     if ( beVerbose ) {
    342         cout << "Reading from " << full_name << endl;
    343     } // if
    344 
    345     if ( ! (ret = fopen(full_name.c_str(), "r" ) ) )
    346         return fopen(name.c_str(), "r" );             // trying current directory
    347     else
    348         return ret;
    349 } // open_prelude
    350 
    351 FILE *open_builtins() {
    352     FILE *ret;
    353 
    354     const char *name = "builtins.cf";
    355     const char *full_name = CFA_LIBDIR "/builtins.cf";
    356 
    357     if ( beVerbose ) {
    358         cout << "Reading from " << full_name << endl;
    359     } // if
    360 
    361     if ( ! (ret = fopen(full_name, "r" ) ) )
    362         return fopen(name, "r" );                       // trying current directory
    363     else
    364         return ret;
    365 } // open_builtins
    366 
    367361// Local Variables: //
    368 // compile-command: "make" //
     362// tab-width: 4 //
     363// mode: c++ //
     364// compile-command: "make install" //
    369365// End:  //
Note: See TracChangeset for help on using the changeset viewer.