Skip to content

Instantly share code, notes, and snippets.

@BraedonWooding
Last active July 9, 2018 09:22
Show Gist options
  • Save BraedonWooding/c0cf35716d40218e0aed3427cb27ada9 to your computer and use it in GitHub Desktop.
Save BraedonWooding/c0cf35716d40218e0aed3427cb27ada9 to your computer and use it in GitHub Desktop.
#ifndef AST_H
#define AST_H
#include <experimental/optional>
#include "../../Utils/utils.h"
#include <utility>
#include <vector>
#include <string>
#include "../../Utils/variant.h"
// 1 + 2 + (3 * 4) / sin(h)^3e+4 > 5
/* == Grammar ==
* equation := arithmeticExpression (comparison_op arithmeticExpression)?
* arithmeticExpression := multiplyingExpression (('+' | '-') multiplyingExpression)*
* multiplyingExpression := powExpression (('*' | '/' | '%') powExpression)*
* powExpression := signedAtom (('^') signedAtom)*
* signedAtom := sign? (func | atom)
* func := variable '(' (arithmeticExpression (',' arithmeticExpression)*)? ')'
* atom := literal
* | variable
* | '(' arithmeticExpression ')'
* literal := scientific
* | ('true' | 'false')
* variable := valid_var_start (valid_var)*
* valid_var_start := ('A' - 'z') | '_'
* valid_var := valid_var_start | ('0' - '9')
* number := ('0' - '9')+
* | '.' ('0' - '9')+
* | ('0' - '9')+ '.' ('0' - '9')+
* scientific := sign? number (('e' | 'E') sign? number)?
* sign := ('+' | '-')
* comparison_op := ('<' | '=' | '>')
*/
enum class Token
{
NONE,
GT,
LT,
EQ,
PLUS,
MINUS,
LPAREN,
RPAREN,
POW,
DIVIDE,
MODULUS,
MULTIPLY,
SCIENTIFIC_E,
COMMA,
DIGIT,
LETTER,
UNDERSCORE,
WHITE_SPACE,
OTHER,
};
using std::experimental::optional;
template<class T>
using nodePair = std::vector<std::pair<Token, std::unique_ptr<T>>>;
template<class T>
using optionalMany = optional<nodePair<T>>;
class ArithmeticExpressionNode;
class MultiplyingExpressionNode;
class PowExpressionNode;
class SignedAtomNode;
class AtomNode;
class FunctionNode;
class LiteralNode;
class VariableNode;
class ArithmeticExpressionNode
{
public:
std::unique_ptr<MultiplyingExpressionNode> lhs;
optionalMany<MultiplyingExpressionNode> rhs; // '+' | '-'
ArithmeticExpressionNode(std::unique_ptr<MultiplyingExpressionNode> lhs) : lhs(std::move(lhs)) {}
ArithmeticExpressionNode(std::unique_ptr<MultiplyingExpressionNode> lhs, nodePair<MultiplyingExpressionNode> rhs)
: lhs(std::move(lhs)), rhs(std::move(rhs)) {}
};
class EquationNode
{
public:
std::unique_ptr<ArithmeticExpressionNode> lhs;
optional<std::pair<Token, std::unique_ptr<ArithmeticExpressionNode>>> rhs; // '>', '<', '='
EquationNode(std::unique_ptr<ArithmeticExpressionNode> lhs) : lhs(std::move(lhs)) {}
EquationNode(std::unique_ptr<ArithmeticExpressionNode> lhs, optional<std::pair<Token, std::unique_ptr<ArithmeticExpressionNode>>> rhs)
: lhs(std::move(lhs)), rhs(std::move(rhs)) {}
};
class MultiplyingExpressionNode
{
public:
std::unique_ptr<PowExpressionNode> lhs;
optionalMany<PowExpressionNode> rhs; // '*' | '/' | '%'
MultiplyingExpressionNode(std::unique_ptr<PowExpressionNode> lhs) : lhs(std::move(lhs)) {}
MultiplyingExpressionNode(std::unique_ptr<PowExpressionNode> lhs, nodePair<PowExpressionNode> rhs)
: lhs(std::move(lhs)), rhs(std::move(rhs)) {}
};
class PowExpressionNode
{
public:
std::unique_ptr<SignedAtomNode> lhs;
optionalMany<SignedAtomNode> rhs; // '^'
PowExpressionNode(std::unique_ptr<SignedAtomNode> lhs) : lhs(std::move(lhs)) {}
PowExpressionNode(std::unique_ptr<SignedAtomNode> lhs, nodePair<SignedAtomNode> rhs)
: lhs(std::move(lhs)), rhs(std::move(rhs)) {}
};
class SignedAtomNode
{
typedef mpark::variant<std::unique_ptr<FunctionNode>, std::unique_ptr<AtomNode>> SignedAtomNodeExpr;
public:
std::experimental::optional<Token> sign; // '+' '-'
SignedAtomNodeExpr node;
SignedAtomNode(SignedAtomNodeExpr node) : node(std::move(node)) { }
SignedAtomNode(SignedAtomNodeExpr node, Token token) : sign(token), node(std::move(node)) { }
};
class AtomNode
{
typedef mpark::variant<std::unique_ptr<VariableNode>, std::unique_ptr<LiteralNode>, std::unique_ptr<ArithmeticExpressionNode>> AtomNodeExpr;
public:
AtomNodeExpr expr; // arithmetic is for parenthesis
AtomNode(AtomNodeExpr node) : expr(std::move(node)) { }
};
class FunctionNode
{
public:
std::string variable;
optional<std::vector<std::unique_ptr<ArithmeticExpressionNode>>> arguments;
FunctionNode(std::string variable) : variable(variable) { }
FunctionNode(std::string variable, std::vector<std::unique_ptr<ArithmeticExpressionNode>> args)
: variable(variable), arguments(std::move(args)) { }
};
class LiteralNode
{
public:
mpark::variant<bool, double> value;
LiteralNode(bool value) : value(value) { }
LiteralNode(double value) : value(value) { }
};
class VariableNode
{
public:
std::string variableName;
VariableNode(std::string variableName) : variableName(variableName) {}
};
#endif // AST_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment