#include "Parser.h" Parser::Parser(vector> tokens): tokens(tokens) { } vector> Parser::getStatements() { vector> statements; while (tokens.at(currentIndex)->getKind() != TokenKind::END) { shared_ptr statement = nextStatement(); // Abort parsing if we got an error if (!statement->isValid()) { cerr << statement->toString(0); exit(1); } statements.push_back(statement); } return statements; } // // Statement // shared_ptr Parser::nextStatement() { shared_ptr statement; statement = matchStatementFunctionDeclaration(); if (statement != nullptr) return statement; statement = matchStatementVarDeclaration(); if (statement != nullptr) return statement; statement = matchStatementReturn(); if (statement != nullptr) return statement; statement = matchStatementExpression(); if (statement != nullptr) return statement; return matchStatementInvalid(); } shared_ptr Parser::matchStatementFunctionDeclaration() { if (!matchesTokenKinds({TokenKind::IDENTIFIER, TokenKind::COLON, TokenKind::FUNCTION})) return nullptr; shared_ptr identifierToken = tokens.at(currentIndex); currentIndex++; currentIndex++; // skip colon currentIndex++; // skip fun while (tokens.at(currentIndex)->getKind() != TokenKind::NEW_LINE) { currentIndex++; } currentIndex++; // new line shared_ptr statementBlock = matchStatementBlock(); if (statementBlock == nullptr) return matchStatementInvalid(); else if (!statementBlock->isValid()) return statementBlock; else return make_shared(identifierToken->getLexme(), ValueType::SINT32, dynamic_pointer_cast(statementBlock)); } shared_ptr Parser::matchStatementVarDeclaration() { if (!matchesTokenKinds({TokenKind::IDENTIFIER, TokenKind::COLON, TokenKind::TYPE})) return nullptr; shared_ptr identifierToken = tokens.at(currentIndex); currentIndex++; currentIndex++; // skip colon shared_ptr valueTypeToken = tokens.at(currentIndex); currentIndex++; // skip fun // Expect left arrow if (tokens.at(currentIndex)->getKind() != TokenKind::LEFT_ARROW) return matchStatementInvalid(); currentIndex++; shared_ptr expression = nextExpression(); if (expression == nullptr || !expression->isValid()) return matchStatementInvalid(); ValueType valueType; if (valueTypeToken->getLexme().compare("Void") == 0) valueType = ValueType::VOID; else if (valueTypeToken->getLexme().compare("Bool") == 0) valueType = ValueType::BOOL; else if (valueTypeToken->getLexme().compare("SInt32") == 0) valueType = ValueType::SINT32; else if (valueTypeToken->getLexme().compare("Real32") == 0) valueType = ValueType::REAL32; else return matchStatementInvalid(); // Expect new line if (tokens.at(currentIndex)->getKind() != TokenKind::NEW_LINE) return matchStatementInvalid(); currentIndex++; return make_shared(identifierToken->getLexme(), valueType, expression); } shared_ptr Parser::matchStatementBlock() { vector> statements; while (!tokens.at(currentIndex)->isOfKind({TokenKind::SEMICOLON, TokenKind::COLON})) { shared_ptr statement = nextStatement(); if (statement == nullptr) return matchStatementInvalid(); else if (!statement->isValid()) return statement; else statements.push_back(statement); } // consune ';' only if (tokens.at(currentIndex)->getKind() == TokenKind::SEMICOLON) { currentIndex++; if (!tokens.at(currentIndex)->isOfKind({TokenKind::NEW_LINE, TokenKind::END})) return matchStatementInvalid(); if (tokens.at(currentIndex)->getKind() == TokenKind::NEW_LINE) currentIndex++; } return make_shared(statements); } shared_ptr Parser::matchStatementReturn() { if (tokens.at(currentIndex)->getKind() != TokenKind::RETURN) return nullptr; currentIndex++; shared_ptr expression = nextExpression(); if (expression != nullptr && !expression->isValid()) return matchStatementInvalid(); if (!tokens.at(currentIndex)->isOfKind({TokenKind::NEW_LINE, TokenKind::SEMICOLON})) return matchStatementInvalid(); if (tokens.at(currentIndex)->getKind() == TokenKind::NEW_LINE) currentIndex++; // new line return make_shared(expression); } shared_ptr Parser::matchStatementExpression() { shared_ptr expression = nextExpression(); if (expression == nullptr) return nullptr; else if (!expression->isValid()) return make_shared(tokens.at(currentIndex)); // Consume new line if (tokens.at(currentIndex)->getKind() == TokenKind::NEW_LINE) currentIndex++; return make_shared(expression); } shared_ptr Parser::matchStatementInvalid() { return make_shared(tokens.at(currentIndex)); } // // Expression // shared_ptr Parser::nextExpression() { shared_ptr expression; expression = matchEquality(); if (expression != nullptr) return expression; expression = matchExpressionIfElse(); if (expression != nullptr) return expression; expression = matchExpressionVar(); if (expression != nullptr) return expression; return nullptr; } shared_ptr Parser::matchEquality() { shared_ptr expression = matchComparison(); if (expression == nullptr || !expression->isValid()) return expression; while (tokens.at(currentIndex)->isOfKind(Token::tokensEquality)) expression = matchExpressionBinary(expression); return expression; } shared_ptr Parser::matchComparison() { shared_ptr expression = matchTerm(); if (expression == nullptr || !expression->isValid()) return expression; while (tokens.at(currentIndex)->isOfKind(Token::tokensComparison)) expression = matchExpressionBinary(expression); return expression; } shared_ptr Parser::matchTerm() { shared_ptr expression = matchFactor(); if (expression == nullptr || !expression->isValid()) return expression; while (tokens.at(currentIndex)->isOfKind(Token::tokensTerm)) expression = matchExpressionBinary(expression); return expression; } shared_ptr Parser::matchFactor() { shared_ptr expression = matchPrimary(); if (expression == nullptr || !expression->isValid()) return expression; while (tokens.at(currentIndex)->isOfKind(Token::tokensFactor)) expression = matchExpressionBinary(expression); return expression; } shared_ptr Parser::matchPrimary() { shared_ptr expression; expression = matchExpressionLiteral(); if (expression != nullptr) return expression; expression = matchExpressionGrouping(); if (expression != nullptr) return expression; return nullptr; } shared_ptr Parser::matchExpressionLiteral() { shared_ptr token = tokens.at(currentIndex); if (token->isOfKind({TokenKind::BOOL, TokenKind::INTEGER, TokenKind::REAL})) { currentIndex++; return make_shared(token); } return nullptr; } shared_ptr Parser::matchExpressionGrouping() { shared_ptr token = tokens.at(currentIndex); if (token->getKind() == TokenKind::LEFT_PAREN) { currentIndex++; shared_ptr expression = matchTerm(); // has grouped expression failed? if (expression == nullptr) { return matchExpressionInvalid(); } else if(!expression->isValid()) { return expression; } else if (tokens.at(currentIndex)->getKind() == TokenKind::RIGHT_PAREN) { currentIndex++; return make_shared(expression); } else { return matchExpressionInvalid(); } } return nullptr; } shared_ptr Parser::matchExpressionBinary(shared_ptr left) { shared_ptr token = tokens.at(currentIndex); shared_ptr right; // What level of binary expression are we having? if (token->isOfKind(Token::tokensEquality)) { currentIndex++; right = matchComparison(); } else if (token->isOfKind(Token::tokensComparison)) { currentIndex++; right = matchTerm(); } else if (token->isOfKind(Token::tokensTerm)) { currentIndex++; right = matchFactor(); } else if (token->isOfKind(Token::tokensFactor)) { currentIndex++; right = matchPrimary(); } if (right == nullptr) { return matchExpressionInvalid(); } else if (!right->isValid()) { return right; } else { return make_shared(token, left, right); } return nullptr; } shared_ptr Parser::matchExpressionIfElse() { // Try maching '?' shared_ptr token = tokens.at(currentIndex); if (token->getKind() != TokenKind::QUESTION) return nullptr; currentIndex++; // Then get condition shared_ptr condition = nextExpression(); if (condition == nullptr) return matchExpressionInvalid(); else if (!condition->isValid()) return condition; // Match ':', '\n', or ':\n' if (matchesTokenKinds({TokenKind::COLON, TokenKind::NEW_LINE})) currentIndex += 2; else if (tokens.at(currentIndex)->isOfKind({TokenKind::COLON, TokenKind::NEW_LINE})) currentIndex++; else return matchExpressionInvalid(); // Match then block shared_ptr thenBlock = matchStatementBlock(); if (thenBlock == nullptr) return matchExpressionInvalid(); else if (!thenBlock->isValid()) return matchExpressionInvalid(); // FIXME // Match else block shared_ptr elseBlock; if (tokens.at(currentIndex)->getKind() == TokenKind::COLON) { currentIndex++; if (tokens.at(currentIndex)->getKind() == TokenKind::NEW_LINE) currentIndex++; elseBlock = matchStatementBlock(); 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--; } return make_shared(condition, dynamic_pointer_cast(thenBlock), dynamic_pointer_cast(elseBlock)); } shared_ptr Parser::matchExpressionVar() { shared_ptr token = tokens.at(currentIndex); if (token->isOfKind({TokenKind::IDENTIFIER})) { currentIndex++; return make_shared(token->getLexme()); } return nullptr; } shared_ptr Parser::matchExpressionInvalid() { return make_shared(tokens.at(currentIndex)); } bool Parser::matchesTokenKinds(vector kinds) { if (currentIndex + kinds.size() >= tokens.size()) return false; for (int i=0; igetKind()) return false; } return true; }