Improved loop parsing
This commit is contained in:
55
Syntax.md
55
Syntax.md
@@ -9,19 +9,11 @@ This documents specifies what is the allowed syntax for statements and expressio
|
|||||||
|
|
||||||
`+` 1 or more instances
|
`+` 1 or more instances
|
||||||
|
|
||||||
`<TER>` Terminal token, usually new line <NL>, but it can also sometimes be `,`, `else`, or `;`
|
|
||||||
|
|
||||||
`<NL>` New line
|
`<NL>` New line
|
||||||
|
|
||||||
`<ID>` Identifier
|
`<ID>` Identifier
|
||||||
|
|
||||||
`<EXPR_BLOCK>` Expression block
|
`<TYPE>` Type
|
||||||
|
|
||||||
`<STMT_BLOCK>` Statements block
|
|
||||||
|
|
||||||
`<EXPR>` Expression
|
|
||||||
|
|
||||||
`<STMT>` Statement
|
|
||||||
|
|
||||||
### Overall structure
|
### Overall structure
|
||||||
```
|
```
|
||||||
@@ -36,7 +28,7 @@ This documents specifies what is the allowed syntax for statements and expressio
|
|||||||
+ <Statemnet Variable>
|
+ <Statemnet Variable>
|
||||||
+ <Statement Assignment>
|
+ <Statement Assignment>
|
||||||
+ <Statement Return>
|
+ <Statement Return>
|
||||||
+ <Statement Loop>
|
+ <Statement Repeat>
|
||||||
|
|
|
|
||||||
+ <Statement Block>...
|
+ <Statement Block>...
|
||||||
+ <Statement Expression>
|
+ <Statement Expression>
|
||||||
@@ -77,47 +69,52 @@ sint32
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Statement Assignment
|
### Statement Assignment
|
||||||
`<ID> <- <EXPR> <TER>`
|
`<ID> <- <Expression>`
|
||||||
```
|
```
|
||||||
num1 <- 5
|
num1 <- 5
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Statement Block
|
### Statement Block
|
||||||
(<Statement> <NL>)*
|
`(<Statement> <NL>)*`
|
||||||
|
|
||||||
|
### Statement Repeat
|
||||||
|
`rep [<StatementVariable> | <StatementAssignment>]? : <Statement Block>`
|
||||||
|
|
||||||
### Statement Expression
|
`rep [<StatementVariable> | <StatementAssignment>]? : <NL> <Statement Block> ;`
|
||||||
<Expression> <NL>
|
|
||||||
|
|
||||||
### StatementLoop
|
`rep [<StatementVariable> | <StatementAssignment>] (, <NL>? <Expression> (, <NL>? <Expression>)? )? : <StatementBlock>`
|
||||||
`loop [<StatementVariable> | <StatementAssignment>] (, <NL>? <Expression> (, <NL>? <Expression>)?)? <NL> <StatementBlock> ;`
|
|
||||||
|
`rep [<StatementVariable> | <StatementAssignment>] (, <NL>? <Expression> (, <NL>? <Expression>)? )? : <NL> <StatementBlock> ;`
|
||||||
|
|
||||||
|
`rep (<Expression> (, <NL>? <Expression>)? )? : <StatementBlock>`
|
||||||
|
|
||||||
|
`rep (<Expression> (, <NL>? <Expression>)? )? : <NL> <StatementBlock> ;`
|
||||||
```
|
```
|
||||||
loop i sint32 <- 0, true, i < 10
|
rep i sint32 <- 0, true, i < 10:
|
||||||
doStuff(i)
|
doStuff(i)
|
||||||
;
|
;
|
||||||
|
|
||||||
loop i sint32 <- 0,
|
rep i sint32 <- 0,
|
||||||
true, i < 10
|
true, i < 10:
|
||||||
doStuff(i)
|
doStuff(i)
|
||||||
;
|
;
|
||||||
|
|
||||||
loop i sint32 <- 0,
|
rep i sint32 <- 0,
|
||||||
true,
|
true,
|
||||||
i < 10
|
i < 10:
|
||||||
doStuff(i)
|
doStuff(i)
|
||||||
;
|
;
|
||||||
```
|
|
||||||
|
|
||||||
`loop (<ExpressionLogical> (, <NL>? <ExpressionLogical>)?)? <NL> <StatementBlock> ;`
|
rep: infiniteCall()
|
||||||
|
```
|
||||||
|
|
||||||
### Statement Return
|
### Statement Return
|
||||||
`ret <Expression>? <NL>`
|
`ret <Expression>?`
|
||||||
|
|
||||||
### ExpressionVariable:
|
### Expression Variable
|
||||||
`<IDENT>`
|
`<ID>`
|
||||||
|
|
||||||
### Expression If Else:
|
### Expression If-Else:
|
||||||
`if <Expression> : <ExpressionBlock>`
|
`if <Expression> : <ExpressionBlock>`
|
||||||
```
|
```
|
||||||
if num1 > 10: putchar('T')
|
if num1 > 10: putchar('T')
|
||||||
@@ -158,4 +155,4 @@ if num1 > 10: putchar('T') else
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Expression Block
|
### Expression Block
|
||||||
`(<Statement> <NL>)* (<StatementExpression> <NL>?)? <TER>!`
|
`<Statement> <NL>)* <Statement Expression>?`
|
||||||
@@ -274,48 +274,59 @@ shared_ptr<Statement> Parser::matchStatementLoop() {
|
|||||||
shared_ptr<Statement> initStatement;
|
shared_ptr<Statement> initStatement;
|
||||||
shared_ptr<Expression> preConditionExpression;
|
shared_ptr<Expression> preConditionExpression;
|
||||||
shared_ptr<Expression> postConditionExpression;
|
shared_ptr<Expression> postConditionExpression;
|
||||||
|
shared_ptr<Statement> bodyBlockStatement;
|
||||||
|
|
||||||
|
bool isMultiLine;
|
||||||
|
|
||||||
// initial
|
// initial
|
||||||
initStatement = matchStatementVariable();
|
initStatement = matchStatementVariable() ?: matchStatementAssignment();
|
||||||
if (initStatement != nullptr && !initStatement->isValid())
|
if (initStatement != nullptr && !initStatement->isValid())
|
||||||
initStatement = nullptr;
|
initStatement = nullptr;
|
||||||
|
|
||||||
if (tokens.at(currentIndex-1)->getKind() != TokenKind::NEW_LINE) {
|
if (!tryMatchingTokenKinds({TokenKind::COLON}, false, true)) {
|
||||||
// got initial, expect comma
|
// got initial, expect comma
|
||||||
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
|
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
|
||||||
return matchStatementInvalid("Expected comma after initial statement");
|
return matchStatementInvalid("Expected comma after initial statement");
|
||||||
|
|
||||||
|
// optional new line
|
||||||
|
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
|
||||||
|
|
||||||
// pre condition
|
// pre condition
|
||||||
preConditionExpression = nextExpression();
|
preConditionExpression = nextExpression();
|
||||||
if (preConditionExpression != nullptr && !preConditionExpression->isValid())
|
if (preConditionExpression != nullptr && !preConditionExpression->isValid())
|
||||||
return matchStatementInvalid("Expected pre-condition expression");
|
return matchStatementInvalid("Expected pre-condition expression");
|
||||||
|
|
||||||
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
|
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
|
||||||
// got pre-condition, expect comma
|
// got pre-condition, expect comma
|
||||||
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
|
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
|
||||||
return matchStatementInvalid("Expected comma after pre-condition statement");
|
return matchStatementInvalid("Expected comma after pre-condition statement");
|
||||||
|
|
||||||
|
// optional new line
|
||||||
|
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
|
||||||
|
|
||||||
// post condition
|
// post condition
|
||||||
postConditionExpression = nextExpression();
|
postConditionExpression = nextExpression();
|
||||||
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
|
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
|
||||||
return matchStatementInvalid("Expected post-condition expression");
|
return matchStatementInvalid("Expected post-condition expression");
|
||||||
|
|
||||||
// epxect new line
|
// expect colon
|
||||||
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
|
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true))
|
||||||
return matchStatementInvalid("Expected new line");
|
return matchStatementInvalid("Expected \":\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// body
|
isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
|
||||||
shared_ptr<Statement> bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON});
|
|
||||||
if (bodyBlockStatement == nullptr)
|
|
||||||
return matchStatementInvalid("Expected block statement");
|
|
||||||
else if (!bodyBlockStatement->isValid())
|
|
||||||
return bodyBlockStatement;
|
|
||||||
|
|
||||||
// epxect new line
|
// body
|
||||||
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
|
if (isMultiLine)
|
||||||
return matchStatementInvalid("Expected new line");
|
bodyBlockStatement = matchStatementBlock({TokenKind::SEMICOLON});
|
||||||
|
else
|
||||||
|
bodyBlockStatement = matchStatementBlock({TokenKind::NEW_LINE});
|
||||||
|
|
||||||
|
if (bodyBlockStatement == nullptr || !bodyBlockStatement->isValid())
|
||||||
|
return bodyBlockStatement ?: matchStatementInvalid("Expected block statement");
|
||||||
|
|
||||||
|
tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true);
|
||||||
|
|
||||||
return make_shared<StatementLoop>(initStatement, preConditionExpression, postConditionExpression, dynamic_pointer_cast<StatementBlock>(bodyBlockStatement));
|
return make_shared<StatementLoop>(initStatement, preConditionExpression, postConditionExpression, dynamic_pointer_cast<StatementBlock>(bodyBlockStatement));
|
||||||
}
|
}
|
||||||
@@ -563,7 +574,7 @@ shared_ptr<Expression> Parser::matchExpressionBlock(vector<TokenKind> terminalTo
|
|||||||
vector<shared_ptr<Statement>> statements;
|
vector<shared_ptr<Statement>> statements;
|
||||||
|
|
||||||
while (!tryMatchingTokenKinds(terminalTokenKinds, false, false)) {
|
while (!tryMatchingTokenKinds(terminalTokenKinds, false, false)) {
|
||||||
shared_ptr<Statement> statement = nextStatement();
|
shared_ptr<Statement> statement = nextInBlockStatement();
|
||||||
if (statement == nullptr || !statement->isValid())
|
if (statement == nullptr || !statement->isValid())
|
||||||
return matchExpressionInvalid("Expected statement");
|
return matchExpressionInvalid("Expected statement");
|
||||||
statements.push_back(statement);
|
statements.push_back(statement);
|
||||||
|
|||||||
Reference in New Issue
Block a user