예제 #1
0
/**
 * Checks the progression of complex statements.
 * - checks for else after if
 * - checks for if after else
 * - checks for while after do
 * - checks for open brace in BRACE2 and BRACE_DO stages, inserts open VBRACE
 * - checks for open paren in PAREN1 and PAREN2 stages, complains
 *
 * @param frm  The parse frame
 * @param pc   The current chunk
 * @return     true - done with this chunk, false - keep processing
 */
static bool check_complex_statements(struct parse_frame *frm, chunk_t *pc)
{
   c_token_t parent;
   chunk_t   *vbrace;

   /* Turn an optional paren into either a real paren or a brace */
   if (frm->pse[frm->pse_tos].stage == BS_OP_PAREN1)
   {
      frm->pse[frm->pse_tos].stage = (pc->type != CT_PAREN_OPEN) ? BS_BRACE2 : BS_PAREN1;
   }

   /* Check for CT_ELSE after CT_IF */
   while (frm->pse[frm->pse_tos].stage == BS_ELSE)
   {
      if (pc->type == CT_ELSE)
      {
         /* Replace CT_IF with CT_ELSE on the stack & we are done */
         frm->pse[frm->pse_tos].type  = CT_ELSE;
         frm->pse[frm->pse_tos].stage = BS_ELSEIF;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      /* Remove the CT_IF and close the statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-IF-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   /* Check for CT_IF after CT_ELSE */
   if (frm->pse[frm->pse_tos].stage == BS_ELSEIF)
   {
      if (pc->type == CT_IF)
      {
         if (!cpd.settings[UO_indent_else_if].b ||
             !chunk_is_newline(chunk_get_prev_nc(pc)))
         {
            /* Replace CT_ELSE with CT_IF */
            pc->type = CT_ELSEIF;
            frm->pse[frm->pse_tos].type  = CT_ELSEIF;
            frm->pse[frm->pse_tos].stage = BS_PAREN1;
            return(true);
         }
      }

      /* Jump to the 'expecting brace' stage */
      frm->pse[frm->pse_tos].stage = BS_BRACE2;
   }

   /* Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH */
   while (frm->pse[frm->pse_tos].stage == BS_CATCH)
   {
      if ((pc->type == CT_CATCH) || (pc->type == CT_FINALLY))
      {
         /* Replace CT_TRY with CT_CATCH on the stack & we are done */
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = (pc->type == CT_CATCH) ? BS_OP_PAREN1 : BS_BRACE2;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      /* Remove the CT_TRY and close the statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-TRY-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   /* Check for CT_WHILE after the CT_DO */
   if (frm->pse[frm->pse_tos].stage == BS_WHILE)
   {
      if (pc->type == CT_WHILE)
      {
         pc->type = CT_WHILE_OF_DO;
         frm->pse[frm->pse_tos].type  = CT_WHILE_OF_DO; //CT_WHILE;
         frm->pse[frm->pse_tos].stage = BS_WOD_PAREN;
         return(true);
      }

      LOG_FMT(LWARN, "%s:%d Error: Expected 'while', got '%s'\n",
              cpd.filename, pc->orig_line, pc->str.c_str());
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   /* Insert a CT_VBRACE_OPEN, if needed */
   if ((pc->type != CT_BRACE_OPEN) &&
       ((frm->pse[frm->pse_tos].stage == BS_BRACE2) ||
        (frm->pse[frm->pse_tos].stage == BS_BRACE_DO)))
   {
      parent = frm->pse[frm->pse_tos].type;

      vbrace = insert_vbrace_open_before(pc, frm);
      vbrace->parent_type = parent;

      frm->level++;
      frm->brace_level++;

      push_fmr_pse(frm, vbrace, BS_NONE, "+VBrace ");
      frm->pse[frm->pse_tos].parent = parent;

      /* update the level of pc */
      pc->level       = frm->level;
      pc->brace_level = frm->brace_level;

      /* Mark as a start of a statement */
      frm->stmt_count = 0;
      frm->expr_count = 0;
      pc->flags      |= PCF_STMT_START | PCF_EXPR_START;
      frm->stmt_count = 1;
      frm->expr_count = 1;
      LOG_FMT(LSTMT, "%d] 2.marked %s as stmt start\n", pc->orig_line, pc->str.c_str());
   }

   /* Verify open paren in complex statement */
   if ((pc->type != CT_PAREN_OPEN) &&
       ((frm->pse[frm->pse_tos].stage == BS_PAREN1) ||
        (frm->pse[frm->pse_tos].stage == BS_WOD_PAREN)))
   {
      LOG_FMT(LWARN, "%s:%d Error: Expected '(', got '%s' for '%s'\n",
              cpd.filename, pc->orig_line, pc->str.c_str(),
              get_token_name(frm->pse[frm->pse_tos].type));

      /* Throw out the complex statement */
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   return(false);
}
예제 #2
0
static bool check_complex_statements(parse_frame_t *frm, chunk_t *pc)
{
   LOG_FUNC_ENTRY();
   c_token_t parent;

   // Turn an optional parenthesis into either a real parenthesis or a brace
   if (frm->pse[frm->pse_tos].stage == brace_stage_e::OP_PAREN1)
   {
      frm->pse[frm->pse_tos].stage = (pc->type != CT_PAREN_OPEN) ? brace_stage_e::BRACE2 : brace_stage_e::PAREN1;
   }

   // Check for CT_ELSE after CT_IF
   while (frm->pse[frm->pse_tos].stage == brace_stage_e::ELSE)
   {
      if (pc->type == CT_ELSE)
      {
         // Replace CT_IF with CT_ELSE on the stack & we are done
         frm->pse[frm->pse_tos].type  = CT_ELSE;
         frm->pse[frm->pse_tos].stage = brace_stage_e::ELSEIF;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      // Remove the CT_IF and close the statement
      frm->pse_tos--;
      print_stack(LBCSPOP, "-IF-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   // Check for CT_IF after CT_ELSE
   if (frm->pse[frm->pse_tos].stage == brace_stage_e::ELSEIF)
   {
      if (pc->type == CT_IF)
      {
         if (  !cpd.settings[UO_indent_else_if].b
            || !chunk_is_newline(chunk_get_prev_nc(pc)))
         {
            // Replace CT_ELSE with CT_IF
            set_chunk_type(pc, CT_ELSEIF);
            frm->pse[frm->pse_tos].type  = CT_ELSEIF;
            frm->pse[frm->pse_tos].stage = brace_stage_e::PAREN1;
            return(true);
         }
      }

      // Jump to the 'expecting brace' stage
      frm->pse[frm->pse_tos].stage = brace_stage_e::BRACE2;
   }

   // Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH
   while (frm->pse[frm->pse_tos].stage == brace_stage_e::CATCH)
   {
      if (pc->type == CT_CATCH || pc->type == CT_FINALLY)
      {
         // Replace CT_TRY with CT_CATCH on the stack & we are done
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = (pc->type == CT_CATCH) ? brace_stage_e::CATCH_WHEN : brace_stage_e::BRACE2;
         print_stack(LBCSSWAP, "=Swap   ", frm, pc);
         return(true);
      }

      // Remove the CT_TRY and close the statement
      frm->pse_tos--;
      print_stack(LBCSPOP, "-TRY-CCS ", frm, pc);
      if (close_statement(frm, pc))
      {
         return(true);
      }
   }

   // Check for optional parenthesis and optional CT_WHEN after CT_CATCH
   if (frm->pse[frm->pse_tos].stage == brace_stage_e::CATCH_WHEN)
   {
      if (pc->type == CT_PAREN_OPEN) // this is for the paren after "catch"
      {
         // Replace CT_PAREN_OPEN with CT_SPAREN_OPEN
         set_chunk_type(pc, CT_SPAREN_OPEN);
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = brace_stage_e::PAREN1;
         return(false);
      }

      if (pc->type == CT_WHEN)
      {
         frm->pse[frm->pse_tos].type  = pc->type;
         frm->pse[frm->pse_tos].stage = brace_stage_e::OP_PAREN1;
         return(true);
      }

      if (pc->type == CT_BRACE_OPEN)
      {
         frm->pse[frm->pse_tos].stage = brace_stage_e::BRACE2;
         return(false);
      }
   }

   // Check for CT_WHILE after the CT_DO
   if (frm->pse[frm->pse_tos].stage == brace_stage_e::WHILE)
   {
      if (pc->type == CT_WHILE)
      {
         set_chunk_type(pc, CT_WHILE_OF_DO);
         frm->pse[frm->pse_tos].type  = CT_WHILE_OF_DO; //CT_WHILE;
         frm->pse[frm->pse_tos].stage = brace_stage_e::WOD_PAREN;
         return(true);
      }

      LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected 'while', got '%s'\n",
              __func__, __LINE__, cpd.filename, pc->orig_line, pc->text());
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   // Insert a CT_VBRACE_OPEN, if needed
   if (  pc->type != CT_BRACE_OPEN
      && (  (frm->pse[frm->pse_tos].stage == brace_stage_e::BRACE2)
         || (frm->pse[frm->pse_tos].stage == brace_stage_e::BRACE_DO)))
   {
      if (  (cpd.lang_flags & LANG_CS)
         && pc->type == CT_USING_STMT
         && (!cpd.settings[UO_indent_using_block].b))
      {
         // don't indent the using block
      }
      else
      {
         parent = frm->pse[frm->pse_tos].type;

         chunk_t *vbrace = insert_vbrace_open_before(pc, frm);
         set_chunk_parent(vbrace, parent);

         frm->level++;
         frm->brace_level++;

         push_fmr_pse(frm, vbrace, brace_stage_e::NONE, "+VBrace ");
         frm->pse[frm->pse_tos].parent = parent;

         // update the level of pc
         pc->level       = frm->level;
         pc->brace_level = frm->brace_level;

         // Mark as a start of a statement
         frm->stmt_count = 0;
         frm->expr_count = 0;
         pc->flags      |= PCF_STMT_START | PCF_EXPR_START;
         frm->stmt_count = 1;
         frm->expr_count = 1;
         LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, 2.marked '%s' as stmt start\n",
                 __func__, __LINE__, pc->orig_line, pc->text());
      }
   }

   // Verify open parenthesis in complex statement
   if (  pc->type != CT_PAREN_OPEN
      && (  (frm->pse[frm->pse_tos].stage == brace_stage_e::PAREN1)
         || (frm->pse[frm->pse_tos].stage == brace_stage_e::WOD_PAREN)))
   {
      LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected '(', got '%s' for '%s'\n",
              __func__, __LINE__, cpd.filename, pc->orig_line, pc->text(),
              get_token_name(frm->pse[frm->pse_tos].type));

      // Throw out the complex statement
      frm->pse_tos--;
      print_stack(LBCSPOP, "-Error  ", frm, pc);
      cpd.error_count++;
   }

   return(false);
} // check_complex_statements