From 505eb7eca7406d12f77ad53eb5f8ec613df19182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Grodzi=C5=84ski?= Date: Tue, 1 Jul 2025 13:45:40 +0900 Subject: [PATCH] Improved loop parsing --- Syntax.md | 55 ++++++++++++++++++++----------------------- src/Parser/Parser.cpp | 41 ++++++++++++++++++++------------ test.brc | 6 ++--- 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/Syntax.md b/Syntax.md index 64bcfe9..16a2af9 100644 --- a/Syntax.md +++ b/Syntax.md @@ -9,19 +9,11 @@ This documents specifies what is the allowed syntax for statements and expressio `+` 1 or more instances -`` Terminal token, usually new line , but it can also sometimes be `,`, `else`, or `;` - `` New line `` Identifier -`` Expression block - -`` Statements block - -`` Expression - -`` Statement +`` Type ### Overall structure ``` @@ -36,7 +28,7 @@ This documents specifies what is the allowed syntax for statements and expressio + + + - + + + | + ... + @@ -77,47 +69,52 @@ sint32 ``` ### Statement Assignment -` <- ` +` <- ` ``` num1 <- 5 - ``` ### Statement Block -( )* +`( )*` +### Statement Repeat +`rep [ | ]? : ` -### Statement Expression - +`rep [ | ]? : ;` -### StatementLoop -`loop [ | ] (, ? (, ? )?)? ;` +`rep [ | ] (, ? (, ? )? )? : ` + +`rep [ | ] (, ? (, ? )? )? : ;` + +`rep ( (, ? )? )? : ` + +`rep ( (, ? )? )? : ;` ``` -loop i sint32 <- 0, true, i < 10 +rep i sint32 <- 0, true, i < 10: doStuff(i) ; -loop i sint32 <- 0, -true, i < 10 +rep i sint32 <- 0, +true, i < 10: doStuff(i) ; -loop i sint32 <- 0, +rep i sint32 <- 0, true, -i < 10 +i < 10: doStuff(i) ; -``` -`loop ( (, ? )?)? ;` +rep: infiniteCall() +``` ### Statement Return -`ret ? ` +`ret ?` -### ExpressionVariable: -`` +### Expression Variable +`` -### Expression If Else: +### Expression If-Else: `if : ` ``` if num1 > 10: putchar('T') @@ -158,4 +155,4 @@ if num1 > 10: putchar('T') else ``` ### Expression Block -`( )* ( ?)? !` \ No newline at end of file +` )* ?` \ No newline at end of file diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 69748d3..e52d777 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -274,48 +274,59 @@ shared_ptr Parser::matchStatementLoop() { shared_ptr initStatement; shared_ptr preConditionExpression; shared_ptr postConditionExpression; + shared_ptr bodyBlockStatement; + + bool isMultiLine; // initial - initStatement = matchStatementVariable(); + initStatement = matchStatementVariable() ?: matchStatementAssignment(); if (initStatement != nullptr && !initStatement->isValid()) initStatement = nullptr; - if (tokens.at(currentIndex-1)->getKind() != TokenKind::NEW_LINE) { + if (!tryMatchingTokenKinds({TokenKind::COLON}, false, true)) { // got initial, expect comma if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) return matchStatementInvalid("Expected comma after initial statement"); + // optional new line + tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + // pre condition preConditionExpression = nextExpression(); if (preConditionExpression != nullptr && !preConditionExpression->isValid()) return matchStatementInvalid("Expected pre-condition expression"); - if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) { + if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) { // got pre-condition, expect comma if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) return matchStatementInvalid("Expected comma after pre-condition statement"); + // optional new line + tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + // post condition postConditionExpression = nextExpression(); if (postConditionExpression == nullptr || !postConditionExpression->isValid()) return matchStatementInvalid("Expected post-condition expression"); - // epxect new line - if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) - return matchStatementInvalid("Expected new line"); + // expect colon + if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) + return matchStatementInvalid("Expected \":\""); } } + isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + // body - shared_ptr bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON}); - if (bodyBlockStatement == nullptr) - return matchStatementInvalid("Expected block statement"); - else if (!bodyBlockStatement->isValid()) - return bodyBlockStatement; + if (isMultiLine) + bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON}); + else + bodyBlockStatement = matchStatementBlock({TokenKind::NEW_LINE}); + + if (bodyBlockStatement == nullptr || !bodyBlockStatement->isValid()) + return bodyBlockStatement ?: matchStatementInvalid("Expected block statement"); - // epxect new line - if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) - return matchStatementInvalid("Expected new line"); + tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true); return make_shared(initStatement, preConditionExpression, postConditionExpression, dynamic_pointer_cast(bodyBlockStatement)); } @@ -563,7 +574,7 @@ shared_ptr Parser::matchExpressionBlock(vector terminalTo vector> statements; while (!tryMatchingTokenKinds(terminalTokenKinds, false, false)) { - shared_ptr statement = nextStatement(); + shared_ptr statement = nextInBlockStatement(); if (statement == nullptr || !statement->isValid()) return matchExpressionInvalid("Expected statement"); statements.push_back(statement); diff --git a/test.brc b/test.brc index bd1d6ef..2b3a5e5 100644 --- a/test.brc +++ b/test.brc @@ -1,6 +1,6 @@ dummy sint32 <- 55 stuff fun: num1 sint32, num2 sint32 -> sint32 - num1 sint32 <- 42 - num1 <- 5 * num1 - ret num1 + rep: + i <- i + 1 + ; ; \ No newline at end of file