#ifndef DEF_PARSER_H #define DEF_PARSER_H #include #include #include #include "tokenize.h" using namespace std; /** Grammar: Prog -> Instruction Prog | Instruction Instruction -> Statement | ExprStatement; | Expr; | ; Statement -> | { Prog } | If (Expr) Instruction Else Instruction ExprStatement -> | Type ParIdentifier = Expr // AssignedDeclaration | Type ParIdentifier // Declaration Expr -> | T | T + Expr | T - Expr T -> | U | U * T | U / T | U % T U -> | F | - U | + U F -> | Number | ++ParIdentifier | --ParIdentifier | ParIdentifier = Expr // Assignment | ParIdentifier++ | ParIdentifier-- | ParIdentifier // This makes the grammar ambiguous but simpler to parse | (Expr) ParIdentifier -> | Identifier | (ParIdentifier) */ /** * Type de Noeuds */ enum class NodeType { /* On ne créé pas de nouveau noeud -> ; Prog */ Prog, // -> Instruction Prog Epsilon, // -> ; AssignedDeclaration, // -> Type Identifier = Expr Declaration, // -> Type Identifier Plus, // -> T + Expr Minus, // -> T - Expr Mult, // -> F * T Div, // -> F / T Mod, // -> F % T UnaryMinus, // -> -F UnaryPlus, // -> +F Assignment, // -> Identifier = Expr LIncr, // -> ++ParIdentifier RIncr, // -> ParIdentifier++ LDecr, // -> --ParIdentifier RDecr // -> ParIdentifier-- }; struct InnerNode; /** * InnerNode: noeud interne * Token: feuille */ using Node = variant; /** * Noeud interne */ struct InnerNode { NodeType type; vector children; CodePosition pos; }; // A Leaf is always corresponding to a Token /** * Node: AST * tokens: tokens pas encore parsés */ struct ParseReturn { Node node; vector tokens; }; /** * Utilisé pour revenir en arrière quand quelque chose n'est pas reconnu */ class ParseException : public std::exception { const char* what() const noexcept override { return "Parse Exception"; } }; class SyntaxError : public runtime_error { public: explicit SyntaxError(const string& message, CodePosition pos) : runtime_error(message), pos(pos) {} const CodePosition pos; }; /** * Parse a list of tokens and return the associated AST */ Node parse(vector tokens); /** * Parse something derivated from Instruction */ ParseReturn parse_instruction(vector tokens); /** * Parse something derivated from Statement */ ParseReturn parse_statement(vector tokens); /** * Parse something derivated from ExprStatement */ ParseReturn parse_expr_statement(vector tokens); /** * Parse something derivated from Expr */ ParseReturn parse_expr(vector tokens); /** * Parse something derivated from T */ ParseReturn parse_t(vector tokens); /** * Parse something derivated from U */ ParseReturn parse_u(vector tokens); /** * Parse something derivated from F */ ParseReturn parse_f(vector tokens); /** * Parse something derivated from ParIdentifier * (An identifier with 0+ parentheses around it) */ ParseReturn parse_par_identifier(vector tokens); /** * Prints a tree for debugging it */ void _debug_print_tree(const Node& node, int depth, const string& prefix); /** * Returns the CodePosition of a node */ CodePosition get_node_pos(Node node); #endif