// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // ParseNode.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 13:26:29 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Sun Jul 24 02:17:01 2016 // Update Count : 90 // #include #include "ParseNode.h" using namespace std; // Difficult to separate extra parts of constants during lexing because actions are not allow in the middle of patterns: // // prefix action constant action suffix // // Alternatively, breaking a pattern using BEGIN does not work if the following pattern can be empty: // // constant BEGIN CONT ... // (...)? BEGIN 0 ... // possible empty suffix // // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their // type. static Type::Qualifiers emptyQualifiers; // no qualifiers on constants static inline bool checkU( char c ) { return c == 'u' || c == 'U'; } static inline bool checkL( char c ) { return c == 'l' || c == 'L'; } static inline bool checkF( char c ) { return c == 'f' || c == 'F'; } static inline bool checkD( char c ) { return c == 'd' || c == 'D'; } static inline bool checkI( char c ) { return c == 'i' || c == 'I'; } static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } ConstantNode *makeConstantInteger( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt }, { BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt }, }; bool dec = true, Unsigned = false; // decimal, unsigned constant int size; // 0 => int, 1 => long, 2 => long long unsigned long long v; // converted integral value size_t last = str.length() - 1; // last character of constant if ( str[0] == '0' ) { // octal/hex constant ? dec = false; if ( last != 0 && checkX( str[1] ) ) { // hex constant ? sscanf( (char *)str.c_str(), "%llx", &v ); //printf( "%llx %llu\n", v, v ); } else { // octal constant sscanf( (char *)str.c_str(), "%llo", &v ); //printf( "%llo %llu\n", v, v ); } // if } else { // decimal constant ? sscanf( (char *)str.c_str(), "%llu", &v ); //printf( "%llu %llu\n", v, v ); } // if if ( v <= INT_MAX ) { // signed int size = 0; } else if ( v <= UINT_MAX && ! dec ) { // unsigned int size = 0; Unsigned = true; // unsigned } else if ( v <= LONG_MAX ) { // signed long int size = 1; } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int size = 1; Unsigned = true; // unsigned long int } else if ( v <= LLONG_MAX ) { // signed long long int size = 2; } else { // unsigned long long int size = 2; Unsigned = true; // unsigned long long int } // if if ( checkU( str[last] ) ) { // suffix 'u' ? Unsigned = true; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'l' ? size = 1; if ( last > 1 && checkL( str[last - 2] ) ) { // suffix 'll' ? size = 2; } // if } // if } else if ( checkL( str[ last ] ) ) { // suffix 'l' ? size = 1; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'll' ? size = 2; if ( last > 1 && checkU( str[last - 2] ) ) { // suffix 'u' ? Unsigned = true; } // if } else { if ( last > 0 && checkU( str[last - 1] ) ) { // suffix 'u' ? Unsigned = true; } // if } // if } // if return new ConstantNode( new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[Unsigned][size] ), str ), nullptr ) ); } // makeConstantInteger ConstantNode *makeConstantFloat( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::Float, BasicType::Double, BasicType::LongDouble }, { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex }, }; bool complx = false; // real, complex int size = 1; // 0 => float, 1 => double (default), 2 => long double // floating-point constant has minimum of 2 characters: 1. or .1 size_t last = str.length() - 1; if ( checkI( str[last] ) ) { // imaginary ? complx = true; last -= 1; // backup one character } // if if ( checkF( str[last] ) ) { // float ? size = 0; } else if ( checkD( str[last] ) ) { // double ? size = 1; } else if ( checkL( str[last] ) ) { // long double ? size = 2; } // if if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ? complx = true; } // if return new ConstantNode( new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[complx][size] ), str ), nullptr ) ); } // makeConstantFloat ConstantNode *makeConstantChar( std::string & str ) { return new ConstantNode( new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::Char ), str ), nullptr ) ); } // makeConstantChar ConstantNode *makeConstantStr( std::string & str ) { // string should probably be a primitive type ArrayType *at = new ArrayType( emptyQualifiers, new BasicType( emptyQualifiers, BasicType::Char ), new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::UnsignedInt ), toString( str.size()+1-2 ) ) ), // +1 for '\0' and -2 for '"' false, false ); return new ConstantNode( new ConstantExpr( Constant( at, str ), nullptr ) ); } // makeConstantStr // Builder int ParseNode::indent_by = 4; ParseNode::ParseNode() : next( 0 ) {}; ParseNode::ParseNode( const string *name ) : name( *name ), next( 0 ) { delete name; } ParseNode::ParseNode( const string &name ) : name( name ), next( 0 ) { } ParseNode::~ParseNode() { delete next; }; ParseNode *ParseNode::get_last() { ParseNode *current = this; while ( current->get_link() != 0 ) current = current->get_link(); return current; } ParseNode *ParseNode::set_link( ParseNode *next_ ) { if ( next_ != 0 ) get_last()->next = next_; return this; } void ParseNode::print( std::ostream &os, int indent ) const {} void ParseNode::printList( std::ostream &os, int indent ) const { print( os, indent ); if ( next ) { next->printList( os, indent ); } // if } ParseNode &ParseNode::operator,( ParseNode &p ) { set_link( &p ); return *this; } ParseNode *mkList( ParseNode &pn ) { // it just relies on `operator,' to take care of the "arguments" and provides a nice interface to an awful-looking // address-of, rendering, for example (StatementNode *)(&(*$5 + *$7)) into (StatementNode *)mkList(($5, $7)) // (although "nice" is probably not the word) return &pn; } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //