private static Expression ParseTerm(TokenStream tokenStream, SymbolTable symbols)
 {
     if (tokenStream.Peek() == '(')
     {
         tokenStream.Consume('(');
         var inner = ParseExp(tokenStream, symbols);
         tokenStream.Consume(')');
         return inner;
     }
     if (tokenStream.Peek() == 'λ')
     {
         tokenStream.Consume('λ');
         char id = tokenStream.Peek();
         if (!Char.IsLetter(id))
             throw new ParserException(String.Format("Expected identifier at position {0}", tokenStream.Position));
         tokenStream.Consume(id);
         tokenStream.Consume('.');
         var variable = new Symbol(id);
         var body = ParseExp(tokenStream, symbols.Plus(id, variable));
         return new Lambda(variable, body);
     }
     if (Char.IsLetter(tokenStream.Peek()))
     {
         char id = tokenStream.Peek();
         tokenStream.Consume(id);
         var variable = symbols.Lookup(id);
         if (variable != null)
             return new BoundVariable(variable);
         else
             return new FreeVariable(id);
     }
     throw new ParserException(String.Format("Unexpected character \"{0}\" at position {1}", tokenStream.Peek(), tokenStream.Position));
 }
 public SymbolTable Plus(char id, Symbol variable)
 {
     var symbols = _symbols.ContainsKey(id)
         ? _symbols.Remove(id)
         : _symbols;
     symbols = symbols.Add(id, variable);
     return new SymbolTable(symbols);
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     var newHead = _head.Replace(variable, argument);
     var newTail = _tail.Replace(variable, argument);
     if (newHead == _head && newTail == _tail)
         return this;
     return new Apply(newHead, newTail);
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     var newBody = _body.Replace(variable, argument);
     if (newBody == _body)
         return this;
     ImmutableList<char> taken = newBody.FreeVariableNames(new Symbol[] { _variable }.ToImmutableList());
     if (taken.Contains(_variable.Default))
     {
         int ordinal = (int)(char.ToLower(_variable.Default) - 'a') + 1 % 26;
         while (taken.Contains((char)('a' + ordinal)))
             ordinal++;
         var newVariable = new Symbol((char)('a' + ordinal));
         newBody = newBody.Replace(_variable, new BoundVariable(newVariable));
         return new Lambda(newVariable, newBody);
     }
     return new Lambda(_variable, newBody);
 }
 public override bool DependsUpon(Symbol variable)
 {
     return _head.DependsUpon(variable) || _tail.DependsUpon(variable);
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     return this;
 }
 public override bool DependsUpon(Symbol variable)
 {
     return false;
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     if (_variable == variable)
         return argument;
     return this;
 }
 public override bool DependsUpon(Symbol variable)
 {
     return _variable == variable;
 }
 public BoundVariable(Symbol variable)
 {
     _variable = variable;
 }
 public override bool DependsUpon(Symbol variable)
 {
     return _body.DependsUpon(variable);
 }
 public Lambda(Symbol variable, Expression body)
 {
     _variable = variable;
     _body = body;
 }
 public abstract bool DependsUpon(Symbol variable);
 public abstract Expression Replace(Symbol variable, Expression argument);