// File: /workspace/github_cpp_makefile_star2_O1/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 %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %r14
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0xbfa0
movl (%rbx), %eax
decl %eax
cmpl $0x5, %eax
ja 0xc91b
leaq 0x310c(%rip), %rcx      # 0xf6c8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x38, %edi
callq 0x31c0
movq %rax, %rbx
movl $0x1, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
movq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
leaq 0x10(%rsp), %rsi
callq 0x30f0
jmp 0xc91d
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0xbfa0
leaq 0x38(%rsp), %rbx
movl -0x8(%rbx), %eax
leaq 0x10(%rsp), %r15
movl %eax, -0x8(%r15)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3210
movq (%rbx), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0xc649
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x31d0
cmpl $0x2, 0x8(%rsp)
jne 0xc94a
movl $0x38, %edi
callq 0x31c0
movq %rax, %rbx
movl $0x3, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
movq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
movq %r15, %rsi
callq 0x30f0
movq %r14, %rdi
callq 0xc494
movq %rbx, %rcx
addq $0x28, %rcx
movq %rax, (%rcx)
jmp 0xc91d
leaq 0x10(%rsp), %r15
leaq 0x348b(%rip), %rsi      # 0xfb3c
movq %r15, %rdi
callq 0x3070
testl %eax, %eax
je 0xc7cf
leaq 0x3478(%rip), %rsi      # 0xfb40
movq %r15, %rdi
callq 0x3070
testl %eax, %eax
je 0xc907
movl $0x38, %edi
callq 0x31c0
movq %rax, %rbx
movl $0x2, (%rax)
leaq 0x8(%rax), %rdi
addq $0x18, %rax
movq %rax, 0x8(%rbx)
movq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
leaq 0x10(%rsp), %r14
movq %r14, %rsi
callq 0x30f0
movq 0x10(%rsp), %rax
cmpb $0x27, (%rax)
jne 0xc7bf
movsbl 0x1(%rax), %eax
jmp 0xc7c7
movq %r14, %rdi
callq 0xc494
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0xbfa0
leaq 0x38(%rsp), %r14
movl -0x8(%r14), %eax
leaq 0x10(%rsp), %rdi
movl %eax, -0x8(%rdi)
movq %r14, %rsi
callq 0x3210
movq (%r14), %rdi
leaq 0x48(%rsp), %rax
cmpq %rax, %rdi
je 0xc779
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x31d0
cmpl $0x6, 0x8(%rsp)
je 0xc91d
movq 0x8865(%rip), %rdi      # 0x14ff0
leaq 0x33d3(%rip), %rsi      # 0xfb65
movl $0x18, %edx
callq 0x31f0
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq 0x8843(%rip), %rdi      # 0x14ff0
callq 0x31f0
movq %rax, %rdi
callq 0x30d0
jmp 0xc9f0
movq %r14, %rdi
callq 0xdc6c
movl %eax, 0x4(%rbx)
jmp 0xc91d
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0xbfa0
leaq 0x38(%rsp), %rbx
movl -0x8(%rbx), %eax
movl %eax, 0x8(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3210
movq (%rbx), %rdi
leaq 0x48(%rsp), %r13
cmpq %r13, %rdi
je 0xc80d
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x31d0
cmpl $0x2, 0x8(%rsp)
jne 0xc9ba
movl $0x38, %edi
callq 0x31c0
movq %rax, %rbx
movl $0x4, (%rax)
addq $0x18, %rax
movq %rax, 0x8(%rbx)
movq $0x0, 0x10(%rbx)
movb $0x0, 0x18(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rbx)
movl $0x38, %edi
callq 0x31c0
movq %rbx, %rbp
addq $0x28, %rbp
movl $0x3, (%rax)
leaq 0x8(%rax), %rdi
movq %rax, %rcx
addq $0x18, %rcx
movq %rcx, 0x8(%rax)
movq $0x0, 0x10(%rax)
movb $0x0, 0x18(%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x28(%rax)
movq %rax, (%rbp)
movq %r15, %rsi
callq 0x30f0
movq %r14, %rdi
callq 0xc494
movq %rax, 0x30(%rbx)
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0xbfa0
leaq 0x38(%rsp), %r12
movl -0x8(%r12), %eax
movl %eax, 0x8(%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0x3210
movq (%r12), %rdi
cmpq %r13, %rdi
je 0xc8d3
movq 0x48(%rsp), %rsi
incq %rsi
callq 0x31d0
cmpl $0x3, 0x8(%rsp)
jne 0xc982
leaq 0x325b(%rip), %rsi      # 0xfb40
movq %r15, %rdi
callq 0x3070
testl %eax, %eax
jne 0xc982
movq %r14, %rdi
callq 0xc494
movq (%rbp), %rcx
movq %rax, 0x28(%rcx)
jmp 0xc91d
cmpl $0x7, 0x8(%rsp)
je 0xc91b
leaq 0x8(%rsp), %rsi
movq %r14, %rdi
callq 0xdc2a
xorl %ebx, %ebx
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0xc938
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x31d0
movq %rbx, %rax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x869f(%rip), %rdi      # 0x14ff0
leaq 0x31c3(%rip), %rsi      # 0xfb1b
movl $0x20, %edx
callq 0x31f0
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq 0x867d(%rip), %rdi      # 0x14ff0
callq 0x31f0
movq %rax, %rdi
callq 0x30d0
jmp 0xc9f0
movq 0x8667(%rip), %rdi      # 0x14ff0
leaq 0x31b3(%rip), %rsi      # 0xfb43
movl $0x21, %edx
callq 0x31f0
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq 0x8645(%rip), %rdi      # 0x14ff0
callq 0x31f0
movq %rax, %rdi
callq 0x30d0
jmp 0xc9f0
movq 0x862f(%rip), %rdi      # 0x14ff0
leaq 0x3153(%rip), %rsi      # 0xfb1b
movl $0x20, %edx
callq 0x31f0
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq 0x860d(%rip), %rdi      # 0x14ff0
callq 0x31f0
movq %rax, %rdi
callq 0x30d0
movl $0x1, %edi
callq 0x3200
jmp 0xca02
jmp 0xca02
jmp 0xca02
jmp 0xca02
movq %rax, %rbx
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0xca20
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x31d0
movq %rbx, %rdi
callq 0x32d0