|
|
@@ -7,8 +7,8 @@
|
|
|
* @date : 2023/8/17
|
|
|
******************************************************************************
|
|
|
*/
|
|
|
-#include "common.h"
|
|
|
#include "compiler.h"
|
|
|
+#include "common.h"
|
|
|
#include "scanner.h"
|
|
|
#ifdef DEBUG_PRINT_CODE
|
|
|
#include "debug.h"
|
|
|
@@ -23,15 +23,15 @@ typedef struct {
|
|
|
|
|
|
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_ASSIGNMENT,// =
|
|
|
+ PREC_OR, // or
|
|
|
+ PREC_AND, // and
|
|
|
+ PREC_EQUALITY, // == !=
|
|
|
+ PREC_COMPARISON,// < > <= >=
|
|
|
+ PREC_TERM, // + -
|
|
|
+ PREC_FACTOR, // * /
|
|
|
+ PREC_UNARY, // ! -
|
|
|
+ PREC_CALL, // . ()
|
|
|
PREC_PRIMARY
|
|
|
} Precedence;
|
|
|
|
|
|
@@ -135,6 +135,10 @@ static void number() {
|
|
|
double value = strtod(parser.previous.start, NULL);
|
|
|
emitConstant(NUMBER_VAL(value));
|
|
|
}
|
|
|
+static void string() {
|
|
|
+ emitConstant(OBJ_VAL(copyString(parser.previous.start + 1,
|
|
|
+ parser.previous.length - 2)));
|
|
|
+}
|
|
|
/// Unary negation: -123
|
|
|
static void unary() {
|
|
|
TokenType operatorType = parser.previous.type;
|
|
|
@@ -144,9 +148,13 @@ static void unary() {
|
|
|
|
|
|
// Emit the operator instruction.
|
|
|
switch (operatorType) {
|
|
|
- case TOKEN_MINUS: emitByte(OP_NEGATE);
|
|
|
+ case TOKEN_BANG:
|
|
|
+ emitByte(OP_NOT);
|
|
|
+ break;
|
|
|
+ case TOKEN_MINUS:
|
|
|
+ emitByte(OP_NEGATE);
|
|
|
break;
|
|
|
- default: return; // Unreachable.
|
|
|
+ default: return;// Unreachable.
|
|
|
}
|
|
|
}
|
|
|
/// \brief infix parser
|
|
|
@@ -156,58 +164,94 @@ static void binary() {
|
|
|
parsePrecedence((Precedence) rule->precedence + 1);
|
|
|
|
|
|
switch (operatorType) {
|
|
|
- case TOKEN_PLUS: emitByte(OP_ADD);
|
|
|
+ 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_MINUS: emitByte(OP_SUBTRACT);
|
|
|
+ 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() {
|
|
|
+ switch (parser.previous.type) {
|
|
|
+ case TOKEN_FALSE:
|
|
|
+ emitByte(OP_FALSE);
|
|
|
break;
|
|
|
- case TOKEN_STAR: emitByte(OP_MULTIPLY);
|
|
|
+ case TOKEN_NIL:
|
|
|
+ emitByte(OP_NIL);
|
|
|
break;
|
|
|
- case TOKEN_SLASH: emitByte(OP_DIVIDE);
|
|
|
+ case TOKEN_TRUE:
|
|
|
+ emitByte(OP_TRUE);
|
|
|
break;
|
|
|
- default: return; // Unreachable.
|
|
|
+ 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] = {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},
|
|
|
+ [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] = {NULL, NULL, PREC_NONE},
|
|
|
+ [TOKEN_STRING] = {string, 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] = {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, 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] = {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 优先级处理
|
|
|
@@ -220,12 +264,12 @@ static void parsePrecedence(Precedence precedence) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- prefixRule(); ///! 执行具体函数
|
|
|
+ prefixRule();///! 执行具体函数
|
|
|
|
|
|
while (precedence <= getRule(parser.current.type)->precedence) {
|
|
|
advance();
|
|
|
ParseFn infixRule = getRule(parser.previous.type)->infix;
|
|
|
- infixRule(); ///! 执行具体函数
|
|
|
+ infixRule();///! 执行具体函数
|
|
|
}
|
|
|
}
|
|
|
static ParseRule *getRule(TokenType type) {
|
|
|
@@ -241,6 +285,6 @@ bool compile(const char *source, Chunk *chunk) {
|
|
|
advance();
|
|
|
expression();
|
|
|
consume(TOKEN_EOF, "Expect end of expression");
|
|
|
- endCompiler(); //! return opcode
|
|
|
+ endCompiler();//! return opcode
|
|
|
return !parser.hadError;
|
|
|
}
|