|
@@ -2,285 +2,285 @@
|
|
|
|
|
|
using namespace lexer;
|
|
|
namespace parser{
|
|
|
- //===----------------------------------------------------------------------===//
|
|
|
- // Parser
|
|
|
- //===----------------------------------------------------------------------===//
|
|
|
-
|
|
|
- /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
|
|
|
- /// token the parser is looking at. getNextToken reads another token from the
|
|
|
- /// lexer and updates CurTok with its results.
|
|
|
- int getNextToken() { return CurTok = gettok(); }
|
|
|
-
|
|
|
- /// BinopPrecedence - This holds the precedence for each binary operator that is
|
|
|
- /// defined.
|
|
|
-
|
|
|
- /// GetTokPrecedence - Get the precedence of the pending binary operator token.
|
|
|
- static int GetTokPrecedence() {
|
|
|
- if (!isascii(CurTok))
|
|
|
- return -1;
|
|
|
-
|
|
|
- // Make sure it's a declared binop.
|
|
|
- int TokPrec = BinopPrecedence[CurTok];
|
|
|
- if (TokPrec <= 0)
|
|
|
- return -1;
|
|
|
- return TokPrec;
|
|
|
- }
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
+// Parser
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
+
|
|
|
+/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
|
|
|
+/// token the parser is looking at. getNextToken reads another token from the
|
|
|
+/// lexer and updates CurTok with its results.
|
|
|
+int getNextToken() { return CurTok = gettok(); }
|
|
|
+
|
|
|
+/// BinopPrecedence - This holds the precedence for each binary operator that is
|
|
|
+/// defined.
|
|
|
+
|
|
|
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
|
|
|
+static int GetTokPrecedence() {
|
|
|
+ if (!isascii(CurTok))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ // Make sure it's a declared binop.
|
|
|
+ int TokPrec = BinopPrecedence[CurTok];
|
|
|
+ if (TokPrec <= 0)
|
|
|
+ return -1;
|
|
|
+ return TokPrec;
|
|
|
+}
|
|
|
|
|
|
- /// Error* - These are little helper functions for error handling.
|
|
|
- std::unique_ptr<ExprAST> Error(const char *Str) {
|
|
|
- fprintf(stderr, "Error: %s\n", Str);
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+/// Error* - These are little helper functions for error handling.
|
|
|
+std::unique_ptr<ExprAST> Error(const char *Str) {
|
|
|
+ fprintf(stderr, "Error: %s\n", Str);
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
|
|
|
- std::unique_ptr<PrototypeAST> ErrorP(const char *Str) {
|
|
|
- Error(Str);
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+std::unique_ptr<PrototypeAST> ErrorP(const char *Str) {
|
|
|
+ Error(Str);
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
|
|
|
- static std::unique_ptr<ExprAST> ParseExpression();
|
|
|
+static std::unique_ptr<ExprAST> ParseExpression();
|
|
|
|
|
|
- /// numberexpr ::= number
|
|
|
- static std::unique_ptr<ExprAST> ParseNumberExpr() {
|
|
|
- auto Result = llvm::make_unique<NumberExprAST>(NumVal);
|
|
|
- getNextToken(); // consume the number
|
|
|
- return std::move(Result);
|
|
|
- }
|
|
|
+/// numberexpr ::= number
|
|
|
+static std::unique_ptr<ExprAST> ParseNumberExpr() {
|
|
|
+ auto Result = llvm::make_unique<NumberExprAST>(NumVal);
|
|
|
+ getNextToken(); // consume the number
|
|
|
+ return std::move(Result);
|
|
|
+}
|
|
|
|
|
|
- /// parenexpr ::= '(' expression ')'
|
|
|
- static std::unique_ptr<ExprAST> ParseParenExpr() {
|
|
|
- getNextToken(); // eat (.
|
|
|
- auto V = ParseExpression();
|
|
|
- if (!V)
|
|
|
- return nullptr;
|
|
|
+/// parenexpr ::= '(' expression ')'
|
|
|
+static std::unique_ptr<ExprAST> ParseParenExpr() {
|
|
|
+ getNextToken(); // eat (.
|
|
|
+ auto V = ParseExpression();
|
|
|
+ if (!V)
|
|
|
+ return nullptr;
|
|
|
|
|
|
- if (CurTok != ')')
|
|
|
- return Error("expected ')'");
|
|
|
- getNextToken(); // eat ).
|
|
|
- return V;
|
|
|
- }
|
|
|
+ if (CurTok != ')')
|
|
|
+ return Error("expected ')'");
|
|
|
+ getNextToken(); // eat ).
|
|
|
+ return V;
|
|
|
+}
|
|
|
|
|
|
- /// identifierexpr
|
|
|
- /// ::= identifier
|
|
|
- /// ::= identifier '(' expression* ')'
|
|
|
- static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
|
|
|
- std::string IdName = IdentifierStr;
|
|
|
-
|
|
|
- getNextToken(); // eat identifier.
|
|
|
-
|
|
|
- if (CurTok != '(') // Simple variable ref.
|
|
|
- return llvm::make_unique<VariableExprAST>(IdName);
|
|
|
-
|
|
|
- // Call.
|
|
|
- getNextToken(); // eat (
|
|
|
- std::vector<std::unique_ptr<ExprAST>> Args;
|
|
|
- if (CurTok != ')') {
|
|
|
- while (1) {
|
|
|
- if (auto Arg = ParseExpression())
|
|
|
- Args.push_back(std::move(Arg));
|
|
|
- else
|
|
|
- return nullptr;
|
|
|
-
|
|
|
- if (CurTok == ')')
|
|
|
- break;
|
|
|
-
|
|
|
- if (CurTok != ',')
|
|
|
- return Error("Expected ')' or ',' in argument list");
|
|
|
- getNextToken();
|
|
|
- }
|
|
|
- }
|
|
|
+/// identifierexpr
|
|
|
+/// ::= identifier
|
|
|
+/// ::= identifier '(' expression* ')'
|
|
|
+static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
|
|
|
+ std::string IdName = IdentifierStr;
|
|
|
|
|
|
- // Eat the ')'.
|
|
|
- getNextToken();
|
|
|
+ getNextToken(); // eat identifier.
|
|
|
|
|
|
- return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
|
|
|
- }
|
|
|
+ if (CurTok != '(') // Simple variable ref.
|
|
|
+ return llvm::make_unique<VariableExprAST>(IdName);
|
|
|
|
|
|
- /// primary
|
|
|
- /// ::= identifierexpr
|
|
|
- /// ::= numberexpr
|
|
|
- /// ::= parenexpr
|
|
|
- static std::unique_ptr<ExprAST> ParsePrimary() {
|
|
|
- switch (CurTok) {
|
|
|
- default:
|
|
|
- return Error("unknown token when expecting an expression");
|
|
|
- case tok_identifier:
|
|
|
- return ParseIdentifierExpr();
|
|
|
- case tok_number:
|
|
|
- return ParseNumberExpr();
|
|
|
- case '(':
|
|
|
- return ParseParenExpr();
|
|
|
+ // Call.
|
|
|
+ getNextToken(); // eat (
|
|
|
+ std::vector<std::unique_ptr<ExprAST>> Args;
|
|
|
+ if (CurTok != ')') {
|
|
|
+ while (1) {
|
|
|
+ if (auto Arg = ParseExpression())
|
|
|
+ Args.push_back(std::move(Arg));
|
|
|
+ else
|
|
|
+ return nullptr;
|
|
|
+
|
|
|
+ if (CurTok == ')')
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (CurTok != ',')
|
|
|
+ return Error("Expected ')' or ',' in argument list");
|
|
|
+ getNextToken();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// binoprhs
|
|
|
- /// ::= ('+' primary)*
|
|
|
- static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
|
|
|
- std::unique_ptr<ExprAST> LHS) {
|
|
|
- // If this is a binop, find its precedence.
|
|
|
- while (1) {
|
|
|
- int TokPrec = GetTokPrecedence();
|
|
|
+ // Eat the ')'.
|
|
|
+ getNextToken();
|
|
|
|
|
|
- // If this is a binop that binds at least as tightly as the current binop,
|
|
|
- // consume it, otherwise we are done.
|
|
|
- if (TokPrec < ExprPrec)
|
|
|
- return LHS;
|
|
|
+ return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
|
|
|
+}
|
|
|
|
|
|
- // Okay, we know this is a binop.
|
|
|
- int BinOp = CurTok;
|
|
|
- getNextToken(); // eat binop
|
|
|
+/// primary
|
|
|
+/// ::= identifierexpr
|
|
|
+/// ::= numberexpr
|
|
|
+/// ::= parenexpr
|
|
|
+static std::unique_ptr<ExprAST> ParsePrimary() {
|
|
|
+ switch (CurTok) {
|
|
|
+ default:
|
|
|
+ return Error("unknown token when expecting an expression");
|
|
|
+ case tok_identifier:
|
|
|
+ return ParseIdentifierExpr();
|
|
|
+ case tok_number:
|
|
|
+ return ParseNumberExpr();
|
|
|
+ case '(':
|
|
|
+ return ParseParenExpr();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/// binoprhs
|
|
|
+/// ::= ('+' primary)*
|
|
|
+static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
|
|
|
+ std::unique_ptr<ExprAST> LHS) {
|
|
|
+ // If this is a binop, find its precedence.
|
|
|
+ while (1) {
|
|
|
+ int TokPrec = GetTokPrecedence();
|
|
|
+
|
|
|
+ // If this is a binop that binds at least as tightly as the current binop,
|
|
|
+ // consume it, otherwise we are done.
|
|
|
+ if (TokPrec < ExprPrec)
|
|
|
+ return LHS;
|
|
|
+
|
|
|
+ // Okay, we know this is a binop.
|
|
|
+ int BinOp = CurTok;
|
|
|
+ getNextToken(); // eat binop
|
|
|
+
|
|
|
+ // Parse the primary expression after the binary operator.
|
|
|
+ auto RHS = ParsePrimary();
|
|
|
+ if (!RHS)
|
|
|
+ return nullptr;
|
|
|
|
|
|
- // Parse the primary expression after the binary operator.
|
|
|
- auto RHS = ParsePrimary();
|
|
|
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
|
|
|
+ // the pending operator take RHS as its LHS.
|
|
|
+ int NextPrec = GetTokPrecedence();
|
|
|
+ if (TokPrec < NextPrec) {
|
|
|
+ RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS));
|
|
|
if (!RHS)
|
|
|
return nullptr;
|
|
|
-
|
|
|
- // If BinOp binds less tightly with RHS than the operator after RHS, let
|
|
|
- // the pending operator take RHS as its LHS.
|
|
|
- int NextPrec = GetTokPrecedence();
|
|
|
- if (TokPrec < NextPrec) {
|
|
|
- RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS));
|
|
|
- if (!RHS)
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- // Merge LHS/RHS.
|
|
|
- LHS =
|
|
|
- llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- /// expression
|
|
|
- /// ::= primary binoprhs
|
|
|
- ///
|
|
|
- static std::unique_ptr<ExprAST> ParseExpression() {
|
|
|
- auto LHS = ParsePrimary();
|
|
|
- if (!LHS)
|
|
|
- return nullptr;
|
|
|
|
|
|
- return ParseBinOpRHS(0, std::move(LHS));
|
|
|
+ // Merge LHS/RHS.
|
|
|
+ LHS =
|
|
|
+ llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /// prototype
|
|
|
- /// ::= id '(' id* ')'
|
|
|
- static std::unique_ptr<PrototypeAST> ParsePrototype() {
|
|
|
- if (CurTok != tok_identifier)
|
|
|
- return ErrorP("Expected function name in prototype");
|
|
|
+/// expression
|
|
|
+/// ::= primary binoprhs
|
|
|
+///
|
|
|
+static std::unique_ptr<ExprAST> ParseExpression() {
|
|
|
+ auto LHS = ParsePrimary();
|
|
|
+ if (!LHS)
|
|
|
+ return nullptr;
|
|
|
|
|
|
- std::string FnName = IdentifierStr;
|
|
|
- getNextToken();
|
|
|
+ return ParseBinOpRHS(0, std::move(LHS));
|
|
|
+}
|
|
|
|
|
|
- if (CurTok != '(')
|
|
|
- return ErrorP("Expected '(' in prototype");
|
|
|
+/// prototype
|
|
|
+/// ::= id '(' id* ')'
|
|
|
+static std::unique_ptr<PrototypeAST> ParsePrototype() {
|
|
|
+ if (CurTok != tok_identifier)
|
|
|
+ return ErrorP("Expected function name in prototype");
|
|
|
|
|
|
- std::vector<std::string> ArgNames;
|
|
|
- while (getNextToken() == tok_identifier)
|
|
|
- ArgNames.push_back(IdentifierStr);
|
|
|
- if (CurTok != ')')
|
|
|
- return ErrorP("Expected ')' in prototype");
|
|
|
+ std::string FnName = IdentifierStr;
|
|
|
+ getNextToken();
|
|
|
|
|
|
- // success.
|
|
|
- getNextToken(); // eat ')'.
|
|
|
+ if (CurTok != '(')
|
|
|
+ return ErrorP("Expected '(' in prototype");
|
|
|
|
|
|
- return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
|
|
|
- }
|
|
|
+ std::vector<std::string> ArgNames;
|
|
|
+ while (getNextToken() == tok_identifier)
|
|
|
+ ArgNames.push_back(IdentifierStr);
|
|
|
+ if (CurTok != ')')
|
|
|
+ return ErrorP("Expected ')' in prototype");
|
|
|
|
|
|
- /// definition ::= 'def' prototype expression
|
|
|
- static std::unique_ptr<FunctionAST> ParseDefinition() {
|
|
|
- getNextToken(); // eat def.
|
|
|
- auto Proto = ParsePrototype();
|
|
|
- if (!Proto)
|
|
|
- return nullptr;
|
|
|
+ // success.
|
|
|
+ getNextToken(); // eat ')'.
|
|
|
|
|
|
- if (auto E = ParseExpression())
|
|
|
- return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+ return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
|
|
|
+}
|
|
|
|
|
|
- /// toplevelexpr ::= expression
|
|
|
- static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
|
|
|
- if (auto E = ParseExpression()) {
|
|
|
- // Make an anonymous proto.
|
|
|
- auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
|
|
|
- std::vector<std::string>());
|
|
|
- return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
|
|
|
- }
|
|
|
+/// definition ::= 'def' prototype expression
|
|
|
+static std::unique_ptr<FunctionAST> ParseDefinition() {
|
|
|
+ getNextToken(); // eat def.
|
|
|
+ auto Proto = ParsePrototype();
|
|
|
+ if (!Proto)
|
|
|
return nullptr;
|
|
|
- }
|
|
|
|
|
|
- /// external ::= 'extern' prototype
|
|
|
- static std::unique_ptr<PrototypeAST> ParseExtern() {
|
|
|
- getNextToken(); // eat extern.
|
|
|
- return ParsePrototype();
|
|
|
+ if (auto E = ParseExpression())
|
|
|
+ return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+/// toplevelexpr ::= expression
|
|
|
+static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
|
|
|
+ if (auto E = ParseExpression()) {
|
|
|
+ // Make an anonymous proto.
|
|
|
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
|
|
|
+ std::vector<std::string>());
|
|
|
+ return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
|
|
|
}
|
|
|
- //===----------------------------------------------------------------------===//
|
|
|
- // Top-Level parsing and JIT Driver
|
|
|
- //===----------------------------------------------------------------------===//
|
|
|
-
|
|
|
- static void HandleDefinition() {
|
|
|
- if (auto FnAST = ParseDefinition()) {
|
|
|
- if (auto *FnIR = FnAST->codegen()) {
|
|
|
- fprintf(stderr, "Read function definition:");
|
|
|
- FnIR->dump();
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Skip token for error recovery.
|
|
|
- getNextToken();
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+/// external ::= 'extern' prototype
|
|
|
+static std::unique_ptr<PrototypeAST> ParseExtern() {
|
|
|
+ getNextToken(); // eat extern.
|
|
|
+ return ParsePrototype();
|
|
|
+}
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
+// Top-Level parsing and JIT Driver
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
+
|
|
|
+static void HandleDefinition() {
|
|
|
+ if (auto FnAST = ParseDefinition()) {
|
|
|
+ if (auto *FnIR = FnAST->codegen()) {
|
|
|
+ fprintf(stderr, "Read function definition:");
|
|
|
+ FnIR->dump();
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // Skip token for error recovery.
|
|
|
+ getNextToken();
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- static void HandleExtern() {
|
|
|
- if (auto ProtoAST = ParseExtern()) {
|
|
|
- if (auto *FnIR = ProtoAST->codegen()) {
|
|
|
- fprintf(stderr, "Read extern: ");
|
|
|
- FnIR->dump();
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Skip token for error recovery.
|
|
|
- getNextToken();
|
|
|
+static void HandleExtern() {
|
|
|
+ if (auto ProtoAST = ParseExtern()) {
|
|
|
+ if (auto *FnIR = ProtoAST->codegen()) {
|
|
|
+ fprintf(stderr, "Read extern: ");
|
|
|
+ FnIR->dump();
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // Skip token for error recovery.
|
|
|
+ getNextToken();
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- static void HandleTopLevelExpression() {
|
|
|
- // Evaluate a top-level expression into an anonymous function.
|
|
|
- if (auto FnAST = ParseTopLevelExpr()) {
|
|
|
- if (auto *FnIR = FnAST->codegen()) {
|
|
|
- fprintf(stderr, "Read top-level expression:");
|
|
|
- FnIR->dump();
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Skip token for error recovery.
|
|
|
- getNextToken();
|
|
|
+static void HandleTopLevelExpression() {
|
|
|
+ // Evaluate a top-level expression into an anonymous function.
|
|
|
+ if (auto FnAST = ParseTopLevelExpr()) {
|
|
|
+ if (auto *FnIR = FnAST->codegen()) {
|
|
|
+ fprintf(stderr, "Read top-level expression:");
|
|
|
+ FnIR->dump();
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // Skip token for error recovery.
|
|
|
+ getNextToken();
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /// top ::= definition | external | expression | ';'
|
|
|
- void MainLoop() {
|
|
|
- // Install standard binary operators.
|
|
|
- // 1 is lowest precedence.
|
|
|
- BinopPrecedence['<'] = 10;
|
|
|
- BinopPrecedence['+'] = 20;
|
|
|
- BinopPrecedence['-'] = 20;
|
|
|
- BinopPrecedence['*'] = 40; // highest.
|
|
|
- while (1) {
|
|
|
- fprintf(stderr, "ready> ");
|
|
|
- switch (CurTok) {
|
|
|
- case tok_eof:
|
|
|
- return;
|
|
|
- case ';': // ignore top-level semicolons.
|
|
|
- getNextToken();
|
|
|
- break;
|
|
|
- case tok_def:
|
|
|
- HandleDefinition();
|
|
|
- break;
|
|
|
- case tok_extern:
|
|
|
- HandleExtern();
|
|
|
- break;
|
|
|
- default:
|
|
|
- HandleTopLevelExpression();
|
|
|
- break;
|
|
|
- }
|
|
|
+/// top ::= definition | external | expression | ';'
|
|
|
+void MainLoop() {
|
|
|
+ // Install standard binary operators.
|
|
|
+ // 1 is lowest precedence.
|
|
|
+ BinopPrecedence['<'] = 10;
|
|
|
+ BinopPrecedence['+'] = 20;
|
|
|
+ BinopPrecedence['-'] = 20;
|
|
|
+ BinopPrecedence['*'] = 40; // highest.
|
|
|
+ while (1) {
|
|
|
+ fprintf(stderr, "ready> ");
|
|
|
+ switch (CurTok) {
|
|
|
+ case tok_eof:
|
|
|
+ return;
|
|
|
+ case ';': // ignore top-level semicolons.
|
|
|
+ getNextToken();
|
|
|
+ break;
|
|
|
+ case tok_def:
|
|
|
+ HandleDefinition();
|
|
|
+ break;
|
|
|
+ case tok_extern:
|
|
|
+ HandleExtern();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ HandleTopLevelExpression();
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
|
|
|
}
|