123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- #include "Parser.h"
- 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;
- }
- /// 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;
- }
- static std::unique_ptr<ExprAST> ParseExpression();
- /// numberexpr ::= number
- static std::unique_ptr<ExprAST> ParseNumberExpr() {
- auto Result = llvm::make_unique<NumberExprAST>(LexerObjects::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;
- if (CurTok != ')')
- return Error("expected ')'");
- getNextToken(); // eat ).
- return V;
- }
- /// identifierexpr
- /// ::= identifier
- /// ::= identifier '(' expression* ')'
- static std::unique_ptr<ExprAST> ParseIdentifierExpr() {
- std::string IdName = LexerObjects::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();
- }
- }
- // Eat the ')'.
- getNextToken();
- return llvm::make_unique<CallExprAST>(IdName, std::move(Args));
- }
- /// 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;
- // 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));
- }
- /// prototype
- /// ::= id '(' id* ')'
- static std::unique_ptr<PrototypeAST> ParsePrototype() {
- if (CurTok != tok_identifier)
- return ErrorP("Expected function name in prototype");
- std::string FnName = LexerObjects::IdentifierStr;
- getNextToken();
- if (CurTok != '(')
- return ErrorP("Expected '(' in prototype");
- std::vector<std::string> ArgNames;
- while (getNextToken() == tok_identifier)
- ArgNames.push_back(LexerObjects::IdentifierStr);
- if (CurTok != ')')
- return ErrorP("Expected ')' in prototype");
- // success.
- getNextToken(); // eat ')'.
- return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames));
- }
- /// definition ::= 'def' prototype expression
- static std::unique_ptr<FunctionAST> ParseDefinition() {
- getNextToken(); // eat def.
- auto Proto = ParsePrototype();
- if (!Proto)
- return nullptr;
- 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));
- }
- 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 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;
- }
- }
- }
- }
|