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);
}
Aggregations