diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index c7851ba1a361f903d55c4795c184239aa90154d4..e3380a01caa9bc1d0bba62acdba579217b596546 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -306,6 +306,8 @@
     // https://savannah.gnu.org/forum/forum.php?forum_id=9735
 %token YYEOF 0 "end of file"
 
+%type	<number>        sentence sentences statements statement
+
 %type   <number>        star_cbl_opt close_how
 
 %type   <number>        test_before usage_clause1 might_be
@@ -784,36 +786,7 @@
 %precedence NEG
 %right POW
 
-%{
-const char * keyword_str( int token );
-
-static YYLTYPE current_location;
-
-const YYLTYPE& cobol_location() { return current_location; }
-
-static void
-location_set( const YYLTYPE& loc ) {
-  current_location = loc;
-}
 
-static int prior_statement;
-
-static void
-statement_begin( const YYLTYPE& loc, int token ) {
-    // The following statement generates a message at run-time
-    // parser_print_string("statement_begin()\n");
-    location_set(loc);
-    prior_statement = token;
-
-  if( enabled_exceptions.size() ) {
-    current.declaratives_evaluate(ec_none_e);
-    cbl_enabled_exceptions_array_t enabled(enabled_exceptions);
-    parser_exception_prepare( keyword_str(token), &enabled );
-  }
-  if( getenv(__func__) ) symbol_temporaries_free();
-}
-
-%}
 
 %{
   static cbl_field_type_t
@@ -4010,8 +3983,14 @@ declaratives:   %empty { $$ = NULL; }
 		}
                 ;
 
-sentences:      sentence
-        |       sentences sentence
+sentences:      sentence {
+		  if( $1 != PARAGRAPH ) 
+		      symbol_temporaries_free();
+		}
+        |       sentences sentence {
+		  if( $1 != PARAGRAPH ) 
+		      symbol_temporaries_free();
+		}
                 ;
 
 sentence:       statements  '.'
@@ -4057,7 +4036,7 @@ sentence:       statements  '.'
                 ;
 
 statements:                statement
-        |       statements statement
+        |       statements statement { $$ = $2; }
                 ;
 
 statement:      error {
@@ -4070,49 +4049,49 @@ statement:      error {
 		    YYABORT;
 		  }
 		}
-        |       cdf
-        |       accept
-        |       add
-        |       allocate
-        |       alter
-        |       call
-        |       cancel
-        |       close
-        |       compute
-        |       CONTINUE
-        |       delete
-        |       display
-        |       divide
-        |       entry
-        |       evaluate
-        |       exit
-        |       free
-        |       go_to
-        |       if_stmt
-        |       initialize
-        |       inspect
-        |       merge
-        |       move
-        |       multiply
-        |       open
-        |       return_stmt
-        |       paragraph
-        |       perform
-        |       raise
-        |       read
-        |       release
-        |       resume
-        |       rewrite
-        |       search
-        |       section
-        |       set
-        |       sort
-        |       start
-        |       stop
-        |       string
-        |       subtract
-        |       unstring
-        |       write
+        |       cdf		{ $$ =  CDF_IF; }
+        |       accept		{ $$ =  ACCEPT; }
+        |       add		{ $$ =  ADD; }
+        |       allocate	{ $$ =  ALLOCATE; }
+        |       alter		{ $$ =  ALTER; }
+        |       call		{ $$ =  CALL; }
+        |       cancel		{ $$ =  CANCEL; }
+        |       close		{ $$ =  CLOSE; }
+        |       compute		{ $$ =  COMPUTE; }
+        |       CONTINUE	{ $$ =  CONTINUE; }
+        |       delete		{ $$ =  DELETE; }
+        |       display		{ $$ =  DISPLAY; }
+        |       divide		{ $$ =  DIVIDE; }
+        |       entry		{ $$ =  ENTRY; }
+        |       evaluate	{ $$ =  EVALUATE; }
+        |       exit		{ $$ =  EXIT; }
+        |       free		{ $$ =  FREE; }
+        |       go_to		{ $$ =  GOTO; }
+        |       if_stmt		{ $$ =  IF; }
+        |       initialize	{ $$ =  INITIALIZE; }
+        |       inspect		{ $$ =  INSPECT; }
+        |       merge		{ $$ =  MERGE; }
+        |       move		{ $$ =  MOVE; }
+        |       multiply	{ $$ =  MULTIPLY; }
+        |       open		{ $$ =  OPEN; }
+        |       return_stmt	{ $$ =  RETURN; }
+        |       paragraph	{ $$ =  PARAGRAPH; }
+        |       perform		{ $$ =  PERFORM; }
+        |       raise		{ $$ =  RAISE; }
+        |       read		{ $$ =  READ; }
+        |       release		{ $$ =  RELEASE; }
+        |       resume		{ $$ =  RESUME; }
+        |       rewrite		{ $$ =  REWRITE; }
+        |       search		{ $$ =  SEARCH; }
+        |       section		{ $$ =  SECTION; }
+        |       set		{ $$ =  SET; }
+        |       sort		{ $$ =  SORT; }
+        |       start		{ $$ =  START; }
+        |       stop		{ $$ =  STOP; }
+        |       string		{ $$ =  STRING_kw; }
+        |       subtract	{ $$ =  SUBTRACT; }
+        |       unstring	{ $$ =  UNSTRING; }
+        |       write		{ $$ =  WRITE; }
                 ;
 
 accept:		accept_body end_accept
@@ -6328,11 +6307,6 @@ subtract_impl:  SUBTRACT subtract_body[body]
                   statement_begin(@1, SUBTRACT);
                   $$ = $body;
                 }
-        |       SUBTRACT subtract_body[body] END_SUBTRACT
-                {
-                  statement_begin(@1, SUBTRACT);
-                  $$ = $body;
-                }
                 ;
 subtract_cond:  SUBTRACT subtract_body[body] arith_errs[err]
                 {
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 70eacc18dbe31cc9bda04549c8a80f23cb37a07d..ca292b322d85caa8f50494f30922a9192ea00df1 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -2971,3 +2971,32 @@ goodnight_gracie() {
   return true;
 }
 
+const char * keyword_str( int token );
+
+static YYLTYPE current_location;
+
+const YYLTYPE& cobol_location() { return current_location; }
+
+static void
+location_set( const YYLTYPE& loc ) {
+  current_location = loc;
+}
+
+static int prior_statement;
+
+static size_t
+    statement_begin( const YYLTYPE& loc, int token ) {
+    // The following statement generates a message at run-time
+    // parser_print_string("statement_begin()\n");
+    location_set(loc);
+    prior_statement = token;
+
+  if( enabled_exceptions.size() ) {
+    current.declaratives_evaluate(ec_none_e);
+    cbl_enabled_exceptions_array_t enabled(enabled_exceptions);
+    parser_exception_prepare( keyword_str(token), &enabled );
+  }
+  if( getenv(__func__) ) symbol_temporaries_free();
+  return 0;
+}
+
diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc
index 7a94b0d245b8f20554d1d34715a1b0fe25ea6151..a09f4c011988e1d478c84c3cd6b3fb1277a19016 100644
--- a/gcc/cobol/symbols.cc
+++ b/gcc/cobol/symbols.cc
@@ -3090,13 +3090,40 @@ temporaries_t::acquire( cbl_field_type_t type ) {
   return field;
 }
 
+size_t
+temporaries_t::keep() {
+  keepers.push(used);
+  used.clear();
+  return keepers.size();
+}
+
+void
+temporaries_t::release( size_t keeper ) {
+  if( keepers.size() != keeper ) {
+    warnx("%s: logic error: releasing %zu of %zu kept temporaries:",
+          __func__, keeper, keepers.size() );
+  }
+  assert( ! keepers.empty() );
+  assert( keepers.size() == keeper );
+  fieldmap_t& used( keepers.top() );
+
+  for( auto& elem : used ) {
+    const cbl_field_type_t& type(elem.first);
+    temporaries_t::fieldset_t& used(elem.second);
+
+    auto freer = std::inserter(freed[type],
+                               freed[type].begin());
+    std::copy( used.begin(), used.end(), freer );
+  }
+  keepers.pop();
+}
+
 void
 symbol_temporaries_free() {
   for( auto& elem : temporaries.used ) {
     const cbl_field_type_t& type(elem.first);
     temporaries_t::fieldset_t& used(elem.second);
-    if( type == FldConditional ) continue;
-    
+
     auto freed = std::inserter(temporaries.freed[type],
                                temporaries.freed[type].begin());
     std::copy( used.begin(), used.end(), freed );
@@ -3104,16 +3131,15 @@ symbol_temporaries_free() {
   }
 }
 
-#if 0
+size_t
+symbol_temporaries_push() {
+  return temporaries.keep();
+}
+
 void
-temporaries_t::release( cbl_field_type_t type ) {
-  fieldset_t& used[type];
-  auto freed = std::inserter(freed[type],
-                             freed[type].begin());
-  std::copy( used.begin(), used.end(), freed );
-  used.clear();
+symbol_temporaries_pop( size_t kept ) {
+  return temporaries.release( kept );
 }
-#endif
 
 cbl_field_t *
 new_temporary( enum cbl_field_type_t type ) {
diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h
index 5f4b5a56b879b98180b12b314e7f3f678afd0916..ed4263e3b55350155a0f799b80a440f8aa44cb57 100644
--- a/gcc/cobol/symbols.h
+++ b/gcc/cobol/symbols.h
@@ -41,6 +41,7 @@
 #include <list>
 #include <map>
 #include <set>
+#include <stack>
 #include <string>
 
 #define COUNT_OF(X) (sizeof(X) / sizeof(X[0]))
@@ -1217,14 +1218,20 @@ class temporaries_t {
 
   std::map<literal_an, cbl_field_t *> literals;
   typedef std::set<cbl_field_t *> fieldset_t;
-  std::map<cbl_field_type_t, fieldset_t> used, freed;  
+  typedef std::map<cbl_field_type_t, fieldset_t> fieldmap_t;
+  fieldmap_t used, freed;
+  std::stack<fieldmap_t> keepers;
 
 public:
   cbl_field_t * literal( const char value[], uint32_t len, cbl_field_attr_t attr  = none_e );
   cbl_field_t * acquire( cbl_field_type_t type );
+  size_t keep();
+  void release( size_t kept);
   void add( cbl_field_t *field );
 };
 
+size_t symbol_temporaries_push();
+void symbol_temporaries_pop( size_t kept );
 
 static inline bool is_table( const cbl_field_t *field ) {
   return field && field->occurs.ntimes() > 0;