WIP
[kaleidoscope.git] / Kaleidoscope / lexer.cpp
index ac75490ff45d8c343200b0e3a4da55bbbadc7b08..049dc51b0f3cad0560f68f2cbdfd013b91b4cfda 100644 (file)
@@ -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<PrototypeAST> LogErrorP(const char *Str) {
-       LogError(Str);
+std::unique_ptr<PrototypeAST> LogErrorP(std::string str) {
+       LogError(str);
        return nullptr;
 }
 
@@ -149,21 +164,95 @@ static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
        return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
 }
 
+static std::unique_ptr<ExprAST> 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<IfExprAST>(std::move(condExpr),
+                                                                               std::move(thenExpr),
+                                                                               std::move(elseExpr));
+}
+
+static std::unique_ptr<ExprAST> 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<ExprAST> 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<ForExprAST>(id,
+                                                                                std::move(start),
+                                                                                std::move(end),
+                                                                                std::move(step),
+                                                                                std::move(body));
+}
+
 static std::unique_ptr<ExprAST> 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<char, int> BinopPrecedence;
-
 static int GetTokPrecedence() {
        if (!isascii(CurTok))
                return -1;
@@ -206,11 +295,34 @@ static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
 }
 
 static std::unique_ptr<PrototypeAST> 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<PrototypeAST> ParsePrototype() {
        
        getNextToken(); // eat ')'
 
-       return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
+       if (Kind && ArgNames.size() != Kind)
+               return LogErrorP("Invalid number of of arguments for operator");
+       
+       return llvm::make_unique<PrototypeAST>(FnName,
+                                                                                  std::move(ArgNames),
+                                                                                  Kind != 0,
+                                                                                  BinaryPrecedence);
 }
 
 static std::unique_ptr<FunctionAST> 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;
 }