Chapter 17.5 - 17.6
This commit is contained in:
parent
0b89bd5de0
commit
964859a8a1
1 changed files with 96 additions and 2 deletions
|
@ -26,6 +26,14 @@ typedef enum {
|
||||||
PREC_PRIMARY
|
PREC_PRIMARY
|
||||||
} Precedence;
|
} Precedence;
|
||||||
|
|
||||||
|
typedef void (*ParseFn)();
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ParseFn prefix;
|
||||||
|
ParseFn infix;
|
||||||
|
Precedence precedence;
|
||||||
|
} ParseRule;
|
||||||
|
|
||||||
Parser parser;
|
Parser parser;
|
||||||
Chunk *compilingChunk;
|
Chunk *compilingChunk;
|
||||||
|
|
||||||
|
@ -103,9 +111,33 @@ static void emitConstant(Value value) {
|
||||||
|
|
||||||
static void endCompiler() { emitReturn(); }
|
static void endCompiler() { emitReturn(); }
|
||||||
|
|
||||||
static void parsePrecedence(Precedence precedence) {
|
static void expression();
|
||||||
// What goes here?
|
static ParseRule *getRule(TokenType type);
|
||||||
|
static void parsePrecedence(Precedence precedence);
|
||||||
|
|
||||||
|
static void binary() {
|
||||||
|
TokenType operatorType = parser.previous.type;
|
||||||
|
ParseRule *rule = getRule(operatorType);
|
||||||
|
parsePrecedence((Precedence)(rule->precedence + 1));
|
||||||
|
|
||||||
|
switch (operatorType) {
|
||||||
|
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 expression() { parsePrecedence(PREC_ASSIGNMENT); }
|
static void expression() { parsePrecedence(PREC_ASSIGNMENT); }
|
||||||
|
|
||||||
static void number() {
|
static void number() {
|
||||||
|
@ -134,6 +166,68 @@ static void grouping() {
|
||||||
consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
|
consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_BANG_EQUAL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_EQUAL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_EQUAL_EQUAL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_GREATER] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_GREATER_EQUAL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_LESS] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_LESS_EQUAL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_IDENTIFIER] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_STRING] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_NUMBER] = {number, NULL, PREC_NONE},
|
||||||
|
[TOKEN_AND] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_CLASS] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_ELSE] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_FALSE] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_FOR] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_FUN] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_IF] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_NIL] = {NULL, NULL, PREC_NONE},
|
||||||
|
[TOKEN_OR] = {NULL, NULL, PREC_NONE},
|
||||||
|
[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] = {NULL, 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},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void parsePrecedence(Precedence precedence) {
|
||||||
|
advance();
|
||||||
|
ParseFn prefixRule = getRule(parser.previous.type)->prefix;
|
||||||
|
if (prefixRule == NULL) {
|
||||||
|
error("Expect expression.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixRule();
|
||||||
|
|
||||||
|
while (precedence <= getRule(parser.current.type)->precedence) {
|
||||||
|
advance();
|
||||||
|
ParseFn infixRule = getRule(parser.previous.type)->infix;
|
||||||
|
infixRule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ParseRule *getRule(TokenType type) { return &rules[type]; }
|
||||||
|
|
||||||
bool compile(const char *source, Chunk *chunk) {
|
bool compile(const char *source, Chunk *chunk) {
|
||||||
initScanner(source);
|
initScanner(source);
|
||||||
compilingChunk = chunk;
|
compilingChunk = chunk;
|
||||||
|
|
Loading…
Reference in a new issue