diff --git a/src/Lexer.cpp b/src/Lexer.cpp index f09fb19..08ca571 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -20,6 +20,10 @@ vector> Lexer::getTokens() { exit(1); } + // Insert an additional new line just before end + if (token->getKind() == TokenKind::END && tokens.back()->getKind() != TokenKind::NEW_LINE) + tokens.push_back(make_shared(TokenKind::NEW_LINE, "\n", token->getLine(), token->getColumn())); + // filter out multiple new lines if (tokens.empty() || token->getKind() != TokenKind::NEW_LINE || tokens.back()->getKind() != token->getKind()) tokens.push_back(token); diff --git a/src/Parser.cpp b/src/Parser.cpp index 7d18952..094300f 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -45,7 +45,6 @@ shared_ptr Parser::nextStatement() { } shared_ptr Parser::matchStatementFunctionDeclaration() { - //if (!matchesTokenKinds({TokenKind::IDENTIFIER, TokenKind::COLON, TokenKind::FUNCTION})) if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::COLON, TokenKind::FUNCTION}, true, false)) return nullptr; @@ -59,13 +58,16 @@ shared_ptr Parser::matchStatementFunctionDeclaration() { currentIndex++; currentIndex++; // new line - shared_ptr statementBlock = matchStatementBlock(); + shared_ptr statementBlock = matchStatementBlock({TokenKind::SEMICOLON}, true); if (statementBlock == nullptr) return matchStatementInvalid(); else if (!statementBlock->isValid()) return statementBlock; - else - return make_shared(identifierToken->getLexme(), ValueType::SINT32, dynamic_pointer_cast(statementBlock)); + + if(!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true)) + return matchStatementInvalid("Expected a new line after a function declaration"); + + return make_shared(identifierToken->getLexme(), ValueType::SINT32, dynamic_pointer_cast(statementBlock)); } shared_ptr Parser::matchStatementVarDeclaration() { @@ -99,16 +101,17 @@ shared_ptr Parser::matchStatementVarDeclaration() { return matchStatementInvalid(); // Expect new line - if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) - return matchStatementInvalid("Expected a new line"); + if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true)) + return matchStatementInvalid("Expected a new line after variable declaration"); return make_shared(identifierToken->getLexme(), valueType, expression); } -shared_ptr Parser::matchStatementBlock() { +shared_ptr Parser::matchStatementBlock(vector terminalTokenKinds, bool shouldConsumeTerminal) { vector> statements; - while (!tryMatchingTokenKinds({TokenKind::SEMICOLON, TokenKind::COLON}, false, false)) { + bool hasNewLineTerminal = find(terminalTokenKinds.begin(), terminalTokenKinds.end(), TokenKind::NEW_LINE) != terminalTokenKinds.end(); + while (!tryMatchingTokenKinds(terminalTokenKinds, false, shouldConsumeTerminal)) { shared_ptr statement = nextStatement(); if (statement == nullptr) return matchStatementInvalid(); @@ -116,15 +119,12 @@ shared_ptr Parser::matchStatementBlock() { return statement; else statements.push_back(statement); - } - // consune ';' only - if (tryMatchingTokenKinds({TokenKind::SEMICOLON}, true, true)) { - if (!tryMatchingTokenKinds({TokenKind::NEW_LINE, TokenKind::END}, false, false)) - return matchStatementInvalid(); - tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + if (hasNewLineTerminal && tokens.at(currentIndex-1)->getKind() == TokenKind::NEW_LINE) + currentIndex--; } + return make_shared(statements); } @@ -302,7 +302,6 @@ shared_ptr Parser::matchExpressionIfElse() { // Try maching '?' shared_ptr token = tokens.at(currentIndex); - //if (!tryAdvancingForOneOfTokenKinds({TokenKind::QUESTION})) if (!tryMatchingTokenKinds({TokenKind::QUESTION}, true, true)) return nullptr; @@ -313,37 +312,33 @@ shared_ptr Parser::matchExpressionIfElse() { else if (!condition->isValid()) return condition; - // Match ':', '\n', or ':\n' - if (tryMatchingTokenKinds({TokenKind::COLON, TokenKind::NEW_LINE}, true, false)) - currentIndex += 2; - else if (tryMatchingTokenKinds({TokenKind::COLON, TokenKind::NEW_LINE}, false, false)) - currentIndex++; - else - return matchExpressionInvalid(); + // Consume optional ':' + tryMatchingTokenKinds({TokenKind::COLON}, true, true); + // Consume optional new line + tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // Match then block - shared_ptr thenBlock = matchStatementBlock(); + shared_ptr thenBlock = matchStatementBlock({TokenKind::COLON, TokenKind::SEMICOLON}, false); if (thenBlock == nullptr) return matchExpressionInvalid(); else if (!thenBlock->isValid()) return matchExpressionInvalid(); // FIXME - // Match else block + // Match else block. Then and else block are separated by ':' shared_ptr elseBlock; - if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) { - tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + bool isSingleLine = !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); + vector terminalTokens = {TokenKind::SEMICOLON}; + if (isSingleLine) + terminalTokens.push_back(TokenKind::NEW_LINE); - elseBlock = matchStatementBlock(); + elseBlock = matchStatementBlock(terminalTokens, false); if (elseBlock == nullptr) return matchExpressionInvalid(); else if (!elseBlock->isValid()) return matchExpressionInvalid(); // FIXME - - // hack to treat statement as an expression - if (tokens.at(currentIndex-1)->getKind() == TokenKind::NEW_LINE) - currentIndex--; } + tryMatchingTokenKinds({TokenKind::SEMICOLON}, true, true); return make_shared(condition, dynamic_pointer_cast(thenBlock), dynamic_pointer_cast(elseBlock)); } diff --git a/src/Parser.h b/src/Parser.h index b3f1fda..39d1ce7 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -17,7 +17,7 @@ private: shared_ptr nextStatement(); shared_ptr matchStatementFunctionDeclaration(); shared_ptr matchStatementVarDeclaration(); - shared_ptr matchStatementBlock(); + shared_ptr matchStatementBlock(vector terminalTokenKinds, bool shouldConsumeTerminal); shared_ptr matchStatementReturn(); shared_ptr matchStatementExpression(); shared_ptr matchStatementInvalid(string message = ""); diff --git a/src/Statement.cpp b/src/Statement.cpp index cef5634..4be7302 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -177,7 +177,7 @@ Statement(StatementKind::INVALID), token(token), message(message) { } string StatementInvalid::toString(int indent) { - return "Error for token " + token->getLexme() + " at " + to_string(token->getLine()) + ":" + to_string(token->getColumn()) + ": " + message + "\n"; + return "Error for token " + token->toString() + " at " + to_string(token->getLine()) + ":" + to_string(token->getColumn()) + ": " + message + "\n"; } string StatementInvalid::getMessage() {