#include "elna/parser.hpp" #include namespace elna { /** * AST node. */ void Node::accept(ParserVisitor *) { } void Definition::accept(ParserVisitor *visitor) { visitor->visit(this); } void Block::accept(ParserVisitor *visitor) { visitor->visit(this); } void Expression::accept(ParserVisitor *visitor) { visitor->visit(this); } void Number::accept(ParserVisitor *visitor) { visitor->visit(this); } void Variable::accept(ParserVisitor *visitor) { visitor->visit(this); } BinaryExpression::BinaryExpression(Expression *lhs, Expression *rhs, unsigned char _operator) { this->lhs = lhs; this->rhs = rhs; switch (_operator) { case '+': this->_operator = BinaryOperator::sum; break; case '-': this->_operator = BinaryOperator::subtraction; break; case '*': this->_operator = BinaryOperator::multiplication; break; case '/': this->_operator = BinaryOperator::division; break; default: throw std::logic_error("Invalid binary operator"); } } void BinaryExpression::accept(ParserVisitor *visitor) { visitor->visit(this); } void BangStatement::accept(ParserVisitor *visitor) { visitor->visit(this); } Block *parse(lex::Token *tokenStream, std::size_t length) { return parseBlock(&tokenStream, &length); } Expression *parseFactor(lex::Token **tokens, size_t *length) { if ((*tokens)[0].of() == lex::Token::type::identifier) { auto variable = new Variable(); variable->identifier = (*tokens)[0].identifier(); ++(*tokens); --(*length); return variable; } else if ((*tokens)[0].of() == lex::Token::Token::type::number) { auto number = new Number(); number->value = (*tokens)[0].number(); ++(*tokens); --(*length); return number; } else if ((*tokens)[0].of() == lex::Token::type::left_paren) { ++(*tokens); --(*length); auto expression = parseExpression(tokens, length); ++(*tokens); --(*length); return expression; } return nullptr; } Expression *parseTerm(lex::Token **tokens, size_t *length) { auto lhs = parseFactor(tokens, length); if (lhs == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::factor_operator) { return lhs; } auto _operator = (*tokens)[0].identifier()[0]; ++(*tokens); --(*length); auto rhs = parseFactor(tokens, length); if (rhs != nullptr) { return new BinaryExpression(lhs, rhs, _operator); } return nullptr; } Expression *parseExpression(lex::Token **tokens, size_t *length) { auto term = parseTerm(tokens, length); if (term == nullptr || *length == 0 || (*tokens)[0].of() != lex::Token::type::term_operator) { return term; } auto _operator = (*tokens)[0].identifier()[0]; ++(*tokens); --(*length); auto expression = parseExpression(tokens, length); if (expression != nullptr) { return new BinaryExpression(term, expression, _operator); } return nullptr; } Definition *parseDefinition(lex::Token **tokens, size_t *length) { auto definition = new Definition(); definition->identifier = (*tokens)[0].identifier(); // Copy. ++(*tokens); ++(*tokens); // Skip the equals sign. *length -= 2; if ((*tokens)[0].of() == lex::Token::type::number) { auto number = new Number(); number->value = (*tokens)[0].number(); definition->number = number; ++(*tokens); --(*length); return definition; } return nullptr; } Statement *parseStatement(lex::Token **tokens, std::size_t *length) { if ((*tokens)[0].of() == lex::Token::type::bang) { ++(*tokens); --(*length); auto statement = new BangStatement(); auto expression = parseExpression(tokens, length); if (expression != nullptr) { statement->expression = expression; } else { return nullptr; } return statement; } return nullptr; } Definition **parseDefinitions(lex::Token **tokens, size_t *length, size_t *resultLength) { ++(*tokens); // Skip const. --(*length); Definition **definitions; *resultLength = 0; while (*length != 0) { auto definition = parseDefinition(tokens, length); if (definition == nullptr) { return nullptr; } definitions = reinterpret_cast( realloc(definitions, (*resultLength + 1) * sizeof(Definition*))); definitions[(*resultLength)++] = definition; if ((*tokens)[0].of() == lex::Token::type::semicolon) { break; } if ((*tokens)[0].of() == lex::Token::type::comma) { ++(*tokens); --(*length); } } return definitions; } Block *parseBlock(lex::Token **tokens, std::size_t *length) { auto block = new Block(); if ((*tokens)[0].of() == lex::Token::type::let) { size_t length_ = 0; auto constDefinitions = parseDefinitions(tokens, length, &length_); if (constDefinitions != nullptr) { block->definitionsLength = length_; block->definitions = constDefinitions; } else { return nullptr; } ++(*tokens); --(*length); } auto statement = parseStatement(tokens, length); if (statement != nullptr) { block->statement = statement; } else { return nullptr; } return block; } }