Search in sources :

Example 1 with InfixCallChain

use of dyvilx.tools.compiler.ast.expression.operator.InfixCallChain in project Dyvil by Dyvil.

the class ExpressionParser method parseInfixAccess.

private void parseInfixAccess(IParserManager pm, IToken token, Name name, boolean forceInfix) {
    final int type = token.type();
    final IToken next = token.next();
    final int nextType = next.type();
    if (isSymbolic(type)) {
        // Identifier is an operator
        final IToken prev = token.prev();
        final boolean leftNeighbor = prev.isNeighboring(token);
        final boolean rightNeighbor = token.isNeighboring(next);
        if (// prefix
        this.value == null) {
            if (// only true iff this.value == null
            forceInfix) {
                pm.report(SourcePosition.before(token), "expression.infix.before");
            }
            // OPERATOR EXPRESSION
            // token    next
            this.mode = ACCESS;
            if (this.isOperatorEnd(nextType)) {
                this.value = new FieldAccess(token.raw(), null, name);
                return;
            }
            final PrefixCall call = new PrefixCall(token.raw(), name);
            this.value = call;
            this.parseApply(pm, next, call);
            return;
        } else if (!forceInfix && !leftNeighbor && rightNeighbor) {
            // Revert to Juxtaposition
            this.parseApply(pm, token);
            return;
        }
        if (this.isOperatorEnd(nextType) || !forceInfix && leftNeighbor && !rightNeighbor) {
            if (// only true iff this.isOperatorEnd(nextType)
            forceInfix) {
                pm.report(SourcePosition.after(token), "expression.infix.after");
            }
            // EXPRESSION_OPERATOR EXPRESSION
            // EXPRESSION OPERATOR EOF
            // token    next
            this.value = new PostfixCall(token.raw(), this.value, name);
            this.mode = ACCESS;
            return;
        }
        if (this.hasFlag(IGNORE_OPERATOR)) {
            this.valueConsumer.setValue(this.value);
            pm.popParser(true);
            return;
        }
        // EXPRESSION OPERATOR EXPRESSION
        // token    next
        final InfixCallChain chain;
        if (this.value.valueTag() == IValue.OPERATOR_CHAIN) {
            chain = (InfixCallChain) this.value;
        } else {
            chain = new InfixCallChain();
            chain.addOperand(this.value);
            this.value = chain;
        }
        chain.addOperator(name, token.raw());
        pm.pushParser(new ExpressionParser(chain::addOperand).withFlags(this.flags | IGNORE_OPERATOR));
        return;
    }
    switch(nextType) {
        case BaseSymbols.OPEN_PARENTHESIS:
            {
                // IDENTIFIER (
                final MethodCall call = new MethodCall(token.raw(), this.value, name);
                ArgumentListParser.parseArguments(pm, next.next(), call);
                this.value = call;
                this.mode = PARAMETERS_END;
                pm.skip();
                return;
            }
        case BaseSymbols.OPEN_SQUARE_BRACKET:
            {
                // IDENTIFIER [
                final FieldAccess fieldAccess = new FieldAccess(token.raw(), this.value, name);
                final SubscriptAccess subscriptAccess = new SubscriptAccess(next.raw(), fieldAccess);
                ArgumentListParser.parseArguments(pm, next.next(), subscriptAccess);
                this.value = subscriptAccess;
                this.mode = SUBSCRIPT_END;
                pm.skip();
                return;
            }
        case DyvilSymbols.ARROW_RIGHT:
        case DyvilSymbols.DOUBLE_ARROW_RIGHT:
            if (this.hasFlag(IGNORE_LAMBDA)) {
                break;
            }
            // IDENTIFIER =>   ...
            // token      next
            // Lambda Expression with one untyped parameter
            pm.pushParser(new LambdaOrTupleParser(this, LambdaOrTupleParser.SINGLE_PARAMETER), true);
            this.mode = END;
            return;
    }
    if (isGenericCall(next, nextType)) {
        final MethodCall call = new MethodCall(token.raw(), this.value, name, ArgumentList.EMPTY);
        this.value = call;
        pm.splitJump(next, 1);
        pm.pushParser(new TypeListParser(call.getGenericData().getTypes(), true));
        this.mode = TYPE_ARGUMENTS_END;
        return;
    }
    if (this.isFieldAccess(token, next, nextType)) {
        this.value = new FieldAccess(token.raw(), this.value, name);
        this.mode = ACCESS;
        return;
    }
    // IDENTIFIER EXPRESSION
    // token      next
    // Parse a single-argument call
    // e.g. println "abc"
    // println -1
    // println i
    final MethodCall call = new MethodCall(token.raw(), this.value, name, ArgumentList.empty());
    this.value = call;
    this.mode = ACCESS;
    this.parseApply(pm, token.next(), call);
}
Also used : InfixCallChain(dyvilx.tools.compiler.ast.expression.operator.InfixCallChain) TypeListParser(dyvilx.tools.compiler.parser.type.TypeListParser) PostfixCall(dyvilx.tools.compiler.ast.expression.operator.PostfixCall) IToken(dyvilx.tools.parsing.token.IToken) PrefixCall(dyvilx.tools.compiler.ast.expression.operator.PrefixCall)

Aggregations

InfixCallChain (dyvilx.tools.compiler.ast.expression.operator.InfixCallChain)1 PostfixCall (dyvilx.tools.compiler.ast.expression.operator.PostfixCall)1 PrefixCall (dyvilx.tools.compiler.ast.expression.operator.PrefixCall)1 TypeListParser (dyvilx.tools.compiler.parser.type.TypeListParser)1 IToken (dyvilx.tools.parsing.token.IToken)1