package bluej.stride.framedjava.convert;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.function.BiFunction;
import java.util.function.Consumer;

import bluej.parser.lexer.JavaTokenTypes;
import bluej.parser.lexer.LocatableToken;
import bluej.stride.framedjava.ast.FilledExpressionSlotFragment;
import bluej.stride.framedjava.ast.OptionalExpressionSlotFragment;
import bluej.stride.framedjava.ast.SuperThisParamsExpressionFragment;
import bluej.stride.framedjava.convert.ConversionWarning.UnsupportedFeature;
import bluej.stride.framedjava.elements.AssignElement;
import bluej.stride.framedjava.elements.CodeElement;
import threadchecker.OnThread;
import threadchecker.Tag;


| Class in charge of building expressions. | | Because expressions can nest, beginExpression/endExpression will likely be called | multiple times on the same handler. We pair them off, and only finish when | the outermost expression is completed. | class ExpressionBuilder { private LocatableToken start; private int outstanding = 0; private final Consumer<Expression> handler; private final TriFunction<LocatableToken, LocatableToken, List<Mask>, String> getText; private LocatableToken assignOp; private List<Integer> incDec = new ArrayList<>(); private final Consumer<ConversionWarning> addWarning; private final Stack<Mask> curMasks = new Stack<>(); private final List<Mask> completeMasks = new ArrayList<>(); ExpressionBuilder(Consumer<Expression> handler, TriFunction<LocatableToken, LocatableToken, List<Mask>, String> getText, Consumer<ConversionWarning> addWarning) { this.handler = handler; this.getText = getText; this.addWarning = addWarning; } p.public void expressionBegun(LocatableToken start) { if (outstanding == 0) this.start = start; outstanding += 1; } p.public boolean expressionEnd(LocatableToken end) { outstanding -= 1; if (outstanding == 0) { if (assignOp == null) { String java = getText.apply(start, end, completeMasks); handler.accept(new Expression(java, incDec, addWarning)); } else { String wholeJava = getText.apply(start, end, completeMasks); String lhs = getText.apply(start, assignOp, completeMasks).trim(); String rhs = assignOp.getText().equals("=") ? getText.apply(assignOp, end, completeMasks).substring(assignOp.getText().length()) : lhs + " " + assignOp.getText().substring(0, assignOp.getText().length() - 1) + " " + getText.apply(assignOp, end, completeMasks).substring(assignOp.getText().length()); handler.accept(new Expression(wholeJava, incDec, addWarning) { @Override FilledExpressionSlotFragment toFilled() { addWarning.accept(new UnsupportedFeature(assignOp.getText() + " in expression")); return super.toFilled(); } @Override OptionalExpressionSlotFragment toOptional() { addWarning.accept(new UnsupportedFeature(assignOp.getText() + " in expression")); return super.toOptional(); } @Override SuperThisParamsExpressionFragment toSuperThis() { addWarning.accept(new UnsupportedFeature(assignOp.getText() + " in expression")); return super.toSuperThis(); } @Override public CodeElement toStatement() { return new AssignElement(null, new Expression(lhs, incDec, addWarning).toFilled(), new Expression(rhs, Collections.emptyList(), addWarning).toFilled(), true); } }); } return true; } else{ return false; } } public void binaryOperator(LocatableToken opToken) { switch (opToken.getType()) { case JavaTokenTypes.BAND_ASSIGN: case JavaTokenTypes.BOR_ASSIGN: case JavaTokenTypes.BSR_ASSIGN: case JavaTokenTypes.BXOR_ASSIGN: case JavaTokenTypes.DIV_ASSIGN: case JavaTokenTypes.MINUS_ASSIGN: case JavaTokenTypes.MOD_ASSIGN: case JavaTokenTypes.PLUS_ASSIGN: case JavaTokenTypes.SL_ASSIGN: case JavaTokenTypes.SR_ASSIGN: case JavaTokenTypes.STAR_ASSIGN: case JavaTokenTypes.ASSIGN: if (outstanding == 1) assignOp = opToken; else{ addWarning.accept(new UnsupportedFeature(opToken.getText() + " in expression")); } break; default: return; } } public void unaryOperator(LocatableToken token) { if (token.getType() == JavaTokenTypes.INC || token.getType() == JavaTokenTypes.DEC) incDec.add(token.getType()); } public void postOperator(LocatableToken token) { unaryOperator(token); } public void beginMask(LocatableToken from) { curMasks.push(new Mask(from)); } public void endMask(LocatableToken to) { Mask mask = curMasks.pop(); if (curMasks.isEmpty()) { mask.setEnd(to); completeMasks.add(mask); } } public static interface TriFunction<T1, T2, T3, R> { public R apply(T1 t1, T2 t2, T3 t3); } }

.   - ExpressionBuilder
.   expressionBegun
.   expressionEnd
.   toStatement
.   binaryOperator
.   unaryOperator
.   postOperator
.   beginMask
.   endMask
.   apply




228 neLoCode + 4 LoComm