// // 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.h -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 13:28:16 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Thu Feb 9 14:45:28 2017 // Update Count : 658 // #ifndef PARSENODE_H #define PARSENODE_H #include #include #include #include #include "Parser/LinkageSpec.h" #include "SynTree/Type.h" #include "SynTree/Expression.h" #include "SynTree/Statement.h" #include "SynTree/Label.h" #include "Common/utility.h" #include "Common/UniqueName.h" class StatementNode; class CompoundStmtNode; class DeclarationNode; class ExpressionNode; class InitializerNode; class Attribute; //############################################################################## extern char* yyfilename; extern int yylineno; class ParseNode { public: ParseNode() {}; virtual ~ParseNode() { delete next; delete name; }; virtual ParseNode * clone() const = 0; ParseNode * get_next() const { return next; } ParseNode * set_next( ParseNode * newlink ) { next = newlink; return this; } ParseNode * get_last() { ParseNode * current; for ( current = this; current->get_next() != nullptr; current = current->get_next() ); return current; } ParseNode * set_last( ParseNode * newlast ) { if ( newlast != nullptr ) get_last()->set_next( newlast ); return this; } virtual void print( std::ostream &os, int indent = 0 ) const {} virtual void printList( std::ostream &os, int indent = 0 ) const {} static int indent_by; ParseNode * next = nullptr; std::string * name = nullptr; CodeLocation location = { yyfilename, yylineno }; }; // ParseNode //############################################################################## class InitializerNode : public ParseNode { public: InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr ); InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr ); ~InitializerNode(); virtual InitializerNode * clone() const { assert( false ); return nullptr; } ExpressionNode * get_expression() const { return expr; } InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; } ExpressionNode * get_designators() const { return designator; } InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; } bool get_maybeConstructed() const { return maybeConstructed; } InitializerNode * next_init() const { return kids; } void print( std::ostream &os, int indent = 0 ) const; void printOneLine( std::ostream & ) const; virtual Initializer * build() const; private: ExpressionNode * expr; bool aggregate; ExpressionNode * designator; // may be list InitializerNode * kids; bool maybeConstructed; }; // InitializerNode //############################################################################## class ExpressionNode final : public ParseNode { public: ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {} ExpressionNode( const ExpressionNode &other ); virtual ~ExpressionNode() {} virtual ExpressionNode * clone() const { return expr ? new ExpressionNode( expr->clone() ) : nullptr; } bool get_extension() const { return extension; } ExpressionNode * set_extension( bool exten ) { extension = exten; return this; } virtual void print( std::ostream &os, int indent = 0 ) const override {} void printOneLine( std::ostream &os, int indent = 0 ) const {} template bool isExpressionType() const { return nullptr != dynamic_cast(expr.get()); } Expression * build() const { return const_cast(this)->expr.release(); } private: bool extension = false; std::unique_ptr expr; }; // ExpressionNode template< typename T > struct maybeBuild_t< Expression, T > { static inline Expression * doit( const T * orig ) { if ( orig ) { Expression * p = orig->build(); p->set_extension( orig->get_extension() ); return p; } else { return nullptr; } // if } }; enum class OperKinds { // diadic SizeOf, AlignOf, OffsetOf, Plus, Minus, Mul, Div, Mod, Or, And, BitOr, BitAnd, Xor, Cast, LShift, RShift, LThan, GThan, LEThan, GEThan, Eq, Neq, Assign, AtAssn, MulAssn, DivAssn, ModAssn, PlusAssn, MinusAssn, LSAssn, RSAssn, AndAssn, ERAssn, OrAssn, Index, Range, // monadic UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress, Ctor, Dtor, }; // OperKinds struct LabelNode { std::list< Label > labels; }; Expression * build_constantInteger( const std::string &str ); Expression * build_constantFloat( const std::string &str ); Expression * build_constantChar( const std::string &str ); Expression * build_constantZeroOne( const std::string &str ); ConstantExpr * build_constantStr( const std::string &str ); Expression * build_field_name_FLOATINGconstant( const std::string & str ); Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ); Expression * build_field_name_REALFRACTIONconstant( const std::string & str ); Expression * build_field_name_REALDECIMALconstant( const std::string & str ); NameExpr * build_varref( const std::string * name, bool labelp = false ); Expression * build_typevalue( DeclarationNode * decl ); Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ); Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ); Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ); Expression * build_addressOf( ExpressionNode * expr_node ); Expression * build_sizeOfexpr( ExpressionNode * expr_node ); Expression * build_sizeOftype( DeclarationNode * decl_node ); Expression * build_alignOfexpr( ExpressionNode * expr_node ); Expression * build_alignOftype( DeclarationNode * decl_node ); Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ); Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 ); Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ); Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ); Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ); Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ); Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ); Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ); Expression * build_comma( ExpressionNode * expr_node1, ExpressionNode * expr_node2 ); Expression * build_attrexpr( NameExpr * var, ExpressionNode * expr_node ); Expression * build_attrtype( NameExpr * var, DeclarationNode * decl_node ); Expression * build_tuple( ExpressionNode * expr_node = nullptr ); Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ); Expression * build_range( ExpressionNode * low, ExpressionNode * high ); Expression * build_asmexpr( ExpressionNode * inout, ConstantExpr * constraint, ExpressionNode * operand ); Expression * build_valexpr( StatementNode * s ); Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ); //############################################################################## struct TypeData; class DeclarationNode : public ParseNode { public: // These must remain in the same order as the corresponding DeclarationNode names. // enum StorageClass { Extern, Static, Auto, Register, NoStorageClass }; // enum FunctionSpec { Inline, Fortran, Noreturn, NoFunctionSpec }; // enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, Threadlocal, Mutex, NoQualifier }; enum StorageClass { Extern, Static, Auto, Register, Inline, Fortran, Noreturn, Threadlocal, NoStorageClass, }; enum Qualifier { Const, Restrict, Volatile, Lvalue, Atomic, NoQualifier }; enum BasicType { Void, Bool, Char, Int, Float, Double, LongDouble, NoBasicType }; enum ComplexType { Complex, Imaginary, NoComplexType }; enum Signedness { Signed, Unsigned, NoSignedness }; enum Length { Short, Long, LongLong, NoLength }; enum Aggregate { Struct, Union, Trait, NoAggregate }; enum TypeClass { Otype, Dtype, Ftype, Ttype, NoTypeClass }; enum BuiltinType { Valist, Zero, One, NoBuiltinType }; static const char * storageName[]; static const char * qualifierName[]; static const char * basicTypeName[]; static const char * complexTypeName[]; static const char * signednessName[]; static const char * lengthName[]; static const char * aggregateName[]; static const char * typeClassName[]; static const char * builtinTypeName[]; static DeclarationNode * newFunction( std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body, bool newStyle = false ); static DeclarationNode * newQualifier( Qualifier ); static DeclarationNode * newForall( DeclarationNode * ); static DeclarationNode * newStorageClass( StorageClass ); static DeclarationNode * newBasicType( BasicType ); static DeclarationNode * newComplexType( ComplexType ); static DeclarationNode * newSignedNess( Signedness sn ); static DeclarationNode * newLength( Length lnth ); static DeclarationNode * newBuiltinType( BuiltinType ); static DeclarationNode * newFromTypedef( std::string * ); static DeclarationNode * newAggregate( Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ); static DeclarationNode * newEnum( std::string * name, DeclarationNode * constants ); static DeclarationNode * newEnumConstant( std::string * name, ExpressionNode * constant ); static DeclarationNode * newName( std::string * ); static DeclarationNode * newFromTypeGen( std::string *, ExpressionNode * params ); static DeclarationNode * newTypeParam( TypeClass, std::string * ); static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts ); static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params ); static DeclarationNode * newTypeDecl( std::string * name, DeclarationNode * typeParams ); static DeclarationNode * newPointer( DeclarationNode * qualifiers ); static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic ); static DeclarationNode * newVarArray( DeclarationNode * qualifiers ); static DeclarationNode * newBitfield( ExpressionNode * size ); static DeclarationNode * newTuple( DeclarationNode * members ); static DeclarationNode * newTypeof( ExpressionNode * expr ); static DeclarationNode * newAttr( std::string *, ExpressionNode * expr ); // @ attributes static DeclarationNode * newAttr( std::string *, DeclarationNode * type ); // @ attributes static DeclarationNode * newAttribute( std::string *, ExpressionNode * expr = nullptr ); // gcc attributes static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement DeclarationNode(); ~DeclarationNode(); DeclarationNode * clone() const; DeclarationNode * addQualifiers( DeclarationNode * ); void checkQualifiers( const TypeData *, const TypeData * ); void checkStorageClasses( DeclarationNode * ); DeclarationNode * copyStorageClasses( DeclarationNode * ); DeclarationNode * addType( DeclarationNode * ); DeclarationNode * addTypedef(); DeclarationNode * addAssertions( DeclarationNode * ); DeclarationNode * addName( std::string * ); DeclarationNode * addAsmName( DeclarationNode * ); DeclarationNode * addBitfield( ExpressionNode * size ); DeclarationNode * addVarArgs(); DeclarationNode * addFunctionBody( StatementNode * body ); DeclarationNode * addOldDeclList( DeclarationNode * list ); DeclarationNode * setBase( TypeData * newType ); DeclarationNode * copyAttribute( DeclarationNode * attr ); DeclarationNode * addPointer( DeclarationNode * qualifiers ); DeclarationNode * addArray( DeclarationNode * array ); DeclarationNode * addNewPointer( DeclarationNode * pointer ); DeclarationNode * addNewArray( DeclarationNode * array ); DeclarationNode * addParamList( DeclarationNode * list ); DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions DeclarationNode * addInitializer( InitializerNode * init ); DeclarationNode * cloneType( std::string * newName ); DeclarationNode * cloneBaseType( DeclarationNode * newdecl ); DeclarationNode * appendList( DeclarationNode * node ) { return (DeclarationNode *)set_last( node ); } virtual void print( std::ostream &os, int indent = 0 ) const override; virtual void printList( std::ostream &os, int indent = 0 ) const override; Declaration * build() const; ::Type * buildType() const; bool get_hasEllipsis() const; LinkageSpec::Spec get_linkage() const { return linkage; } DeclarationNode * extractAggregate() const; bool has_enumeratorValue() const { return (bool)enumeratorValue; } ExpressionNode * consume_enumeratorValue() const { return const_cast(this)->enumeratorValue.release(); } bool get_extension() const { return extension; } DeclarationNode * set_extension( bool exten ) { extension = exten; return this; } public: struct Variable_t { // const std::string * name; DeclarationNode::TypeClass tyClass; DeclarationNode * assertions; }; Variable_t variable; struct Attr_t { // const std::string * name; ExpressionNode * expr; DeclarationNode * type; }; Attr_t attr; BuiltinType builtin; TypeData * type; StorageClass storageClass; ExpressionNode * bitfieldWidth; bool isInline, isNoreturn; std::unique_ptr enumeratorValue; bool hasEllipsis; LinkageSpec::Spec linkage; ConstantExpr *asmName; std::list< Attribute * > attributes; InitializerNode * initializer; bool extension = false; std::string error; StatementNode * asmStmt; static UniqueName anonymous; }; // DeclarationNode Type * buildType( TypeData * type ); static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) { Type* ret = orig ? orig->buildType() : nullptr; delete orig; return ret; } //############################################################################## class StatementNode final : public ParseNode { public: StatementNode() { stmt = nullptr; } StatementNode( Statement * stmt ) : stmt( stmt ) {} StatementNode( DeclarationNode * decl ); virtual ~StatementNode() {} virtual StatementNode * clone() const final { assert( false ); return nullptr; } Statement * build() const { return const_cast(this)->stmt.release(); } virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) { stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} ); delete attr; delete name; return this; } virtual StatementNode * append_last_case( StatementNode * ); virtual void print( std::ostream &os, int indent = 0 ) const override {} virtual void printList( std::ostream &os, int indent = 0 ) const override {} private: std::unique_ptr stmt; }; // StatementNode Statement * build_expr( ExpressionNode * ctl ); struct ForCtl { ForCtl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) : init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {} ForCtl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) : init( new StatementNode( decl ) ), condition( condition ), change( change ) {} StatementNode * init; ExpressionNode * condition; ExpressionNode * change; }; Statement * build_if( ExpressionNode * ctl, StatementNode * then_stmt, StatementNode * else_stmt ); Statement * build_switch( ExpressionNode * ctl, StatementNode * stmt ); Statement * build_case( ExpressionNode * ctl ); Statement * build_default(); Statement * build_while( ExpressionNode * ctl, StatementNode * stmt, bool kind = false ); Statement * build_for( ForCtl * forctl, StatementNode * stmt ); Statement * build_branch( BranchStmt::Type kind ); Statement * build_branch( std::string * identifier, BranchStmt::Type kind ); Statement * build_computedgoto( ExpressionNode * ctl ); Statement * build_return( ExpressionNode * ctl ); Statement * build_throw( ExpressionNode * ctl ); Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt ); Statement * build_catch( DeclarationNode * decl, StatementNode * stmt, bool catchAny = false ); Statement * build_finally( StatementNode * stmt ); Statement * build_compound( StatementNode * first ); Statement * build_asmstmt( bool voltile, ConstantExpr * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr ); //############################################################################## template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args > void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > &outputList ) { SemanticError errors; std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList ); const NodeType * cur = firstNode; while ( cur ) { try { SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) ); if ( result ) { result->location = cur->location; * out++ = result; } // if } catch( SemanticError &e ) { e.set_location( cur->location ); errors.append( e ); } // try cur = dynamic_cast< NodeType * >( cur->get_next() ); } // while if ( ! errors.isEmpty() ) { throw errors; } // if } // in DeclarationNode.cc void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList ); void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList ); void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList ); template< typename SynTreeType, typename NodeType > void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > &outputList ) { buildList(firstNode, outputList); delete firstNode; } // in ParseNode.cc std::ostream & operator<<( std::ostream & out, const ParseNode * node ); #endif // PARSENODE_H // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //