// File: /workspace/github_cpp_makefile_star2_O2/silverneko[P]Lambda-calculus-interpreter/src/ExpressionParser.cpp
// Function: parseExpressionTail(Scanner&)
Expression * parseExpressionTail(Scanner &scanner){
  Token token = scanner.getToken();
  Expression * expr(nullptr);
  switch(token.type){
    case Token::Lambda:
      token = scanner.getToken();
      if(token.type != Token::Identifier){
        cerr << "[Parse] Expected an identifier: " << token.name << endl;
        exit(1);
      }
      expr = new Expression(Expression::Lambda);
      expr->name = token.name;
      expr->body = parseExpression(scanner);
      return expr;

    case Token::Identifier:
      expr = new Expression(Expression::Var);
      expr->name = token.name;
      return expr;

    case Token::Keyword:
      if(token.name == "let"){
        token = scanner.getToken();
        if(token.type != Token::Identifier){
          cerr << "[Parse] Expected an identifier: " << token.name << endl;
          exit(1);
        }
        expr = new Expression(Expression::Ap);
        expr->body = new Expression(Expression::Lambda);
        expr->body->name = token.name;
        expr->arg = parseExpression(scanner);
        token = scanner.getToken();
        if(token.type != Token::Keyword || token.name != "in"){
          cerr << "[Parse] Expected a keyword `in`: " << token.name << endl;
          exit(1);
        }
        expr->body->body = parseExpression(scanner);
        return expr;
      }else if(token.name == "in"){
        scanner.ungetToken(token);
        return nullptr;
      }

    case Token::Constant:
      expr = new Expression(Expression::Constant);
      expr->name = token.name;
      if(token.name[0] == '\''){
        // character literal
        expr->val = (int)token.name[1];
      }else{
        expr->val = stringTo<int>(token.name);
      }
      return expr;

    case Token::LeftBracket:
      expr = parseExpression(scanner);
      token = scanner.getToken();
      if(token.type != Token::RightBracket){
        cerr << "[Parse] Expected a `)`: " << token.name << endl;
        exit(1);
      }
      return expr;

    case Token::RightBracket:
      scanner.ungetToken(token);
      return nullptr;

    case Token::EndOfFile:
    default:
      return nullptr;
  }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x50, %rsp
movq %rdi, %r14
movq %rsp, %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x888e
movl (%rbx), %eax
decl %eax
cmpl $0x5, %eax
ja 0x8fff
leaq 0x2990(%rip), %rcx      # 0xb6c8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
pushq $0x38
popq %rdi
callq 0x31b0
movq %rax, %rbx
movl $0x2, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
andq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
leaq 0x8(%rsp), %r14
movq %r14, %rsi
callq 0x3100
movq 0x8(%rsp), %rax
cmpb $0x27, (%rax)
jne 0x8fd0
movsbl 0x1(%rax), %eax
jmp 0x8fd8
leaq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x888e
movq %rsp, %rbx
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0x9e8a
leaq 0x30(%rsp), %rdi
callq 0x30c0
cmpl $0x2, (%rbx)
jne 0x901c
pushq $0x38
popq %rdi
callq 0x31b0
movq %rax, %rbx
movl $0x3, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
andq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
leaq 0x8(%rsp), %rsi
callq 0x3100
movq %r14, %rdi
callq 0x8c40
movq %rbx, %rcx
addq $0x28, %rcx
movq %rax, (%rcx)
jmp 0x9001
leaq 0x8(%rsp), %r15
leaq 0x2d26(%rip), %rsi      # 0xbb42
movq %r15, %rdi
callq 0x9ea4
testb %al, %al
je 0x8fdd
leaq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x888e
movq %rsp, %rbx
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0x9e8a
leaq 0x30(%rsp), %rdi
callq 0x30c0
cmpl $0x2, (%rbx)
jne 0x906e
pushq $0x38
popq %rdi
callq 0x31b0
movq %rax, %rbx
movl $0x4, (%rax)
addq $0x18, %rax
movq %rax, 0x8(%rbx)
andq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
pushq $0x38
popq %rdi
callq 0x31b0
movq %rbx, %r13
addq $0x28, %r13
movl $0x3, (%rax)
movq %rax, %rcx
addq $0x18, %rcx
movq %rcx, 0x8(%rax)
andq $0x0, 0x10(%rax)
leaq 0x8(%rax), %rdi
movb $0x0, 0x18(%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rax)
movq %rax, (%r13)
movq %r15, %rsi
callq 0x3100
movq %r14, %rdi
callq 0x8c40
movq %rax, 0x30(%rbx)
leaq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x888e
movq %rsp, %r12
leaq 0x28(%rsp), %rsi
movq %r12, %rdi
callq 0x9e8a
leaq 0x30(%rsp), %rdi
callq 0x30c0
cmpl $0x3, (%r12)
jne 0x9046
leaq 0x2c3c(%rip), %rsi      # 0xbb46
movq %r15, %rdi
callq 0x9eb1
testb %al, %al
jne 0x9046
movq %r14, %rdi
callq 0x8c40
movq (%r13), %rcx
movq %rax, 0x28(%rcx)
jmp 0x9001
pushq $0x38
popq %rdi
callq 0x31b0
movq %rax, %rbx
movl $0x1, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
andq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
leaq 0x8(%rsp), %rsi
callq 0x3100
jmp 0x9001
movq %r14, %rdi
callq 0x8c40
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x888e
movq %rsp, %r14
leaq 0x28(%rsp), %rsi
movq %r14, %rdi
callq 0x9e8a
leaq 0x30(%rsp), %rdi
callq 0x30c0
cmpl $0x6, (%r14)
je 0x9001
movq 0x8046(%rip), %rdi      # 0x10ff0
leaq 0x2bba(%rip), %rsi      # 0xbb6b
callq 0x31a0
leaq 0x8(%rsp), %rsi
movq %rax, %rdi
callq 0x3180
movq %rax, %rdi
callq 0x30e0
jmp 0x9094
movq %r14, %rdi
callq 0x9ebb
movl %eax, 0x4(%rbx)
jmp 0x9001
leaq 0x2b62(%rip), %rsi      # 0xbb46
movq %r15, %rdi
callq 0x9ea4
testb %al, %al
je 0x8d41
movq %rsp, %rsi
movq %r14, %rdi
callq 0x898a
xorl %ebx, %ebx
leaq 0x8(%rsp), %rdi
callq 0x30c0
movq %rbx, %rax
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movq 0x7fcd(%rip), %rdi      # 0x10ff0
leaq 0x2af7(%rip), %rsi      # 0xbb21
callq 0x31a0
leaq 0x8(%rsp), %rsi
movq %rax, %rdi
callq 0x3180
movq %rax, %rdi
callq 0x30e0
jmp 0x9094
movq 0x7fa3(%rip), %rdi      # 0x10ff0
leaq 0x2af5(%rip), %rsi      # 0xbb49
callq 0x31a0
movq %rax, %rdi
movq %r15, %rsi
callq 0x3180
movq %rax, %rdi
callq 0x30e0
jmp 0x9094
movq 0x7f7b(%rip), %rdi      # 0x10ff0
leaq 0x2aa5(%rip), %rsi      # 0xbb21
callq 0x31a0
movq %rax, %rdi
movq %r15, %rsi
callq 0x3180
movq %rax, %rdi
callq 0x30e0
pushq $0x1
popq %rdi
callq 0x31e0
jmp 0x90a4
jmp 0x90a4
jmp 0x90a4
jmp 0x90a4
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x30c0
movq %rbx, %rdi
callq 0x32b0
nop