/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: chuck_parse.cpp// desc: chuck parser interface (using flex and bison)//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2002 - original in chuck_main.cpp// Autumn 2005 - this file//-----------------------------------------------------------------------------#include "chuck_parse.h"#include "chuck_errmsg.h"#include "util_string.h"#include "util_platforms.h" #include <string.h>#include <sys/stat.h>#if defined(__PLATFORM_WIN32__) #include "dirent_win32.h"#endif #include <string>using namespace std; // globalstatic std::string g_filename;// file to parsestatic FILE * g_fd2parse = NULL;// whether to auto closestatic t_CKBOOL g_fd2autoClose = FALSE;// clean up functionstatic void fd2parse_cleanup(); // external from lexerextern "C" { extern FILE * yyin;} //-----------------------------------------------------------------------------// name: chuck_parse()// desc: INPUT: chuck code (either from file or actual code) to be parsed// OUTPUT: abstract syntax tree representation of the code//-----------------------------------------------------------------------------t_CKBOOL chuck_parse( const std::string & fname, const std::string & codeLiteral ){ // return value t_CKBOOL ret = FALSE; // file descriptor | normally NULL unless g_fd2parse is set FILE * fd = g_fd2parse; // our own lexer/parser buffer YY_BUFFER_STATE yyCodeBuffer = NULL; // check for conflict if( fd && codeLiteral != "" ) { CK_FPRINTF_STDERR( "[chuck](parser): (internal) code and FILE descriptor both present!\n" ); CK_FPRINTF_STDERR( "[chuck](parser): |- ignoring FILE descriptor...\n" ); } // copy it g_filename = fname; // if actual code was passed in if( codeLiteral != "" ) { // clean lexer yyrestart( NULL ); // load string (yy_scan_string will copy the C string) yyCodeBuffer = yy_scan_string( codeLiteral.c_str() ); // if could load if( !yyCodeBuffer ) goto cleanup; } else { // test it if( !fd ) { // open, could potentially change g_filename fd = ck_openFileAutoExt( g_filename, ".ck" ); // check file open result if( !fd ) // if couldn't open { g_filename = fname; } // revert filename else if( ck_isdir(g_filename) ) // check for directory; if so, clean up { EM_error2( 0, "cannot parse file: '%s' is a directory", mini(fname.c_str()) ); goto cleanup; } } // if still none if( !fd ) { EM_error2( 0, "no such file: '%s'", mini(fname.c_str()) ); goto cleanup; } // set to beginning0 else fseek( fd, 0, SEEK_SET ); // reset yyin to fd yyrestart( fd ); // set to initial condition | 1.5.0.5 (ge) added yyinitial(); // check if( yyin == NULL ) goto cleanup; } // reset if( EM_reset( g_filename.c_str() ) == FALSE ) goto cleanup; // TODO: clean g_program g_program = NULL; // parse if( !(yyparse() == 0) ) goto cleanup; // flag success ret = TRUE; cleanup: // clean up the file descriptor if( fd ) { // check fd2parse if( g_fd2parse ) { fd2parse_cleanup(); fd = NULL; } else { fclose( fd ); fd = NULL; } } // set to NULL | 1.5.0.5 (ge) added to reset yyin yyin = NULL; // clean up lexer buffer, if we used one if( yyCodeBuffer ) { yy_delete_buffer( yyCodeBuffer ); yyCodeBuffer = NULL; } return ret;} //------------------------------------------------------------------------------// name: fd2parse_cleanup()// desc: clean up fd2parse//------------------------------------------------------------------------------void fd2parse_cleanup(){ // check if( g_fd2parse && g_fd2autoClose ) { fclose( g_fd2parse ); } // reset g_fd2parse = NULL; g_fd2autoClose = FALSE;} //------------------------------------------------------------------------------// name: fd2parse_set()// desc: special FILE input mode | added 1.5.0.5 (ge)// set an already open FILE descriptor `fd` for one time use// by the next call to go(), which will use `fd` as the input// to the parser (NOTE in any invocation of go(), `codeLiteral`// and `fd` should not both be non-empty, otherwise a warning// will be output and the `codeLiteral` will take precedence// and the `fd` will be cleaned up and skipped// MEMORY: if `autoClose` is true, the compiler will automatically// call fclose() on `fd` on the next call to go(), regardless of// the aforementioned conflict with `codeLiteral`//------------------------------------------------------------------------------void fd2parse_set( FILE * fd, t_CKBOOL autoClose ){ // clean up fd2parse_cleanup(); // copy g_fd2parse = fd; g_fd2autoClose = autoClose;} //------------------------------------------------------------------------------// name: reset_parse()// desc: ...//------------------------------------------------------------------------------void reset_parse( ){ // empty file name EM_change_file( NULL );} //-----------------------------------------------------------------------------// name: parseLine()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL SyntaxQuery::parseLine( const std::string & line, SyntaxTokenList & tokens ){ // clear the token list tokens.howmany = 0; return TRUE;} //-----------------------------------------------------------------------------// absyn to string functions//-----------------------------------------------------------------------------#include "chuck_type.h"string absyn_exp2str( a_Exp exp, t_CKBOOL iterate = true );string absyn_binary2str( a_Exp_Binary binary );string absyn_unary2str( a_Exp_Unary unary );string absyn_op2str( ae_Operator op );string absyn_cast2str( a_Exp_Cast cast );string absyn_postfix2str( a_Exp_Postfix postfix );string absyn_dur2str( a_Exp_Dur dur );string absyn_primary2str( a_Exp_Primary primary );string absyn_array2str( a_Exp_Array array );string absyn_func_call2str( a_Exp_Func_Call func_call );string absyn_dot_member2str( a_Exp_Dot_Member dot_member );string absyn_exp_if2str( a_Exp_If exp_if );string absyn_decl2str( a_Exp_Decl decl ); //-----------------------------------------------------------------------------// name: absyn2str()// desc: convert abstract syntax exp to string//-----------------------------------------------------------------------------string absyn2str( a_Exp exp ){ return absyn_exp2str( exp ) + ";";} //-----------------------------------------------------------------------------// name: name_demangle()// desc: demangle chuck function names// e.g., input: "version@0@Machine" output: "version"//-----------------------------------------------------------------------------string name_demangle( const string & name ){ // find the first @ size_t pos = name.find_first_of('@'); // if found, substring return ( pos != string::npos ) ? name.substr(0,pos) : name;} //-----------------------------------------------------------------------------// name: absyn_exp2str()// desc: convert abstract syntax exp to string//-----------------------------------------------------------------------------string absyn_exp2str( a_Exp exp, t_CKBOOL iterate ){ string str = ""; // loop over while( exp ) { switch( exp->s_type ) { case ae_exp_binary: str += absyn_binary2str( &exp->binary ); break; case ae_exp_unary: str += absyn_unary2str( &exp->unary ); break; case ae_exp_cast: str += absyn_cast2str( &exp->cast ); break; case ae_exp_postfix: str += absyn_postfix2str( &exp->postfix ); break; case ae_exp_dur: str += absyn_dur2str( &exp->dur ); break; case ae_exp_primary: str += absyn_primary2str( &exp->primary ); break; case ae_exp_array: str += absyn_array2str( &exp->array ); break; case ae_exp_func_call: str += absyn_func_call2str( &exp->func_call ); break; case ae_exp_dot_member: str += absyn_dot_member2str( &exp->dot_member ); break; case ae_exp_if: str += absyn_exp_if2str( &exp->exp_if ); break; case ae_exp_decl: str += absyn_decl2str( &exp->decl ); break; default: return ""; } // implicit cast if( exp->cast_to != NULL ) break; // break if( !iterate ) break; // next exp = exp->next; // if more if( exp ) str += ","; } return str;} //-----------------------------------------------------------------------------// name: absyn_op2str()// desc: convert abstract syntax operator to string//-----------------------------------------------------------------------------string absyn_op2str( ae_Operator op ){ string str; // get operation string switch( op ) { case ae_op_plus: str = "+"; break; case ae_op_plus_chuck: str = "+=>"; break; case ae_op_minus: str = "-"; break; case ae_op_minus_chuck: str = "-=>"; break; case ae_op_times: str = "*"; break; case ae_op_times_chuck: str = "*=>"; break; case ae_op_divide: str = "/"; break; case ae_op_divide_chuck: str = "/=>"; break; case ae_op_s_or: str = "|"; break; case ae_op_s_or_chuck: str = "|=>"; break; case ae_op_s_and: str = "&"; break; case ae_op_s_and_chuck: str = "&=>"; break; case ae_op_shift_left: str = "<<"; break; case ae_op_shift_left_chuck: str = "<<=>"; break; case ae_op_shift_right: str = ">>"; break; case ae_op_shift_right_chuck: str = ">>=>"; break; case ae_op_percent: str = "%"; break; case ae_op_percent_chuck: str = "%=>"; break; case ae_op_s_xor: str = "^"; break; case ae_op_s_xor_chuck: str = "^=>"; break; case ae_op_chuck: str = "=>"; break; case ae_op_unchuck: str = "=<"; break; case ae_op_upchuck: str = "=^"; break; case ae_op_at_chuck: str = "@=>"; break; case ae_op_s_chuck: str = ""; break; case ae_op_eq: str = "=="; break; case ae_op_neq: str = "!="; break; case ae_op_lt: str = "<"; break; case ae_op_le: str = "<="; break; case ae_op_gt: str = ">"; break; case ae_op_ge: str = ">="; break; case ae_op_and: str = "&&"; break; case ae_op_or: str = "||"; break; case ae_op_arrow_left: str = "<-"; break; case ae_op_arrow_right: str = "->"; break; // unary case ae_op_plusplus: str = "++"; break; case ae_op_minusminus: str = "--"; break; case ae_op_tilda: str = "~"; break; case ae_op_exclamation: str = "!"; break; case ae_op_spork: str = "spork ~"; break; case ae_op_new: str = "new"; break; // not used case ae_op_typeof: str = "typeof"; break; case ae_op_sizeof: str = "sizeof"; break; default: str = "[OP]"; break; } return str;} //-----------------------------------------------------------------------------// name: absyn_binary2str()// desc: convert abstract syntax binary to string//-----------------------------------------------------------------------------string absyn_binary2str( a_Exp_Binary binary ){ string lhs = absyn_exp2str(binary->lhs); string op = absyn_op2str(binary->op); string rhs = absyn_exp2str(binary->rhs); // use paren? bool paren = false; // spacing? bool spacing = false; switch(binary->op) { case ae_op_plus_chuck: case ae_op_minus_chuck: case ae_op_times_chuck: case ae_op_divide_chuck: case ae_op_s_or_chuck: case ae_op_s_and_chuck: case ae_op_shift_left_chuck: case ae_op_shift_right_chuck: case ae_op_percent_chuck: case ae_op_s_xor_chuck: case ae_op_chuck: case ae_op_unchuck: case ae_op_upchuck: case ae_op_lt: case ae_op_gt: case ae_op_le: case ae_op_ge: case ae_op_at_chuck: paren = false; spacing = true; break; default: paren = true; spacing = false; break; } // (lhs OP rhs) string str = string(paren?"(":"") + lhs + (spacing?" ":"") + op + (spacing?" ":"") + rhs + (paren?")":""); // return return str;} //-----------------------------------------------------------------------------// name: absyn_unary2str()// desc: convert abstract syntax unary to string//-----------------------------------------------------------------------------string absyn_unary2str( a_Exp_Unary unary ){ string s; // check switch( unary->op ) { case ae_op_new: s = absyn_op2str(unary->op) + " " + unary->self->type->str(); break; default: s = absyn_op2str(unary->op) + " " + absyn_exp2str(unary->exp); break; } return s;}Lines 1–500 of 696. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_parse.cpp // desc: chuck parser interface (using flex and bison) // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Autumn 2002 - original in chuck_main.cpp // Autumn 2005 - this file //----------------------------------------------------------------------------- #include "chuck_parse.h" #include "chuck_errmsg.h" #include "util_string.h" #include "util_platforms.h" #include <string.h> #include <sys/stat.h> #if defined(__PLATFORM_WIN32__) #include "dirent_win32.h" #endif #include <string> using namespace std; // global static std::string g_filename; // file to parse static FILE * g_fd2parse = NULL; // whether to auto close static t_CKBOOL g_fd2autoClose = FALSE; // clean up function static void fd2parse_cleanup(); // external from lexer extern "C" { extern FILE * yyin; } //----------------------------------------------------------------------------- // name: chuck_parse() // desc: INPUT: chuck code (either from file or actual code) to be parsed // OUTPUT: abstract syntax tree representation of the code //----------------------------------------------------------------------------- t_CKBOOL chuck_parse( const std::string & fname, const std::string & codeLiteral ) { // return value t_CKBOOL ret = FALSE; // file descriptor | normally NULL unless g_fd2parse is set FILE * fd = g_fd2parse; // our own lexer/parser buffer YY_BUFFER_STATE yyCodeBuffer = NULL; // check for conflict if( fd && codeLiteral != "" ) { CK_FPRINTF_STDERR( "[chuck](parser): (internal) code and FILE descriptor both present!\n" ); CK_FPRINTF_STDERR( "[chuck](parser): |- ignoring FILE descriptor...\n" ); } // copy it g_filename = fname; // if actual code was passed in if( codeLiteral != "" ) { // clean lexer yyrestart( NULL ); // load string (yy_scan_string will copy the C string) yyCodeBuffer = yy_scan_string( codeLiteral.c_str() ); // if could load if( !yyCodeBuffer ) goto cleanup; } else { // test it if( !fd ) { // open, could potentially change g_filename fd = ck_openFileAutoExt( g_filename, ".ck" ); // check file open result if( !fd ) // if couldn't open { g_filename = fname; } // revert filename else if( ck_isdir(g_filename) ) // check for directory; if so, clean up { EM_error2( 0, "cannot parse file: '%s' is a directory", mini(fname.c_str()) ); goto cleanup; } } // if still none if( !fd ) { EM_error2( 0, "no such file: '%s'", mini(fname.c_str()) ); goto cleanup; } // set to beginning0 else fseek( fd, 0, SEEK_SET ); // reset yyin to fd yyrestart( fd ); // set to initial condition | 1.5.0.5 (ge) added yyinitial(); // check if( yyin == NULL ) goto cleanup; } // reset if( EM_reset( g_filename.c_str() ) == FALSE ) goto cleanup; // TODO: clean g_program g_program = NULL; // parse if( !(yyparse() == 0) ) goto cleanup; // flag success ret = TRUE; cleanup: // clean up the file descriptor if( fd ) { // check fd2parse if( g_fd2parse ) { fd2parse_cleanup(); fd = NULL; } else { fclose( fd ); fd = NULL; } } // set to NULL | 1.5.0.5 (ge) added to reset yyin yyin = NULL; // clean up lexer buffer, if we used one if( yyCodeBuffer ) { yy_delete_buffer( yyCodeBuffer ); yyCodeBuffer = NULL; } return ret; } //------------------------------------------------------------------------------ // name: fd2parse_cleanup() // desc: clean up fd2parse //------------------------------------------------------------------------------ void fd2parse_cleanup() { // check if( g_fd2parse && g_fd2autoClose ) { fclose( g_fd2parse ); } // reset g_fd2parse = NULL; g_fd2autoClose = FALSE; } //------------------------------------------------------------------------------ // name: fd2parse_set() // desc: special FILE input mode | added 1.5.0.5 (ge) // set an already open FILE descriptor `fd` for one time use // by the next call to go(), which will use `fd` as the input // to the parser (NOTE in any invocation of go(), `codeLiteral` // and `fd` should not both be non-empty, otherwise a warning // will be output and the `codeLiteral` will take precedence // and the `fd` will be cleaned up and skipped // MEMORY: if `autoClose` is true, the compiler will automatically // call fclose() on `fd` on the next call to go(), regardless of // the aforementioned conflict with `codeLiteral` //------------------------------------------------------------------------------ void fd2parse_set( FILE * fd, t_CKBOOL autoClose ) { // clean up fd2parse_cleanup(); // copy g_fd2parse = fd; g_fd2autoClose = autoClose; } //------------------------------------------------------------------------------ // name: reset_parse() // desc: ... //------------------------------------------------------------------------------ void reset_parse( ) { // empty file name EM_change_file( NULL ); } //----------------------------------------------------------------------------- // name: parseLine() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL SyntaxQuery::parseLine( const std::string & line, SyntaxTokenList & tokens ) { // clear the token list tokens.howmany = 0; return TRUE; } //----------------------------------------------------------------------------- // absyn to string functions //----------------------------------------------------------------------------- #include "chuck_type.h" string absyn_exp2str( a_Exp exp, t_CKBOOL iterate = true ); string absyn_binary2str( a_Exp_Binary binary ); string absyn_unary2str( a_Exp_Unary unary ); string absyn_op2str( ae_Operator op ); string absyn_cast2str( a_Exp_Cast cast ); string absyn_postfix2str( a_Exp_Postfix postfix ); string absyn_dur2str( a_Exp_Dur dur ); string absyn_primary2str( a_Exp_Primary primary ); string absyn_array2str( a_Exp_Array array ); string absyn_func_call2str( a_Exp_Func_Call func_call ); string absyn_dot_member2str( a_Exp_Dot_Member dot_member ); string absyn_exp_if2str( a_Exp_If exp_if ); string absyn_decl2str( a_Exp_Decl decl ); //----------------------------------------------------------------------------- // name: absyn2str() // desc: convert abstract syntax exp to string //----------------------------------------------------------------------------- string absyn2str( a_Exp exp ) { return absyn_exp2str( exp ) + ";"; } //----------------------------------------------------------------------------- // name: name_demangle() // desc: demangle chuck function names // e.g., input: "version@0@Machine" output: "version" //----------------------------------------------------------------------------- string name_demangle( const string & name ) { // find the first @ size_t pos = name.find_first_of('@'); // if found, substring return ( pos != string::npos ) ? name.substr(0,pos) : name; } //----------------------------------------------------------------------------- // name: absyn_exp2str() // desc: convert abstract syntax exp to string //----------------------------------------------------------------------------- string absyn_exp2str( a_Exp exp, t_CKBOOL iterate ) { string str = ""; // loop over while( exp ) { switch( exp->s_type ) { case ae_exp_binary: str += absyn_binary2str( &exp->binary ); break; case ae_exp_unary: str += absyn_unary2str( &exp->unary ); break; case ae_exp_cast: str += absyn_cast2str( &exp->cast ); break; case ae_exp_postfix: str += absyn_postfix2str( &exp->postfix ); break; case ae_exp_dur: str += absyn_dur2str( &exp->dur ); break; case ae_exp_primary: str += absyn_primary2str( &exp->primary ); break; case ae_exp_array: str += absyn_array2str( &exp->array ); break; case ae_exp_func_call: str += absyn_func_call2str( &exp->func_call ); break; case ae_exp_dot_member: str += absyn_dot_member2str( &exp->dot_member ); break; case ae_exp_if: str += absyn_exp_if2str( &exp->exp_if ); break; case ae_exp_decl: str += absyn_decl2str( &exp->decl ); break; default: return ""; } // implicit cast if( exp->cast_to != NULL ) break; // break if( !iterate ) break; // next exp = exp->next; // if more if( exp ) str += ","; } return str; } //----------------------------------------------------------------------------- // name: absyn_op2str() // desc: convert abstract syntax operator to string //----------------------------------------------------------------------------- string absyn_op2str( ae_Operator op ) { string str; // get operation string switch( op ) { case ae_op_plus: str = "+"; break; case ae_op_plus_chuck: str = "+=>"; break; case ae_op_minus: str = "-"; break; case ae_op_minus_chuck: str = "-=>"; break; case ae_op_times: str = "*"; break; case ae_op_times_chuck: str = "*=>"; break; case ae_op_divide: str = "/"; break; case ae_op_divide_chuck: str = "/=>"; break; case ae_op_s_or: str = "|"; break; case ae_op_s_or_chuck: str = "|=>"; break; case ae_op_s_and: str = "&"; break; case ae_op_s_and_chuck: str = "&=>"; break; case ae_op_shift_left: str = "<<"; break; case ae_op_shift_left_chuck: str = "<<=>"; break; case ae_op_shift_right: str = ">>"; break; case ae_op_shift_right_chuck: str = ">>=>"; break; case ae_op_percent: str = "%"; break; case ae_op_percent_chuck: str = "%=>"; break; case ae_op_s_xor: str = "^"; break; case ae_op_s_xor_chuck: str = "^=>"; break; case ae_op_chuck: str = "=>"; break; case ae_op_unchuck: str = "=<"; break; case ae_op_upchuck: str = "=^"; break; case ae_op_at_chuck: str = "@=>"; break; case ae_op_s_chuck: str = ""; break; case ae_op_eq: str = "=="; break; case ae_op_neq: str = "!="; break; case ae_op_lt: str = "<"; break; case ae_op_le: str = "<="; break; case ae_op_gt: str = ">"; break; case ae_op_ge: str = ">="; break; case ae_op_and: str = "&&"; break; case ae_op_or: str = "||"; break; case ae_op_arrow_left: str = "<-"; break; case ae_op_arrow_right: str = "->"; break; // unary case ae_op_plusplus: str = "++"; break; case ae_op_minusminus: str = "--"; break; case ae_op_tilda: str = "~"; break; case ae_op_exclamation: str = "!"; break; case ae_op_spork: str = "spork ~"; break; case ae_op_new: str = "new"; break; // not used case ae_op_typeof: str = "typeof"; break; case ae_op_sizeof: str = "sizeof"; break; default: str = "[OP]"; break; } return str; } //----------------------------------------------------------------------------- // name: absyn_binary2str() // desc: convert abstract syntax binary to string //----------------------------------------------------------------------------- string absyn_binary2str( a_Exp_Binary binary ) { string lhs = absyn_exp2str(binary->lhs); string op = absyn_op2str(binary->op); string rhs = absyn_exp2str(binary->rhs); // use paren? bool paren = false; // spacing? bool spacing = false; switch(binary->op) { case ae_op_plus_chuck: case ae_op_minus_chuck: case ae_op_times_chuck: case ae_op_divide_chuck: case ae_op_s_or_chuck: case ae_op_s_and_chuck: case ae_op_shift_left_chuck: case ae_op_shift_right_chuck: case ae_op_percent_chuck: case ae_op_s_xor_chuck: case ae_op_chuck: case ae_op_unchuck: case ae_op_upchuck: case ae_op_lt: case ae_op_gt: case ae_op_le: case ae_op_ge: case ae_op_at_chuck: paren = false; spacing = true; break; default: paren = true; spacing = false; break; } // (lhs OP rhs) string str = string(paren?"(":"") + lhs + (spacing?" ":"") + op + (spacing?" ":"") + rhs + (paren?")":""); // return return str; } //----------------------------------------------------------------------------- // name: absyn_unary2str() // desc: convert abstract syntax unary to string //----------------------------------------------------------------------------- string absyn_unary2str( a_Exp_Unary unary ) { string s; // check switch( unary->op ) { case ae_op_new: s = absyn_op2str(unary->op) + " " + unary->self->type->str(); break; default: s = absyn_op2str(unary->op) + " " + absyn_exp2str(unary->exp); break; } return s; }