| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #pragma once
- #include "codeobject.h"
- #include "common.h"
- #include "expr.h"
- #include "obj.h"
- namespace pkpy{
- class Compiler;
- typedef void (Compiler::*PrattCallback)();
- struct PrattRule{
- PrattCallback prefix;
- PrattCallback infix;
- Precedence precedence;
- };
- class Compiler {
- inline static PrattRule rules[kTokenCount];
- std::unique_ptr<Lexer> lexer;
- stack<CodeEmitContext> contexts;
- VM* vm;
- bool unknown_global_scope; // for eval/exec() call
- bool used;
- // for parsing token stream
- int i = 0;
- std::vector<Token> tokens;
- const Token& prev() const{ return tokens.at(i-1); }
- const Token& curr() const{ return tokens.at(i); }
- const Token& next() const{ return tokens.at(i+1); }
- const Token& err() const{
- if(i >= tokens.size()) return prev();
- return curr();
- }
- void advance(int delta=1) { i += delta; }
- CodeEmitContext* ctx() { return &contexts.top(); }
- CompileMode mode() const{ return lexer->src->mode; }
- NameScope name_scope() const;
- CodeObject_ push_global_context();
- FuncDecl_ push_f_context(Str name);
- void pop_context();
- static void init_pratt_rules();
- bool match(TokenIndex expected);
- void consume(TokenIndex expected);
- bool match_newlines_repl();
- bool match_newlines(bool repl_throw=false);
- bool match_end_stmt();
- void consume_end_stmt();
- /*************************************************/
- void EXPR(bool push_stack=true);
- void EXPR_TUPLE(bool push_stack=true);
- Expr_ EXPR_VARS(); // special case for `for loop` and `comp`
- template <typename T, typename... Args>
- std::unique_ptr<T> make_expr(Args&&... args) {
- std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
- expr->line = prev().line;
- return expr;
- }
- template<typename T>
- void _consume_comp(Expr_ expr){
- static_assert(std::is_base_of<CompExpr, T>::value);
- std::unique_ptr<CompExpr> ce = make_expr<T>();
- ce->expr = std::move(expr);
- ce->vars = EXPR_VARS();
- consume(TK("in"));
- parse_expression(PREC_TERNARY + 1);
- ce->iter = ctx()->s_expr.popx();
- match_newlines_repl();
- if(match(TK("if"))){
- parse_expression(PREC_TERNARY + 1);
- ce->cond = ctx()->s_expr.popx();
- }
- ctx()->s_expr.push(std::move(ce));
- match_newlines_repl();
- }
- void exprLiteral();
- void exprLong();
- void exprBytes();
- void exprFString();
- void exprLambda();
- void exprTuple();
- void exprOr();
- void exprAnd();
- void exprTernary();
- void exprBinaryOp();
- void exprNot();
- void exprUnaryOp();
- void exprGroup();
- void exprList();
- void exprMap();
- void exprCall();
- void exprName();
- void exprAttrib();
- void exprSubscr();
- void exprLiteral0();
- void compile_block_body();
- void compile_normal_import();
- void compile_from_import();
- bool is_expression();
- void parse_expression(int precedence, bool push_stack=true);
- void compile_if_stmt();
- void compile_while_loop();
- void compile_for_loop();
- void compile_try_except();
- void compile_decorated();
- bool try_compile_assignment();
- void compile_stmt();
- void consume_type_hints();
- void compile_class();
- void _compile_f_args(FuncDecl_ decl, bool enable_type_hints);
- void compile_function(const std::vector<Expr_>& decorators={});
- PyObject* to_object(const TokenValue& value);
- PyObject* read_literal();
- void SyntaxError(Str msg){ lexer->throw_err("SyntaxError", msg, err().line, err().start); }
- void SyntaxError(){ lexer->throw_err("SyntaxError", "invalid syntax", err().line, err().start); }
- void IndentationError(Str msg){ lexer->throw_err("IndentationError", msg, err().line, err().start); }
- public:
- Compiler(VM* vm, const Str& source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
- CodeObject_ compile();
- Compiler(const Compiler&) = delete;
- Compiler& operator=(const Compiler&) = delete;
- };
- } // namespace pkpy
|