Beispiel #1
0
 public string Visit(Expr.Application app)
 {
     return(MakeParend("app", app.Fn, app.Arg));
 }
Beispiel #2
0
        private Expr ParseExpr(int minBp = 0)
        {
            Expr item;

            if (Check(TokenType.Operator))
            {
                // Prefix operator
                Token op  = Consume(TokenType.Operator);
                int   rBp = _ops.PrefixBp(op.Contents !, op.Span);
                Expr  opE = new Expr.Variable($"@({op.Contents})", true, op.Span);
                Expr  rhs = ParseExpr(rBp);
                item = new Expr.Application(opE, rhs, op.Span.Combine(rhs.Span));
            }
            else
            {
                item = ParseExprItem();
            }

            while (true)
            {
                if (IsAtEnd() || Check(TokenType.LineBreak) || Check(TokenType.RParen))
                {
                    break;
                }
                Span  span = CurrentSpan();
                Token op   = Check(TokenType.Operator)
                    ? Peek()
                    : new Token(_fnApp, TokenType.Operator, item.Span.Between(span));

                if (op.Contents != _fnApp)
                {
                    // Possible postfix operator
                    if (_ops.Postfix.ContainsKey(op.Contents !) && // If it's contained as a postfix op...
                        // ... and it isn't a binary operator, or it's at the end of a line/eof/paren
                        (!_ops.Binary.ContainsKey(op.Contents !) || IsAtEnd() || Check(TokenType.LineBreak) ||
                         Check(TokenType.RParen)))
                    {
                        // then it's a postfix operator!
                        var lBpPost = _ops.PostfixBp(op.Contents !, op.Span);
                        if (lBpPost < minBp)
                        {
                            break;
                        }

                        Advance();
                        Expr opE = new Expr.Variable($"({op.Contents!})@", true, op.Span);
                        item = new Expr.Application(opE, item, item.Span.Combine(opE.Span));
                        continue;
                    }
                }

                var(lBp, rBp) = _ops.BinaryBp(op.Contents !, op.Span);
                if (lBp < minBp)
                {
                    break;
                }

                if (op.Contents != _fnApp)
                {
                    Advance();
                }

                Expr rhs = ParseExpr(rBp);
                Span sp  = item.Span.Combine(rhs.Span);

                if (op.Contents == _fnApp)
                {
                    item = new Expr.Application(item, rhs, sp);
                }
                else
                {
                    Expr opE = new Expr.Variable(op.Contents !, true, op.Span);
                    item = new Expr.Application(new Expr.Application(opE, item, sp), rhs, sp);
                }
            }

            return(item);
        }