acc_specification: acc_declare
                 | acc_routine
                 ;
acc_directive: acc_region
             | acc_end_region      
             | acc_checksection
             | acc_end_checksection
             | acc_get_actual
             | acc_actual 
	     ;

acc_region: ACC_REGION end_spec  opt_clause 
             {  $$ = get_bfnd(fi,ACC_REGION_DIR,SMNULL,$3,LLNULL,LLNULL);}
             ;

acc_checksection: ACC_CHECKSECTION end_spec 
             {  $$ = get_bfnd(fi,ACC_CHECKSECTION_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
             ;

acc_get_actual:  ACC_GET_ACTUAL end_spec LEFTPAR acc_var_list RIGHTPAR
             {  $$ = get_bfnd(fi,ACC_GET_ACTUAL_DIR,SMNULL,$4,LLNULL,LLNULL);}
              |  ACC_GET_ACTUAL end_spec LEFTPAR RIGHTPAR
             {  $$ = get_bfnd(fi,ACC_GET_ACTUAL_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
              |  ACC_GET_ACTUAL end_spec 
             {  $$ = get_bfnd(fi,ACC_GET_ACTUAL_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
             ;

acc_actual:     ACC_ACTUAL end_spec LEFTPAR acc_var_list RIGHTPAR
             {  $$ = get_bfnd(fi,ACC_ACTUAL_DIR,SMNULL,$4,LLNULL,LLNULL);}
          |   ACC_ACTUAL end_spec LEFTPAR RIGHTPAR
             {  $$ = get_bfnd(fi,ACC_ACTUAL_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
          |   ACC_ACTUAL end_spec 
             {  $$ = get_bfnd(fi,ACC_ACTUAL_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
             ;

opt_clause:  needkeyword keywordoff
              { $$ = LLNULL;}
          |  acc_clause_list
              { $$ = $1; }
          ;

acc_clause_list:   acc_clause
	          { $$ = set_ll_list($1,LLNULL,EXPR_LIST); }
               | acc_clause_list COMMA acc_clause
	          { $$ = set_ll_list($1,$3,EXPR_LIST); }	
               ;

acc_clause:    needkeyword data_clause
               { $$ = $2;}

             | needkeyword async_clause
               { $$ = $2;}
               
             | needkeyword targets_clause
               { $$ = $2;}                   
             ;


data_clause:   INOUT   LEFTPAR acc_var_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_INOUT_OP,$3,LLNULL,SMNULL);}
             | IN      LEFTPAR acc_var_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_IN_OP,$3,LLNULL,SMNULL);}
             | OUT     LEFTPAR acc_var_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_OUT_OP,$3,LLNULL,SMNULL);}
             | ACC_LOCAL   LEFTPAR acc_var_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_LOCAL_OP,$3,LLNULL,SMNULL);}             
             | ACC_INLOCAL LEFTPAR acc_var_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_INLOCAL_OP,$3,LLNULL,SMNULL);}             
             ;

targets_clause:   ACC_TARGETS LEFTPAR computer_list RIGHTPAR
               { $$ = make_llnd(fi,ACC_TARGETS_OP,$3,LLNULL,SMNULL);}
             ;

async_clause:   ACC_ASYNC             
               { $$ = make_llnd(fi,ACC_ASYNC_OP,LLNULL,LLNULL,SMNULL);}
             ;


acc_var_list: variable_list
              { $$ = $1;}
            ;

computer_list:   computer
	       { $$ = set_ll_list($1,LLNULL,EXPR_LIST); }
             | computer_list COMMA computer
	       { $$ = set_ll_list($1,$3,EXPR_LIST); }	
             ;

computer:       needkeyword ACC_HOST
              { $$ = make_llnd(fi,ACC_HOST_OP, LLNULL,LLNULL,SMNULL);}
             |  needkeyword ACC_CUDA
              { $$ = make_llnd(fi,ACC_CUDA_OP, LLNULL,LLNULL,SMNULL);}
             ;

acc_end_region: ACC_END_REGION
              {  $$ = get_bfnd(fi,ACC_END_REGION_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
              ;
     
acc_end_checksection: ACC_END_CHECKSECTION
              {  $$ = get_bfnd(fi,ACC_END_CHECKSECTION_DIR,SMNULL,LLNULL,LLNULL,LLNULL);}
              ;     

acc_declare: ACC_DECLARE in_dcl opt_double_colon acc_declare_list
	   {
	      $$ = get_bfnd(fi,ACC_DECLARE_DIR, SMNULL, $4, LLNULL, LLNULL);
           }
           ;
acc_declare_list: declare_var
                  { $$ = make_llnd(fi,EXPR_LIST, $1, LLNULL, SMNULL); }
	        | acc_declare_list COMMA declare_var
                  { $$ = set_ll_list($1, $3, EXPR_LIST); }
	        ;

declare_var: name
           {
              PTR_SYMB s;
              s = make_scalar($1,TYNULL,LOCAL);
              if((s->attr & PROCESSORS_BIT) ||(s->attr & TASK_BIT)  || (s->attr & TEMPLATE_BIT) || (s->attr & ALIGN_BIT) || (s->attr & DISTRIBUTE_BIT) || (s->attr & DYNAMIC_BIT) || (s->attr & HEAP_BIT)|| (s->attr & DVM_POINTER_BIT) || (s->attr & INHERIT_BIT) ||(s->attr & SHADOW_BIT)) 
                errstr("Inconsistent declaration of identifier  %s", s->ident, 16);	
	      $$ = make_llnd(fi,VAR_REF, LLNULL, LLNULL, s); 
           }
           ;
        
acc_routine: ACC_ROUTINE in_dcl opt_routine_clauses 
             {  $$ = get_bfnd(fi,ACC_ROUTINE_DIR,SMNULL,$3,LLNULL,LLNULL);} 
           ;

opt_routine_clauses:
                     {  $$ = LLNULL;}
                   | routine_clause_list
                     { $$ = $1;}
                   ;

routine_clause_list: routine_clause
	             { $$ = set_ll_list($1,LLNULL,EXPR_LIST); }
                   | routine_clause_list routine_clause
	           { $$ = set_ll_list($1,$2,EXPR_LIST); }	
                   ;
           
routine_clause: COMMA needkeyword PRIVATE LEFTPAR acc_declare_list RIGHTPAR
                    { $$ = make_llnd(fi,ACC_PRIVATE_OP,$5,LLNULL,SMNULL);}  
              | COMMA needkeyword targets_clause
                    { $$ = $3;} 
              ;
