Changeset b87a5ed
- Timestamp:
- May 16, 2015, 3:36:19 PM (10 years ago)
- 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
- Files:
-
- 2 deleted
- 38 edited
Legend:
- Unmodified
- Added
- Removed
-
INSTALL
rb8508a2 rb87a5ed 2 2 ====================================== 3 3 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 4 Cforall is built using GNU Make and the GNU Autoconf system. It also requires 5 g++ version 3, bison and flex. On systems where GNU Make is the default make 6 it may suffice to build the system by entering the commands 8 7 9 8 ./configure … … 13 12 Options for 'configure' 14 13 ----------------------- 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 themost useful arguments.14 The 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 16 most useful arguments. 18 17 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 19 cfa-cc components. Some components will be installed in /some/directory/bin, 20 others in /some/directory/lib. If unspecified, this defaults to /usr/local. 23 21 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 23 defaults to the first command named 'gcc' in the current PATH. 27 24 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.25 cfa-cc itself is built with the version of g++ specified by the environment 26 variable CXX. If CXX is unset, cfa-cc is built using the first command named 27 'g++' in the current PATH. -
Makefile.in
rb8508a2 rb87a5ed 38 38 $(top_srcdir)/libcfa/Makefile.in \ 39 39 $(top_srcdir)/translator/Makefile.in \ 40 $(top_srcdir)/translator/examples/Makefile.in AUTHORS COPYING\41 ChangeLog INSTALL NEWSinstall-sh missing mkinstalldirs40 $(top_srcdir)/translator/examples/Makefile.in AUTHORS INSTALL \ 41 TODO install-sh missing mkinstalldirs 42 42 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 43 43 am__aclocal_m4_deps = $(top_srcdir)/configure.in … … 225 225 case '$(am__configure_deps)' in \ 226 226 *$$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 \ 229 229 && exit 0; \ 230 230 exit 1;; \ 231 231 esac; \ 232 232 done; \ 233 echo ' cd $(top_srcdir) && $(AUTOMAKE) -- gnuMakefile'; \233 echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ 234 234 $(am__cd) $(top_srcdir) && \ 235 $(AUTOMAKE) -- gnuMakefile235 $(AUTOMAKE) --foreign Makefile 236 236 .PRECIOUS: Makefile 237 237 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -
configure
rb8508a2 rb87a5ed 2593 2593 2594 2594 # Define the identity of the package. 2595 PACKAGE= cfa2596 VERSION= 1.02595 PACKAGE='cfa-cc' 2596 VERSION='1.0' 2597 2597 2598 2598 … … 2633 2633 2634 2634 2635 2635 # do not follow GNU standard 2636 2636 ac_config_headers="$ac_config_headers config.h" 2637 2637 … … 6472 6472 6473 6473 6474 { $as_echo "$as_me:${as_lineno-$LINENO}: result: The Cforall translator is now configured for your system" >&56475 $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 2 2 AC_CONFIG_SRCDIR([translator/main.cc]) 3 3 4 AM_INIT_AUTOMAKE( cfa, 1.0)4 AM_INIT_AUTOMAKE([foreign]) # do not follow GNU standard 5 5 AM_CONFIG_HEADER(config.h) 6 6 … … 105 105 dnl Final text 106 106 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) 107 AC_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 ############################################################################### 6 16 7 17 CXX=@CXX@ … … 11 21 12 22 SRCS:=cfa.cc cc1.cc 13 OBJECTS:=$ (SRCS:.cc=.o)14 DEPS:=$ (SRCS:.cc=.d)23 OBJECTS:=${SRCS:.cc=.o} 24 DEPS:=${SRCS:.cc=.d} 15 25 16 26 all: cfa cc1 17 27 18 28 cfa: cfa.o 19 $ (CXX)$< -o $@29 ${CXX} $< -o $@ 20 30 21 31 cc1 : cc1.o 22 $ (CXX)$< -o $@32 ${CXX} $< -o $@ 23 33 24 34 install: 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@ 29 39 30 40 clean: 31 rm -f cfa cc1 $ (OBJECTS) $(DEPS)core41 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 // 5 7 // cc1.cc -- 6 // 7 // Author : Richard C. Bilson8 // 9 // Author : Peter A. Buhr 8 10 // Created On : Fri Aug 26 14:23:51 2005 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Thu May 14 13:24:45201511 // Update Count : 4 312 // Last Modified On : Sat May 16 07:42:14 2015 13 // Update Count : 49 12 14 // 13 14 15 15 16 #include <iostream> … … 18 19 #include <string> 19 20 using std::string; 20 #include <cstdio> // stderr, stdout, perror, fprintf21 #include <cstdlib> // getenv, exit, mkstemp22 #include <unistd.h> // execvp, fork, unlink23 #include <sys/wait.h> // wait24 25 #include "config.h" // configure info21 #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 26 27 27 28 … … 29 30 30 31 31 string compiler_name( GCC_PATH ); 32 string compiler_name( GCC_PATH ); // path/name of C compiler 32 33 33 34 string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" ); … … 39 40 40 41 bool prefix( string arg, string pre ) { 41 42 return arg.substr( 0, pre.size() ) == pre; 42 43 } // prefix 43 44 44 45 45 46 void 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 77 void 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 86 void sigTermHandler( int signal ) { 87 if ( tmpfilefd != -1 ) { // RACE, file created ? 88 rmtmpfile(); // remove 89 exit( EXIT_FAILURE ); // terminate 90 } // if 91 } // sigTermHandler 92 93 94 void 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 366 void 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 62 441 nargs += 1; 63 } // if64 65 value = getenv( "__GCC_VERSION__" );66 if ( value != NULL ) {67 args[nargs] = ( *new string( value ) ).c_str(); // pass the argument along68 #ifdef __DEBUG_H__69 cerr << "env arg:\"" << args[nargs] << "\"" << endl;70 #endif // __DEBUG_H__71 nargs += 1;72 } // if73 } // checkEnv74 75 76 void rmtmpfile() {77 if ( unlink( tmpname ) == -1 ) { // remove tmpname78 perror ( "CFA Translator error: cpp failed" );79 exit( EXIT_FAILURE );80 } // if81 tmpfilefd = -1; // mark closed82 } // rmtmpfile83 84 85 void sigTermHandler( int signal ) {86 if ( tmpfilefd != -1 ) { // RACE, file created ?87 rmtmpfile(); // remove88 exit( EXIT_FAILURE ); // terminate89 } // if90 } // sigTermHandler91 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 values108 int nargs = 1; // number of arguments in args list; 0 => command name109 const char *uargs[20]; // leave space for 20 additional cfa-cpp command line values110 int nuargs = 1; // 0 => command name111 112 signal( SIGINT, sigTermHandler );113 signal( SIGTERM, sigTermHandler );114 115 // process all the arguments116 117 checkEnv( args, nargs ); // arguments passed via environment variables118 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 passes129 130 if ( arg == "-quiet" ) {131 } else if ( arg == "-imultilib" || arg == "-imultiarch" ) {132 i += 1; // and the argument133 } 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 argument140 141 // strip flags controlling cpp step142 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 argument147 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 argument152 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 argument160 } 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 argument165 166 // all other flags167 168 } else if ( arg == "-o" ) {169 i += 1;170 o_name = argv[i];171 } else {172 args[nargs] = argv[i]; // pass the flag along173 nargs += 1;174 // CPP flags with an argument175 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 along180 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 file186 nargs += 1;187 i += 1;188 args[nargs] = argv[i]; // pass the argument along189 nargs += 1;190 #ifdef __DEBUG_H__191 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;192 #endif // __DEBUG_H__193 } // if194 } // if195 } else { // obtain input and possibly output files196 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 } // if210 } // if211 } // for212 213 #ifdef __DEBUG_H__214 cerr << "args:";215 for ( i = 1; i < nargs; i += 1 ) {216 cerr << " " << args[i];217 } // for218 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 } // if227 228 if ( cpp_flag ) {229 // The -E flag is specified on the cfa command so only run the preprocessor and output is written to standard230 // 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();233 442 args[nargs] = cpp_in; 234 443 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; 245 448 for ( i = 0; args[i] != NULL; i += 1 ) { 246 449 cerr << args[i] << " "; 247 450 } // for 248 451 cerr << endl; 249 452 #endif // __DEBUG_H__ 250 453 251 execvp( args[0], (char * const *)args );// should not return454 execvp( args[0], (char * const *)args ); // should not return 252 455 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 460 int 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 { 423 482 cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl; 424 483 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 484 485 } // main 485 486 486 487 487 // Local Variables: // 488 // tab-width: 4 // 489 // mode: c++ // 488 490 // compile-command: "make install" // 489 491 // 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 // 5 7 // cfa.cc -- 6 // 8 // 7 9 // Author : Peter A. Buhr 8 10 // Created On : Tue Aug 20 13:44:49 2002 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Fri May 15 15:01:26201511 // Update Count : 1 0812 // 12 // Last Modified On : Sat May 16 07:47:05 2015 13 // Update Count : 111 14 // 13 15 14 16 #include <iostream> 15 #include <cstdio> // perror16 #include <cstdlib> // putenv, exit17 #include <unistd.h> // execvp18 #include <string> // STL version19 20 #include "config.h" // configure info17 #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 21 23 22 24 using std::cerr; … … 29 31 30 32 bool prefix( string arg, string pre ) { 31 33 return arg.substr( 0, pre.size() ) == pre; 32 34 } // prefix 33 35 34 36 35 37 void shuffle( const char *args[], int S, int E, int N ) { 36 37 #ifdef __DEBUG_H__ 38 39 #endif // __DEBUG_H__ 40 41 #ifdef __DEBUG_H__ 42 cerr << "\t" << j << " " << j-N << endl;43 #endif // __DEBUG_H__ 44 args[j] = args[j-N];45 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 46 48 } // shuffle 47 49 48 50 49 51 int 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; 60 57 } 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 ); 150 65 } // 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; 164 278 args[nargs] = ( *new string( string("-D__GCC_BPREFIX__=") + Bprefix ) ).c_str(); 165 279 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; 171 333 } // 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" ); 230 354 exit( EXIT_FAILURE ); 231 } // if232 233 string d;234 if ( debug ) {235 d = "-d";236 } // if237 238 args[nargs] = "-I" CFA_INCDIR;239 nargs += 1;240 241 if ( link ) {242 // include the cfa library in case it's needed243 args[nargs] = "-L" CFA_LIBDIR;244 nargs += 1;245 args[nargs] = "-lcfa";246 nargs += 1;247 } // if248 249 // add the correct set of flags based on the type of compile this is250 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 } // if260 261 if ( CFA_flag ) {262 args[nargs] = "-D__CFA__";263 nargs += 1;264 } // if265 266 if ( debug ) {267 heading += " (debug)";268 args[nargs] = "-D__CFA_DEBUG__";269 nargs += 1;270 } else {271 heading += " (no debug)";272 } // if273 274 if ( Bprefix.length() == 0 ) {275 Bprefix = installlibdir;276 args[nargs] = ( *new string( string("-D__GCC_BPREFIX__=") + Bprefix ) ).c_str();277 nargs += 1;278 } // if279 280 // execute the compilation command281 282 args[0] = compiler_path.c_str(); // set compiler command for exec283 // find actual name of the compiler independent of the path to it284 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 } // if290 291 if ( prefix( compiler_name, "gcc" ) ) { // allow suffix on gcc name292 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 } // if304 305 for ( int i = 0; i < nlibs; i += 1 ) { // copy non-user libraries after all user libraries306 args[nargs] = libs[i];307 nargs += 1;308 } // for309 310 args[nargs] = NULL; // terminate with NULL311 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 } // for318 #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 } // if332 } // if333 334 if ( verbose ) {335 if ( argc == 2 ) exit( EXIT_SUCCESS ); // if only the -v flag is specified, do not invoke gcc336 337 for ( int i = 0; args[i] != NULL; i += 1 ) {338 cerr << args[i] << " ";339 } // for340 cerr << endl;341 } // if342 343 if ( ! nonoptarg ) {344 cerr << argv[0] << " error, no input files" << endl;345 exit( EXIT_FAILURE );346 } // if347 348 // execute the command and return the result349 350 execvp( args[0], (char *const *)args ); // should not return351 perror( "CFA Translator error: cfa level, execvp" );352 exit( EXIT_FAILURE );353 355 } // main 354 356 355 357 // Local Variables: // 358 // tab-width: 4 // 359 // mode: c++ // 356 360 // compile-command: "make install" // 357 361 // 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 // 5 7 // bfd.h -- 6 // 8 // 7 9 // Author : Peter A. Buhr 8 10 // Created On : Thu Jan 8 15:50:56 2015 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Sat Jan 10 14:12:35201511 // Update Count : 312 // Last Modified On : Sat May 16 07:54:59 2015 13 // Update Count : 5 12 14 13 15 // This include file uses the CFA keyword "type" as a field name of a structure. … … 19 21 20 22 // Local Variables: // 23 // tab-width: 4 // 24 // mode: c++ // 21 25 // compile-command: "make install" // 22 26 // 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 // 5 7 // math.h -- 6 // 8 // 7 9 // Author : Peter A. Buhr 8 10 // Created On : Mon Nov 10 23:41:29 2014 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Sat Jan 10 14:12:21201511 // Update Count : 212 // Last Modified On : Sat May 16 07:55:52 2015 13 // Update Count : 3 12 14 13 15 // This include file uses the CFA keyword "type" as a field name of a structure. … … 19 21 20 22 // Local Variables: // 23 // tab-width: 4 // 24 // mode: c++ // 21 25 // compile-command: "make install" // 22 26 // 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 1 17 INSTALL=@INSTALL@ 2 18 BACKEND_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 1 16 # http://llvm.org/svn/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def 2 17 … … 4 19 FS = "(" 5 20 # 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" 18 33 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 *" 34 49 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" 50 65 N = 44 51 66 } # BEGIN … … 60 75 # generate C types for macros names 61 76 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] ) 63 78 } # for 64 79 printf( "\n" ) 65 80 66 81 for ( prototype in prototypes ) { 67 if ( index( "BT_LAST", prototype ) == 1 ) {68 69 } # if82 if ( index( "BT_LAST", prototype ) == 1 ) { 83 continue 84 } # if 70 85 71 printf( "#define %s(NAME) FUNC_SIMPLE(", prototype )86 printf( "#define %s(NAME) FUNC_SIMPLE(", prototype ) 72 87 73 if ( sub( "BT_FN_", "", prototype ) == 0 ) {74 75 76 } # if88 if ( sub( "BT_FN_", "", prototype ) == 0 ) { 89 printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype ) 90 exit 0 91 } # if 77 92 78 # generate function return type as macro79 for ( t = 0; t < N; t += 1 ) {# find longest match80 81 if ( index( prototype, type ) == 1 ) {# found match82 printf( "BT_%s, NAME", type )83 sub( type, "", prototype )84 break;85 86 } # for93 # 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 87 102 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 105 122 } # if 106 } # for 107 } # if 108 printf( ")\n" ) 123 printf( ")\n" ) 109 124 } # for 110 125 … … 115 130 printf( "typedef int wchar_t;\n" ); 116 131 } # 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 1 16 #include <list> 2 17 #include <vector> … … 10 25 11 26 namespace ArgTweak { 27 FunctionFixer::FunctionFixer( SymTab::Indexer *ind ) : index( ind ) { 28 if ( index == 0 ) index = new SymTab::Indexer(); 29 } 12 30 31 FunctionFixer::~FunctionFixer() { 32 delete index; 33 } 13 34 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 } 18 41 19 FunctionFixer::~FunctionFixer() 20 { 21 delete index; 22 } 42 Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr ) throw ( SemanticError ) { 43 assert( untypedExpr != 0 ); 44 NameExpr *function; 23 45 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(); 32 53 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; 38 57 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 } 49 64 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; 53 69 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; 60 73 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 ); 66 75 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 70 82 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 72 99 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() ); 79 102 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 } 96 105 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; 99 108 100 return goAhead; 101 } 109 std::string FunctionFixer::Matcher::extract_key ( DeclarationWithType *decl ) { 110 return decl->get_name(); 111 } 102 112 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 105 120 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 // 7 15 8 16 #include "MakeLibCfa.h" 17 #include "SynTree/Visitor.h" 9 18 #include "SynTree/Declaration.h" 10 19 #include "SynTree/Type.h" … … 12 21 #include "SynTree/Statement.h" 13 22 #include "SynTree/Initializer.h" 14 #include "SynTree/Visitor.h"15 23 #include "CodeGen/OperatorTable.h" 16 24 #include "UniqueName.h" 17 25 26 namespace 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 }; 18 36 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 } 20 42 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; 26 45 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; 28 97 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 32 105 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 // 7 15 8 16 #ifndef LIBCFA_MAKELIBCFA_H … … 13 21 14 22 namespace LibCfa { 15 16 void makeLibCfa( std::list< Declaration* > &prelude ); 17 23 void makeLibCfa( std::list< Declaration* > &prelude ); 18 24 } // namespace LibCfa 19 25 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 ############################################################################### 5 16 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 19 MODULES := Common Parser SynTree SymTab ResolvExpr CodeGen ControlStruct GenPoly Tuples InitTweak Designators # Try ArgTweak Explain 7 20 TARGET := cfa-cpp 8 21 9 all: $ (TARGET)22 all: ${TARGET} 10 23 11 24 # look for include files in each of the modules … … 16 29 # this is the back-end compiler, used to compile libcfa & builtins to link with user code 17 30 BACKEND_CC := @BACKEND_CC@ 18 19 # uncomment the definition of this variable to enable purify20 # (do a "purerun" first)21 #PURIFY := purify --cache-dir=$(HOME)/tmp22 31 23 32 # extra libraries if required … … 31 40 32 41 # include the description for each module 33 include $ (patsubst %,%/module.mk,$(MODULES))42 include ${patsubst %,%/module.mk,${MODULES}} 34 43 35 44 # 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)))45 OBJ := ${patsubst %.cc,%.o,${filter %.cc,${SRC}}} \ 46 ${patsubst %.y,%.tab.o,${filter %.y,${SRC}}} \ 47 ${patsubst %.l,%.yy.o,${filter %.l,${SRC}}} 39 48 40 49 # include the C include dependencies 41 DEPS := $ (OBJ:.o=.d)42 -include $ (DEPS)50 DEPS := ${OBJ:.o=.d} 51 -include ${DEPS} 43 52 44 53 # link the program 45 $ (TARGET): $(OBJ)46 $ (PURIFY) $(CXX) -o $@ $(OBJ) $(LIBS)54 ${TARGET}: ${OBJ} 55 ${PURIFY} ${CXX} -o $@ ${OBJ} ${LIBS} 47 56 48 57 #installing 49 install: $ (TARGET)50 $ (INSTALL)-d @CFA_LIBDIR@51 $ (INSTALL) $(TARGET)@CFA_LIBDIR@58 install: ${TARGET} 59 ${INSTALL} -d @CFA_LIBDIR@ 60 ${INSTALL} ${TARGET} @CFA_LIBDIR@ 52 61 53 62 # clean-up rule 54 63 clean: 55 rm -f $ (OBJ) $(DEPS) $(TARGET) tags $(EXTRA_OUTPUT)64 rm -f ${OBJ} ${DEPS} ${TARGET} tags ${EXTRA_OUTPUT} 56 65 find . -name "Expected*" -prune -o \( -name "*.tst" -o -name "report" \) -print | xargs rm -f 57 66 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 1 16 #include <string> 2 17 #include <list> … … 23 38 24 39 DeclarationNode *DeclarationNode::clone() const { 25 26 27 28 29 30 31 32 33 34 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; 35 50 } 36 51 … … 39 54 40 55 DeclarationNode::~DeclarationNode() { 41 42 43 56 delete type; 57 delete bitfieldWidth; 58 delete initializer; 44 59 } 45 60 46 61 bool DeclarationNode::get_hasEllipsis() const { 47 62 return hasEllipsis; 48 63 } 49 64 50 65 const char *storageClassName[] = { 51 52 53 54 55 56 57 66 // order must correspond with DeclarationNode::StorageClass 67 "extern", 68 "static", 69 "auto", 70 "register", 71 "inline", 72 "fortran", 58 73 }; 59 74 60 75 void DeclarationNode::print( std::ostream &os, int indent ) const { 61 62 63 os << "unnamed: ";64 65 os << name << ": ";66 67 68 69 os << LinkageSpec::toString( linkage ) << " ";70 71 72 73 74 type->print( os, indent );75 76 os << "untyped entity ";77 78 79 80 os << endl << string(indent+2, ' ') << "with bitfield width ";81 bitfieldWidth->printOneLine( os );82 83 84 85 os << endl << string(indent+2, ' ') << "with initializer ";86 initializer->printOneLine( os );87 88 89 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; 90 105 } 91 106 92 107 void DeclarationNode::printList( std::ostream &os, int indent ) const { 93 94 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 } 97 112 } 98 113 99 114 DeclarationNode *DeclarationNode::newFunction( std::string *name, DeclarationNode *ret, DeclarationNode *param, StatementNode *body, bool newStyle ) { 100 101 102 103 104 105 106 107 108 109 newnode->type->function->hasBody = true;110 111 112 113 newnode->type->base = ret->type;114 ret->type = 0;115 delete ret;116 117 118 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; 119 134 } 120 135 121 136 DeclarationNode *DeclarationNode::newQualifier( Qualifier q ) { 122 123 124 125 137 DeclarationNode *newnode = new DeclarationNode; 138 newnode->type = new TypeData(); 139 newnode->type->qualifiers.push_back( q ); 140 return newnode; 126 141 } 127 142 128 143 DeclarationNode *DeclarationNode::newStorageClass( StorageClass sc ) { 129 130 131 144 DeclarationNode *newnode = new DeclarationNode; 145 newnode->storageClasses.push_back( sc ); 146 return newnode; 132 147 } 133 148 134 149 DeclarationNode *DeclarationNode::newBasicType( BasicType bt ) { 135 136 137 138 150 DeclarationNode *newnode = new DeclarationNode; 151 newnode->type = new TypeData( TypeData::Basic ); 152 newnode->type->basic->typeSpec.push_back( bt ); 153 return newnode; 139 154 } 140 155 141 156 DeclarationNode *DeclarationNode::newModifier( Modifier mod ) { 142 143 144 145 157 DeclarationNode *newnode = new DeclarationNode; 158 newnode->type = new TypeData( TypeData::Basic ); 159 newnode->type->basic->modifiers.push_back( mod ); 160 return newnode; 146 161 } 147 162 148 163 DeclarationNode *DeclarationNode::newForall( DeclarationNode* forall ) { 149 150 151 152 164 DeclarationNode *newnode = new DeclarationNode; 165 newnode->type = new TypeData( TypeData::Unknown ); 166 newnode->type->forall = forall; 167 return newnode; 153 168 } 154 169 155 170 DeclarationNode *DeclarationNode::newFromTypedef( std::string* name ) { 156 157 158 159 160 161 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; 162 177 } 163 178 164 179 DeclarationNode *DeclarationNode::newAggregate( TyCon kind, std::string* name, DeclarationNode *formals, ExpressionNode *actuals, DeclarationNode *fields ) { 165 166 167 168 169 170 newnode->type->aggregate->name = DeclarationNode::anonymous.newName();171 172 173 174 175 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; 176 191 } 177 192 178 193 DeclarationNode *DeclarationNode::newEnum( std::string *name, DeclarationNode *constants ) { 179 180 181 182 183 184 newnode->type->enumeration->name = DeclarationNode::anonymous.newName();185 186 187 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; 188 203 } 189 204 190 205 DeclarationNode *DeclarationNode::newEnumConstant( std::string* name, ExpressionNode *constant ) { 191 192 193 194 206 DeclarationNode *newnode = new DeclarationNode; 207 newnode->name = assign_strptr( name ); 208 // do something with the constant 209 return newnode; 195 210 } 196 211 197 212 DeclarationNode *DeclarationNode::newName( std::string* name ) { 198 199 200 213 DeclarationNode *newnode = new DeclarationNode; 214 newnode->name = assign_strptr( name ); 215 return newnode; 201 216 } 202 217 203 218 DeclarationNode *DeclarationNode::newFromTypeGen( std::string* name, ExpressionNode *params ) { 204 205 206 207 208 209 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; 210 225 } 211 226 212 227 DeclarationNode *DeclarationNode::newTypeParam( TypeClass tc, std::string* name ) { 213 214 215 216 217 218 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; 219 234 } 220 235 221 236 DeclarationNode *DeclarationNode::newContext( std::string *name, DeclarationNode *params, DeclarationNode *asserts ) { 222 223 224 225 226 227 228 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; 229 244 } 230 245 231 246 DeclarationNode *DeclarationNode::newContextUse( std::string *name, ExpressionNode *params ) { 232 233 234 235 236 237 238 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; 239 254 } 240 255 241 256 DeclarationNode *DeclarationNode::newTypeDecl( std::string *name, DeclarationNode *typeParams ) { 242 243 244 245 246 247 248 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; 249 264 } 250 265 251 266 DeclarationNode *DeclarationNode::newPointer( DeclarationNode *qualifiers ) { 252 253 254 267 DeclarationNode *newnode = new DeclarationNode; 268 newnode->type = new TypeData( TypeData::Pointer ); 269 return newnode->addQualifiers( qualifiers ); 255 270 } 256 271 257 272 DeclarationNode *DeclarationNode::newArray( ExpressionNode *size, DeclarationNode *qualifiers, bool isStatic ) { 258 259 260 261 262 263 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 ); 264 279 } 265 280 266 281 DeclarationNode *DeclarationNode::newVarArray( DeclarationNode *qualifiers ) { 267 268 269 270 271 272 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 ); 273 288 } 274 289 275 290 DeclarationNode *DeclarationNode::newBitfield( ExpressionNode *size ) { 276 277 278 291 DeclarationNode *newnode = new DeclarationNode; 292 newnode->bitfieldWidth = size; 293 return newnode; 279 294 } 280 295 281 296 DeclarationNode *DeclarationNode::newTuple( DeclarationNode *members ) { 282 283 284 285 297 DeclarationNode *newnode = new DeclarationNode; 298 newnode->type = new TypeData( TypeData::Tuple ); 299 newnode->type->tuple->members = members; 300 return newnode; 286 301 } 287 302 288 303 DeclarationNode *DeclarationNode::newTypeof( ExpressionNode *expr ) { 289 290 291 292 304 DeclarationNode *newnode = new DeclarationNode; 305 newnode->type = new TypeData( TypeData::Typeof ); 306 newnode->type->typeexpr->expr = expr; 307 return newnode; 293 308 } 294 309 295 310 DeclarationNode *DeclarationNode::newAttr( std::string *name, ExpressionNode *expr ) { 296 297 298 299 300 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; 301 316 } 302 317 303 318 DeclarationNode *DeclarationNode::newAttr( std::string *name, DeclarationNode *type ) { 304 305 306 307 308 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; 309 324 } 310 325 311 326 static void addQualifiersToType( TypeData *&src, TypeData *dst ) { 312 313 if ( src->forall && dst->kind == TypeData::Function ) {314 315 dst->forall->appendList( src->forall );316 317 dst->forall = src->forall;318 319 320 }321 if ( dst->base ) {322 323 } else if ( dst->kind == TypeData::Function ) {324 325 326 } else {327 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 332 347 DeclarationNode *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 369 DeclarationNode *DeclarationNode::copyStorageClasses( DeclarationNode *q ) { 370 storageClasses = q->storageClasses; 371 return this; 372 } 373 374 static 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 ); 343 386 } 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 431 DeclarationNode *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 459 DeclarationNode *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 469 DeclarationNode *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 } 377 478 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; 385 485 } 386 486 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; 478 493 } 479 494 480 495 DeclarationNode *DeclarationNode::addName( std::string* newname ) { 481 482 496 name = assign_strptr( newname ); 497 return this; 483 498 } 484 499 485 500 DeclarationNode *DeclarationNode::addBitfield( ExpressionNode *size ) { 486 487 501 bitfieldWidth = size; 502 return this; 488 503 } 489 504 490 505 DeclarationNode *DeclarationNode::addVarArgs() { 491 492 493 506 assert( type ); 507 hasEllipsis = true; 508 return this; 494 509 } 495 510 496 511 DeclarationNode *DeclarationNode::addFunctionBody( StatementNode *body ) { 497 498 499 500 501 502 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; 503 518 } 504 519 505 520 DeclarationNode *DeclarationNode::addOldDeclList( DeclarationNode *list ) { 506 507 508 509 510 521 assert( type ); 522 assert( type->kind == TypeData::Function ); 523 assert( type->function->oldDeclList == 0 ); 524 type->function->oldDeclList = list; 525 return this; 511 526 } 512 527 513 528 static void 514 529 setBase( TypeData *&type, TypeData *newType ) { 515 516 TypeData *prevBase = type;517 TypeData *curBase = type->base;518 while( curBase != 0 ) {519 520 521 }522 prevBase->base = newType;523 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 } 526 541 } 527 542 528 543 DeclarationNode *DeclarationNode::addPointer( DeclarationNode *p ) { 529 530 assert( p->type->kind == TypeData::Pointer );531 setBase( type, p->type );532 p->type = 0;533 delete p;534 535 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; 536 551 } 537 552 538 553 DeclarationNode *DeclarationNode::addArray( DeclarationNode *a ) { 539 540 assert( a->type->kind == TypeData::Array );541 setBase( type, a->type );542 a->type = 0;543 delete a;544 545 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; 546 561 } 547 562 548 563 DeclarationNode *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 590 static 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 599 DeclarationNode *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 626 DeclarationNode *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 633 static TypeData *addIdListToType( TypeData *type, DeclarationNode *ids ) { 551 634 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; 623 641 } 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 634 648 DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) { 635 636 649 type = addIdListToType( type, ids ); 650 return this; 637 651 } 638 652 639 653 DeclarationNode *DeclarationNode::addInitializer( InitializerNode *init ) { 640 641 642 654 //assert 655 initializer = init; 656 return this; 643 657 } 644 658 645 659 DeclarationNode *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 683 DeclarationNode *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 715 DeclarationNode *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 723 DeclarationNode *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 739 DeclarationNode *DeclarationNode::appendList( DeclarationNode *node ) { 740 if ( node != 0 ) { 741 set_link( node ); 742 } 743 return this; 744 } 745 746 DeclarationNode *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 } 657 756 } 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 } 745 759 } 746 760 747 761 void 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 } 773 786 } 774 787 775 788 void buildList( const DeclarationNode *firstNode, std::list< DeclarationWithType* > &outputList ) { 776 777 778 779 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 { 781 794 /// if ( DeclarationNode *extr = cur->extractAggregate() ) { 782 795 /// // handle the case where a structure declaration is contained within an object or type … … 787 800 /// } 788 801 /// } 789 790 791 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {792 793 } else if ( StructDecl *agg = dynamic_cast< StructDecl* >( decl ) ) {794 795 796 797 } else if ( UnionDecl *agg = dynamic_cast< UnionDecl* >( decl ) ) {798 799 800 }801 802 } catch( SemanticError &e ) {803 804 }805 cur = dynamic_cast< DeclarationNode* >( cur->get_link() );806 807 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 } 810 823 } 811 824 812 825 void buildTypeList( const DeclarationNode *firstNode, std::list< Type* > &outputList ) { 813 814 815 816 817 try {818 819 } catch( SemanticError &e ) {820 821 }822 cur = dynamic_cast< DeclarationNode* >( cur->get_link() );823 824 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 } 827 840 } 828 841 829 842 Declaration *DeclarationNode::build() const { 830 843 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 } 834 850 } 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; 844 857 } 845 858 846 859 Type *DeclarationNode::buildType() const { 847 860 assert( type ); 848 861 849 850 851 return new EnumInstType( type->buildQualifiers(), type->enumeration->name );852 853 ReferenceToType *ret;854 switch ( type->aggregate->kind ) {855 856 857 858 859 860 861 862 863 864 865 866 } // switch867 buildList( type->aggregate->actuals, ret->get_parameters() );868 return ret;869 870 871 TypeInstType *ret = new TypeInstType( type->buildQualifiers(), type->symbolic->name, false );872 buildList( type->symbolic->actuals, ret->get_parameters() );873 return ret;874 875 876 return type->build();877 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 878 891 } 879 892 880 893 Declaration::StorageClass DeclarationNode::buildStorageClass() const { 881 882 Declaration::Extern,883 Declaration::Static,884 Declaration::Auto,885 Declaration::Register,886 Declaration::Inline,887 Declaration::Fortran888 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 }; 889 902 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 916 bool 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; 896 920 } 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 906 929 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 1 16 #include <cassert> 2 17 #include <cctype> … … 17 32 18 33 ExpressionNode::ExpressionNode( string *name_) : ParseNode( *name_ ), argName( 0 ) { 19 34 delete name_; 20 35 } 21 36 22 37 ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.name ) { 23 24 argName = other.argName->clone();25 26 argName = 0;27 38 if ( other.argName ) { 39 argName = other.argName->clone(); 40 } else { 41 argName = 0; 42 } // if 28 43 } 29 44 30 45 ExpressionNode * ExpressionNode::set_asArgName( std::string *aName ) { 31 32 46 argName = new VarRefNode( aName ); 47 return this; 33 48 } 34 49 35 50 ExpressionNode * ExpressionNode::set_asArgName( ExpressionNode *aDesignator ) { 36 37 51 argName = aDesignator; 52 return this; 38 53 } 39 54 40 55 void ExpressionNode::printDesignation( std::ostream &os, int indent ) const { 41 42 os << string(' ', indent ) << "(designated by: ";43 argName->printOneLine( os, indent );44 os << ")" << std::endl;45 56 if ( argName ) { 57 os << string(' ', indent ) << "(designated by: "; 58 argName->printOneLine( os, indent ); 59 os << ")" << std::endl; 60 } // if 46 61 } 47 62 … … 49 64 50 65 NullExprNode *NullExprNode::clone() const { 51 66 return new NullExprNode(); 52 67 } 53 68 54 69 void NullExprNode::print( std::ostream & os, int indent ) const { 55 56 70 printDesignation( os ); 71 os << "null expression"; 57 72 } 58 73 59 74 void NullExprNode::printOneLine( std::ostream & os, int indent ) const { 60 61 75 printDesignation( os ); 76 os << "null"; 62 77 } 63 78 64 79 Expression *NullExprNode::build() const { 65 80 return 0; 66 81 } 67 82 68 83 CommaExprNode *ExpressionNode::add_to_list( ExpressionNode *exp ){ 69 84 return new CommaExprNode( this, exp ); 70 85 } 71 86 … … 77 92 78 93 ConstantNode::ConstantNode( Type t, string *inVal ) : type( t ), sign( true ), longs(0), size(0) { 79 80 value = *inVal;81 delete inVal;82 83 value = "";84 85 86 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 104 ConstantNode::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 ) { 91 106 } 92 107 93 108 // for some reason, std::tolower doesn't work as an argument to std::transform in g++ 3.1 94 109 inline char tolower_hack( char c ) { 95 110 return std::tolower( c ); 96 111 } 97 112 98 113 void 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 ; 129 156 } 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 159 ConstantNode::Type ConstantNode::get_type( void ) const { 160 return type; 161 } 162 163 ConstantNode *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 177 void 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; 137 197 } 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 << ' '; 185 200 } 186 201 187 202 void ConstantNode::print( std::ostream &os, int indent ) const { 188 189 203 printOneLine( os, indent ); 204 os << endl; 190 205 } 191 206 192 207 Expression *ConstantNode::build() const { 193 194 195 196 197 198 /* Cfr. standard 6.4.4.1 */199 //bt.set_kind( BasicType::SignedInt );200 bt = new BasicType( q, BasicType::SignedInt );201 break;202 203 bt = new BasicType( q, BasicType::Float );204 break;205 206 bt = new BasicType( q, BasicType::Char );207 break;208 209 // string should probably be a primitive type210 ArrayType *at;211 std::string value = get_value();212 at = new ArrayType( q, new BasicType( q, BasicType::Char ),213 214 215 216 return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) );217 218 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() ) ); 219 234 } 220 235 … … 227 242 228 243 Expression *VarRefNode::build() const { 229 244 return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) ); 230 245 } 231 246 232 247 void VarRefNode::printOneLine( std::ostream &os, int indent ) const { 233 234 248 printDesignation( os ); 249 os << get_name() << ' '; 235 250 } 236 251 237 252 void VarRefNode::print( std::ostream &os, int indent ) const { 238 239 240 241 253 printDesignation( os ); 254 os << '\r' << string( indent, ' ') << "Referencing: "; 255 os << "Variable: " << get_name(); 256 os << endl; 242 257 } 243 258 … … 250 265 251 266 OperatorNode::Type OperatorNode::get_type( void ) const{ 252 267 return type; 253 268 } 254 269 255 270 void OperatorNode::printOneLine( std::ostream &os, int indent ) const { 256 257 271 printDesignation( os ); 272 os << OpName[ type ] << ' '; 258 273 } 259 274 260 275 void OperatorNode::print( std::ostream &os, int indent ) const{ 261 262 263 276 printDesignation( os ); 277 os << '\r' << string( indent, ' ') << "Operator: " << OpName[type] << endl; 278 return; 264 279 } 265 280 266 281 std::string OperatorNode::get_typename( void ) const{ 267 282 return string( OpName[ type ]); 268 283 } 269 284 270 285 const char *OperatorNode::OpName[] = { 271 272 273 274 275 276 277 278 279 280 281 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" 282 297 }; 283 298 … … 289 304 290 305 CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *args ): 291 306 function( f ), arguments( args ) { 292 307 } 293 308 294 309 CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2): 295 296 310 function( f ), arguments( arg1) { 311 arguments->set_link( arg2); 297 312 } 298 313 299 314 CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) { 300 301 302 if ( arguments ) {303 304 } else {305 306 } // if307 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 } 309 324 } 310 325 311 326 CompositeExprNode::~CompositeExprNode() { 312 313 327 delete function; 328 delete arguments; 314 329 } 315 330 316 331 // the names that users use to define operator functions 317 332 static const char *opFuncName[] = { 318 319 320 321 322 323 324 325 326 333 "", "", "", 334 "", "", 335 // diadic 336 "", "", "", "", "?+?", "?-?", "?*?", "?/?", "?%?", "", "", 337 "?|?", "?&?", "?^?", "", "?<<?", "?>>?", "?<?", "?>?", "?<=?", 338 "?>=?", "?==?", "?!=?", "?=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", 339 "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "","","Range", 340 // monadic 341 "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress" 327 342 }; 328 343 … … 330 345 331 346 Expression *CompositeExprNode::build() const { 332 333 334 335 336 337 338 // a function as opposed to an operator339 return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() ));340 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 358 359 360 361 default:362 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 407 case OperatorNode::AddressOf:408 409 410 411 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 423 424 } else {425 426 } // if427 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 437 438 439 /* else if ( memberTup != 0 )440 {441 UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front());442 delete member;443 return ret;444 } */445 } else446 447 448 case OperatorNode::PFieldSel:449 450 assert( args.size() == 2 );451 452 NameExpr *member = dynamic_cast<NameExpr *>( args.back()); // modify for Tuples xxx453 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 { 465 480 /// bool isSizeOf = ( op->get_type() == OperatorNode::SizeOf ); 466 481 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; 695 538 } 696 539 } 697 698 if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) ) 699 list->set_next( flattenCommas( next ) ); 700 701 return list; 540 } 541 542 void 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 552 void 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 565 void CompositeExprNode::set_function( ExpressionNode *f ){ 566 function = f; 567 } 568 569 void CompositeExprNode::set_args( ExpressionNode *args ){ 570 arguments = args; 571 } 572 573 ExpressionNode *CompositeExprNode::get_function( void ) const { 574 return function; 575 } 576 577 ExpressionNode *CompositeExprNode::get_args( void ) const { 578 return arguments; 579 } 580 581 void CompositeExprNode::add_arg( ExpressionNode *arg ){ 582 if ( arguments ) 583 arguments->set_link( arg ); 584 else 585 set_args( arg ); 586 } 587 588 CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {} 589 590 CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) { 591 } 592 593 CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) { 594 } 595 596 CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ){ 597 add_arg( exp ); 598 599 return this; 600 } 601 602 CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) { 603 } 604 605 ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {} 606 607 ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) { 608 } 609 610 ValofExprNode::~ValofExprNode() { 611 delete body; 612 } 613 614 void 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 620 void ValofExprNode::printOneLine( std::ostream &, int indent ) const { 621 assert( false ); 622 } 623 624 Expression *ValofExprNode::build() const { 625 return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) ); 626 } 627 628 ForCtlExprNode::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 644 ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other ) 645 : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) { 646 } 647 648 ForCtlExprNode::~ForCtlExprNode(){ 649 delete init; 650 delete condition; 651 delete change; 652 } 653 654 Expression *ForCtlExprNode::build() const { 655 // this shouldn't be used! 656 assert( false ); 657 return 0; 658 } 659 660 void 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 675 void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const { 676 assert( false ); 677 } 678 679 TypeValueNode::TypeValueNode( DeclarationNode *decl ) 680 : decl( decl ) { 681 } 682 683 TypeValueNode::TypeValueNode( const TypeValueNode &other ) 684 : ExpressionNode( other ), decl( maybeClone( other.decl ) ) { 685 } 686 687 Expression *TypeValueNode::build() const { 688 return new TypeExpr( decl->buildType() ); 689 } 690 691 void TypeValueNode::print( std::ostream &os, int indent ) const { 692 os << std::string( indent, ' ' ) << "Type:"; 693 get_decl()->print( os, indent + 2); 694 } 695 696 void TypeValueNode::printOneLine( std::ostream &os, int indent ) const { 697 os << "Type:"; 698 get_decl()->print( os, indent + 2); 699 } 700 701 ExpressionNode *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; 702 717 } 703 718 704 719 ExpressionNode *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 1 16 #include <cassert> 2 17 #include <iostream> … … 9 24 InitializerNode::InitializerNode( ExpressionNode *_expr, bool aggrp, ExpressionNode *des ) 10 25 : expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) { 11 12 kids = dynamic_cast< InitializerNode *>( get_link() );26 if ( aggrp ) 27 kids = dynamic_cast< InitializerNode *>( get_link() ); 13 28 14 15 set_link( 0 );29 if ( kids != 0 ) 30 set_link( 0 ); 16 31 } 17 32 18 33 InitializerNode::InitializerNode( InitializerNode *init, bool aggrp, ExpressionNode *des ) 19 20 21 set_link(init);34 : expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) { 35 if ( init != 0 ) 36 set_link(init); 22 37 23 24 kids = dynamic_cast< InitializerNode *>( get_link() );38 if ( aggrp ) 39 kids = dynamic_cast< InitializerNode *>( get_link() ); 25 40 26 27 set_next( 0 );41 if ( kids != 0 ) 42 set_next( 0 ); 28 43 } 29 44 30 45 InitializerNode::~InitializerNode() { 31 46 delete expr; 32 47 } 33 48 34 49 void InitializerNode::print( std::ostream &os, int indent ) const { 35 50 os << std::string(indent, ' ') << "Initializer expression" << std::endl; 36 51 } 37 52 38 53 void 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 << "--]"; 49 71 } // if 50 if ( expr ) expr->printOneLine(os);51 } else { // It's an aggregate52 os << "[--";53 if ( next_init() != 0 )54 next_init()->printOneLine(os);55 if (aggregate) os << "--]";56 } // if57 72 58 59 60 moreInit->printOneLine( os );73 InitializerNode *moreInit; 74 if ( get_link() != 0 && ((moreInit = dynamic_cast< InitializerNode * >( get_link() ) ) != 0) ) 75 moreInit->printOneLine( os ); 61 76 } 62 77 63 78 Initializer *InitializerNode::build() const { 64 79 // if ( get_expression() == 0 ) return 0; // XXX (?) 65 80 66 67 assert( next_init() != 0 );81 if ( aggregate ) { 82 assert( next_init() != 0 ); 68 83 69 std::list< Initializer *> initlist;70 buildList<Initializer, InitializerNode>( next_init(), initlist );84 std::list< Initializer *> initlist; 85 buildList<Initializer, InitializerNode>( next_init(), initlist ); 71 86 72 std::list< Expression *> designlist;87 std::list< Expression *> designlist; 73 88 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 ); 76 102 } // if 77 103 78 return new ListInit( initlist, designlist ); 79 } else { 80 std::list< Expression *> designators; 104 return 0; 105 } 81 106 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 1 16 #include <string> 2 17 #include <cassert> … … 6 21 7 22 LinkageSpec::Type LinkageSpec::fromString( const std::string &stringSpec ) { 8 9 return Cforall;10 11 return C;12 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 } 15 30 } 16 31 17 32 std::string LinkageSpec::toString( LinkageSpec::Type linkage ) { 18 19 20 return "intrinsic";21 22 return "Cforall";23 24 return "C";25 26 return "automatically generated";27 28 return "compiler built-in";29 30 31 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 ""; 32 47 } 33 48 34 49 bool 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 ); 42 60 return false; 43 }44 assert( false );45 return false;46 61 } 47 62 48 63 bool 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 ); 56 74 return false; 57 }58 assert( false );59 return false;60 75 } 61 76 62 77 bool LinkageSpec::isOverloadable( Type t ) { 63 78 return isDecoratable( t ); 64 79 } 65 80 66 81 bool 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 ); 71 92 return false; 72 case Intrinsic:73 case Compiler:74 return true;75 }76 assert( false );77 return false;78 93 } 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 1 16 #ifndef LINKAGESPEC_H 2 17 #define LINKAGESPEC_H … … 5 20 6 21 struct LinkageSpec { 7 8 Intrinsic,// C built-in defined in prelude9 Cforall,// ordinary10 C,// not overloadable, not mangled11 AutoGen,// built by translator (struct assignment)12 Compiler// gcc internal13 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 }; 14 29 15 16 30 static Type fromString( const std::string & ); 31 static std::string toString( Type ); 17 32 18 19 20 21 33 static bool isDecoratable( Type ); 34 static bool isGeneratable( Type ); 35 static bool isOverloadable( Type ); 36 static bool isBuiltin( Type ); 22 37 }; 23 38 24 39 #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 1 16 #include "ParseNode.h" 2 17 using namespace std; … … 74 89 75 90 ParseNode *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) 81 94 return &pn; 82 95 } 83 96 84 85 97 // Local Variables: // 86 // mode: C++ // 87 // compile-command: "gmake" // 98 // tab-width: 4 // 99 // mode: c++ // 100 // compile-command: "make install" // 88 101 // 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 1 16 #ifndef PARSENODE_H 2 17 #define PARSENODE_H … … 21 36 class ParseNode { 22 37 public: 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 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 &); 44 59 protected: 45 46 47 60 std::string name; 61 ParseNode *next; 62 static int indent_by; 48 63 }; 49 64 … … 52 67 class ExpressionNode : public ParseNode { 53 68 public: 54 55 56 57 virtual ~ExpressionNode() { /* can't delete asArgName because it might be referenced elsewhere */ }; 58 59 60 61 62 63 64 65 66 67 68 69 70 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; 71 86 protected: 72 73 private: 74 87 void printDesignation ( std::ostream &, int indent = 0) const; 88 private: 89 ExpressionNode *argName; 75 90 }; 76 91 … … 78 93 class NullExprNode : public ExpressionNode { 79 94 public: 80 81 82 83 84 85 86 87 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; 88 103 }; 89 104 90 105 class ConstantNode : public ExpressionNode { 91 106 public: 92 93 Integer, Float, Character, String /* , Range, EnumConstant */94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 private: 112 113 114 115 116 117 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; 118 133 }; 119 134 120 135 class VarRefNode : public ExpressionNode { 121 136 public: 122 123 124 125 126 127 128 129 130 131 132 private: 133 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; 134 149 }; 135 150 136 151 class TypeValueNode : public ExpressionNode { 137 152 public: 138 139 140 141 142 143 144 145 146 147 148 149 private: 150 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; 151 166 }; 152 167 153 168 class OperatorNode : public ExpressionNode { 154 169 public: 155 156 Cond, NCond,157 SizeOf, AlignOf, Attr, CompLit, Plus, Minus, Mul, Div, Mod, Or, And,158 159 160 161 UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 private: 178 179 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[]; 180 195 }; 181 196 … … 183 198 class CompositeExprNode : public ExpressionNode { 184 199 public: 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 private: 206 207 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; 208 223 }; 209 224 210 225 class CommaExprNode : public CompositeExprNode { 211 226 public: 212 213 214 215 216 217 218 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 ); } 219 234 }; 220 235 221 236 class ForCtlExprNode : public ExpressionNode { 222 237 public: 223 224 225 226 227 228 229 230 231 232 233 234 235 236 private: 237 238 239 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; 240 255 }; 241 256 242 257 class ValofExprNode : public ExpressionNode { 243 258 public: 244 245 246 247 259 ValofExprNode(); 260 ValofExprNode( StatementNode *s = 0 ); 261 ValofExprNode( const ValofExprNode &other ); 262 ~ValofExprNode(); 248 263 249 250 251 252 253 254 255 256 private: 257 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; 258 273 }; 259 274 … … 262 277 class DeclarationNode : public ParseNode { 263 278 public: 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 StatementNode *body, bool newStyle = false );279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 private: 344 345 346 347 348 349 350 351 352 353 354 355 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; 356 371 }; 357 372 358 373 class StatementNode : public ParseNode { 359 374 public: 360 361 While, Do, For,362 Goto, Continue, Break, Return, Throw,363 Try, Catch, Finally, Asm,364 Decl365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 private: 403 404 405 406 407 408 409 410 411 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; 412 427 }; 413 428 414 429 class CompoundStmtNode : public StatementNode { 415 430 public: 416 417 418 419 420 421 422 423 424 425 426 private: 427 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; 428 443 }; 429 444 430 445 class NullStmtNode : public CompoundStmtNode { 431 446 public: 432 433 447 Statement *build() const; 448 void print( std::ostream &, int indent = 0) const; 434 449 }; 435 450 436 451 class InitializerNode : public ParseNode { 437 452 public: 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 private: 454 455 456 457 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; 458 473 }; 459 474 … … 461 476 462 477 template< 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 478 void 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 485 498 } 486 499 … … 497 510 498 511 // Local Variables: // 499 // mode: C++ // 500 // compile-command: "gmake" // 512 // tab-width: 4 // 513 // mode: c++ // 514 // compile-command: "make install" // 501 515 // 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 // 7 15 8 16 #include "Parser.h" … … 11 19 #include "cfa.tab.h" 12 20 13 / * global variables in cfa.y */21 // global variables in cfa.y 14 22 extern int yyparse(void); 15 16 23 extern int yydebug; 17 24 extern LinkageSpec::Type linkage; 18 19 25 extern TypedefTable typedefTable; 20 26 extern DeclarationNode *theTree; 21 /* end of globals */22 27 23 28 Parser *Parser::theParser = 0; … … 25 30 Parser::Parser(): parseTree( 0 ), parseStatus( 1 ) {} 26 31 27 Parser::~Parser() 28 { 29 delete parseTree; 32 Parser::~Parser() { 33 delete parseTree; 30 34 } 31 35 32 /* static class method */ 33 Parser & 34 Parser::get_parser() 35 { 36 if( theParser == 0 ) { 37 theParser = new Parser; 38 } 39 return *theParser; 36 Parser &Parser::get_parser() { 37 if ( theParser == 0 ) { 38 theParser = new Parser; 39 } // if 40 return *theParser; 40 41 } 41 42 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; 43 void 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; 52 51 } 53 52 54 void 55 Parser::set_debug( bool debug ) 56 { 57 yydebug = debug; 53 void Parser::set_debug( bool debug ) { 54 yydebug = debug; 58 55 } 59 56 60 void 61 Parser::set_linkage( LinkageSpec::Type linkage ) 62 { 63 ::linkage = linkage; 57 void Parser::set_linkage( LinkageSpec::Type linkage ) { 58 ::linkage = linkage; 64 59 } 65 60 66 67 void 68 Parser::freeTree() 69 { 70 delete parseTree; 71 parseTree = 0; 61 void Parser::freeTree() { 62 delete parseTree; 63 parseTree = 0; 72 64 } 73 65 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 // 9 15 10 16 #ifndef PARSER_H … … 16 22 #include "LinkageSpec.h" 17 23 18 class Parser 19 { 20 public: 21 static Parser &get_parser(); 24 class Parser { 25 public: 26 static Parser &get_parser(); 22 27 23 /* do the actual parse */ 24 28 // do the actual parse 29 void parse( FILE *input ); 25 30 26 /* accessors to return the result of the parse */ 27 28 31 // accessors to return the result of the parse 32 DeclarationNode *get_parseTree() const { return parseTree; } 33 int get_parseStatus() const { return parseStatus; } 29 34 30 /* mutators to control parse options */ 31 32 35 // mutators to control parse options 36 void set_debug( bool debug ); 37 void set_linkage( LinkageSpec::Type linkage ); 33 38 34 /* free the parse tree without actually destroying the parser */ 35 39 // free the parse tree without actually destroying the parser 40 void freeTree(); 36 41 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; 44 48 }; 45 49 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 2 16 #include <list> 3 17 #include <algorithm> … … 12 26 using namespace std; 13 27 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; 28 const 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 36 StatementNode::StatementNode() : ParseNode(), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {} 37 38 StatementNode::StatementNode( string name_) : ParseNode( name_), control( 0 ), block( 0 ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) {} 39 40 StatementNode::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 62 StatementNode::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; 57 66 } 58 67 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 64 65 66 67 68 } 69 70 StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) {71 72 73 74 75 68 StatementNode::StatementNode( Type t, string *_target ) : 69 type( t ), control( 0 ), block( 0 ), labels( 0 ), target(_target ), decl( 0 ), isCatchRest ( false ) {} 70 71 StatementNode::~StatementNode() { 72 delete control; 73 delete block; 74 delete labels; 75 delete target; 76 delete decl; 77 } 78 79 StatementNode * 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; 76 85 } 77 86 78 87 std::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 94 StatementNode * 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 105 void StatementNode::set_control( ExpressionNode *c ) { 106 control = c; 107 } 108 109 StatementNode * StatementNode::set_block( StatementNode *b ) { 110 block = b; 111 112 return this; 113 } 114 115 ExpressionNode *StatementNode::get_control() const { 116 return control; 117 } 118 119 StatementNode *StatementNode::get_block() const { 120 return block; 121 } 122 123 StatementNode::Type StatementNode::get_type() const { 124 return type; 125 } 126 127 StatementNode *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 138 std::list<std::string> *StatementNode::get_labels() const { return labels; } 139 140 StatementNode *StatementNode::add_controlexp( ExpressionNode *e ) { 141 if ( control && e ) 142 control->add_to_list( e ); // xxx - check this 143 144 return this; 145 } 146 147 StatementNode *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 157 StatementNode *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; 167 169 } 168 170 169 171 void 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 } 225 219 } 226 220 227 221 Statement *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 347 CompoundStmtNode::CompoundStmtNode() : first( 0 ), last( 0 ) { 348 } 349 350 CompoundStmtNode::CompoundStmtNode( string *name_) : StatementNode(*name_), first( 0 ), last( 0 ) { 351 } 352 353 CompoundStmtNode::CompoundStmtNode( StatementNode *stmt ): first( stmt ) { 354 if ( first ) { 355 last = ( StatementNode *)( stmt->get_last()); 356 } else { 357 last = 0; 358 } 359 } 360 361 CompoundStmtNode::~CompoundStmtNode() { 362 delete first; 363 } 364 365 void CompoundStmtNode::add_statement( StatementNode *stmt ) { 366 if ( stmt != 0 ) { 367 last->set_link( stmt ); 368 last = ( StatementNode *)( stmt->get_link()); 369 } 370 } 371 372 void CompoundStmtNode::print( ostream &os, int indent ) const { 373 if ( first ) { 374 first->printList( os, indent+2 ); 375 } 409 376 } 410 377 411 378 Statement *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 392 void NullStmtNode::print( ostream &os, int indent ) const { 393 os << "\r" << string( indent, ' ') << "Null Statement:" << endl; 428 394 } 429 395 430 396 Statement *NullStmtNode::build() const { 431 397 return new NullStmt; 432 398 } 433 399 434 400 // Local Variables: // 435 // mode: C++ // 436 // compile-command: "gmake -f ../Makefile" // 401 // tab-width: 4 // 402 // mode: c++ // 403 // compile-command: "make install" // 437 404 // 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 1 16 #include <cassert> 2 17 #include <algorithm> … … 9 24 #include "SynTree/Statement.h" 10 25 11 12 26 TypeData::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 } 80 92 } 81 93 82 94 TypeData::~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 } 148 158 } 149 159 150 160 TypeData *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; 221 229 } 222 230 223 231 void TypeData::print( std::ostream &os, int indent ) const { 224 225 226 227 228 229 230 os << "forall " << endl;231 forall->printList( os, indent+4 );232 233 234 235 236 os << "entity of unknown type ";237 break;238 239 os << "pointer ";240 if ( base ) {241 242 243 }244 break;245 246 os << "enumeration constant ";247 break;248 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 253 if ( array->isStatic ) {254 255 }256 if ( array->dimension ) {257 258 259 } else if ( array->isVarLen ) {260 261 } else {262 263 }264 if ( base ) {265 266 }267 break;268 269 os << "function" << endl;270 if ( function->params ) {271 272 273 } else {274 275 }276 if ( function->idList ) {277 278 279 }280 if ( function->oldDeclList ) {281 282 283 }284 os << string( indent+2, ' ' ) << "returning ";285 if ( base ) {286 287 } else {288 289 }290 os << endl;291 if ( function->hasBody ) {292 293 }294 if ( function->body ) {295 296 }297 break;298 299 os << DeclarationNode::tyConName[ aggregate->kind ] << ' ' << aggregate->name << endl;300 if ( aggregate->params ) {301 302 303 }304 if ( aggregate->actuals ) {305 306 307 }308 if ( aggregate->members ) {309 310 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 ); 311 319 /// } else { 312 320 /// 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 402 TypeData *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 431 void 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 444 Declaration *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(); 319 475 } 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 485 Type *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 521 Type::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 548 Type *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 ); 344 748 } 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 756 PointerType *TypeData::buildPointer() const { 757 PointerType *pt; 356 758 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 767 ArrayType *TypeData::buildArray() const { 768 ArrayType *at; 418 769 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 ); 452 772 } 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 780 FunctionType *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 } 473 795 } 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 801 AggregateDecl *TypeData::buildAggregate() const { 802 assert( kind == Aggregate ); 803 AggregateDecl *at; 804 switch ( aggregate->kind ) { 805 case DeclarationNode::Struct: 806 at = new StructDecl( aggregate->name ); 606 807 break; 607 808 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 804 817 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; 837 824 } 838 825 … … 850 837 851 838 ReferenceToType *TypeData::buildAggInst() const { 852 853 854 855 856 857 ret = new EnumInstType( buildQualifiers(), aggInst->aggregate->enumeration->name );858 859 assert( aggInst->aggregate->kind == Aggregate );860 switch ( aggInst->aggregate->aggregate->kind ) {861 case DeclarationNode::Struct:862 863 864 case DeclarationNode::Union:865 866 867 case DeclarationNode::Context:868 869 870 default:871 872 }873 874 875 876 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; 877 864 } 878 865 879 866 NamedTypeDecl *TypeData::buildSymbolic( const std::string &name, Declaration::StorageClass sc ) const { 880 881 882 883 ret = new TypedefDecl( name, sc, maybeBuild< Type >( base ) );884 885 ret = new TypeDecl( name, sc, maybeBuild< Type >( base ), TypeDecl::Any );886 887 888 889 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; 890 877 } 891 878 892 879 TypeDecl *TypeData::buildVariable() const { 893 894 895 896 897 898 899 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; 900 887 } 901 888 902 889 EnumDecl *TypeData::buildEnum() const { 903 904 905 906 907 890 assert( kind == Enum ); 891 EnumDecl *ret = new EnumDecl( enumeration->name ); 892 buildList( enumeration->constants, ret->get_members() ); 893 894 return ret; 908 895 } 909 896 910 897 TypeInstType *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; 919 904 } 920 905 921 906 TupleType *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; 930 913 } 931 914 932 915 TypeofType *TypeData::buildTypeof() const { 933 934 935 936 937 938 916 assert( kind == Typeof ); 917 assert( typeexpr ); 918 assert( typeexpr->expr ); 919 TypeofType *ret = new TypeofType( buildQualifiers(), typeexpr->expr->build() ); 920 921 return ret; 939 922 } 940 923 941 924 AttrType *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 1 16 #ifndef TYPEDATA_H 2 17 #define TYPEDATA_H … … 8 23 9 24 struct TypeData { 10 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; 12 27 13 14 15 16 28 TypeData( Kind k = Unknown ); 29 ~TypeData(); 30 void print( std::ostream &, int indent = 0 ) const; 31 TypeData *clone() const; 17 32 18 19 33 Type *build() const; 34 FunctionType *buildFunction() const; 20 35 21 22 23 36 TypeData *base; 37 std::list< DeclarationNode::Qualifier > qualifiers; 38 DeclarationNode *forall; 24 39 25 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 }; 29 44 30 31 DeclarationNode::TyCon kind;32 std::string name;33 DeclarationNode *params;34 ExpressionNode *actuals;// holds actual parameters later applied to AggInst35 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 }; 37 52 38 39 TypeData *aggregate;40 ExpressionNode *params;41 53 struct AggInst_t { 54 TypeData *aggregate; 55 ExpressionNode *params; 56 }; 42 57 43 44 ExpressionNode *dimension;45 bool isVarLen;46 bool isStatic;47 58 struct Array_t { 59 ExpressionNode *dimension; 60 bool isVarLen; 61 bool isStatic; 62 }; 48 63 49 50 std::string name;51 DeclarationNode *constants;52 64 struct Enumeration_t { 65 std::string name; 66 DeclarationNode *constants; 67 }; 53 68 54 55 DeclarationNode *params;56 DeclarationNode *idList;// old-style57 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 }; 62 77 63 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 }; 70 85 71 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 }; 76 91 77 78 DeclarationNode *members;79 92 struct Tuple_t { 93 DeclarationNode *members; 94 }; 80 95 81 82 ExpressionNode *expr;83 96 struct Typeof_t { 97 ExpressionNode *expr; 98 }; 84 99 85 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 }; 90 105 91 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 }; 104 119 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 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; 122 137 }; 123 138 124 139 #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 1 16 #include <map> 2 17 #include <list> … … 7 22 #if 0 8 23 #include <iostream> 9 # define debugPrint(x) cerr << x24 #define debugPrint(x ) cerr << x 10 25 #else 11 # define debugPrint(x)26 #define debugPrint( x ) 12 27 #endif 13 28 14 TypedefTable::TypedefTable() : currentScope( 0) {}29 TypedefTable::TypedefTable() : currentScope( 0 ) {} 15 30 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 21 return (*((*id_pos).second.begin())).kind == kind;22 31 bool 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 } 23 38 } 24 39 25 bool TypedefTable::isIdentifier( string identifier) const {26 return isKind(identifier, ID);40 bool TypedefTable::isIdentifier( string identifier ) const { 41 return isKind( identifier, ID ); 27 42 } 28 43 29 bool TypedefTable::isTypedef( string identifier) const {30 return isKind(identifier, TD);44 bool TypedefTable::isTypedef( string identifier ) const { 45 return isKind( identifier, TD ); 31 46 } 32 47 33 bool TypedefTable::isTypegen( string identifier) const {34 return isKind(identifier, TG);48 bool TypedefTable::isTypegen( string identifier ) const { 49 return isKind( identifier, TG ); 35 50 } 36 51 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; 52 void 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 ); 49 56 } 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 } 55 71 } 56 }57 72 } 58 73 59 void TypedefTable::addToCurrentScope( const std::string &identifier, kind_t kind) {60 74 void TypedefTable::addToCurrentScope( const std::string &identifier, kind_t kind ) { 75 addToScope( identifier, kind, currentScope ); 61 76 } 62 77 63 void TypedefTable::addToCurrentScope( kind_t kind) {64 78 void TypedefTable::addToCurrentScope( kind_t kind ) { 79 addToCurrentScope( nextIdentifiers.top(), kind ); 65 80 } 66 81 67 void TypedefTable::addToEnclosingScope( const std::string &identifier, kind_t kind) {68 69 82 void TypedefTable::addToEnclosingScope( const std::string &identifier, kind_t kind ) { 83 assert( currentScope >= 1 ); 84 addToScope( identifier, kind, currentScope - 1 ); 70 85 } 71 86 72 void TypedefTable::addToEnclosingScope( kind_t kind) {73 87 void TypedefTable::addToEnclosingScope( kind_t kind ) { 88 addToEnclosingScope( nextIdentifiers.top(), kind ); 74 89 } 75 90 76 void TypedefTable::addToEnclosingScope2( const std::string &identifier, kind_t kind) {77 78 91 void TypedefTable::addToEnclosingScope2( const std::string &identifier, kind_t kind ) { 92 assert( currentScope >= 2 ); 93 addToScope( identifier, kind, currentScope - 2 ); 79 94 } 80 95 81 void TypedefTable::addToEnclosingScope2( kind_t kind) {82 96 void TypedefTable::addToEnclosingScope2( kind_t kind ) { 97 addToEnclosingScope2( nextIdentifiers.top(), kind ); 83 98 } 84 99 85 100 void TypedefTable::setNextIdentifier( const std::string &identifier ) { 86 101 nextIdentifiers.top() = identifier; 87 102 } 88 103 89 104 void 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 } 95 111 } 96 }97 112 } 98 113 99 void TypedefTable::enterScope( void) {100 101 102 103 114 void TypedefTable::enterScope( void ) { 115 currentScope += 1; 116 deferListStack.push( deferListType() ); 117 nextIdentifiers.push( "" ); 118 debugPrint( "Entering scope " << currentScope << ", nextIdentifiers size is " << nextIdentifiers.size() << endl ); 104 119 } 105 120 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(); 121 void 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; 112 131 } 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(); 124 139 } 125 140 126 141 void TypedefTable::enterContext( std::string contextName ) { 127 128 142 currentContext = contextName; 143 contextScope = currentScope; 129 144 } 130 145 131 void TypedefTable::leaveContext( void) {132 146 void TypedefTable::leaveContext( void ) { 147 currentContext = ""; 133 148 } 134 149 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 << ") " ); 150 void 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 ); 141 158 } 142 debugPrint( endl );143 }144 159 } 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 1 16 #ifndef TYPEDEFTABLE_H 2 17 #define TYPEDEFTABLE_H … … 9 24 class TypedefTable { 10 25 public: 11 26 enum kind_t { ID, TD, TG }; 12 27 private: 13 14 int scope;15 kind_t kind;16 17 18 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 }; 22 37 23 24 38 typedef std::map<std::string, std::list<Entry> > tableType; 39 tableType table; 25 40 26 27 28 29 30 31 32 33 34 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; 35 50 36 37 51 bool isKind( std::string identifier, kind_t kind ) const; 52 void addToScope( const std::string &identifier, kind_t kind, int scope ); 38 53 public: 39 54 TypedefTable(); 40 55 41 42 43 44 45 46 47 48 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() 49 64 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 void enterScope( void);67 void leaveScope( void);68 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(); 70 85 71 void print( void) const;86 void print() const; 72 87 }; 73 88 74 89 #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 // 5 7 // cfa.y -- 6 8 // … … 8 10 // Created On : Sat Sep 1 20:22:55 2001 9 11 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Tue May 12 17:24:53201511 // Update Count : 9 6312 // Last Modified On : Sat May 16 11:55:39 2015 13 // Update Count : 975 12 14 // 13 15 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. 23 26 24 27 // The root language for this grammar is ANSI99/11 C. All of ANSI99/11 is parsed, except for: … … 26 29 // 1. designation with '=' (use ':' instead) 27 30 // 28 // Most of the syntactic extensions from ANSI90 to ANSI11 C are marked with the comment "C99/C11". This grammar also has29 // 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: 30 33 // 31 34 // 1. nested functions … … 34 37 // 4. attributes not allowed in parenthesis of declarator 35 38 // 36 // All of the syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall37 // (CFA), which fixes several of C's outstanding problems and extends C with many modern language concepts. All of the38 // syntactic extensions for CFA C are marked with the comment "CFA". As noted above, there is one unreconcileable39 // 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. 41 44 42 45 %{ 43 #define YYDEBUG_LEXER_TEXT (yylval) // lexer loads this up each time44 #define YYDEBUG 1 // get the pretty debugging code to compile46 #define YYDEBUG_LEXER_TEXT (yylval) // lexer loads this up each time 47 #define YYDEBUG 1 // get the pretty debugging code to compile 45 48 46 49 #undef __GNUC_MINOR__ … … 53 56 #include "LinkageSpec.h" 54 57 55 DeclarationNode *theTree = 0; // the resulting parse tree58 DeclarationNode *theTree = 0; // the resulting parse tree 56 59 LinkageSpec::Type linkage = LinkageSpec::Cforall; 57 60 std::stack< LinkageSpec::Type > linkageStack; … … 64 67 %token TYPEDEF 65 68 %token AUTO EXTERN REGISTER STATIC 66 %token INLINE // C9967 %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) 68 71 %token CONST VOLATILE 69 %token RESTRICT // C9970 %token FORALL LVALUE // CFA72 %token RESTRICT // C99 73 %token FORALL LVALUE // CFA 71 74 %token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED 72 %token BOOL COMPLEX IMAGINARY // C9973 %token TYPEOF LABEL // GCC75 %token BOOL COMPLEX IMAGINARY // C99 76 %token TYPEOF LABEL // GCC 74 77 %token ENUM STRUCT UNION 75 %token TYPE FTYPE DTYPE CONTEXT // CFA78 %token TYPE FTYPE DTYPE CONTEXT // CFA 76 79 %token SIZEOF 77 %token ATTRIBUTE EXTENSION // GCC80 %token ATTRIBUTE EXTENSION // GCC 78 81 %token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN 79 %token CHOOSE FALLTHRU TRY CATCH FINALLY THROW // CFA80 %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) 81 84 %token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATICASSERT THREADLOCAL // C11 82 85 83 86 // names and constants: lexer differentiates between identifier and typedef names 84 %token<tok> IDENTIFIER QUOTED_IDENTIFIER TYPEDEFnameTYPEGENname85 %token<tok> ATTR_IDENTIFIER ATTR_TYPEDEFnameATTR_TYPEGENname86 %token<tok> INTEGERconstant FLOATINGconstant CHARACTERconstantSTRINGliteral87 %token<tok> ZERO ONE// CFA87 %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 88 91 89 92 // 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 // &= ^= |= 101 104 102 105 // Types declaration 103 106 %union 104 107 { 105 106 107 108 109 110 111 112 113 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; 114 117 } 115 118 … … 120 123 // expressions 121 124 %type<constant> constant 122 %type<en> tuple tuple_expression_list123 %type<en> unary_operator 124 %type<en> primary_expression postfix_expressionunary_expression125 %type<en> cast_expression multiplicative_expression additive_expressionshift_expression126 %type<en> relational_expression equality_expression AND_expressionexclusive_OR_expression127 %type<en> inclusive_OR_expression logical_AND_expression logical_OR_expressionconditional_expression128 %type<en> constant_expression assignment_expression assignment_expression_opt129 %type<en> comma_expression comma_expression_opt130 %type<en> argument_expression_list argument_expression for_control_expressionassignment_opt125 %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 131 134 %type<en> subrange 132 135 133 136 // statements 134 %type<sn> labeled_statement compound_statement expression_statementselection_statement135 %type<sn> iteration_statement jump_statement exception_statementasm_statement136 %type<sn> fall_through_opt fall_through137 %type<sn> statement statement_list138 %type<sn> block_item_list block_item137 %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 139 142 %type<sn> case_clause 140 %type<en> case_value case_value_list141 %type<sn> case_label case_label_list142 %type<sn> switch_clause_list_opt switch_clause_list choose_clause_list_optchoose_clause_list143 %type<pn> handler_list handler_clausefinally_clause143 %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 144 147 145 148 // declarations … … 232 235 233 236 234 // Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string is235 // ambiguous:236 // .---------. matches IF '(' comma_expression ')' statement237 // 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 237 240 // if ( C ) S1 else S2 238 // `-----------------' matches IF '(' comma_expression ')' statement ELSE statement */241 // `-----------------' matches IF '(' comma_expression ')' statement ELSE statement */ 239 242 240 243 %nonassoc THEN // rule precedence for IF '(' comma_expression ')' statement 241 244 %nonassoc ELSE // token precedence for start of else clause in IF statement 242 245 243 %start translation_unit // parse-tree root246 %start translation_unit // parse-tree root 244 247 245 248 %% 246 249 //************************* Namespace Management ******************************** 247 250 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. 274 279 275 280 push: 276 {277 278 }279 ;281 { 282 typedefTable.enterScope(); 283 } 284 ; 280 285 281 286 pop: 282 {283 284 }285 ;287 { 288 typedefTable.leaveScope(); 289 } 290 ; 286 291 287 292 //************************* CONSTANTS ******************************** 288 293 289 294 constant: 290 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration291 //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 ; 296 301 297 302 identifier: 298 IDENTIFIER299 | ATTR_IDENTIFIER// CFA300 | zero_one// CFA301 ;303 IDENTIFIER 304 | ATTR_IDENTIFIER // CFA 305 | zero_one // CFA 306 ; 302 307 303 308 no_01_identifier: 304 IDENTIFIER305 | ATTR_IDENTIFIER// CFA306 ;309 IDENTIFIER 310 | ATTR_IDENTIFIER // CFA 311 ; 307 312 308 313 no_attr_identifier: 309 IDENTIFIER310 ;311 312 zero_one: // CFA313 ZERO314 | ONE315 ;316 317 string_literal_list: // juxtaposed strings are concatenated318 STRINGliteral{ $$ = new ConstantNode(ConstantNode::String, $1); }319 | string_literal_list STRINGliteral{ $$ = $1->append( $2 ); }320 ;314 IDENTIFIER 315 ; 316 317 zero_one: // CFA 318 ZERO 319 | ONE 320 ; 321 322 string_literal_list: // juxtaposed strings are concatenated 323 STRINGliteral { $$ = new ConstantNode(ConstantNode::String, $1); } 324 | string_literal_list STRINGliteral { $$ = $1->append( $2 ); } 325 ; 321 326 322 327 //************************* EXPRESSIONS ******************************** 323 328 324 329 primary_expression: 325 IDENTIFIER// typedef name cannot be used as a variable name326 { $$ = new VarRefNode($1); }327 | zero_one328 { $$ = new VarRefNode($1); }329 | constant330 { $$ = $1; }331 | string_literal_list332 { $$ = $1; }333 | '(' comma_expression ')'334 { $$ = $2; }335 | '(' compound_statement ')'// GCC, lambda expression336 { $$ = 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 ; 338 343 339 344 postfix_expression: 340 primary_expression341 | 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 backwards344 // compatible, there seems to be little advantage to this feature and many disadvantages. It is345 //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_identifier350 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), $1, new VarRefNode($3)); }351 | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector352 | postfix_expression ARROW no_attr_identifier353 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), $1, new VarRefNode($3)); }354 | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector355 | postfix_expression ICR356 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::IncrPost), $1); }357 | postfix_expression DECR358 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::DecrPost), $1); }359 // GCC has priority: cast_expression360 | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99361 { $$ = 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 ; 363 368 364 369 argument_expression_list: 365 argument_expression366 | argument_expression_list ',' argument_expression367 368 ;370 argument_expression 371 | argument_expression_list ',' argument_expression 372 { $$ = (ExpressionNode *)($1->set_link($3)); } 373 ; 369 374 370 375 argument_expression: 371 // empty372 { $$ = 0; }// use default argument373 | assignment_expression374 | no_attr_identifier ':' assignment_expression375 376 // Only a list of no_attr_identifier_or_typedef_name is allowed in this context. However, there is377 // insufficient look ahead to distinguish between this list of parameter names and a tuple, so the378 //tuple form must be used with an appropriate semantic check.379 | '[' push assignment_expression pop ']' ':' assignment_expression380 381 | '[' push assignment_expression ',' tuple_expression_list pop ']' ':' assignment_expression382 383 ;384 385 field_list: // CFA, tuple field selector386 field387 | field_list ',' field{ $$ = (ExpressionNode *)$1->set_link( $3 ); }388 ;389 390 field: // CFA, tuple field selector391 no_attr_identifier392 393 | no_attr_identifier '.' field394 395 | no_attr_identifier '.' '[' push field_list pop ']'396 397 | no_attr_identifier ARROW field398 399 | no_attr_identifier ARROW '[' push field_list pop ']'400 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 390 field_list: // CFA, tuple field selector 391 field 392 | field_list ',' field { $$ = (ExpressionNode *)$1->set_link( $3 ); } 393 ; 394 395 field: // 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 ; 402 407 403 408 unary_expression: 404 postfix_expression405 | ICR unary_expression406 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Incr), $2); }407 | DECR unary_expression408 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Decr), $2); }409 | EXTENSION cast_expression// GCC410 { $$ = $2; }411 | unary_operator cast_expression412 { $$ = new CompositeExprNode($1, $2); }413 | '!' cast_expression414 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neg), $2); }415 | '*' cast_expression// CFA416 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PointTo), $2); }417 // '*' is is separated from unary_operator because of shift/reduce conflict in:418 //{ * X; } // dereference X419 //{ * int X; } // CFA declaration of pointer to int420 // '&' must be moved here if C++ reference variables are supported.421 | SIZEOF unary_expression422 { $$ = 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_IDENTIFIER426 { $$ = 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 alignment432 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), $2); }433 | ALIGNOF '(' type_name_no_function ')'// GCC, type alignment434 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), new TypeValueNode($3)); }435 | ANDAND no_attr_identifier// GCC, address of label436 { $$ = 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 ; 438 443 439 444 unary_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 ; 445 450 446 451 cast_expression: 447 unary_expression448 | '(' type_name_no_function ')' cast_expression449 450 | '(' type_name_no_function ')' tuple451 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 ; 453 458 454 459 multiplicative_expression: 455 cast_expression456 | multiplicative_expression '*' cast_expression457 458 | multiplicative_expression '/' cast_expression459 460 | multiplicative_expression '%' cast_expression461 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 ; 463 468 464 469 additive_expression: 465 multiplicative_expression466 | additive_expression '+' multiplicative_expression467 468 | additive_expression '-' multiplicative_expression469 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 ; 471 476 472 477 shift_expression: 473 additive_expression474 | shift_expression LS additive_expression475 476 | shift_expression RS additive_expression477 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 ; 479 484 480 485 relational_expression: 481 shift_expression482 | relational_expression '<' shift_expression483 484 | relational_expression '>' shift_expression485 486 | relational_expression LE shift_expression487 488 | relational_expression GE shift_expression489 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 ; 491 496 492 497 equality_expression: 493 relational_expression494 | equality_expression EQ relational_expression495 496 | equality_expression NE relational_expression497 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 ; 499 504 500 505 AND_expression: 501 equality_expression502 | AND_expression '&' equality_expression503 504 ;506 equality_expression 507 | AND_expression '&' equality_expression 508 { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::BitAnd), $1, $3); } 509 ; 505 510 506 511 exclusive_OR_expression: 507 AND_expression508 | exclusive_OR_expression '^' AND_expression509 510 ;512 AND_expression 513 | exclusive_OR_expression '^' AND_expression 514 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Xor), $1, $3); } 515 ; 511 516 512 517 inclusive_OR_expression: 513 exclusive_OR_expression514 | inclusive_OR_expression '|' exclusive_OR_expression515 516 ;518 exclusive_OR_expression 519 | inclusive_OR_expression '|' exclusive_OR_expression 520 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::BitOr), $1, $3); } 521 ; 517 522 518 523 logical_AND_expression: 519 inclusive_OR_expression520 | logical_AND_expression ANDAND inclusive_OR_expression521 522 ;524 inclusive_OR_expression 525 | logical_AND_expression ANDAND inclusive_OR_expression 526 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::And), $1, $3); } 527 ; 523 528 524 529 logical_OR_expression: 525 logical_AND_expression526 | logical_OR_expression OROR logical_AND_expression527 528 ;530 logical_AND_expression 531 | logical_OR_expression OROR logical_AND_expression 532 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Or), $1, $3); } 533 ; 529 534 530 535 conditional_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 ; 541 544 542 545 constant_expression: 543 conditional_expression544 ;546 conditional_expression 547 ; 545 548 546 549 assignment_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 ; 562 560 563 561 assignment_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 567 tuple: // 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 ; 581 580 582 581 tuple_expression_list: 583 assignment_expression_opt584 | tuple_expression_list ',' assignment_expression_opt585 { $$ = (ExpressionNode *)$1->set_link( $3 ); }586 ;582 assignment_expression_opt 583 | tuple_expression_list ',' assignment_expression_opt 584 { $$ = (ExpressionNode *)$1->set_link( $3 ); } 585 ; 587 586 588 587 assignment_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 ; 600 599 601 600 comma_expression: 602 assignment_expression603 | comma_expression ',' assignment_expression // { $$ = (ExpressionNode *)$1->add_to_list($3); }604 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 ; 606 605 607 606 comma_expression_opt: 608 // empty609 { $$ = 0; }610 | comma_expression611 ;607 // empty 608 { $$ = 0; } 609 | comma_expression 610 ; 612 611 613 612 //*************************** STATEMENTS ******************************* 614 613 615 614 statement: 616 labeled_statement617 | compound_statement618 | expression_statement{ $$ = $1; }619 | selection_statement620 | iteration_statement621 | jump_statement622 | exception_statement623 | asm_statement624 ;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 ; 625 624 626 625 labeled_statement: 627 no_attr_identifier ':' attribute_list_opt statement628 { $$ = $4->add_label($1);}629 ;626 no_attr_identifier ':' attribute_list_opt statement 627 { $$ = $4->add_label($1);} 628 ; 630 629 631 630 compound_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 block636 //also requires its own scope637 push push638 label_declaration_opt// GCC, local labels639 block_item_list pop '}'// C99, intermix declarations and statements640 { $$ = new CompoundStmtNode( $5 ); }641 ;642 643 block_item_list: // C99644 block_item645 | block_item_list push block_item646 { 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 642 block_item_list: // C99 643 block_item 644 | block_item_list push block_item 645 { if ($1 != 0) { $1->set_link($3); $$ = $1; } } 646 ; 648 647 649 648 block_item: 650 declaration// CFA, new & old style declarations651 { $$ = new StatementNode( $1 ); }652 | EXTENSION declaration// GCC653 { $$ = new StatementNode( $2 ); }654 | statement pop655 ;649 declaration // CFA, new & old style declarations 650 { $$ = new StatementNode( $1 ); } 651 | EXTENSION declaration // GCC 652 { $$ = new StatementNode( $2 ); } 653 | statement pop 654 ; 656 655 657 656 statement_list: 658 statement659 | statement_list statement660 { 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 ; 662 661 663 662 expression_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 ; 667 666 668 667 selection_statement: 669 IF '(' comma_expression ')' statement%prec THEN670 // explicitly deal with the shift/reduce conflict on if/else671 { $$ = new StatementNode(StatementNode::If, $3, $5); }672 | IF '(' comma_expression ')' statement ELSE statement673 { $$ = new StatementNode(StatementNode::If, $3, (StatementNode *)mkList((*$5, *$7)) ); }674 | SWITCH '(' comma_expression ')' case_clause // CFA675 { $$ = new StatementNode(StatementNode::Switch, $3, $5); }676 | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA677 { $$ = new StatementNode(StatementNode::Switch, $3, $8); /* xxx */ }678 // The semantics of the declaration list is changed to include any associated initialization, which is679 // performed *before* the transfer to the appropriate case clause. Statements after the initial680 // declaration list can never be executed, and therefore, are removed from the grammar even though C681 //allows it.682 | CHOOSE '(' comma_expression ')' case_clause // CFA683 { $$ = new StatementNode(StatementNode::Choose, $3, $5); }684 | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt choose_clause_list_opt '}' // CFA685 { $$ = 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 case689 // c lause allows a list of values and subranges.690 691 case_value: // CFA692 constant_expression{ $$ = $1; }693 | constant_expression ELLIPSIS constant_expression // GCC, subrange694 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range),$1,$3); }695 | subrange// CFA, subrange696 ;697 698 case_value_list: // CFA699 case_value700 | case_value_list ',' case_value701 {$$ = new CompositeExprNode(new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(tupleContents($1))->set_link($3) ); }702 ;703 704 case_label: // CFA705 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: // CFA711 case_label712 | case_label_list case_label{ $$ = (StatementNode *)($1->set_link($2)); }713 ;714 715 case_clause: // CFA716 case_label_list statement {$$ = $1->append_last_case($2); }717 ;718 719 switch_clause_list_opt: // CFA720 // empty721 { $$ = 0; }722 | switch_clause_list723 ;724 725 switch_clause_list: // CFA726 case_label_list statement_list727 728 | switch_clause_list case_label_list statement_list729 730 ;731 732 choose_clause_list_opt: // CFA733 // empty734 { $$ = 0; }735 | choose_clause_list736 ;737 738 choose_clause_list: // CFA739 case_label_list fall_through740 { $$ = $1->append_last_case($2); }741 | case_label_list statement_list fall_through_opt742 { $$ = $1->append_last_case((StatementNode *)mkList((*$2,*$3))); }743 | choose_clause_list case_label_list fall_through744 { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }745 | choose_clause_list case_label_list statement_list fall_through_opt746 { $$ = (StatementNode *)($1->set_link($2->append_last_case((StatementNode *)mkList((*$3,*$4))))); }747 ;748 749 fall_through_opt: // CFA750 // empty751 { $$ = 0; }752 | fall_through753 ;754 755 fall_through: // CFA756 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 690 case_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 697 case_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 703 case_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 709 case_label_list: // CFA 710 case_label 711 | case_label_list case_label { $$ = (StatementNode *)($1->set_link($2)); } 712 ; 713 714 case_clause: // CFA 715 case_label_list statement { $$ = $1->append_last_case($2); } 716 ; 717 718 switch_clause_list_opt: // CFA 719 // empty 720 { $$ = 0; } 721 | switch_clause_list 722 ; 723 724 switch_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 731 choose_clause_list_opt: // CFA 732 // empty 733 { $$ = 0; } 734 | choose_clause_list 735 ; 736 737 choose_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 748 fall_through_opt: // CFA 749 // empty 750 { $$ = 0; } 751 | fall_through 752 ; 753 754 fall_through: // CFA 755 FALLTHRU { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); } 756 | FALLTHRU ';' { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); } 757 ; 759 758 760 759 iteration_statement: 761 WHILE '(' comma_expression ')' statement762 763 | DO statement WHILE '(' comma_expression ')' ';'764 765 | FOR '(' push for_control_expression ')' statement766 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 ; 768 767 769 768 for_control_expression: 770 comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt771 772 | declaration comma_expression_opt ';' comma_expression_opt // C99773 // Like C++, the loop index can be declared local to the loop.774 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 ; 776 775 777 776 jump_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 ; 807 808 808 809 exception_statement: 809 TRY compound_statement handler_list810 811 | TRY compound_statement finally_clause812 813 | TRY compound_statement handler_list finally_clause814 815 816 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 ; 819 820 820 821 handler_list: 821 // There must be at least one catch clause822 handler_clause823 // ISO/IEC 9899:1999 Section 15.3(6) If present, a "..." handler shall be the last handler for its try824 //block.825 | CATCH '(' ELLIPSIS ')' compound_statement826 827 | handler_clause CATCH '(' ELLIPSIS ')' compound_statement828 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 ; 830 831 831 832 handler_clause: 832 CATCH '(' push push exception_declaration pop ')' compound_statement pop833 834 | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop835 { $$ = $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 ; 837 838 838 839 finally_clause: 839 FINALLY compound_statement840 841 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 ; 844 845 845 846 exception_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_specifier852 | type_specifier declarator853 {854 855 856 }857 | type_specifier variable_abstract_declarator858 {$$ = $2->addType( $1 ); }859 | new_abstract_declarator_tuple no_attr_identifier // CFA860 {861 862 863 }864 | new_abstract_declarator_tuple// CFA865 ;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 ; 866 867 867 868 asm_statement: 868 ASM type_qualifier_list_opt '(' constant_expression ')' ';'869 870 | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ')' ';' // remaining GCC871 872 | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ')' ';'873 874 | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ':'875 asm_clobbers_list ')' ';'876 877 ;878 879 asm_operands_opt: // GCC880 // empty881 | asm_operands_list882 ;883 884 asm_operands_list: // GCC885 asm_operand886 | asm_operands_list ',' asm_operand887 ;888 889 asm_operand: // GCC890 STRINGliteral '(' constant_expression ')'{}891 ;892 893 asm_clobbers_list: // GCC894 STRINGliteral{}895 | asm_clobbers_list ',' STRINGliteral896 ;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 880 asm_operands_opt: // GCC 881 // empty 882 | asm_operands_list 883 ; 884 885 asm_operands_list: // GCC 886 asm_operand 887 | asm_operands_list ',' asm_operand 888 ; 889 890 asm_operand: // GCC 891 STRINGliteral '(' constant_expression ')' {} 892 ; 893 894 asm_clobbers_list: // GCC 895 STRINGliteral {} 896 | asm_clobbers_list ',' STRINGliteral 897 ; 897 898 898 899 //******************************* DECLARATIONS ********************************* 899 900 900 declaration_list_opt: // used at beginning of switch statement901 pop902 { $$ = 0; }903 | declaration_list904 ;901 declaration_list_opt: // used at beginning of switch statement 902 pop 903 { $$ = 0; } 904 | declaration_list 905 ; 905 906 906 907 declaration_list: 907 declaration908 | declaration_list push declaration909 { $$ = $1->appendList( $3 ); }910 ;911 912 old_declaration_list_opt: // used to declare parameter types in K&R style functions913 pop914 { $$ = 0; }915 | old_declaration_list916 ;908 declaration 909 | declaration_list push declaration 910 { $$ = $1->appendList( $3 ); } 911 ; 912 913 old_declaration_list_opt: // used to declare parameter types in K&R style functions 914 pop 915 { $$ = 0; } 916 | old_declaration_list 917 ; 917 918 918 919 old_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 925 label_declaration_opt: // GCC, local label 926 // empty 927 | label_declaration_list 928 ; 929 930 label_declaration_list: // GCC, local label 931 LABEL label_list ';' 932 | label_declaration_list LABEL label_list ';' 933 ; 934 935 label_list: // GCC, local label 936 no_attr_identifier_or_typedef_name {} 937 | label_list ',' no_attr_identifier_or_typedef_name {} 938 ; 939 940 declaration: // 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 957 new_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 965 new_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 985 new_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 1005 new_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 1025 new_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 1056 new_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 1065 new_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. 1084 1086 1085 1087 typedef_declaration: 1086 TYPEDEF type_specifier declarator1087 {1088 typedefTable.addToEnclosingScope( TypedefTable::TD);1089 $$ = $3->addType( $2 )->addTypedef();1090 }1091 | typedef_declaration pop ',' push declarator1092 {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 declarator1102 {1103 typedefTable.addToEnclosingScope( TypedefTable::TD);1104 $$ = $3->addType( $1 )->addTypedef();1105 }1106 | type_specifier TYPEDEF type_qualifier_list declarator1107 {1108 typedefTable.addToEnclosingScope( TypedefTable::TD);1109 $$ = $4->addQualifiers($1)->addTypedef()->addType($1);1110 }1111 ;1112 1113 typedef_expression: // GCC, naming expression type1114 TYPEDEF no_attr_identifier '=' assignment_expression1115 {1116 typedefTable.addToEnclosingScope(*($2), TypedefTable::TD);1117 $$ = DeclarationNode::newName( 0 ); // XXX1118 }1119 | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression1120 {1121 typedefTable.addToEnclosingScope(*($5), TypedefTable::TD);1122 $$ = DeclarationNode::newName( 0 ); // XXX1123 }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 1115 typedef_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 ; 1125 1127 1126 1128 old_declaration: 1127 declaring_list pop ';'1128 | typedef_declaration pop ';'1129 | typedef_expression pop ';'// GCC, naming expression type1130 | 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 ; 1132 1134 1133 1135 declaring_list: 1134 /*A semantic check is required to ensure asm_name only appears on declarations with implicit1135 or explicit static storage-class */1136 declaration_specifier declarator asm_name_opt initializer_opt1137 {1138 typedefTable.addToEnclosingScope( TypedefTable::ID );1139 $$ = ($2->addType( $1 ))->addInitializer($4);1140 }1141 | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt1142 {1143 typedefTable.addToEnclosingScope( TypedefTable::ID );1144 $$ = $1->appendList( $1->cloneBaseType( $4->addInitializer($6) ) );1145 }1146 ;1147 1148 declaration_specifier: // type specifier + storage class1149 basic_declaration_specifier1150 | sue_declaration_specifier1151 | typedef_declaration_specifier1152 | typegen_declaration_specifier1153 ;1154 1155 type_specifier: // declaration specifier - storage class1156 basic_type_specifier1157 | sue_type_specifier1158 | typedef_type_specifier1159 | typegen_type_specifier1160 ;1161 1162 type_qualifier_list_opt: // GCC, used in asm_statement1163 // empty1164 { $$ = 0; }1165 | type_qualifier_list1166 ;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 1150 declaration_specifier: // type specifier + storage class 1151 basic_declaration_specifier 1152 | sue_declaration_specifier 1153 | typedef_declaration_specifier 1154 | typegen_declaration_specifier 1155 ; 1156 1157 type_specifier: // declaration specifier - storage class 1158 basic_type_specifier 1159 | sue_type_specifier 1160 | typedef_type_specifier 1161 | typegen_type_specifier 1162 ; 1163 1164 type_qualifier_list_opt: // GCC, used in asm_statement 1165 // empty 1166 { $$ = 0; } 1167 | type_qualifier_list 1168 ; 1167 1169 1168 1170 type_qualifier_list: 1169 /*A semantic check is necessary to ensure a type qualifier is appropriate for the kind of1170 1171 1172 1173 1174 the same as if it appeared only once. */1175 type_qualifier1176 | type_qualifier_list type_qualifier1177 { $$ = $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 ; 1179 1181 1180 1182 type_qualifier: 1181 type_qualifier_name1182 | attribute1183 { $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); }1184 ;1183 type_qualifier_name 1184 | attribute 1185 { $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); } 1186 ; 1185 1187 1186 1188 type_qualifier_name: 1187 CONST1188 { $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }1189 | RESTRICT1190 { $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }1191 | VOLATILE1192 { $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }1193 | LVALUE// CFA1194 { $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }1195 | ATOMIC1196 { $$ = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }1197 | FORALL '('1198 {1199 typedefTable.enterScope();1200 }1201 type_parameter_list ')'// CFA1202 {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 ; 1207 1209 1208 1210 declaration_qualifier_list: 1209 storage_class_list1210 | type_qualifier_list storage_class_list// remaining OBSOLESCENT (see 2)1211 { $$ = $1->addQualifiers( $2 ); }1212 | declaration_qualifier_list type_qualifier_list storage_class_list1213 { $$ = $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 ; 1215 1217 1216 1218 storage_class_list: 1217 /*A semantic check is necessary to ensure a storage class is appropriate for the kind of1218 1219 1220 1221 1222 the declaration specifiers in a declaration. */1223 storage_class1224 | storage_class_list storage_class1225 { $$ = $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 ; 1227 1229 1228 1230 storage_class: 1229 storage_class_name1230 ;1231 storage_class_name 1232 ; 1231 1233 1232 1234 storage_class_name: 1233 EXTERN1234 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }1235 | STATIC1236 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }1237 | AUTO1238 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }1239 | REGISTER1240 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }1241 | INLINE// C991242 // INLINE is essentially a storage class specifier for functions, and hence, belongs here.1243 { $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }1244 | FORTRAN// C991245 { $$ = 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 ; 1247 1249 1248 1250 basic_type_name: 1249 CHAR1250 { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }1251 | DOUBLE1252 { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }1253 | FLOAT1254 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }1255 | INT1256 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }1257 | LONG1258 { $$ = DeclarationNode::newModifier( DeclarationNode::Long ); }1259 | SHORT1260 { $$ = DeclarationNode::newModifier( DeclarationNode::Short ); }1261 | SIGNED1262 { $$ = DeclarationNode::newModifier( DeclarationNode::Signed ); }1263 | UNSIGNED1264 { $$ = DeclarationNode::newModifier( DeclarationNode::Unsigned ); }1265 | VOID1266 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }1267 | BOOL// C991268 { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }1269 | COMPLEX// C991270 { $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }1271 | IMAGINARY// C991272 { $$ = 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 ; 1274 1276 1275 1277 basic_declaration_specifier: 1276 // A semantic check is necessary for conflicting storage classes.1277 basic_type_specifier1278 | declaration_qualifier_list basic_type_specifier1279 { $$ = $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_list1283 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }1284 | basic_declaration_specifier storage_class basic_type_specifier1285 { $$ = $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 ; 1287 1289 1288 1290 basic_type_specifier: 1289 direct_type_name1290 | type_qualifier_list_opt indirect_type_name type_qualifier_list_opt1291 { $$ = $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 ; 1293 1295 1294 1296 direct_type_name: 1295 // A semantic check is necessary for conflicting type qualifiers.1296 basic_type_name1297 | type_qualifier_list basic_type_name1298 { $$ = $2->addQualifiers( $1 ); }1299 | direct_type_name type_qualifier1300 { $$ = $1->addQualifiers( $2 ); }1301 | direct_type_name basic_type_name1302 { $$ = $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 ; 1304 1306 1305 1307 indirect_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 ; 1315 1317 1316 1318 sue_declaration_specifier: 1317 sue_type_specifier1318 | declaration_qualifier_list sue_type_specifier1319 { $$ = $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_list1323 { $$ = $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 ; 1325 1327 1326 1328 sue_type_specifier: 1327 elaborated_type_name// struct, union, enum1328 | type_qualifier_list elaborated_type_name1329 { $$ = $2->addQualifiers( $1 ); }1330 | sue_type_specifier type_qualifier1331 { $$ = $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 ; 1333 1335 1334 1336 typedef_declaration_specifier: 1335 typedef_type_specifier1336 | declaration_qualifier_list typedef_type_specifier1337 { $$ = $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_list1341 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }1342 ;1343 1344 typedef_type_specifier: // typedef types1345 TYPEDEFname1346 { $$ = DeclarationNode::newFromTypedef( $1 ); }1347 | type_qualifier_list TYPEDEFname1348 { $$ = DeclarationNode::newFromTypedef( $2 )->addQualifiers( $1 ); }1349 | typedef_type_specifier type_qualifier1350 { $$ = $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 1346 typedef_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 ; 1352 1354 1353 1355 elaborated_type_name: 1354 aggregate_name1355 | enum_name1356 ;1356 aggregate_name 1357 | enum_name 1358 ; 1357 1359 1358 1360 aggregate_name: 1359 aggregate_key '{' field_declaration_list '}'1360 { $$ = DeclarationNode::newAggregate( $1, 0, 0, 0, $3 ); }1361 | aggregate_key no_attr_identifier_or_typedef_name1362 { $$ = 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 '}' // CFA1366 { $$ = DeclarationNode::newAggregate( $1, 0, $4, 0, $8 ); }1367 | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name // CFA1368 { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, 0 ); }1369 | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA1370 { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, $9 ); }1371 | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' '{' field_declaration_list '}' // CFA1372 { $$ = DeclarationNode::newAggregate( $1, 0, $4, $8, $11 ); }1373 | aggregate_key '(' push type_name_list pop ')' no_attr_identifier_or_typedef_name // CFA1374 // push and pop are only to prevent S/R conflicts1375 { $$ = 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 '}' // CFA1377 { $$ = 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 ; 1379 1381 1380 1382 aggregate_key: 1381 STRUCT attribute_list_opt1382 { $$ = DeclarationNode::Struct; }1383 | UNION attribute_list_opt1384 { $$ = DeclarationNode::Union; }1385 ;1383 STRUCT attribute_list_opt 1384 { $$ = DeclarationNode::Struct; } 1385 | UNION attribute_list_opt 1386 { $$ = DeclarationNode::Union; } 1387 ; 1386 1388 1387 1389 field_declaration_list: 1388 field_declaration1389 { $$ = $1; }1390 | field_declaration_list field_declaration1391 { $$ = $1->appendList( $2 ); }1392 ;1390 field_declaration 1391 { $$ = $1; } 1392 | field_declaration_list field_declaration 1393 { $$ = $1->appendList( $2 ); } 1394 ; 1393 1395 1394 1396 field_declaration: 1395 new_field_declaring_list ';'// CFA, new style field declaration1396 | EXTENSION new_field_declaring_list ';'// GCC1397 { $$ = $2; }1398 | field_declaring_list ';'1399 | EXTENSION field_declaring_list ';'// GCC1400 { $$ = $2; }1401 ;1402 1403 new_field_declaring_list: // CFA, new style field declaration1404 new_abstract_declarator_tuple// CFA, no field name1405 | new_abstract_declarator_tuple no_attr_identifier_or_typedef_name1406 { $$ = $1->addName( $2 ); }1407 | new_field_declaring_list ',' no_attr_identifier_or_typedef_name1408 { $$ = $1->appendList( $1->cloneType( $3 ) ); }1409 | new_field_declaring_list ','// CFA, no field name1410 { $$ = $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 1405 new_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 ; 1412 1414 1413 1415 field_declaring_list: 1414 type_specifier field_declarator1415 { $$ = $2->addType( $1 ); }1416 | field_declaring_list ',' attribute_list_opt field_declarator1417 { $$ = $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 ; 1419 1421 1420 1422 field_declarator: 1421 // empty1422 { $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name1423 | bit_subrange_size// no field name1424 { $$ = DeclarationNode::newBitfield( $1 ); }1425 | variable_declarator bit_subrange_size_opt1426 // 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_opt1429 // 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 name1432 ;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 ; 1433 1435 1434 1436 bit_subrange_size_opt: 1435 // empty1436 { $$ = 0; }1437 | bit_subrange_size1438 { $$ = $1; }1439 ;1437 // empty 1438 { $$ = 0; } 1439 | bit_subrange_size 1440 { $$ = $1; } 1441 ; 1440 1442 1441 1443 bit_subrange_size: 1442 ':' constant_expression1443 { $$ = $2; }1444 ;1444 ':' constant_expression 1445 { $$ = $2; } 1446 ; 1445 1447 1446 1448 enum_key: 1447 ENUM attribute_list_opt1448 ;1449 ENUM attribute_list_opt 1450 ; 1449 1451 1450 1452 enum_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_name1456 { $$ = 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 ; 1458 1460 1459 1461 enumerator_list: 1460 no_attr_identifier_or_typedef_name enumerator_value_opt1461 { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }1462 | enumerator_list ',' no_attr_identifier_or_typedef_name enumerator_value_opt1463 { $$ = $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 ; 1465 1467 1466 1468 enumerator_value_opt: 1467 // empty1468 { $$ = 0; }1469 | '=' constant_expression1470 { $$ = $2; }1471 ;1469 // empty 1470 { $$ = 0; } 1471 | '=' constant_expression 1472 { $$ = $2; } 1473 ; 1472 1474 1473 1475 // Minimum of one parameter after which ellipsis is allowed only at the end. 1474 1476 1475 new_parameter_type_list_opt: // CFA1476 // empty1477 { $$ = 0; }1478 | new_parameter_type_list1479 ;1480 1481 new_parameter_type_list: // CFA, abstract + real1482 new_abstract_parameter_list1483 | new_parameter_list1484 | new_parameter_list pop ',' push new_abstract_parameter_list1485 { $$ = $1->appendList( $5 ); }1486 | new_abstract_parameter_list pop ',' push ELLIPSIS1487 { $$ = $1->addVarArgs(); }1488 | new_parameter_list pop ',' push ELLIPSIS1489 { $$ = $1->addVarArgs(); }1490 ;1491 1492 new_parameter_list: // CFA1493 // To obtain LR(1) between new_parameter_list and new_abstract_tuple, the last1494 // new_abstract_parameter_list is factored out from new_parameter_list, flattening the rules1495 // to get lookahead to the ']'.1496 new_parameter_declaration1497 | new_abstract_parameter_list pop ',' push new_parameter_declaration1498 { $$ = $1->appendList( $5 ); }1499 | new_parameter_list pop ',' push new_parameter_declaration1500 { $$ = $1->appendList( $5 ); }1501 | new_parameter_list pop ',' push new_abstract_parameter_list pop ',' push new_parameter_declaration1502 { $$ = $1->appendList( $5 )->appendList( $9 ); }1503 ;1504 1505 new_abstract_parameter_list: // CFA, new & old style abstract1506 new_abstract_parameter_declaration1507 | new_abstract_parameter_list pop ',' push new_abstract_parameter_declaration1508 { $$ = $1->appendList( $5 ); }1509 ;1477 new_parameter_type_list_opt: // CFA 1478 // empty 1479 { $$ = 0; } 1480 | new_parameter_type_list 1481 ; 1482 1483 new_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 1494 new_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 1507 new_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 ; 1510 1512 1511 1513 parameter_type_list_opt: 1512 // empty1513 { $$ = 0; }1514 | parameter_type_list1515 ;1514 // empty 1515 { $$ = 0; } 1516 | parameter_type_list 1517 ; 1516 1518 1517 1519 parameter_type_list: 1518 parameter_list1519 | parameter_list pop ',' push ELLIPSIS1520 { $$ = $1->addVarArgs(); }1521 ;1522 1523 parameter_list: // abstract + real1524 abstract_parameter_declaration1525 | parameter_declaration1526 | parameter_list pop ',' push abstract_parameter_declaration1527 { $$ = $1->appendList( $5 ); }1528 | parameter_list pop ',' push parameter_declaration1529 { $$ = $1->appendList( $5 ); }1530 ;1520 parameter_list 1521 | parameter_list pop ',' push ELLIPSIS 1522 { $$ = $1->addVarArgs(); } 1523 ; 1524 1525 parameter_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 ; 1531 1533 1532 1534 // Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different … … 1534 1536 // function prototypes. 1535 1537 1536 new_parameter_declaration: // CFA, new & old style parameter declaration1537 parameter_declaration1538 | new_identifier_parameter_declarator_no_tuple identifier_or_typedef_name assignment_opt1539 { $$ = $1->addName( $2 ); }1540 | new_abstract_tuple identifier_or_typedef_name assignment_opt1541 // 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_opt1544 { $$ = $2->addName( $3 )->addQualifiers( $1 ); }1545 | new_function_specifier1546 ;1547 1548 new_abstract_parameter_declaration: // CFA, new & old style parameter declaration1549 abstract_parameter_declaration1550 | new_identifier_parameter_declarator_no_tuple1551 | new_abstract_tuple1552 // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).1553 | type_qualifier_list new_abstract_tuple1554 { $$ = $2->addQualifiers( $1 ); }1555 | new_abstract_function1556 ;1538 new_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 1550 new_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 ; 1557 1559 1558 1560 parameter_declaration: 1559 declaration_specifier identifier_parameter_declarator assignment_opt1560 {1561 1562 1563 }1564 | declaration_specifier typedef_parameter_redeclarator assignment_opt1565 {1566 1567 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 ; 1570 1572 1571 1573 abstract_parameter_declaration: 1572 declaration_specifier1573 | declaration_specifier abstract_parameter_declarator1574 { $$ = $2->addType( $1 ); }1575 ;1574 declaration_specifier 1575 | declaration_specifier abstract_parameter_declarator 1576 { $$ = $2->addType( $1 ); } 1577 ; 1576 1578 1577 1579 // ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a … … 1579 1581 // based only on identifiers. The ANSI-style parameter-list can redefine a typedef name. 1580 1582 1581 identifier_list: // K&R-style parameter list => no types1582 no_attr_identifier1583 { $$ = DeclarationNode::newName( $1 ); }1584 | identifier_list ',' no_attr_identifier1585 { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }1586 ;1583 identifier_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 ; 1587 1589 1588 1590 identifier_or_typedef_name: 1589 identifier1590 | TYPEDEFname1591 | TYPEGENname1592 ;1591 identifier 1592 | TYPEDEFname 1593 | TYPEGENname 1594 ; 1593 1595 1594 1596 no_01_identifier_or_typedef_name: 1595 no_01_identifier1596 | TYPEDEFname1597 | TYPEGENname1598 ;1597 no_01_identifier 1598 | TYPEDEFname 1599 | TYPEGENname 1600 ; 1599 1601 1600 1602 no_attr_identifier_or_typedef_name: 1601 no_attr_identifier1602 | TYPEDEFname1603 | TYPEGENname1604 ;1605 1606 type_name_no_function: // sizeof, alignof, cast (constructor)1607 new_abstract_declarator_tuple// CFA1608 | type_specifier1609 | type_specifier variable_abstract_declarator1610 { $$ = $2->addType( $1 ); }1611 ;1612 1613 type_name: // typeof, assertion1614 new_abstract_declarator_tuple// CFA1615 | new_abstract_function// CFA1616 | type_specifier1617 | type_specifier abstract_declarator1618 { $$ = $2->addType( $1 ); }1619 ;1603 no_attr_identifier 1604 | TYPEDEFname 1605 | TYPEGENname 1606 ; 1607 1608 type_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 1615 type_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 ; 1620 1622 1621 1623 initializer_opt: 1622 /* empty */ { $$ = 0; } 1623 | '=' initializer { $$ = $2; } 1624 ; 1624 // empty 1625 { $$ = 0; } 1626 | '=' initializer { $$ = $2; } 1627 ; 1625 1628 1626 1629 initializer: 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 ; 1630 1633 1631 1634 initializer_list: 1632 initializer1633 | designation initializer{ $$ = $2->set_designators( $1 ); }1634 | initializer_list ',' initializer{ $$ = (InitializerNode *)( $1->set_link($3) ); }1635 | initializer_list ',' designation initializer1636 1637 ;1638 1639 // There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem 1640 // isuse 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 }; 1643 1646 // 1644 1647 // The string "[1] = 3" can be parsed as a designator assignment or a tuple assignment. To disambiguate this … … 1648 1651 1649 1652 designation: 1650 designator_list ':'// C99, CFA uses ":" instead of "="1651 | no_attr_identifier_or_typedef_name ':'// GCC, field name1652 1653 ;1654 1655 designator_list: // C991656 designator1657 | 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 1658 designator_list: // C99 1659 designator 1660 | designator_list designator { $$ = (ExpressionNode *)($1->set_link( $2 )); } 1661 ; 1659 1662 1660 1663 designator: 1661 '.' no_attr_identifier_or_typedef_name// C99, field name1662 1663 | '[' push assignment_expression pop ']'// C99, single array element1664 /*assignment_expression used instead of constant_expression because of shift/reduce conflicts1665 with tuple. */1666 1667 | '[' push subrange pop ']'// CFA, multiple array elements1668 1669 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements1670 1671 | '.' '[' push field_list pop ']'// CFA, tuple field selector1672 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 ; 1674 1677 1675 1678 // The CFA type system is based on parametric polymorphism, the ability to declare functions with type … … 1692 1695 // to declare requirements on type arguments of polymorphic functions. 1693 1696 1694 typegen_declaration_specifier: // CFA1695 typegen_type_specifier1696 | declaration_qualifier_list typegen_type_specifier1697 { $$ = $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_list1701 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }1702 ;1703 1704 typegen_type_specifier: // CFA1705 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_qualifier1710 { $$ = $1->addQualifiers( $2 ); }1711 ;1712 1713 type_parameter_list: // CFA1714 type_parameter assignment_opt1715 | type_parameter_list ',' type_parameter assignment_opt1716 { $$ = $1->appendList( $3 ); }1717 ;1718 1719 type_parameter: // CFA1720 type_class no_attr_identifier_or_typedef_name1721 { typedefTable.addToEnclosingScope(*($2), TypedefTable::TD); }1722 assertion_list_opt1723 { $$ = DeclarationNode::newTypeParam( $1, $2 )->addAssertions( $4 ); }1724 | type_specifier identifier_parameter_declarator1725 ;1726 1727 type_class: // CFA1728 TYPE1729 { $$ = DeclarationNode::Type; }1730 | DTYPE1731 { $$ = DeclarationNode::Ftype; }1732 | FTYPE1733 { $$ = DeclarationNode::Dtype; }1734 ;1735 1736 assertion_list_opt: // CFA1737 // empty1738 { $$ = 0; }1739 | assertion_list_opt assertion1740 { $$ = $1 == 0 ? $2 : $1->appendList( $2 ); }1741 ;1742 1743 assertion: // CFA1744 '|' no_attr_identifier_or_typedef_name '(' type_name_list ')'1745 {1746 1747 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: // CFA1756 type_name1757 { $$ = new TypeValueNode( $1 ); }1758 | assignment_expression1759 | type_name_list ',' type_name1760 { $$ = (ExpressionNode *)($1->set_link(new TypeValueNode( $3 ))); }1761 | type_name_list ',' assignment_expression1762 { $$ = (ExpressionNode *)($1->set_link($3)); }1763 ;1764 1765 type_declaring_list: // CFA1766 TYPE type_declarator1767 { $$ = $2; }1768 | storage_class_list TYPE type_declarator1769 { $$ = $3->addQualifiers( $1 ); }1770 | type_declaring_list ',' type_declarator1771 { $$ = $1->appendList( $3->copyStorageClasses( $1 ) ); }1772 ;1773 1774 type_declarator: // CFA1775 type_declarator_name assertion_list_opt1776 { $$ = $1->addAssertions( $2 ); }1777 | type_declarator_name assertion_list_opt '=' type_name1778 { $$ = $1->addAssertions( $2 )->addType( $4 ); }1779 ;1780 1781 type_declarator_name: // CFA1782 no_attr_identifier_or_typedef_name1783 {1784 1785 1786 }1787 | no_01_identifier_or_typedef_name '(' push type_parameter_list pop ')'1788 {1789 1790 1791 }1792 ;1793 1794 context_specifier: // CFA1795 CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{' '}'1796 {1797 1798 1799 }1800 | CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{'1801 {1802 1803 1804 }1805 context_declaration_list '}'1806 {1807 1808 1809 1810 }1811 ;1812 1813 context_declaration_list: // CFA1814 context_declaration1815 | context_declaration_list push context_declaration1816 { $$ = $1->appendList( $3 ); }1817 ;1818 1819 context_declaration: // CFA1820 new_context_declaring_list pop ';'1821 | context_declaring_list pop ';'1822 ;1823 1824 new_context_declaring_list: // CFA1825 new_variable_specifier1826 {1827 1828 1829 }1830 | new_function_specifier1831 {1832 1833 1834 }1835 | new_context_declaring_list pop ',' push identifier_or_typedef_name1836 {1837 1838 1839 }1840 ;1841 1842 context_declaring_list: // CFA1843 type_specifier declarator1844 {1845 1846 1847 }1848 | context_declaring_list pop ',' push declarator1849 {1850 1851 1852 }1853 ;1697 typegen_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 1707 typegen_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 1716 type_parameter_list: // CFA 1717 type_parameter assignment_opt 1718 | type_parameter_list ',' type_parameter assignment_opt 1719 { $$ = $1->appendList( $3 ); } 1720 ; 1721 1722 type_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 1730 type_class: // CFA 1731 TYPE 1732 { $$ = DeclarationNode::Type; } 1733 | DTYPE 1734 { $$ = DeclarationNode::Ftype; } 1735 | FTYPE 1736 { $$ = DeclarationNode::Dtype; } 1737 ; 1738 1739 assertion_list_opt: // CFA 1740 // empty 1741 { $$ = 0; } 1742 | assertion_list_opt assertion 1743 { $$ = $1 == 0 ? $2 : $1->appendList( $2 ); } 1744 ; 1745 1746 assertion: // 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 1758 type_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 1768 type_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 1777 type_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 1784 type_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 1797 context_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 1816 context_declaration_list: // CFA 1817 context_declaration 1818 | context_declaration_list push context_declaration 1819 { $$ = $1->appendList( $3 ); } 1820 ; 1821 1822 context_declaration: // CFA 1823 new_context_declaring_list pop ';' 1824 | context_declaring_list pop ';' 1825 ; 1826 1827 new_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 1845 context_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 ; 1854 1857 1855 1858 //***************************** EXTERNAL DEFINITIONS ***************************** 1856 1859 1857 1860 translation_unit: 1858 // empty1859 {}// empty input file1860 | external_definition_list1861 {1862 1863 1864 1865 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 ; 1869 1872 1870 1873 external_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 ; 1881 1878 1882 1879 external_definition_list_opt: 1883 // empty1884 { $$ = 0; }1885 | external_definition_list1886 ;1880 // empty 1881 { $$ = 0; } 1882 | external_definition_list 1883 ; 1887 1884 1888 1885 external_definition: 1889 declaration1890 | function_definition1891 | asm_statement// GCC, global assembler statement1892 {}1893 | EXTERN STRINGliteral1894 {1895 1896 1897 }1898 '{' external_definition_list_opt '}'// C++-style linkage specifier1899 {1900 1901 1902 1903 }1904 | EXTENSION external_definition1905 { $$ = $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 ; 1907 1904 1908 1905 function_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 ; 1996 1992 1997 1993 declarator: 1998 variable_declarator1999 | function_declarator2000 | typedef_redeclarator2001 ;1994 variable_declarator 1995 | function_declarator 1996 | typedef_redeclarator 1997 ; 2002 1998 2003 1999 subrange: 2004 constant_expression '~' constant_expression// CFA, integer subrange2005 { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $1, $3); }2006 ;2007 2008 asm_name_opt: // GCC2009 // empty2010 | ASM '(' string_literal_list ')' attribute_list_opt2011 ;2012 2013 attribute_list_opt: // GCC2014 // empty2015 | attribute_list2016 ;2017 2018 attribute_list: // GCC2019 attribute2020 | attribute_list attribute2021 ;2022 2023 attribute: // GCC2024 ATTRIBUTE '(' '(' attribute_parameter_list ')' ')'2025 ;2026 2027 attribute_parameter_list: // GCC2028 attrib2029 | attribute_parameter_list ',' attrib2030 ;2031 2032 attrib: // GCC2033 // empty2034 | any_word2035 | any_word '(' comma_expression_opt ')'2036 ;2037 2038 any_word: // GCC2039 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 2004 asm_name_opt: // GCC 2005 // empty 2006 | ASM '(' string_literal_list ')' attribute_list_opt 2007 ; 2008 2009 attribute_list_opt: // GCC 2010 // empty 2011 | attribute_list 2012 ; 2013 2014 attribute_list: // GCC 2015 attribute 2016 | attribute_list attribute 2017 ; 2018 2019 attribute: // GCC 2020 ATTRIBUTE '(' '(' attribute_parameter_list ')' ')' 2021 ; 2022 2023 attribute_parameter_list: // GCC 2024 attrib 2025 | attribute_parameter_list ',' attrib 2026 ; 2027 2028 attrib: // GCC 2029 // empty 2030 | any_word 2031 | any_word '(' comma_expression_opt ')' 2032 ; 2033 2034 any_word: // GCC 2035 identifier_or_typedef_name {} 2036 | storage_class_name {} 2037 | basic_type_name {} 2038 | type_qualifier {} 2039 ; 2044 2040 2045 2041 // ============================================================================ … … 2048 2044 // in an expression, as in: 2049 2045 // 2050 // int (*f())[10] { ... };2051 // ... (*f())[3] += 1;// definition mimics usage2046 // int (*f())[10] { ... }; 2047 // ... (*f())[3] += 1; // definition mimics usage 2052 2048 // 2053 2049 // Because these patterns are highly recursive, changes at a lower level in the recursion require copying some … … 2060 2056 // declarators to define a variable or function prototype, e.g.: 2061 2057 // 2062 // valid declarationinvalid definition2063 // -----------------------------------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) {} 2068 2064 // 2069 2065 // To preclude this syntactic anomaly requires separating the grammar rules for variable and function … … 2075 2071 2076 2072 variable_declarator: 2077 paren_identifier attribute_list_opt2078 | variable_ptr2079 | variable_array attribute_list_opt2080 | variable_function attribute_list_opt2081 ;2073 paren_identifier attribute_list_opt 2074 | variable_ptr 2075 | variable_array attribute_list_opt 2076 | variable_function attribute_list_opt 2077 ; 2082 2078 2083 2079 paren_identifier: 2084 identifier2085 {2086 2087 2088 }2089 | '(' paren_identifier ')'// redundant parenthesis2090 { $$ = $2; }2091 ;2080 identifier 2081 { 2082 typedefTable.setNextIdentifier( *($1) ); 2083 $$ = DeclarationNode::newName( $1 ); 2084 } 2085 | '(' paren_identifier ')' // redundant parenthesis 2086 { $$ = $2; } 2087 ; 2092 2088 2093 2089 variable_ptr: 2094 '*' variable_declarator2095 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2096 | '*' type_qualifier_list variable_declarator2097 { $$ = $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 ; 2101 2097 2102 2098 variable_array: 2103 paren_identifier array_dimension2104 { $$ = $1->addArray( $2 ); }2105 | '(' variable_ptr ')' array_dimension2106 { $$ = $2->addArray( $4 ); }2107 | '(' variable_array ')' multi_array_dimension // redundant parenthesis2108 { $$ = $2->addArray( $4 ); }2109 | '(' variable_array ')'// redundant parenthesis2110 { $$ = $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 ; 2112 2108 2113 2109 variable_function: 2114 '(' variable_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)2115 { $$ = $2->addParamList( $6 ); }2116 | '(' variable_function ')'// redundant parenthesis2117 { $$ = $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 ; 2119 2115 2120 2116 // This pattern parses a function declarator that is not redefining a typedef name. Because functions cannot … … 2124 2120 2125 2121 function_declarator: 2126 function_no_ptr attribute_list_opt2127 | function_ptr2128 | function_array attribute_list_opt2129 ;2122 function_no_ptr attribute_list_opt 2123 | function_ptr 2124 | function_array attribute_list_opt 2125 ; 2130 2126 2131 2127 function_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 parenthesis2137 { $$ = $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 ; 2139 2135 2140 2136 function_ptr: 2141 '*' function_declarator2142 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2143 | '*' type_qualifier_list function_declarator2144 { $$ = $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 ; 2148 2144 2149 2145 function_array: 2150 '(' function_ptr ')' array_dimension2151 { $$ = $2->addArray( $4 ); }2152 | '(' function_array ')' multi_array_dimension // redundant parenthesis2153 { $$ = $2->addArray( $4 ); }2154 | '(' function_array ')'// redundant parenthesis2155 { $$ = $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 ; 2157 2153 2158 2154 // This pattern parses an old-style K&R function declarator (OBSOLESCENT, see 4) that is not redefining a … … 2161 2157 2162 2158 old_function_declarator: 2163 old_function_no_ptr2164 | old_function_ptr2165 | old_function_array2166 ;2159 old_function_no_ptr 2160 | old_function_ptr 2161 | old_function_array 2162 ; 2167 2163 2168 2164 old_function_no_ptr: 2169 paren_identifier '(' identifier_list ')'// function_declarator handles empty parameter2170 { $$ = $1->addIdList( $3 ); }2171 | '(' old_function_ptr ')' '(' identifier_list ')'2172 { $$ = $2->addIdList( $5 ); }2173 | '(' old_function_no_ptr ')'// redundant parenthesis2174 { $$ = $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 ; 2176 2172 2177 2173 old_function_ptr: 2178 '*' old_function_declarator2179 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2180 | '*' type_qualifier_list old_function_declarator2181 { $$ = $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 ; 2185 2181 2186 2182 old_function_array: 2187 '(' old_function_ptr ')' array_dimension2188 { $$ = $2->addArray( $4 ); }2189 | '(' old_function_array ')' multi_array_dimension // redundant parenthesis2190 { $$ = $2->addArray( $4 ); }2191 | '(' old_function_array ')'// redundant parenthesis2192 { $$ = $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 ; 2194 2190 2195 2191 // This pattern parses a declaration for a variable or function prototype that redefines a typedef name, e.g.: 2196 2192 // 2197 // typedef int foo;2198 // {2199 // int foo; // redefine typedef name in new scope2200 // }2193 // typedef int foo; 2194 // { 2195 // int foo; // redefine typedef name in new scope 2196 // } 2201 2197 // 2202 2198 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and … … 2204 2200 2205 2201 typedef_redeclarator: 2206 paren_typedef attribute_list_opt2207 | typedef_ptr2208 | typedef_array attribute_list_opt2209 | typedef_function attribute_list_opt2210 ;2202 paren_typedef attribute_list_opt 2203 | typedef_ptr 2204 | typedef_array attribute_list_opt 2205 | typedef_function attribute_list_opt 2206 ; 2211 2207 2212 2208 paren_typedef: 2213 TYPEDEFname2214 {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 ; 2221 2217 2222 2218 typedef_ptr: 2223 '*' typedef_redeclarator2224 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2225 | '*' type_qualifier_list typedef_redeclarator2226 { $$ = $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 ; 2230 2226 2231 2227 typedef_array: 2232 paren_typedef array_dimension2233 { $$ = $1->addArray( $2 ); }2234 | '(' typedef_ptr ')' array_dimension2235 { $$ = $2->addArray( $4 ); }2236 | '(' typedef_array ')' multi_array_dimension // redundant parenthesis2237 { $$ = $2->addArray( $4 ); }2238 | '(' typedef_array ')'// redundant parenthesis2239 { $$ = $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 ; 2241 2237 2242 2238 typedef_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 parenthesis2248 { $$ = $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 ; 2250 2246 2251 2247 // This pattern parses a declaration for a parameter variable or function prototype that is not redefining a … … 2255 2251 2256 2252 identifier_parameter_declarator: 2257 paren_identifier attribute_list_opt2258 | identifier_parameter_ptr2259 | identifier_parameter_array attribute_list_opt2260 | identifier_parameter_function attribute_list_opt2261 ;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 ; 2262 2258 2263 2259 identifier_parameter_ptr: 2264 '*' identifier_parameter_declarator2265 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2266 | '*' type_qualifier_list identifier_parameter_declarator2267 { $$ = $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 ; 2271 2267 2272 2268 identifier_parameter_array: 2273 paren_identifier array_parameter_dimension2274 { $$ = $1->addArray( $2 ); }2275 | '(' identifier_parameter_ptr ')' array_dimension2276 { $$ = $2->addArray( $4 ); }2277 | '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis2278 { $$ = $2->addArray( $4 ); }2279 | '(' identifier_parameter_array ')'// redundant parenthesis2280 { $$ = $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 ; 2282 2278 2283 2279 identifier_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 parenthesis2289 { $$ = $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 scope2297 // 2298 // and allows the C99 array options, which can only appear in a parameter list. In addition, the pattern handles the2299 // 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 in2302 // 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." 2304 2300 // 2305 2301 // which precludes the following cases: 2306 2302 // 2307 // typedef float T;2308 // int f( int ( T [5] ) );// see abstract_parameter_declarator2309 // int g( int ( T ( int ) ) );// see abstract_parameter_declarator2310 // int f( int f1( T a[5] ) );// see identifier_parameter_declarator2311 // int g( int g1( T g2( int p ) ) );// see identifier_parameter_declarator2312 // 2313 // In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type list, and2314 // not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes declaring an array of2315 // functions versus a pointer to an array of functions, and returning arrays and functions versus pointers toarrays and2316 // 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. 2317 2313 2318 2314 typedef_parameter_redeclarator: 2319 typedef attribute_list_opt2320 | typedef_parameter_ptr2321 | typedef_parameter_array attribute_list_opt2322 | typedef_parameter_function attribute_list_opt2323 ;2315 typedef attribute_list_opt 2316 | typedef_parameter_ptr 2317 | typedef_parameter_array attribute_list_opt 2318 | typedef_parameter_function attribute_list_opt 2319 ; 2324 2320 2325 2321 typedef: 2326 TYPEDEFname2327 {2328 2329 2330 }2331 ;2322 TYPEDEFname 2323 { 2324 typedefTable.setNextIdentifier( *($1) ); 2325 $$ = DeclarationNode::newName( $1 ); 2326 } 2327 ; 2332 2328 2333 2329 typedef_parameter_ptr: 2334 '*' typedef_parameter_redeclarator2335 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2336 | '*' type_qualifier_list typedef_parameter_redeclarator2337 { $$ = $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 ; 2341 2337 2342 2338 typedef_parameter_array: 2343 typedef array_parameter_dimension2344 { $$ = $1->addArray( $2 ); }2345 | '(' typedef_parameter_ptr ')' array_parameter_dimension2346 { $$ = $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 ; 2348 2344 2349 2345 typedef_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 to2357 // 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 arrays2363 // 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. 2364 2360 2365 2361 abstract_declarator: 2366 abstract_ptr2367 | abstract_array attribute_list_opt2368 | abstract_function attribute_list_opt2369 ;2362 abstract_ptr 2363 | abstract_array attribute_list_opt 2364 | abstract_function attribute_list_opt 2365 ; 2370 2366 2371 2367 abstract_ptr: 2372 '*'2373 { $$ = DeclarationNode::newPointer( 0 ); }2374 | '*' type_qualifier_list2375 { $$ = DeclarationNode::newPointer( $2 ); }2376 | '*' abstract_declarator2377 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2378 | '*' type_qualifier_list abstract_declarator2379 { $$ = $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 ; 2383 2379 2384 2380 abstract_array: 2385 array_dimension2386 | '(' abstract_ptr ')' array_dimension2387 { $$ = $2->addArray( $4 ); }2388 | '(' abstract_array ')' multi_array_dimension // redundant parenthesis2389 { $$ = $2->addArray( $4 ); }2390 | '(' abstract_array ')'// redundant parenthesis2391 { $$ = $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 ; 2393 2389 2394 2390 abstract_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 parenthesis2400 { $$ = $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 ; 2402 2398 2403 2399 array_dimension: 2404 // Only the first dimension can be empty.2405 '[' push pop ']'2406 { $$ = DeclarationNode::newArray( 0, 0, false ); }2407 | '[' push pop ']' multi_array_dimension2408 { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $5 ); }2409 | multi_array_dimension2410 ;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 ; 2411 2407 2412 2408 multi_array_dimension: 2413 '[' push assignment_expression pop ']'2414 { $$ = DeclarationNode::newArray( $3, 0, false ); }2415 | '[' push '*' pop ']'// C992416 { $$ = 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 ']'// C992420 { $$ = $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 ; 2422 2418 2423 2419 // This pattern parses a declaration of a parameter abstract variable or function prototype, i.e., there is no 2424 2420 // identifier to which the type applies, e.g.: 2425 2421 // 2426 // int f( int );// abstract variable parameter; no parameter name specified2427 // int f( int (int) );// abstract function-prototype parameter; no parameter name specified2428 // 2429 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays2430 // 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. 2431 2427 2432 2428 abstract_parameter_declarator: 2433 abstract_parameter_ptr2434 | abstract_parameter_array attribute_list_opt2435 | abstract_parameter_function attribute_list_opt2436 ;2429 abstract_parameter_ptr 2430 | abstract_parameter_array attribute_list_opt 2431 | abstract_parameter_function attribute_list_opt 2432 ; 2437 2433 2438 2434 abstract_parameter_ptr: 2439 '*'2440 { $$ = DeclarationNode::newPointer( 0 ); }2441 | '*' type_qualifier_list2442 { $$ = DeclarationNode::newPointer( $2 ); }2443 | '*' abstract_parameter_declarator2444 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2445 | '*' type_qualifier_list abstract_parameter_declarator2446 { $$ = $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 ; 2450 2446 2451 2447 abstract_parameter_array: 2452 array_parameter_dimension2453 | '(' abstract_parameter_ptr ')' array_parameter_dimension2454 { $$ = $2->addArray( $4 ); }2455 | '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis2456 { $$ = $2->addArray( $4 ); }2457 | '(' abstract_parameter_array ')'// redundant parenthesis2458 { $$ = $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 ; 2460 2456 2461 2457 abstract_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 parenthesis2467 { $$ = $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 ; 2469 2465 2470 2466 array_parameter_dimension: 2471 // Only the first dimension can be empty or have qualifiers.2472 array_parameter_1st_dimension2473 | array_parameter_1st_dimension multi_array_dimension2474 { $$ = $1->addArray( $2 ); }2475 | multi_array_dimension2476 ;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 ; 2477 2473 2478 2474 // The declaration of an array parameter has additional syntax over arrays in normal variable declarations: 2479 2475 // 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." 2482 2479 2483 2480 array_parameter_1st_dimension: 2484 '[' push pop ']'2485 { $$ = DeclarationNode::newArray( 0, 0, false ); }2486 // multi_array_dimension handles the '[' '*' ']' case2487 | '[' push type_qualifier_list '*' pop ']'// remaining C992488 { $$ = DeclarationNode::newVarArray( $3 ); }2489 | '[' push type_qualifier_list pop ']'2490 { $$ = DeclarationNode::newArray( 0, $3, false ); }2491 // multi_array_dimension handles the '[' assignment_expression ']' case2492 | '[' 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 specified2504 // 2505 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays2506 // 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. 2507 2504 2508 2505 variable_abstract_declarator: 2509 variable_abstract_ptr2510 | variable_abstract_array attribute_list_opt2511 | variable_abstract_function attribute_list_opt2512 ;2506 variable_abstract_ptr 2507 | variable_abstract_array attribute_list_opt 2508 | variable_abstract_function attribute_list_opt 2509 ; 2513 2510 2514 2511 variable_abstract_ptr: 2515 '*'2516 { $$ = DeclarationNode::newPointer( 0 ); }2517 | '*' type_qualifier_list2518 { $$ = DeclarationNode::newPointer( $2 ); }2519 | '*' variable_abstract_declarator2520 { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }2521 | '*' type_qualifier_list variable_abstract_declarator2522 { $$ = $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 ; 2526 2523 2527 2524 variable_abstract_array: 2528 array_dimension2529 | '(' variable_abstract_ptr ')' array_dimension2530 { $$ = $2->addArray( $4 ); }2531 | '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis2532 { $$ = $2->addArray( $4 ); }2533 | '(' variable_abstract_array ')'// redundant parenthesis2534 { $$ = $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 ; 2536 2533 2537 2534 variable_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 parenthesis2541 { $$ = $2; }2542 ;2543 2544 // This pattern parses a new-style declaration for a parameter variable or function prototype that is either an2545 // 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: // CFA2548 new_identifier_parameter_declarator_no_tuple2549 | new_abstract_tuple2550 | type_qualifier_list new_abstract_tuple2551 { $$ = $2->addQualifiers( $1 ); }2552 ;2553 2554 new_identifier_parameter_declarator_no_tuple: // CFA2555 new_identifier_parameter_ptr2556 | new_identifier_parameter_array2557 ;2558 2559 new_identifier_parameter_ptr: // CFA2560 '*' type_specifier2561 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2562 | type_qualifier_list '*' type_specifier2563 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2564 | '*' new_abstract_function2565 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2566 | type_qualifier_list '*' new_abstract_function2567 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2568 | '*' new_identifier_parameter_declarator_tuple2569 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }2570 | type_qualifier_list '*' new_identifier_parameter_declarator_tuple2571 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }2572 ;2573 2574 new_identifier_parameter_array: // CFA2575 // Only the first dimension can be empty or have qualifiers. Empty dimension must be factored out due to2576 // shift/reduce conflict with new-style empty (void) function return type. */2577 '[' push pop ']' type_specifier2578 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }2579 | new_array_parameter_1st_dimension type_specifier2580 { $$ = $2->addNewArray( $1 ); }2581 | '[' push pop ']' multi_array_dimension type_specifier2582 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }2583 | new_array_parameter_1st_dimension multi_array_dimension type_specifier2584 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }2585 | multi_array_dimension type_specifier2586 { $$ = $2->addNewArray( $1 ); }2587 | '[' push pop ']' new_identifier_parameter_ptr2588 { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }2589 | new_array_parameter_1st_dimension new_identifier_parameter_ptr2590 { $$ = $2->addNewArray( $1 ); }2591 | '[' push pop ']' multi_array_dimension new_identifier_parameter_ptr2592 { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }2593 | new_array_parameter_1st_dimension multi_array_dimension new_identifier_parameter_ptr2594 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }2595 | multi_array_dimension new_identifier_parameter_ptr2596 { $$ = $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 2544 new_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 2551 new_identifier_parameter_declarator_no_tuple: // CFA 2552 new_identifier_parameter_ptr 2553 | new_identifier_parameter_array 2554 ; 2555 2556 new_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 2571 new_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 ; 2598 2595 2599 2596 new_array_parameter_1st_dimension: 2600 '[' push type_qualifier_list '*' pop ']'// remaining C992601 { $$ = 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 this2607 //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 no2614 // identifier to which the type applies, e.g.:2615 // 2616 // [int] f( int );// abstract variable parameter; no parameter name specified2617 // [int] f( [int] (int) );// abstract function-prototype parameter; no parameter name specified2597 '[' 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 2618 2615 // 2619 2616 // These rules need LR(3): 2620 2617 // 2621 // new_abstract_tuple identifier_or_typedef_name2622 // '[' 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 ')' 2623 2620 // 2624 2621 // since a function return type can be syntactically identical to a tuple type: 2625 2622 // 2626 // [int, int] t;2627 // [int, int] f( int );2623 // [int, int] t; 2624 // [int, int] f( int ); 2628 2625 // 2629 2626 // 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 2631 new_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 2638 new_abstract_declarator_no_tuple: // CFA 2639 new_abstract_ptr 2640 | new_abstract_array 2641 ; 2642 2643 new_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 2658 new_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 2675 new_abstract_tuple: // CFA 2676 '[' push new_abstract_parameter_list pop ']' 2677 { $$ = DeclarationNode::newTuple( $3 ); } 2678 ; 2679 2680 new_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." 2697 2695 // 2698 2696 // 3) ISO/IEC 9899:1999 Section 6.11.6(1) : "The use of function declarators with empty parentheses (not 2699 2697 // prototype-format parameter type declarators) is an obsolescent feature." 2700 2698 // 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. 2703 2702 2704 2703 //************************* MISCELLANEOUS ******************************** 2705 2704 2706 comma_opt: // redundant comma2707 // empty2708 | ','2709 ;2705 comma_opt: // redundant comma 2706 // empty 2707 | ',' 2708 ; 2710 2709 2711 2710 assignment_opt: 2712 // empty2713 { $$ = 0; }2714 | '=' assignment_expression2715 { $$ = $2; }2716 ;2711 // empty 2712 { $$ = 0; } 2713 | '=' assignment_expression 2714 { $$ = $2; } 2715 ; 2717 2716 2718 2717 %% … … 2720 2719 2721 2720 void yyerror( char *string ) { 2722 2723 2724 2725 2726 cout << "in file " << yyfilename << " ";2727 2728 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; 2729 2728 } 2730 2729 2731 2730 // Local Variables: // 2732 2731 // fill-column: 110 // 2732 // tab-width: 4 // 2733 // mode: c++ // 2733 2734 // compile-command: "make install" // 2734 2735 // 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 // 10 15 11 16 #ifndef PARSER_LEX_H … … 14 19 int yylex(); 15 20 void yyerror(char *); 16 extern "C" {17 #include <malloc.h>18 }19 21 20 / * External declarations for information sharing between lexer and scanner */22 // External declarations for information sharing between lexer and scanner 21 23 #include "TypedefTable.h" 22 24 extern TypedefTable typedefTable; 23 25 24 / * current location in the input */26 // current location in the input 25 27 extern int yylineno; 26 28 extern char *yyfilename; 27 29 28 struct Location 29 { 30 char *file; 31 int line; 30 struct Location { 31 char *file; 32 int line; 32 33 }; 33 34 34 class Token 35 { 36 public: 37 std::string *str; 38 Location loc; 35 class Token { 36 public: 37 std::string *str; 38 Location loc; 39 39 40 operator std::string *() { return str; }40 operator std::string *() { return str; } 41 41 }; 42 42 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 this4 * grammar and to use it within software systems. THIS GRAMMAR IS PROVIDED "AS IS" AND WITHOUT5 * 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. 6 6 * 7 7 * lex.l -- … … 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Wed Jan 21 08:43:59201513 * Update Count : 3 2012 * Last Modified On : Sat May 16 12:14:18 2015 13 * Update Count : 330 14 14 */ 15 15 … … 17 17 18 18 %{ 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. 23 22 24 23 //**************************** Includes and Defines **************************** … … 28 27 #include "lex.h" 29 28 #include "ParseNode.h" 30 #include "cfa.tab.h" 29 #include "cfa.tab.h" // YACC generated definitions based on C++ grammar 31 30 32 31 char *yyfilename; 33 std::string *strtext; // accumulate parts of character and string constant value34 35 #define WHITE_RETURN(x) // do nothing32 std::string *strtext; // accumulate parts of character and string constant value 33 34 #define WHITE_RETURN(x) // do nothing 36 35 #define NEWLINE_RETURN() WHITE_RETURN('\n') 37 36 #define RETURN_VAL(x) yylval.tok.str = new std::string(yytext); \ 38 39 40 37 yylval.tok.loc.file = yyfilename; \ 38 yylval.tok.loc.line = yylineno; \ 39 return(x) 41 40 #define RETURN_STR(x) yylval.tok.str = strtext; \ 42 43 44 45 46 #define KEYWORD_RETURN(x) RETURN_VAL(x) // keyword41 yylval.tok.loc.file = yyfilename; \ 42 yylval.tok.loc.line = yylineno; \ 43 return(x) 44 45 #define KEYWORD_RETURN(x) RETURN_VAL(x) // keyword 47 46 #define IDENTIFIER_RETURN() RETURN_VAL((typedefTable.isIdentifier(yytext) ? IDENTIFIER : typedefTable.isTypedef(yytext) ? TYPEDEFname : TYPEGENname)) 48 47 //#define ATTRIBUTE_RETURN() RETURN_VAL((typedefTable.isIdentifier(yytext) ? ATTR_IDENTIFIER : typedefTable.isTypedef(yytext) ? ATTR_TYPEDEFname : ATTR_TYPEGENname)) 49 48 #define ATTRIBUTE_RETURN() RETURN_VAL(ATTR_IDENTIFIER) 50 49 51 #define ASCIIOP_RETURN() RETURN_VAL((int)yytext[0]) 52 #define NAMEDOP_RETURN(x) RETURN_VAL(x) // multichar operator, with a name50 #define ASCIIOP_RETURN() RETURN_VAL((int)yytext[0]) // single character operator 51 #define NAMEDOP_RETURN(x) RETURN_VAL(x) // multichar operator, with a name 53 52 54 53 #define NUMERIC_RETURN(x) rm_underscore(); RETURN_VAL(x) // numeric constant 55 54 56 55 void rm_underscore() { 57 58 59 60 if ( yytext[i] != '_' ) {61 62 63 } // if64 65 66 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'; 67 66 } 68 67 … … 75 74 universal_char "\\"((u"_"?{hex_quad})|(U"_"?{hex_quad}{2})) 76 75 77 // identifier, GCC: $ in identifier76 // identifier, GCC: $ in identifier 78 77 identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})* 79 78 80 // quoted identifier79 // quoted identifier 81 80 quoted_identifier "`"{identifier}"`" 82 81 83 // attribute identifier, GCC: $ in identifier82 // attribute identifier, GCC: $ in identifier 84 83 attr_identifier "@"{identifier} 85 84 86 // numeric constants, CFA: '_' in constant85 // numeric constants, CFA: '_' in constant 87 86 hex_quad {hex}("_"?{hex}){3} 88 87 integer_suffix "_"?(([uU][lL]?)|([uU]("ll"|"LL")?)|([lL][uU]?)|("ll"|"LL")[uU]?) … … 109 108 hex_floating_constant {hex_prefix}(({hex_fractional_constant}{binary_exponent})|({hex_digits}{binary_exponent})){floating_suffix}? 110 109 111 // character escape sequence, GCC: \e => esc character110 // character escape sequence, GCC: \e => esc character 112 111 simple_escape "\\"[abefnrtv'"?\\] 113 // ' stop highlighting112 // ' stop highlighting 114 113 octal_escape "\\"{octal}("_"?{octal}){0,2} 115 114 hex_escape "\\""x""_"?{hex_digits} 116 115 escape_seq {simple_escape}|{octal_escape}|{hex_escape}|{universal_char} 117 116 118 // display/white-space characters117 // display/white-space characters 119 118 h_tab [\011] 120 119 form_feed [\014] … … 123 122 h_white [ ]|{h_tab} 124 123 125 // operators124 // operators 126 125 op_unary_only "~"|"!" 127 126 op_unary_binary "+"|"-"|"*" … … 140 139 141 140 %% 142 /* line directives */141 /* line directives */ 143 142 ^{h_white}*"#"{h_white}*[0-9]+{h_white}*["][^"\n]+["][^\n]*"\n" { 144 143 /* " stop highlighting */ … … 150 149 begin_string = strchr( end_num, '"' ); 151 150 if ( begin_string ) { 152 153 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 163 162 } 164 163 165 /* ignore preprocessor directives (for now) */164 /* ignore preprocessor directives (for now) */ 166 165 ^{h_white}*"#"[^\n]*"\n" ; 167 166 168 /* ignore C style comments */167 /* ignore C style comments */ 169 168 "/*" { BEGIN COMMENT; } 170 169 <COMMENT>.|\n ; 171 170 <COMMENT>"*/" { BEGIN 0; } 172 171 173 /* ignore C++ style comments */172 /* ignore C++ style comments */ 174 173 "//"[^\n]*"\n" ; 175 174 176 /* ignore whitespace */175 /* ignore whitespace */ 177 176 {h_white}+ { WHITE_RETURN(' '); } 178 177 ({v_tab}|{c_return}|{form_feed})+ { WHITE_RETURN(' '); } 179 178 ({h_white}|{v_tab}|{c_return}|{form_feed})*"\n" { NEWLINE_RETURN(); } 180 179 181 /* keywords */182 _Alignas { KEYWORD_RETURN(ALIGNAS); } // C11183 _Alignof { KEYWORD_RETURN(ALIGNOF); } // C11184 __alignof { KEYWORD_RETURN(ALIGNOF); } // GCC185 __alignof__ { KEYWORD_RETURN(ALIGNOF); } // GCC186 asm { KEYWORD_RETURN(ASM); }187 __asm { KEYWORD_RETURN(ASM); } // GCC188 __asm__ { KEYWORD_RETURN(ASM); } // GCC189 _Atomic { KEYWORD_RETURN(ATOMIC); } // C11190 __attribute { KEYWORD_RETURN(ATTRIBUTE); } // GCC191 __attribute__ { KEYWORD_RETURN(ATTRIBUTE); }// GCC180 /* 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 185 asm { 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 192 191 auto { KEYWORD_RETURN(AUTO); } 193 _Bool { KEYWORD_RETURN(BOOL); } // C99192 _Bool { KEYWORD_RETURN(BOOL); } // C99 194 193 break { KEYWORD_RETURN(BREAK); } 195 194 case { KEYWORD_RETURN(CASE); } 196 catch { KEYWORD_RETURN(CATCH); } // CFA195 catch { KEYWORD_RETURN(CATCH); } // CFA 197 196 char { KEYWORD_RETURN(CHAR); } 198 choose { KEYWORD_RETURN(CHOOSE); } // CFA199 _Complex { KEYWORD_RETURN(COMPLEX); } // C99200 __complex { KEYWORD_RETURN(COMPLEX); } // GCC201 __complex__ { KEYWORD_RETURN(COMPLEX); } // GCC197 choose { KEYWORD_RETURN(CHOOSE); } // CFA 198 _Complex { KEYWORD_RETURN(COMPLEX); } // C99 199 __complex { KEYWORD_RETURN(COMPLEX); } // GCC 200 __complex__ { KEYWORD_RETURN(COMPLEX); } // GCC 202 201 const { KEYWORD_RETURN(CONST); } 203 __const { KEYWORD_RETURN(CONST); } // GCC204 __const__ { KEYWORD_RETURN(CONST); } // GCC205 context { KEYWORD_RETURN(CONTEXT); } // CFA202 __const { KEYWORD_RETURN(CONST); } // GCC 203 __const__ { KEYWORD_RETURN(CONST); } // GCC 204 context { KEYWORD_RETURN(CONTEXT); } // CFA 206 205 continue { KEYWORD_RETURN(CONTINUE); } 207 206 default { KEYWORD_RETURN(DEFAULT); } 208 do { KEYWORD_RETURN(DO); }207 do { KEYWORD_RETURN(DO); } 209 208 double { KEYWORD_RETURN(DOUBLE); } 210 dtype { KEYWORD_RETURN(DTYPE); } // CFA209 dtype { KEYWORD_RETURN(DTYPE); } // CFA 211 210 else { KEYWORD_RETURN(ELSE); } 212 211 enum { KEYWORD_RETURN(ENUM); } 213 __extension__ { KEYWORD_RETURN(EXTENSION); }// GCC212 __extension__ { KEYWORD_RETURN(EXTENSION); } // GCC 214 213 extern { KEYWORD_RETURN(EXTERN); } 215 fallthru { KEYWORD_RETURN(FALLTHRU); } // CFA216 finally { KEYWORD_RETURN(FINALLY); } // CFA214 fallthru { KEYWORD_RETURN(FALLTHRU); } // CFA 215 finally { KEYWORD_RETURN(FINALLY); } // CFA 217 216 float { KEYWORD_RETURN(FLOAT); } 218 __float128 { KEYWORD_RETURN(FLOAT); } // GCC219 for { KEYWORD_RETURN(FOR); }220 forall { KEYWORD_RETURN(FORALL); } // CFA217 __float128 { KEYWORD_RETURN(FLOAT); } // GCC 218 for { KEYWORD_RETURN(FOR); } 219 forall { KEYWORD_RETURN(FORALL); } // CFA 221 220 fortran { KEYWORD_RETURN(FORTRAN); } 222 ftype { KEYWORD_RETURN(FTYPE); } // CFA223 _Generic { KEYWORD_RETURN(GENERIC); } // C11221 ftype { KEYWORD_RETURN(FTYPE); } // CFA 222 _Generic { KEYWORD_RETURN(GENERIC); } // C11 224 223 goto { KEYWORD_RETURN(GOTO); } 225 if { KEYWORD_RETURN(IF); }226 _Imaginary { KEYWORD_RETURN(IMAGINARY); } // C99227 __imag { KEYWORD_RETURN(IMAGINARY); } // GCC228 __imag__ { KEYWORD_RETURN(IMAGINARY); } // GCC229 inline { KEYWORD_RETURN(INLINE); } // C99230 __inline { KEYWORD_RETURN(INLINE); } // GCC231 __inline__ { KEYWORD_RETURN(INLINE); } // GCC232 int { KEYWORD_RETURN(INT); }233 __int128 { KEYWORD_RETURN(INT); } // GCC234 __label__ { KEYWORD_RETURN(LABEL); } // GCC224 if { KEYWORD_RETURN(IF); } 225 _Imaginary { KEYWORD_RETURN(IMAGINARY); } // C99 226 __imag { KEYWORD_RETURN(IMAGINARY); } // GCC 227 __imag__ { KEYWORD_RETURN(IMAGINARY); } // GCC 228 inline { KEYWORD_RETURN(INLINE); } // C99 229 __inline { KEYWORD_RETURN(INLINE); } // GCC 230 __inline__ { KEYWORD_RETURN(INLINE); } // GCC 231 int { KEYWORD_RETURN(INT); } 232 __int128 { KEYWORD_RETURN(INT); } // GCC 233 __label__ { KEYWORD_RETURN(LABEL); } // GCC 235 234 long { KEYWORD_RETURN(LONG); } 236 lvalue { KEYWORD_RETURN(LVALUE); } // CFA237 _Noreturn { KEYWORD_RETURN(NORETURN); } // C11235 lvalue { KEYWORD_RETURN(LVALUE); } // CFA 236 _Noreturn { KEYWORD_RETURN(NORETURN); } // C11 238 237 register { KEYWORD_RETURN(REGISTER); } 239 restrict { KEYWORD_RETURN(RESTRICT); } // C99240 __restrict { KEYWORD_RETURN(RESTRICT); } // GCC241 __restrict__ { KEYWORD_RETURN(RESTRICT); }// GCC238 restrict { KEYWORD_RETURN(RESTRICT); } // C99 239 __restrict { KEYWORD_RETURN(RESTRICT); } // GCC 240 __restrict__ { KEYWORD_RETURN(RESTRICT); } // GCC 242 241 return { KEYWORD_RETURN(RETURN); } 243 242 short { KEYWORD_RETURN(SHORT); } 244 243 signed { KEYWORD_RETURN(SIGNED); } 245 __signed { KEYWORD_RETURN(SIGNED); } // GCC246 __signed__ { KEYWORD_RETURN(SIGNED); } // GCC244 __signed { KEYWORD_RETURN(SIGNED); } // GCC 245 __signed__ { KEYWORD_RETURN(SIGNED); } // GCC 247 246 sizeof { KEYWORD_RETURN(SIZEOF); } 248 247 static { KEYWORD_RETURN(STATIC); } 249 _Static_assert { KEYWORD_RETURN(STATICASSERT); }// C11248 _Static_assert { KEYWORD_RETURN(STATICASSERT); } // C11 250 249 struct { KEYWORD_RETURN(STRUCT); } 251 250 switch { KEYWORD_RETURN(SWITCH); } 252 _Thread_local { KEYWORD_RETURN(THREADLOCAL); }// C11253 throw { KEYWORD_RETURN(THROW); } // CFA254 try { KEYWORD_RETURN(TRY); }// CFA255 type { KEYWORD_RETURN(TYPE); } // CFA251 _Thread_local { KEYWORD_RETURN(THREADLOCAL); } // C11 252 throw { KEYWORD_RETURN(THROW); } // CFA 253 try { KEYWORD_RETURN(TRY); } // CFA 254 type { KEYWORD_RETURN(TYPE); } // CFA 256 255 typedef { KEYWORD_RETURN(TYPEDEF); } 257 typeof { KEYWORD_RETURN(TYPEOF); } // GCC258 __typeof { KEYWORD_RETURN(TYPEOF); } // GCC259 __typeof__ { KEYWORD_RETURN(TYPEOF); } // GCC256 typeof { KEYWORD_RETURN(TYPEOF); } // GCC 257 __typeof { KEYWORD_RETURN(TYPEOF); } // GCC 258 __typeof__ { KEYWORD_RETURN(TYPEOF); } // GCC 260 259 union { KEYWORD_RETURN(UNION); } 261 260 unsigned { KEYWORD_RETURN(UNSIGNED); } 262 261 void { KEYWORD_RETURN(VOID); } 263 262 volatile { KEYWORD_RETURN(VOLATILE); } 264 __volatile { KEYWORD_RETURN(VOLATILE); } // GCC265 __volatile__ { KEYWORD_RETURN(VOLATILE); }// GCC263 __volatile { KEYWORD_RETURN(VOLATILE); } // GCC 264 __volatile__ { KEYWORD_RETURN(VOLATILE); } // GCC 266 265 while { KEYWORD_RETURN(WHILE); } 267 266 268 /* identifier */269 {identifier} 270 {attr_identifier} 267 /* identifier */ 268 {identifier} { IDENTIFIER_RETURN(); } 269 {attr_identifier} { ATTRIBUTE_RETURN(); } 271 270 "`" { BEGIN BKQUOTE; } 272 <BKQUOTE>{identifier} 273 <BKQUOTE>"`" 274 275 /* numeric constants */276 "0" { NUMERIC_RETURN(ZERO); }// CFA277 "1" { NUMERIC_RETURN(ONE); }// CFA271 <BKQUOTE>{identifier} { IDENTIFIER_RETURN(); } 272 <BKQUOTE>"`" { BEGIN 0; } 273 274 /* numeric constants */ 275 "0" { NUMERIC_RETURN(ZERO); } // CFA 276 "1" { NUMERIC_RETURN(ONE); } // CFA 278 277 {decimal_constant} { NUMERIC_RETURN(INTEGERconstant); } 279 278 {octal_constant} { NUMERIC_RETURN(INTEGERconstant); } … … 282 281 {hex_floating_constant} { NUMERIC_RETURN(FLOATINGconstant); } 283 282 284 /* character constant, allows empty value */283 /* character constant, allows empty value */ 285 284 "L"?"_"?['] { BEGIN QUOTE; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); } 286 <QUOTE>[^'\\\n]* 287 <QUOTE>['\n] 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 */ 291 290 "L"?"_"?["] { BEGIN STRING; rm_underscore(); strtext = new std::string; *strtext += std::string( yytext ); } 292 <STRING>[^"\\\n]* 293 <STRING>["\n] 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 */ 295 294 296 295 <QUOTE,STRING>{escape_seq} { rm_underscore(); *strtext += std::string( yytext ); } 297 296 <QUOTE,STRING>[\\] { *strtext += std::string( yytext ); } // unknown escape character 298 297 299 /* punctuation */300 "[" { ASCIIOP_RETURN(); }301 "]" { ASCIIOP_RETURN(); }302 "(" { ASCIIOP_RETURN(); }303 ")" { ASCIIOP_RETURN(); }304 "{" { ASCIIOP_RETURN(); }305 "}" { ASCIIOP_RETURN(); }306 "," { ASCIIOP_RETURN(); }// also operator307 ":" { ASCIIOP_RETURN(); }308 ";" { ASCIIOP_RETURN(); }309 "." { ASCIIOP_RETURN(); }// also operator298 /* 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 310 309 "..." { NAMEDOP_RETURN(ELLIPSIS); } 311 310 312 /* alternative C99 brackets, "<:" & "<:<:" handled by preprocessor */311 /* alternative C99 brackets, "<:" & "<:<:" handled by preprocessor */ 313 312 "<:" { RETURN_VAL('['); } 314 313 ":>" { RETURN_VAL(']'); } … … 316 315 "%>" { RETURN_VAL('}'); } 317 316 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(); } 333 332 334 333 "++" { NAMEDOP_RETURN(ICR); } … … 354 353 ">>=" { NAMEDOP_RETURN(RSassign); } 355 354 356 /* CFA, operator identifier */357 {op_unary}"?" { IDENTIFIER_RETURN(); }// unary355 /* CFA, operator identifier */ 356 {op_unary}"?" { IDENTIFIER_RETURN(); } // unary 358 357 "?"({op_unary_pre_post}|"()"|"[?]") { IDENTIFIER_RETURN(); } 359 "?"{op_binary_over}"?" { IDENTIFIER_RETURN(); } // binary358 "?"{op_binary_over}"?" { IDENTIFIER_RETURN(); } // binary 360 359 /* 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 "?()": 367 365 368 366 int * ?()(); // declaration: space required after '*' 369 367 * ?()(); // expression: space required after '*' 370 368 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. 374 371 375 372 The 4 remaining cases occur in expressions: … … 380 377 i?--i:0; // space required after '?' 381 378 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 '(', which384 is the start of an argument list. In the second two cases, the string "?++x" is385 ambiguous, where this string can be lexed as "?++"/"x" or "?"/"++x"; it requires scanning386 a head 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. 387 384 */ 388 385 {op_unary}"?"(({op_unary_pre_post}|"[?]")|({op_binary_over}"?")) { 389 390 391 392 393 394 395 396 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 */ 400 397 . { printf("unknown character(s):\"%s\" on line %d\n", yytext, yylineno); } 401 398 402 399 %% 403 400 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 ############################################################################### 6 16 7 17 YACC=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 1 16 #include "parseutility.h" 2 17 #include "SynTree/Type.h" 3 18 #include "SynTree/Expression.h" 4 19 20 Expression *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 } 5 26 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 3 18 4 19 #include "SynTree/SynTree.h" … … 6 21 Expression *notZeroExpr( Expression *orig ); 7 22 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 25 25 #include "utility.h" 26 26 27 extern bool resolve Verbose;28 #define PRINT( text ) if ( resolve Verbose) { text }27 extern bool resolvep; 28 #define PRINT( text ) if ( resolvep ) { text } 29 29 //#define DEBUG_COST 30 30 -
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 1 17 CC := @CFA_BINDIR@/cfa 2 CFLAGS = -g -Wall -W unused-function -MMD18 CFLAGS = -g -Wall -Wno-unused-function -MMD 3 19 MAKEFILE_NAME = ${firstword ${MAKEFILE_LIST}} # makefile name 4 20 -
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 1 16 #include <iostream> 2 17 #include <fstream> 3 #include <iterator> 4 #include <algorithm> 18 #include <cstdlib> 5 19 #include <cstdio> 20 #include <getopt.h> 6 21 #include "Parser/Parser.h" 7 22 #include "Parser/ParseNode.h" … … 31 46 #include "SemanticError.h" 32 47 #include "UnimplementedError.h" 33 #include "utility.h"34 48 35 49 #include "../config.h" … … 37 51 using namespace std; 38 52 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; 53 bool 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 68 enum { Ast, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Prototypes, Resolver, Symbol, Parse, }; 69 70 static 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 }; 47 83 48 84 int 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 ); 199 225 200 Parser::get_parser().parse( input );201 if ( debugp || Parser::get_parser().get_parseStatus() != 0 ) {202 203 } // if204 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 ); 205 231 206 if ( treep ) {207 208 209 210 } // if211 212 buildList( Parser::get_parser().get_parseTree(), translationUnit );213 214 Parser::get_parser().freeTree();215 if ( astp ) {216 217 218 } // if219 220 if ( manglep ) {221 222 223 224 225 } // if226 227 if ( symtabp ) {228 229 230 } // if231 232 if ( validp ) {233 234 235 236 } // if237 238 if ( exprp ) {239 240 241 242 243 244 245 246 } // if247 248 if ( codegenp ) {249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 // add the assignment statement after the275 // initialization of a type parameter276 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 306 } // if307 308 309 310 311 312 e.print( cout );313 if ( output != &std::cout ) {314 315 } // if316 return 1;317 318 std::cout << "Sorry, " << e.get_what() << " is not currently implemented" << std::endl;319 if ( output != &std::cout ) {320 321 } // if322 return 1;323 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 328 } // if329 return 1;330 331 332 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; 333 359 } // main 334 360 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 } // if344 345 if ( ! (ret = fopen(full_name.c_str(), "r" ) ) )346 return fopen(name.c_str(), "r" ); // trying current directory347 else348 return ret;349 } // open_prelude350 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 } // if360 361 if ( ! (ret = fopen(full_name, "r" ) ) )362 return fopen(name, "r" ); // trying current directory363 else364 return ret;365 } // open_builtins366 367 361 // Local Variables: // 368 // compile-command: "make" // 362 // tab-width: 4 // 363 // mode: c++ // 364 // compile-command: "make install" // 369 365 // End: //
Note: See TracChangeset
for help on using the changeset viewer.