diff --git a/CLanguage/Parser/CParser.cs b/CLanguage/Parser/CParser.cs index df7b83f..579bb83 100644 --- a/CLanguage/Parser/CParser.cs +++ b/CLanguage/Parser/CParser.cs @@ -1825,25 +1825,25 @@ internal Object yyparse (yyParser.yyInput yyLex) case 292: #line 1115 "CParser.jay" { - yyVal = new ForStatement((Statement)yyVals[-3+yyTop], ((ExpressionStatement)yyVals[-2+yyTop]).Expression, ((Statement)yyVals[0+yyTop]).ToBlock ()); + yyVal = new ForStatement((Statement)yyVals[-3+yyTop], (yyVals[-2+yyTop] as ExpressionStatement)?.Expression, ((Statement)yyVals[0+yyTop]).ToBlock ()); } break; case 293: #line 1119 "CParser.jay" { - yyVal = new ForStatement((Statement)yyVals[-4+yyTop], ((ExpressionStatement)yyVals[-3+yyTop]).Expression, (Expression)yyVals[-2+yyTop], ((Statement)yyVals[0+yyTop]).ToBlock ()); + yyVal = new ForStatement((Statement)yyVals[-4+yyTop], (yyVals[-3+yyTop] as ExpressionStatement)?.Expression, (Expression)yyVals[-2+yyTop], ((Statement)yyVals[0+yyTop]).ToBlock ()); } break; case 294: #line 1123 "CParser.jay" { - yyVal = new ForStatement((Statement)yyVals[-3+yyTop], ((ExpressionStatement)yyVals[-2+yyTop]).Expression, ((Statement)yyVals[0+yyTop]).ToBlock ()); + yyVal = new ForStatement((Statement)yyVals[-3+yyTop], (yyVals[-2+yyTop] as ExpressionStatement)?.Expression, ((Statement)yyVals[0+yyTop]).ToBlock ()); } break; case 295: #line 1127 "CParser.jay" { - yyVal = new ForStatement((Statement)yyVals[-4+yyTop], ((ExpressionStatement)yyVals[-3+yyTop]).Expression, (Expression)yyVals[-2+yyTop], ((Statement)yyVals[0+yyTop]).ToBlock ()); + yyVal = new ForStatement((Statement)yyVals[-4+yyTop], (yyVals[-3+yyTop] as ExpressionStatement)?.Expression, (Expression)yyVals[-2+yyTop], ((Statement)yyVals[0+yyTop]).ToBlock ()); } break; case 297: diff --git a/CLanguage/Parser/CParser.jay b/CLanguage/Parser/CParser.jay index 415cf65..4b2ec44 100644 --- a/CLanguage/Parser/CParser.jay +++ b/CLanguage/Parser/CParser.jay @@ -1111,19 +1111,19 @@ iteration_statement } | FOR '(' expression_statement expression_statement ')' statement { - $$ = new ForStatement((Statement)$3, ((ExpressionStatement)$4).Expression, ((Statement)$6).ToBlock ()); + $$ = new ForStatement((Statement)$3, ($4 as ExpressionStatement)?.Expression, ((Statement)$6).ToBlock ()); } | FOR '(' expression_statement expression_statement expression ')' statement { - $$ = new ForStatement((Statement)$3, ((ExpressionStatement)$4).Expression, (Expression)$5, ((Statement)$7).ToBlock ()); + $$ = new ForStatement((Statement)$3, ($4 as ExpressionStatement)?.Expression, (Expression)$5, ((Statement)$7).ToBlock ()); } | FOR '(' declaration expression_statement ')' statement { - $$ = new ForStatement((Statement)$3, ((ExpressionStatement)$4).Expression, ((Statement)$6).ToBlock ()); + $$ = new ForStatement((Statement)$3, ($4 as ExpressionStatement)?.Expression, ((Statement)$6).ToBlock ()); } | FOR '(' declaration expression_statement expression ')' statement { - $$ = new ForStatement((Statement)$3, ((ExpressionStatement)$4).Expression, (Expression)$5, ((Statement)$7).ToBlock ()); + $$ = new ForStatement((Statement)$3, ($4 as ExpressionStatement)?.Expression, (Expression)$5, ((Statement)$7).ToBlock ()); } ; diff --git a/CLanguage/Syntax/ForStatement.cs b/CLanguage/Syntax/ForStatement.cs index e23cb00..4f6a70f 100644 --- a/CLanguage/Syntax/ForStatement.cs +++ b/CLanguage/Syntax/ForStatement.cs @@ -11,11 +11,11 @@ namespace CLanguage.Syntax public class ForStatement : Statement { public Block InitBlock { get; private set; } - public Expression ContinueExpression { get; private set; } + public Expression? ContinueExpression { get; private set; } public Expression? NextExpression { get; private set; } public Block LoopBody { get; private set; } - public ForStatement (Statement initStatement, Expression continueExpr, Block body) + public ForStatement (Statement initStatement, Expression? continueExpr, Block body) { InitBlock = new Block (VariableScope.Local); if (initStatement != null) { @@ -25,7 +25,7 @@ public ForStatement (Statement initStatement, Expression continueExpr, Block bod LoopBody = body; } - public ForStatement (Statement initStatement, Expression continueExpr, Expression nextExpr, Block body) + public ForStatement (Statement initStatement, Expression? continueExpr, Expression nextExpr, Block body) { InitBlock = new Block (VariableScope.Local); if (initStatement != null) { @@ -63,9 +63,11 @@ protected override void DoEmit (EmitContext initialContext) // var conditionLabel = ec.DefineLabel (); ec.EmitLabel (conditionLabel); - ContinueExpression.Emit (ec); - ec.EmitCastToBoolean (ContinueExpression.GetEvaluatedCType (ec)); - ec.Emit (OpCode.BranchIfFalse, endLabel); + if (ContinueExpression != null) { + ContinueExpression.Emit (ec); + ec.EmitCastToBoolean (ContinueExpression.GetEvaluatedCType (ec)); + ec.Emit (OpCode.BranchIfFalse, endLabel); + } // // Fall through to the loop body diff --git a/CLanguageTests/InterpreterTests.cs b/CLanguageTests/InterpreterTests.cs index 4257505..78ef535 100644 --- a/CLanguageTests/InterpreterTests.cs +++ b/CLanguageTests/InterpreterTests.cs @@ -246,6 +246,58 @@ void main () { }"); } + [TestMethod] + public void ForLoopInfinite () + { + Run (@" +void main () { + int i = 0; + for (;;) { + i++; + if (i >= 10) break; + } + assertAreEqual (10, i); +}"); + } + + [TestMethod] + public void ForLoopEmptyCondition () + { + Run (@" +void main () { + int i; + for (i = 0; ; i++) { + if (i >= 5) break; + } + assertAreEqual (5, i); +}"); + } + + [TestMethod] + public void ForLoopEmptyIncrement () + { + Run (@" +void main () { + int i; + for (i = 0; i < 10;) { + i++; + } + assertAreEqual (10, i); +}"); + } + + [TestMethod] + public void ForLoopEmptyInit () + { + Run (@" +void main () { + int i = 0; + for (; i < 5; i++) { + } + assertAreEqual (5, i); +}"); + } + [TestMethod] public void WhileLoopWithBreak () {