X-Git-Url: http://git.lukelau.me/?p=kaleidoscope.git;a=blobdiff_plain;f=Kaleidoscope%2Flexer.cpp;h=049dc51b0f3cad0560f68f2cbdfd013b91b4cfda;hp=ac75490ff45d8c343200b0e3a4da55bbbadc7b08;hb=HEAD;hpb=5f81038886345b9c1e130bc7cfdd463e76b37b84 diff --git a/Kaleidoscope/lexer.cpp b/Kaleidoscope/lexer.cpp index ac75490..049dc51 100644 --- a/Kaleidoscope/lexer.cpp +++ b/Kaleidoscope/lexer.cpp @@ -35,6 +35,17 @@ enum Token { tok_identifier = -4, tok_number = -5, + + //control flow + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + + //operators + tok_binary = -11, + tok_unary = -12 }; static std::string IdentifierStr; @@ -52,10 +63,14 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if(IdentifierStr == "def") - return tok_def; - if(IdentifierStr == "extern") - return tok_extern; + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + return tok_identifier; } @@ -74,7 +89,7 @@ static int gettok() { //Coment until the end of the line do LastChar = getchar(); - while(LastChar != EOF && LastChar != '\n' && LastChar != 'r'); + while(LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if(LastChar != EOF) return gettok(); @@ -95,8 +110,8 @@ static int getNextToken() { return CurTok = gettok(); } -std::unique_ptr LogErrorP(const char *Str) { - LogError(Str); +std::unique_ptr LogErrorP(std::string str) { + LogError(str); return nullptr; } @@ -149,21 +164,95 @@ static std::unique_ptr ParseIdentifierExpr() { return llvm::make_unique(IdName, std::move(Args)); } +static std::unique_ptr ParseIfExpr() { + getNextToken(); // eat the if + + auto condExpr = ParseExpression(); + if (!condExpr) return nullptr; + + if (CurTok != tok_then) + return LogError("Expected then"); + getNextToken(); // eat the then + + auto thenExpr = ParseExpression(); + if (!thenExpr) return nullptr; + + if (CurTok != tok_else) + return LogError("Expected else"); + getNextToken(); // eat the else + + auto elseExpr = ParseExpression(); + if (!elseExpr) return nullptr; + + return llvm::make_unique(std::move(condExpr), + std::move(thenExpr), + std::move(elseExpr)); +} + +static std::unique_ptr ParseForExpr() { + getNextToken(); // eat the for + + if (CurTok != tok_identifier) + return LogError("Expected identifier after for"); + + std::string id = IdentifierStr; + getNextToken(); // eat the identifier + + if (CurTok != '=') + return LogError("Expected = after for"); + getNextToken(); // eat the = + + auto start = ParseExpression(); + if (!start) return nullptr; + + if (CurTok != ',') + return LogError("Expected , after for start value"); + getNextToken(); // eat the , + + auto end = ParseExpression(); + if (!end) + return nullptr; + + // optional step value + std::unique_ptr step; + if (CurTok == ',') { + getNextToken(); // eat the , + step = ParseExpression(); + if (!step) return nullptr; + } + + if (CurTok != tok_in) + return LogError("Expected in after for"); + getNextToken(); // eat the in + + auto body = ParseExpression(); + if (!body) return nullptr; + + return llvm::make_unique(id, + std::move(start), + std::move(end), + std::move(step), + std::move(body)); +} + static std::unique_ptr ParsePrimary() { switch (CurTok) { default: - return LogError("Unknown token when expected an expression"); + return LogError(std::string("Unknown token when expected an expression: ") + + std::to_string(CurTok)); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); } } -static std::map BinopPrecedence; - static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; @@ -206,11 +295,34 @@ static std::unique_ptr ParseBinOpRHS(int ExprPrec, } static std::unique_ptr ParsePrototype() { - if (CurTok != tok_identifier) - return LogErrorP("Expected function name in prototype"); + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary + unsigned BinaryPrecedence = 30; - std::string FnName = IdentifierStr; + switch (CurTok) { + default: + return LogErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) return LogErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return LogErrorP("Invalid precedence: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } if (CurTok != '(') return LogErrorP("Expected '(' in prototype"); @@ -223,7 +335,13 @@ static std::unique_ptr ParsePrototype() { getNextToken(); // eat ')' - return llvm::make_unique(FnName, std::move(ArgNames)); + if (Kind && ArgNames.size() != Kind) + return LogErrorP("Invalid number of of arguments for operator"); + + return llvm::make_unique(FnName, + std::move(ArgNames), + Kind != 0, + BinaryPrecedence); } static std::unique_ptr ParseDefinition() { @@ -281,8 +399,6 @@ static void HandleExtern() { static void HandleTopLevelExpr() { if (auto expr = ParseTopLevelExpr()) { if (auto gen = expr->codegen()) { - gen->print(errs()); - auto module = TheModule.get(); TheEngine->addModule(std::move(TheModule)); InitializeModuleAndPassManager(); @@ -326,6 +442,8 @@ int main() { InitializeNativeTargetAsmParser(); BinopPrecedence['<'] = 10; + BinopPrecedence['>'] = 10; + BinopPrecedence['|'] = 5; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; @@ -333,7 +451,7 @@ int main() { InitializeModuleAndPassManager(); std::string engineError; - TheEngine = EngineBuilder(std::move(TheModule)).setErrorStr(&engineError).create(); + TheEngine = EngineBuilder(std::move(TheModule)).setEngineKind(EngineKind::JIT).setErrorStr(&engineError).create(); if (!engineError.empty()) std::cout << engineError << "\n"; @@ -345,8 +463,6 @@ int main() { mainLoop(); - PrintModule(); - return 0; }