@@ -158,6 +158,54 @@ Parser::produceASTStrict(const std::string &sourceCode) {
158158 return program;
159159}
160160
161+ // Parse a single statement without skipping leading newlines (for inline forms)
162+ std::unique_ptr<havel::ast::Statement> Parser::parseInlineStatement () {
163+ // Don't skip newlines - they terminate inline statements
164+ // If we hit a newline or EOF, return null
165+ if (at ().type == havel::TokenType::NewLine || at ().type == havel::TokenType::EOF_TOKEN) {
166+ return nullptr ;
167+ }
168+
169+ // Parse based on current token
170+ switch (at ().type ) {
171+ case havel::TokenType::Let:
172+ return parseLetDeclaration ();
173+ case havel::TokenType::If:
174+ return parseIfStatement ();
175+ case havel::TokenType::While:
176+ return parseWhileStatement ();
177+ case havel::TokenType::For:
178+ return parseForStatement ();
179+ case havel::TokenType::Loop:
180+ return parseLoopStatement ();
181+ case havel::TokenType::Repeat:
182+ return parseRepeatStatement ();
183+ case havel::TokenType::Break:
184+ return parseBreakStatement ();
185+ case havel::TokenType::Continue:
186+ return parseContinueStatement ();
187+ case havel::TokenType::Return:
188+ case havel::TokenType::Ret:
189+ return parseReturnStatement ();
190+ case havel::TokenType::Fn:
191+ return parseFunctionDeclaration ();
192+ case havel::TokenType::Switch:
193+ return parseSwitchStatement ();
194+ case havel::TokenType::Try:
195+ return parseTryStatement ();
196+ case havel::TokenType::Catch:
197+ failAt (at (), " 'catch' can only appear within a 'try' statement" );
198+ case havel::TokenType::Finally:
199+ failAt (at (), " 'finally' can only appear within a 'try' statement" );
200+ case havel::TokenType::Throw:
201+ return parseThrowStatement ();
202+ default :
203+ // Expression statement (including assignments, function calls, etc.)
204+ auto expr = parseExpression ();
205+ return std::make_unique<havel::ast::ExpressionStatement>(std::move (expr));
206+ }
207+ }
208+
161209std::unique_ptr<havel::ast::Statement> Parser::parseStatement () {
162210 // Skip leading newlines within statement context
163211 // This allows multiple newlines between statements
@@ -1045,20 +1093,27 @@ std::unique_ptr<havel::ast::Statement> Parser::parseIfStatement() {
10451093 auto condition = parseExpression ();
10461094 allowBraceCallSugar = prevAllow;
10471095
1048- if (at ().type != havel::TokenType::OpenBrace) {
1049- failAt (at (), " Expected '{' after if condition" );
1096+ std::unique_ptr<havel::ast::Statement> consequence;
1097+
1098+ // Block form or inline form
1099+ if (at ().type == havel::TokenType::OpenBrace) {
1100+ consequence = parseBlockStatement ();
1101+ } else {
1102+ // Inline form - single statement (don't skip newlines)
1103+ consequence = parseInlineStatement ();
10501104 }
10511105
1052- auto consequence = parseBlockStatement ();
1053-
10541106 std::unique_ptr<havel::ast::Statement> alternative = nullptr ;
10551107 if (at ().type == havel::TokenType::Else) {
10561108 advance (); // consume "else"
10571109
10581110 if (at ().type == havel::TokenType::If) {
10591111 alternative = parseIfStatement ();
1060- } else {
1112+ } else if ( at (). type == havel::TokenType::OpenBrace) {
10611113 alternative = parseBlockStatement ();
1114+ } else {
1115+ // Inline else - single statement (don't skip newlines)
1116+ alternative = parseInlineStatement ();
10621117 }
10631118 }
10641119
@@ -1074,12 +1129,16 @@ std::unique_ptr<havel::ast::Statement> Parser::parseWhileStatement() {
10741129 auto condition = parseExpression ();
10751130 allowBraceCallSugar = prevAllow;
10761131
1077- if (at ().type != havel::TokenType::OpenBrace) {
1078- failAt (at (), " Expected '{' after while condition" );
1132+ std::unique_ptr<havel::ast::Statement> body;
1133+
1134+ // Block form or inline form
1135+ if (at ().type == havel::TokenType::OpenBrace) {
1136+ body = parseBlockStatement ();
1137+ } else {
1138+ // Inline form - single statement (don't skip newlines)
1139+ body = parseInlineStatement ();
10791140 }
10801141
1081- auto body = parseBlockStatement ();
1082-
10831142 return std::make_unique<havel::ast::WhileStatement>(std::move (condition),
10841143 std::move (body));
10851144}
@@ -1249,17 +1308,21 @@ std::unique_ptr<havel::ast::Statement> Parser::parseForStatement() {
12491308 auto iterable = parseExpression ();
12501309 allowBraceCallSugar = prevAllow;
12511310
1252- // Skip newlines before opening brace
1311+ // Skip newlines before body
12531312 while (at ().type == havel::TokenType::NewLine) {
12541313 advance ();
12551314 }
12561315
1257- if (at ().type != havel::TokenType::OpenBrace) {
1258- failAt (at (), " Expected '{' after for iterable" );
1316+ std::unique_ptr<havel::ast::Statement> body;
1317+
1318+ // Block form or inline form
1319+ if (at ().type == havel::TokenType::OpenBrace) {
1320+ body = parseBlockStatement ();
1321+ } else {
1322+ // Inline form - single statement (don't skip newlines)
1323+ body = parseInlineStatement ();
12591324 }
12601325
1261- auto body = parseBlockStatement ();
1262-
12631326 return std::make_unique<havel::ast::ForStatement>(
12641327 std::move (iterators), std::move (iterable), std::move (body));
12651328}
@@ -1269,33 +1332,37 @@ std::unique_ptr<havel::ast::Statement> Parser::parseLoopStatement() {
12691332
12701333 // Check for optional "while condition"
12711334 std::unique_ptr<havel::ast::Expression> condition;
1272-
1335+
12731336 // Skip newlines
12741337 while (at ().type == havel::TokenType::NewLine) {
12751338 advance ();
12761339 }
12771340
12781341 if (at ().type == havel::TokenType::While) {
12791342 advance (); // consume "while"
1280-
1343+
12811344 // Parse condition expression
12821345 bool prevAllow = allowBraceCallSugar;
12831346 allowBraceCallSugar = false ;
12841347 condition = parseExpression ();
12851348 allowBraceCallSugar = prevAllow;
1286-
1287- // Skip newlines before opening brace
1349+
1350+ // Skip newlines before body
12881351 while (at ().type == havel::TokenType::NewLine) {
12891352 advance ();
12901353 }
12911354 }
12921355
1293- if (at ().type != havel::TokenType::OpenBrace) {
1294- failAt (at (), " Expected '{' after 'loop' or loop condition" );
1356+ std::unique_ptr<havel::ast::Statement> body;
1357+
1358+ // Block form or inline form
1359+ if (at ().type == havel::TokenType::OpenBrace) {
1360+ body = parseBlockStatement ();
1361+ } else {
1362+ // Inline form - single statement (don't skip newlines)
1363+ body = parseInlineStatement ();
12951364 }
12961365
1297- auto body = parseBlockStatement ();
1298-
12991366 return std::make_unique<havel::ast::LoopStatement>(std::move (body), std::move (condition));
13001367}
13011368
@@ -1684,20 +1751,32 @@ std::unique_ptr<havel::ast::Statement> Parser::parseWhenBlock() {
16841751 std::move (statements));
16851752}
16861753
1687- // Parse repeat statement: repeat count { body }
1754+ // Parse repeat statement: repeat count { body } or repeat count statement
16881755std::unique_ptr<havel::ast::Statement> Parser::parseRepeatStatement () {
16891756 advance (); // consume 'repeat'
16901757
16911758 // Parse count - must be a number literal
16921759 if (at ().type != havel::TokenType::Number) {
16931760 failAt (at (), " repeat count must be a number" );
16941761 }
1695-
1762+
16961763 int count = static_cast <int >(std::stod (at ().value ));
16971764 advance (); // consume number
16981765
1699- // Parse body as block statement (parseBlockStatement consumes the '{')
1700- auto body = parseBlockStatement ();
1766+ // Skip newlines before body
1767+ while (at ().type == havel::TokenType::NewLine) {
1768+ advance ();
1769+ }
1770+
1771+ std::unique_ptr<havel::ast::Statement> body;
1772+
1773+ // Block form or inline form
1774+ if (at ().type == havel::TokenType::OpenBrace) {
1775+ body = parseBlockStatement ();
1776+ } else {
1777+ // Inline form - single statement (don't skip newlines)
1778+ body = parseInlineStatement ();
1779+ }
17011780
17021781 return std::make_unique<ast::RepeatStatement>(count, std::move (body));
17031782}
0 commit comments