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;
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;
}
//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();
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;
}
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;
}
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");
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() {
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();
InitializeNativeTargetAsmParser();
BinopPrecedence['<'] = 10;
+ BinopPrecedence['>'] = 10;
+ BinopPrecedence['|'] = 5;
BinopPrecedence['+'] = 20;
BinopPrecedence['-'] = 20;
BinopPrecedence['*'] = 40;
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";
mainLoop();
- PrintModule();
-
return 0;
}