| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /**
- ******************************************************************************
- * @file : compiler.c
- * @author : simon
- * @brief : None
- * @attention : None
- * @date : 2023/8/17
- ******************************************************************************
- */
- #include "compiler.h"
- #include "common.h"
- #include "scanner.h"
- #ifdef DEBUG_PRINT_CODE
- #include "debug.h"
- #endif
- typedef struct {
- Token current;
- Token previous;
- bool hadError;
- bool panicMode;
- } Parser;
- typedef enum {
- PREC_NONE,
- PREC_ASSIGNMENT,// =
- PREC_OR, // or
- PREC_AND, // and
- PREC_EQUALITY, // == !=
- PREC_COMPARISON,// < > <= >=
- PREC_TERM, // + -
- PREC_FACTOR, // * /
- PREC_UNARY, // ! -
- PREC_CALL, // . ()
- PREC_PRIMARY
- } Precedence;
- typedef void (*ParseFn)(bool canAssign);
- typedef struct {
- ParseFn prefix;
- ParseFn infix;
- Precedence precedence;
- } ParseRule;
- typedef struct {
- Token name;
- int depth;
- } Local;
- typedef enum {
- TYPE_FUNCTION,
- TYPE_SCRIPT,
- } FunctionType;
- typedef struct Compiler {
- struct Compiler *enclosing;
- ObjFunction *function;
- FunctionType type;
- Local locals[UINT8_COUNT];
- int localCount;/// how many locals are in scope
- int scopeDepth;
- } Compiler;
- Parser parser;
- Compiler *current = NULL;
- static void parsePrecedence(Precedence);
- static uint8_t parseVariable(const char *);
- static void defineVariable(uint8_t);
- static uint8_t identifierConstant(Token *name);
- static bool identifiersEqual(Token *a, Token *b);
- static ParseRule *getRule(TokenType);
- static void statement();
- static void declaration();
- static void markInitialized();
- static void initCompiler(Compiler *compiler, FunctionType type);
- static void beginScope();
- static void endScope();
- static void block();
- static ObjFunction *endCompiler();
- static Chunk *currentChunk() {
- return ¤t->function->chunk;
- }
- static void errorAt(Token *token, const char *message) {
- if (parser.panicMode) return;
- parser.panicMode = true;
- fprintf(stderr, "[line %d] Error", token->line);
- if (token->type == TOKEN_EOF) {
- fprintf(stderr, " at end");
- } else if (token->type == TOKEN_ERROR) {
- ///! Nothing.
- } else {
- fprintf(stderr, " at '%.*s'", token->length, token->start);
- }
- fprintf(stderr, ": %s\n", message);
- parser.hadError = true;
- }
- static void error(const char *message) {
- errorAt(&parser.previous, message);
- }
- static void errorAtCurrent(const char *message) {
- errorAt(&parser.current, message);
- }
- static void advance() {
- parser.previous = parser.current;
- for (;;) {
- parser.current = scanToken();
- if (parser.current.type != TOKEN_ERROR) break;
- errorAtCurrent(parser.current.start);
- }
- }
- void consume(TokenType type, const char *message) {
- if (parser.current.type == type) {
- advance();
- return;
- }
- errorAtCurrent(message);
- }
- static bool check(TokenType type) {
- return parser.current.type == type;
- }
- static bool match(TokenType type) {
- if (!check(type)) return false;
- advance();
- return true;
- }
- static void emitByte(uint8_t byte) {
- writeChunk(currentChunk(), byte, parser.previous.line);
- }
- static void emitBytes(uint8_t byte1, uint8_t byte2) {
- emitByte(byte1);
- emitByte(byte2);
- }
- static void emitLoop(int loopStart) {
- emitByte(OP_LOOP);
- int offset = currentChunk()->count - loopStart + 2;
- if (offset > UINT16_MAX) error("Loop body too large.");
- emitByte((offset >> 8) & 0xFF);
- emitByte(offset & 0xFF);
- }
- static int emitJump(uint8_t instruction) {
- emitByte(instruction);
- emitByte(0xff);// 占位字节,后面填入需要跳转的 offset
- emitByte(0xff);//
- return currentChunk()->count - 2;
- }
- static void emitReturn() {
- emitByte(OP_RETURN);
- }
- static uint8_t makeConstant(Value value) {
- int constant = addConstant(currentChunk(), value);
- if (constant > UINT8_MAX) {
- error("Too many constants in one chunk.");
- return 0;
- }
- return (uint8_t) constant;
- }
- static void expression() {
- parsePrecedence(PREC_ASSIGNMENT);
- }
- static void function(FunctionType type) {
- Compiler compiler;
- initCompiler(&compiler, type);
- beginScope();
- consume(TOKEN_LEFT_PAREN, "Expect '(' after function name.");
- ///! Parameters
- if (!check(TOKEN_RIGHT_PAREN)) {
- do {
- current->function->arity++;
- if (current->function->arity > 255) {
- errorAtCurrent("Can't have more than 255 parameters.");
- }
- uint8_t constant = parseVariable("Expect parameter name.");
- defineVariable(constant);
- } while (match(TOKEN_COMMA));
- }
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after parameters.");
- consume(TOKEN_LEFT_BRACE, "Expect '{' before function body.");
- ///! Body
- block();
- ObjFunction *fun = endCompiler();
- emitBytes(OP_CONSTANT, makeConstant(OBJ_VAL(fun)));
- }
- static void funDeclaration() {
- uint8_t global = parseVariable("Expect function name.");
- markInitialized();
- function(TYPE_FUNCTION);
- defineVariable(global);
- }
- /// for example: var a; var b = 10;
- static void varDeclaration() {
- uint8_t global = parseVariable("Expect variable name.");
- // 变量初始化
- if (match(TOKEN_EQUAL)) {
- expression();
- } else {
- emitByte(OP_NIL);
- }
- consume(TOKEN_SEMICOLON, "Expect ';' after variable declaration.");
- defineVariable(global);
- }
- static void expressionStatement() {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
- emitByte(OP_POP);
- }
- static void patchJump(int offset) {
- // -2 to adjust for the bytecode for the jump offset itself.
- int jump = currentChunk()->count - offset - 2;
- if (jump > UINT16_MAX) error("Too much code to jump over.");
- currentChunk()->code[offset] = (jump >> 8) & 0xFF;
- currentChunk()->code[offset + 1] = jump & 0xFF;
- }
- static void forStatement() {
- /**
- * *********************************************************
- * initializer clause
- * L4: condition expression
- * OP_JUMP_IF_FALSE L1
- * OP_POP
- * OP_JUMP L3
- * L2: increment expression
- * OP_POP
- * OP_LOOP L4
- * L3: body statement
- * OP_LOOP L2
- * L1: OP_POP
- * continues...
- * *********************************************************
- */
- beginScope();
- // for(I;II;III)
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
- ///! I.<<Initializer Part>>
- if (match(TOKEN_SEMICOLON)) {
- // No initializer.
- } else if (match(TOKEN_VAR)) {
- varDeclaration();
- } else {
- expressionStatement();// ; op_pop
- }
- ///! II.<<Condition Part>>
- int loopStart = currentChunk()->count;
- int exitJump = -1;
- if (!match(TOKEN_SEMICOLON)) {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after loop conditon. ");
- // Jump out of the loop if the condition is false.
- exitJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- }
- ///! III.<<Increment Clause>>
- if (!match(TOKEN_RIGHT_PAREN)) {
- int bodyJump = emitJump(OP_JUMP);
- int incrementStart = currentChunk()->count;
- expression();
- emitByte(OP_POP);
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after for clauses.");
- emitLoop(loopStart);
- loopStart = incrementStart;
- patchJump(bodyJump);
- }
- ///! <<Body Part>>
- statement();
- emitLoop(loopStart);
- if (exitJump != -1) {
- patchJump(exitJump);
- emitByte(OP_POP);// Condition.
- }
- endScope();
- }
- static void ifStatement() {
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
- expression();
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
- int thenJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- statement();// then branch statement
- int elseJump = emitJump(OP_JUMP);
- patchJump(thenJump);
- emitByte(OP_POP);
- if (match(TOKEN_ELSE)) statement();// else branch statement
- patchJump(elseJump);
- }
- static void whileStatement() {
- int loopStart = currentChunk()->count;
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'while'.");
- expression();// while condition.
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
- int exitJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- statement();// while body.
- emitLoop(loopStart);
- patchJump(exitJump);
- emitByte(OP_POP);
- }
- static void printStatement() {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after value.");
- emitByte(OP_PRINT);
- }
- static void synchronize() {
- parser.panicMode = false;
- while (parser.current.type != TOKEN_EOF) {
- if (parser.previous.type == TOKEN_SEMICOLON) return;
- switch (parser.current.type) {
- case TOKEN_CLASS:
- case TOKEN_FUN:
- case TOKEN_VAR:
- case TOKEN_FOR:
- case TOKEN_IF:
- case TOKEN_WHILE:
- case TOKEN_PRINT:
- case TOKEN_RETURN:
- return;
- default:;// Do nothing.
- }
- advance();
- }
- }
- ///declaration → classDecl
- /// | funDecl
- /// | varDecl
- /// | statement ;
- static void declaration() {
- if (match(TOKEN_FUN)) {
- funDeclaration();
- } else if (match(TOKEN_VAR)) {
- varDeclaration();
- } else {
- statement();
- }
- if (parser.panicMode) synchronize();
- }
- static void block() {
- while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF)) {
- declaration();
- }
- consume(TOKEN_RIGHT_BRACE, "Expect '}' after block.");
- }
- ///statement → exprStmt
- /// | forStmt
- /// | ifStmt
- /// | printStmt
- /// | returnStmt
- /// | whileStmt
- /// | block ;
- static void statement() {
- if (match(TOKEN_PRINT)) {
- printStatement();
- } else if (match(TOKEN_FOR)) {
- forStatement();
- } else if (match(TOKEN_IF)) {
- ifStatement();
- } else if (match(TOKEN_WHILE)) {
- whileStatement();
- } else if (match(TOKEN_LEFT_BRACE)) {
- ///! block → "{" declaration* "}" ;
- beginScope();
- block();
- endScope();
- } else {
- expressionStatement();
- }
- }
- static void beginScope() {
- current->scopeDepth++;
- }
- static void endScope() {
- current->scopeDepth--;
- while (current->localCount > 0
- && current->locals[current->localCount - 1].depth > current->scopeDepth) {
- emitByte(OP_POP);
- current->localCount--;
- }
- }
- static void emitConstant(Value value) {
- emitBytes(OP_CONSTANT, makeConstant(value));
- }
- static void initCompiler(Compiler *compiler, FunctionType type) {
- compiler->enclosing = current;// 上一极的 compiler
- compiler->function = NULL;
- compiler->type = type;
- compiler->localCount = 0;
- compiler->scopeDepth = 0;
- compiler->function = newFunction();
- current = compiler;
- if (type != TYPE_SCRIPT) {
- ///! Function name
- current->function->name = copyString(parser.previous.start, parser.previous.length);
- }
- Local *local = ¤t->locals[current->localCount++];
- local->depth = 0;
- local->name.start = "";
- local->name.length = 0;
- }
- static ObjFunction *endCompiler() {
- emitReturn();
- ObjFunction *function = current->function;
- #ifdef DEBUG_PRINT_CODE
- if (!parser.hadError) {
- disassembleChunk(currentChunk(), function->name != NULL ? function->name->chars : "<script>");
- }
- #endif
- current = current->enclosing;// 当前的 compiler 变成上级 compiler
- return function;
- }
- static void grouping(__attribute__((unused)) bool canAssign) {
- expression();
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
- }
- /// \brief parse number token
- /// Number literals: 123
- static void number(__attribute__((unused)) bool canAssign) {
- double value = strtod(parser.previous.start, NULL);
- emitConstant(NUMBER_VAL(value));
- }
- static void string(__attribute__((unused)) bool canAssign) {
- emitConstant(OBJ_VAL(copyString(parser.previous.start + 1,
- parser.previous.length - 2)));
- }
- static void and_(__attribute__((unused)) bool canAssign) {
- /// left operand expression
- /// OP_JUMP_IF_FALSE b
- /// OP_POP
- /// right operand expression
- /// b: continues...
- int endJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- parsePrecedence(PREC_AND);// right operand expression
- patchJump(endJump);
- }
- static void or_(__attribute__((unused)) bool canAssign) {
- /// left operand expression
- /// OP_JUMP_IF_FALSE b1
- /// OP_JUMP b2
- /// b1: OP_POP
- /// right operand expression
- /// b2: continue
- int elseJump = emitJump(OP_JUMP_IF_FALSE);
- int endJump = emitJump(OP_JUMP);
- patchJump(elseJump);
- emitByte(OP_POP);
- parsePrecedence(PREC_OR);// right operand expression
- patchJump(endJump);
- }
- static int resolveLocal(Compiler *compile, Token *name) {
- for (int i = compile->localCount - 1; i >= 0; i--) {
- Local *local = &compile->locals[i];
- if (identifiersEqual(name, &local->name)) {
- if (local->depth == -1) {
- error("Can't read local variable in ints own initializer.");
- }
- return i;
- }
- }
- return -1;
- }
- static void namedVariable(Token name, bool canAssign) {
- uint8_t getOp, setOp;
- int arg = resolveLocal(current, &name);
- if (arg != -1) {
- getOp = OP_GET_LOCAL;
- setOp = OP_SET_LOCAL;
- } else {
- arg = identifierConstant(&name);
- getOp = OP_GET_GLOBAL;
- setOp = OP_SET_GLOBAL;
- }
- if (canAssign && match(TOKEN_EQUAL)) {
- // 如 menu.brunch(sunday).beverage = "mimosa";
- expression();
- emitBytes(setOp, (uint8_t) arg);
- } else {
- emitBytes(getOp, (uint8_t) arg);
- }
- }
- static void variable(bool canAssign) {
- namedVariable(parser.previous, canAssign);
- }
- /// Unary negation: -123
- static void unary(__attribute__((unused)) bool canAssign) {
- TokenType operatorType = parser.previous.type;
- // Compile the operand.
- parsePrecedence(PREC_UNARY);
- // Emit the operator instruction.
- switch (operatorType) {
- case TOKEN_BANG:
- emitByte(OP_NOT);
- break;
- case TOKEN_MINUS:
- emitByte(OP_NEGATE);
- break;
- default: return;// Unreachable.
- }
- }
- /// \brief infix parser
- static void binary(__attribute__((unused)) bool canAssign) {
- TokenType operatorType = parser.previous.type;
- ParseRule *rule = getRule(operatorType);
- parsePrecedence((Precedence) rule->precedence + 1);
- switch (operatorType) {
- case TOKEN_BANG_EQUAL:
- emitBytes(OP_EQUAL, OP_NOT);
- break;
- case TOKEN_EQUAL_EQUAL:
- emitByte(OP_EQUAL);
- break;
- case TOKEN_GREATER:
- emitByte(OP_GREATER);
- break;
- case TOKEN_GREATER_EQUAL:
- emitBytes(OP_LESS, OP_NOT);
- break;
- case TOKEN_LESS:
- emitByte(OP_LESS);
- break;
- case TOKEN_LESS_EQUAL:
- emitBytes(OP_GREATER, OP_NOT);
- break;
- case TOKEN_PLUS:
- emitByte(OP_ADD);
- break;
- case TOKEN_MINUS:
- emitByte(OP_SUBTRACT);
- break;
- case TOKEN_STAR:
- emitByte(OP_MULTIPLY);
- break;
- case TOKEN_SLASH:
- emitByte(OP_DIVIDE);
- break;
- default: return;// Unreachable.
- }
- }
- static void literal(__attribute__((unused)) bool canAssign) {
- switch (parser.previous.type) {
- case TOKEN_FALSE:
- emitByte(OP_FALSE);
- break;
- case TOKEN_NIL:
- emitByte(OP_NIL);
- break;
- case TOKEN_TRUE:
- emitByte(OP_TRUE);
- break;
- default: return;// Unreachable
- }
- }
- ParseRule rules[] = {
- [TOKEN_LEFT_PAREN] = {grouping, NULL, PREC_NONE},
- [TOKEN_RIGHT_PAREN] = {NULL, NULL, PREC_NONE},
- [TOKEN_LEFT_BRACE] = {NULL, NULL, PREC_NONE},
- [TOKEN_RIGHT_BRACE] = {NULL, NULL, PREC_NONE},
- [TOKEN_COMMA] = {NULL, NULL, PREC_NONE},
- [TOKEN_DOT] = {NULL, NULL, PREC_NONE},
- [TOKEN_MINUS] = {unary, binary, PREC_TERM},
- [TOKEN_PLUS] = {NULL, binary, PREC_TERM},
- [TOKEN_SEMICOLON] = {NULL, NULL, PREC_NONE},
- [TOKEN_SLASH] = {NULL, binary, PREC_FACTOR},
- [TOKEN_STAR] = {NULL, binary, PREC_FACTOR},
- [TOKEN_BANG] = {unary, NULL, PREC_NONE},
- [TOKEN_BANG_EQUAL] = {NULL, binary, PREC_EQUALITY},
- [TOKEN_EQUAL] = {NULL, NULL, PREC_NONE},
- [TOKEN_EQUAL_EQUAL] = {NULL, binary, PREC_EQUALITY},
- [TOKEN_GREATER] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_GREATER_EQUAL] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_LESS] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_LESS_EQUAL] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_IDENTIFIER] = {variable, NULL, PREC_NONE},
- [TOKEN_STRING] = {string, NULL, PREC_NONE},
- [TOKEN_NUMBER] = {number, NULL, PREC_NONE},
- [TOKEN_AND] = {NULL, and_, PREC_AND},
- [TOKEN_CLASS] = {NULL, NULL, PREC_NONE},
- [TOKEN_ELSE] = {NULL, NULL, PREC_NONE},
- [TOKEN_FALSE] = {literal, NULL, PREC_NONE},
- [TOKEN_FOR] = {NULL, NULL, PREC_NONE},
- [TOKEN_FUN] = {NULL, NULL, PREC_NONE},
- [TOKEN_IF] = {NULL, NULL, PREC_NONE},
- [TOKEN_NIL] = {literal, NULL, PREC_NONE},
- [TOKEN_OR] = {NULL, or_, PREC_OR},
- [TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
- [TOKEN_RETURN] = {NULL, NULL, PREC_NONE},
- [TOKEN_SUPER] = {NULL, NULL, PREC_NONE},
- [TOKEN_THIS] = {NULL, NULL, PREC_NONE},
- [TOKEN_TRUE] = {literal, NULL, PREC_NONE},
- [TOKEN_VAR] = {NULL, NULL, PREC_NONE},
- [TOKEN_WHILE] = {NULL, NULL, PREC_NONE},
- [TOKEN_ERROR] = {NULL, NULL, PREC_NONE},
- [TOKEN_EOF] = {NULL, NULL, PREC_NONE},
- };
- /// \brief 优先级处理
- /// \param precedence
- static void parsePrecedence(Precedence precedence) {
- advance();
- ParseFn prefixRule = getRule(parser.previous.type)->prefix;
- if (prefixRule == NULL) {
- error("Expect expression.");
- return;
- }
- bool canAssign = precedence <= PREC_ASSIGNMENT;
- prefixRule(canAssign);///! 执行具体函数
- while (precedence <= getRule(parser.current.type)->precedence) {
- advance();
- ParseFn infixRule = getRule(parser.previous.type)->infix;
- infixRule(canAssign);///! 执行具体函数
- }
- if (canAssign && match(TOKEN_EQUAL)) {
- error("Invalid assignment target.");
- }
- }
- static uint8_t identifierConstant(Token *name) {
- return makeConstant(OBJ_VAL(copyString(name->start, name->length)));
- }
- static bool identifiersEqual(Token *a, Token *b) {
- if (a->length != b->length) return false;
- return memcmp(a->start, b->start, a->length) == 0;
- }
- static void addLocal(Token name) {
- if (current->localCount == UINT8_COUNT) {
- error("Too many local variables in function.");
- return;
- }
- Local *local = ¤t->locals[current->localCount++];
- local->name = name;
- local->depth = -1;// 未初始化
- }
- static void declareVariable() {
- if (current->scopeDepth == 0) return;
- Token *name = &parser.previous;
- // we detect the error like:
- // {
- // var a = "first";
- // var a = "second";
- // }
- for (int i = current->localCount - 1; i >= 0; i--) {
- Local *local = ¤t->locals[i];
- if (local->depth != -1 && local->depth < current->scopeDepth) {
- break;
- }
- if (identifiersEqual(name, &local->name)) {
- error("Already a variable with the name in this scope.");
- }
- }
- addLocal(*name);
- }
- static uint8_t parseVariable(const char *errorMessage) {
- consume(TOKEN_IDENTIFIER, errorMessage);
- declareVariable();// 处理本地变量
- if (current->scopeDepth > 0) return 0;
- return identifierConstant(&parser.previous);
- }
- static void markInitialized() {
- if (current->scopeDepth == 0) return;
- current->locals[current->localCount - 1].depth = current->scopeDepth;
- }
- static void defineVariable(uint8_t global) {
- if (current->scopeDepth > 0) {
- // markInitialized 未初始化时值 为 -1
- markInitialized();
- // 本地变量,直接退出
- return;
- }
- emitBytes(OP_DEFINE_GLOBAL, global);
- }
- static ParseRule *getRule(TokenType type) {
- return &rules[type];
- }
- /**
- ******************************************************************************
- * statement → exprStmt
- | forStmt
- | ifStmt
- | printStmt
- | returnStmt
- | whileStmt
- | block ;
- block → "{" declaration* "}" ;
- declaration → classDecl
- | funDecl
- | varDecl
- | statement ;
- ******************************************************************************
- */
- ObjFunction *compile(const char *source) {
- initScanner(source);
- Compiler compiler;
- initCompiler(&compiler, TYPE_SCRIPT);
- parser.hadError = false;
- parser.panicMode = false;
- advance();
- while (!match(TOKEN_EOF)) {
- declaration();
- }
- ObjFunction *function = endCompiler();
- return parser.hadError ? NULL : function;
- }
|