|
|
@@ -11,29 +11,86 @@
|
|
|
#include "compiler.h"
|
|
|
#include "scanner.h"
|
|
|
|
|
|
-void compile(const char *source) {
|
|
|
- initScanner(source);
|
|
|
- int line = -1;
|
|
|
- /// \brief 如 print 1 + 2; 则会输出
|
|
|
- /// 1 31 'print'
|
|
|
- /// | 21 '1'
|
|
|
- /// | 7 '+'
|
|
|
- /// | 21 '2'
|
|
|
- /// | 8 ';'
|
|
|
- /// 2 39 '' // <EOF token>
|
|
|
+typedef struct {
|
|
|
+ Token current;
|
|
|
+ Token previous;
|
|
|
+ bool hadError;
|
|
|
+ bool panicMode;
|
|
|
+} Parser;
|
|
|
+
|
|
|
+Parser parser;
|
|
|
+Chunk *compilingChunk;
|
|
|
+
|
|
|
+static Chunk *currentChunk() {
|
|
|
+ return compilingChunk;
|
|
|
+}
|
|
|
+
|
|
|
+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 (;;) {
|
|
|
- Token token = scanToken();
|
|
|
- if (token.line != line) {
|
|
|
- printf("%4d ", token.line);
|
|
|
- line = token.line;
|
|
|
- } else {
|
|
|
- printf(" | ");
|
|
|
- }
|
|
|
- /// %.*s: *用来指定宽度,对应一个整数。
|
|
|
- /// .(点)与后面的数合起来 是指定必须输出这个宽度,
|
|
|
- /// 如果所输出的字符串长度大于这个数,则按此宽度输出,如果小于,则输出实际长度
|
|
|
- printf("%2d '%.*s'\n", token.type, token.length, token.start);
|
|
|
-
|
|
|
- if (token.type == TOKEN_EOF) break;
|
|
|
+ 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 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 emitReturn() {
|
|
|
+ emitByte(OP_RETURN);
|
|
|
+}
|
|
|
+static void endCompiler() {
|
|
|
+ emitReturn();
|
|
|
+}
|
|
|
+static void expression() {
|
|
|
+ ///! TODO
|
|
|
+}
|
|
|
+bool compile(const char *source, Chunk *chunk) {
|
|
|
+ initScanner(source);
|
|
|
+ compilingChunk = chunk;
|
|
|
+
|
|
|
+ parser.hadError = false;
|
|
|
+ parser.panicMode = false;
|
|
|
+
|
|
|
+ advance();
|
|
|
+ expression();
|
|
|
+ consume(TOKEN_EOF, "Expect end of expression");
|
|
|
+ endCompiler(); //! return opcode
|
|
|
+ return !parser.hadError;
|
|
|
+}
|