Remove the IR for know for simplicity
This commit is contained in:
240
source/parser.cpp
Normal file
240
source/parser.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
#include "elna/parser.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
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;
|
||||
|
||||
if (_operator == '+')
|
||||
{
|
||||
this->_operator = BinaryOperator::sum;
|
||||
}
|
||||
else if (_operator == '-')
|
||||
{
|
||||
this->_operator = BinaryOperator::subtraction;
|
||||
}
|
||||
else
|
||||
{
|
||||
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(Token *tokenStream, std::size_t length)
|
||||
{
|
||||
return parseBlock(&tokenStream, &length);
|
||||
}
|
||||
|
||||
Expression *parseFactor(Token **tokens, size_t *length)
|
||||
{
|
||||
if ((*tokens)[0].of() == Token::TOKEN_IDENTIFIER)
|
||||
{
|
||||
auto variable = new Variable();
|
||||
variable->identifier = (*tokens)[0].identifier();
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
return variable;
|
||||
}
|
||||
else if ((*tokens)[0].of() == Token::TOKEN_NUMBER)
|
||||
{
|
||||
auto number = new Number();
|
||||
number->value = (*tokens)[0].number();
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
return number;
|
||||
}
|
||||
else if ((*tokens)[0].of() == Token::TOKEN_LEFT_PAREN)
|
||||
{
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
|
||||
auto expression = parseExpression(tokens, length);
|
||||
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
|
||||
return expression;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Expression *parseTerm(Token **tokens, size_t *length)
|
||||
{
|
||||
return parseFactor(tokens, length);
|
||||
}
|
||||
|
||||
Expression *parseExpression(Token **tokens, size_t *length)
|
||||
{
|
||||
auto term = parseTerm(tokens, length);
|
||||
if (term == nullptr || *length == 0 || (*tokens)[0].of() != Token::TOKEN_OPERATOR)
|
||||
{
|
||||
return term;
|
||||
}
|
||||
auto _operator = (*tokens)[0].identifier()[0];
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
|
||||
auto expression = parseExpression(tokens, length);
|
||||
|
||||
if (expression != nullptr)
|
||||
{
|
||||
auto binaryExpression = new BinaryExpression(term, expression, _operator);
|
||||
|
||||
return binaryExpression;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Definition *parseDefinition(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() == Token::TOKEN_NUMBER)
|
||||
{
|
||||
auto number = new Number();
|
||||
number->value = (*tokens)[0].number();
|
||||
definition->number = number;
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
return definition;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Statement *parseStatement(Token **tokens, std::size_t *length)
|
||||
{
|
||||
if ((*tokens)[0].of() == Token::TOKEN_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(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<Definition **>(
|
||||
realloc(definitions, (*resultLength + 1) * sizeof(Definition*)));
|
||||
definitions[(*resultLength)++] = definition;
|
||||
|
||||
if ((*tokens)[0].of() == Token::TOKEN_SEMICOLON)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((*tokens)[0].of() == Token::TOKEN_COMMA)
|
||||
{
|
||||
++(*tokens);
|
||||
--(*length);
|
||||
}
|
||||
}
|
||||
|
||||
return definitions;
|
||||
}
|
||||
|
||||
Block *parseBlock(Token **tokens, std::size_t *length)
|
||||
{
|
||||
auto block = new Block();
|
||||
if ((*tokens)[0].of() == Token::TOKEN_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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user