Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
+++ src/Parser/parser.yy	(revision 9fd9d01543f319adc37ab11817b20515dcb04170)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar 22 21:26:01 2023
-// Update Count     : 6002
+// Last Modified On : Wed Mar 29 11:21:38 2023
+// Update Count     : 6321
 //
 
@@ -360,6 +360,6 @@
 
 // names and constants: lexer differentiates between identifier and typedef names
-%token<tok> IDENTIFIER		QUOTED_IDENTIFIER	TYPEDIMname		TYPEDEFname		TYPEGENname
-%token<tok> TIMEOUT			WOR					CATCH			RECOVER			CATCHRESUME		FIXUP		FINALLY		// CFA
+%token<tok> IDENTIFIER		TYPEDIMname		TYPEDEFname		TYPEGENname
+%token<tok> TIMEOUT			WAND	WOR			CATCH			RECOVER			CATCHRESUME		FIXUP		FINALLY		// CFA
 %token<tok> INTEGERconstant	CHARACTERconstant	STRINGliteral
 %token<tok> DIRECTIVE
@@ -430,7 +430,7 @@
 %type<catch_kind> handler_key
 %type<sn> mutex_statement
-%type<en> when_clause					when_clause_opt				waitfor						timeout
-%type<sn> waitfor_statement
-%type<wfs> waitfor_clause
+%type<en> when_clause					when_clause_opt				waitfor		waituntil		timeout
+%type<sn> waitfor_statement				waituntil_statement
+%type<wfs> wor_waitfor_clause			waituntil_clause			wand_waituntil_clause	wor_waituntil_clause
 
 // declarations
@@ -536,7 +536,10 @@
 // Similar issues exit with the waitfor statement.
 
-// Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left
-// associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
+// Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
+// is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
 %precedence THEN		// rule precedence for IF/WAITFOR statement
+%precedence ANDAND		// token precedence for start of WAND in WAITFOR statement
+%precedence WAND		// token precedence for start of WAND in WAITFOR statement
+%precedence OROR		// token precedence for start of WOR in WAITFOR statement
 %precedence WOR			// token precedence for start of WOR in WAITFOR statement
 %precedence TIMEOUT		// token precedence for start of TIMEOUT in WAITFOR statement
@@ -625,4 +628,5 @@
 quasi_keyword:											// CFA
 	TIMEOUT
+	| WAND
 	| WOR
 	| CATCH
@@ -775,7 +779,7 @@
 		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
 	| postfix_expression ICR
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::IncrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::IncrPost, $1 ) ); }
 	| postfix_expression DECR
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::DecrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::DecrPost, $1 ) ); }
 	| '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
 		{ $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
@@ -805,5 +809,5 @@
 	'@'													// CFA, default parameter
 		{ SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
-	 	// { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
+		// { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
 	| assignment_expression
 	;
@@ -880,9 +884,9 @@
 		}
 	| unary_operator cast_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
 	| ICR unary_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::Incr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Incr, $2 ) ); }
 	| DECR unary_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::Decr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Decr, $2 ) ); }
 	| SIZEOF unary_expression
 		{ $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild( $2 ) ) ); }
@@ -1137,4 +1141,5 @@
 	| mutex_statement
 	| waitfor_statement
+	| waituntil_statement
 	| exception_statement
 	| enable_disable_statement
@@ -1246,5 +1251,5 @@
 	| declaration comma_expression						// semi-colon separated
 		{ $$ = new CondCtl( $1, $2 ); }
- 	;
+	;
 
 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
@@ -1329,5 +1334,5 @@
 		}
 	| FOR '(' for_control_expression_list ')' statement	%prec THEN
-	  	{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
+		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
 	| FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
 		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
@@ -1521,5 +1526,5 @@
 			SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
 		}
- 	;
+	;
 
 downupdowneq:
@@ -1530,5 +1535,5 @@
 	| ErangeDownEq
 		{ $$ = OperKinds::GEThan; }
- 	;
+	;
 
 updown:
@@ -1537,5 +1542,5 @@
 	| ErangeDown
 		{ $$ = OperKinds::GThan; }
- 	;
+	;
 
 updowneq:
@@ -1545,5 +1550,5 @@
 	| ErangeDownEq
 		{ $$ = OperKinds::GEThan; }
- 	;
+	;
 
 jump_statement:
@@ -1628,13 +1633,4 @@
 	;
 
-waitfor:
-	WAITFOR '(' cast_expression ')'
-		{ $$ = $3; }
-//	| WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
-//	  	{ $$ = (ExpressionNode *)$3->set_last( $5 ); }
-	| WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
-		{ $$ = (ExpressionNode *)($3->set_last( $5 )); }
-	;
-
 cast_expression_list:
 	cast_expression
@@ -1645,32 +1641,87 @@
 
 timeout:
-	TIMEOUT '(' comma_expression ')'	 		{ $$ = $3; }
-	;
-
-waitfor_clause:
+	TIMEOUT '(' comma_expression ')'			{ $$ = $3; }
+	;
+
+wor:
+	OROR
+	| WOR
+
+waitfor:
+	WAITFOR '(' cast_expression ')'
+		{ $$ = $3; }
+	| WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
+		{ $$ = (ExpressionNode *)($3->set_last( $5 )); }
+	;
+
+wor_waitfor_clause:
 	when_clause_opt waitfor statement					%prec THEN
-		{ $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
-	| when_clause_opt waitfor statement WOR waitfor_clause
-		{ $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
-	| when_clause_opt timeout statement					%prec THEN
-		{ $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
-	| when_clause_opt ELSE statement
-		{ $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
+		// Called first: create header for WaitForStmt.
+		{ $$ = build_waitfor( new WaitForStmt(), $1, $2, maybe_build_compound( $3 ) ); }
+	| wor_waitfor_clause wor when_clause_opt waitfor statement	%prec THEN
+		{ $$ = build_waitfor( $1, $3, $4, maybe_build_compound( $5 ) ); }
+	| wor_waitfor_clause wor when_clause_opt ELSE statement
+		{ $$ = build_waitfor_else( $1, $3, maybe_build_compound( $5 ) ); }
+	| wor_waitfor_clause wor when_clause_opt timeout statement	%prec THEN
+		{ $$ = build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ); }
 	// "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
-	| when_clause_opt timeout statement WOR ELSE statement // syntax error
+	| wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
 		{ SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
-	| when_clause_opt timeout statement WOR when_clause ELSE statement
-		{ $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
-	;
+	| wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
+		{ $$ = build_waitfor_else( build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ), $7, maybe_build_compound( $9 ) ); }
 
 waitfor_statement:
-	when_clause_opt waitfor statement					%prec THEN
- 		{ $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); }
-	| when_clause_opt waitfor statement WOR waitfor_clause
- 		{ $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); }
+	wor_waitfor_clause									%prec THEN
+		{ $$ = new StatementNode( $1 ); }
+	;
+
+wand:
+	ANDAND
+	| WAND
+	;
+
+waituntil:
+	WAITUNTIL '(' cast_expression ')'
+		{ $$ = $3; }
+	;
+
+waituntil_clause:
+	when_clause_opt waituntil statement
+		{ printf( "waituntil_clause 1\n" ); $$ = nullptr; }
+	| '(' wor_waituntil_clause ')'
+		{ printf( "waituntil_clause 2\n" ); $$ = nullptr; }
+	;
+
+wand_waituntil_clause:
+	waituntil_clause									%prec THEN
+		{ printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
+	| waituntil_clause wand wand_waituntil_clause
+		{ printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
+	;
+
+wor_waituntil_clause:
+	wand_waituntil_clause
+		{ printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor wor_waituntil_clause		%prec THEN
+		{ printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt ELSE statement
+		{ printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt timeout statement	%prec THEN
+		{ printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
+	// "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
+	| wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
+		{ SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
+		{ printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
+	;
+
+waituntil_statement:
+	wor_waituntil_clause								%prec THEN
+		// SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
+		{ $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
 	;
 
 exception_statement:
-	TRY compound_statement handler_clause 					%prec THEN
+	TRY compound_statement handler_clause				%prec THEN
 		{ $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }
 	| TRY compound_statement finally_clause
@@ -1832,5 +1883,5 @@
 		{
 			// printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2302,5 +2353,5 @@
 		{
 			// printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2318,5 +2369,5 @@
 		{
 			// printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2396,5 +2447,5 @@
 		{
 			// printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2523,5 +2574,5 @@
 			$$ = fieldDecl( $1, $2 );
 			// printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2530,5 +2581,5 @@
 		{ $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
 	| STATIC type_specifier field_declaring_list_opt ';' // CFA
-	   	{ SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
+		{ SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
 	| INLINE type_specifier field_abstract_list_opt ';'	// CFA
 		{
@@ -2541,5 +2592,5 @@
 		}
 	| INLINE aggregate_control ';'						// CFA
-	   	{ SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
+		{ SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
 	| typedef_declaration ';'							// CFA
 	| cfa_field_declaring_list ';'						// CFA, new style field declaration
@@ -2624,5 +2675,5 @@
 		{ $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
 	| ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
-	 	{
+		{
 			if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
 			{ SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
@@ -3158,5 +3209,5 @@
 		{
 			distQual( $5, $1 );
- 			forall = false;
+			forall = false;
 			$$ = $5;
 		}
@@ -3169,5 +3220,5 @@
 		{
 			distQual( $5, $1 );
- 			forall = false;
+			forall = false;
 			$$ = $5;
 		}
@@ -3180,5 +3231,5 @@
 		{
 			distQual( $6, $1->addQualifiers( $2 ) );
- 			forall = false;
+			forall = false;
 			$$ = $6;
 		}
@@ -3387,5 +3438,5 @@
 	| '(' attribute_list variable_ptr ')' array_dimension
 		{ $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
-	| '(' variable_array ')' multi_array_dimension 		// redundant parenthesis
+	| '(' variable_array ')' multi_array_dimension		// redundant parenthesis
 		{ $$ = $2->addArray( $4 ); }
 	| '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
@@ -3810,5 +3861,5 @@
 	| ErangeUpEq
 		{ $$ = OperKinds::LEThan; }
- 	;
+	;
 
 multi_array_dimension:
