package org.develnext.jphp.core.syntax.generators;
import org.develnext.jphp.core.syntax.SyntaxAnalyzer;
import org.develnext.jphp.core.syntax.generators.manually.BodyGenerator;
import org.develnext.jphp.core.tokenizer.TokenType;
import org.develnext.jphp.core.tokenizer.token.Token;
import org.develnext.jphp.core.tokenizer.token.expr.BraceExprToken;
import org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken;
import org.develnext.jphp.core.tokenizer.token.expr.value.NameToken;
import org.develnext.jphp.core.tokenizer.token.expr.value.VariableExprToken;
import org.develnext.jphp.core.tokenizer.token.stmt.BodyStmtToken;
import org.develnext.jphp.core.tokenizer.token.stmt.CatchStmtToken;
import org.develnext.jphp.core.tokenizer.token.stmt.FinallyStmtToken;
import org.develnext.jphp.core.tokenizer.token.stmt.TryStmtToken;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class TryCatchGenerator extends Generator<TryStmtToken> {
public TryCatchGenerator(SyntaxAnalyzer analyzer) {
super(analyzer);
}
public void processCatch(CatchStmtToken result, ListIterator<Token> iterator){
Token next = nextToken(iterator);
if (!isOpenedBrace(next, BraceExprToken.Kind.SIMPLE))
unexpectedToken(next, "(");
next = nextToken(iterator);
if (!(next instanceof NameToken))
unexpectedToken(next, TokenType.T_STRING);
FulledNameToken exception = analyzer.getRealName((NameToken)next);
result.setException(exception);
next = nextToken(iterator);
if (!(next instanceof VariableExprToken))
unexpectedToken(next, TokenType.T_VARIABLE);
VariableExprToken variable = (VariableExprToken)next;
result.setVariable(variable);
if (analyzer.getFunction() != null){
analyzer.getFunction().variable(variable).setUnstable(true);
}
analyzer.getScope().addVariable(variable);
next = nextToken(iterator);
if (!isClosedBrace(next, BraceExprToken.Kind.SIMPLE))
unexpectedToken(next, ")");
BodyStmtToken body = analyzer.generator(BodyGenerator.class).getToken(nextToken(iterator), iterator);
result.setBody(body);
}
protected void processFinally(TryStmtToken result, Token current, ListIterator<Token> iterator){
if (result.getFinally() != null)
unexpectedToken(current);
result.setFinally(
analyzer.generator(BodyGenerator.class).getToken(nextToken(iterator), iterator)
);
if (!iterator.hasNext())
return;
current = iterator.next();
if (current instanceof CatchStmtToken)
processCatches(result, current, iterator);
else
iterator.previous();
}
protected void processCatches(TryStmtToken result, Token current, ListIterator<Token> iterator){
List<CatchStmtToken> catches = result.getCatches();
do {
CatchStmtToken _catch = (CatchStmtToken) current;
processCatch(_catch, iterator);
catches.add(_catch);
if (!iterator.hasNext())
break;
current = iterator.next();
if (!(current instanceof CatchStmtToken)){
if (current instanceof FinallyStmtToken){
processFinally(result, current, iterator);
break;
}
iterator.previous();
break;
}
} while (true);
}
@Override
public TryStmtToken getToken(Token current, ListIterator<Token> iterator) {
if (current instanceof TryStmtToken){
TryStmtToken result = (TryStmtToken)current;
analyzer.addScope(false);
BodyStmtToken body = analyzer.generator(BodyGenerator.class).getToken(nextToken(iterator), iterator);
result.setBody(body);
Token next = nextToken(iterator);
result.setCatches(new ArrayList<CatchStmtToken>());
if (next instanceof CatchStmtToken){
processCatches(result, next, iterator);
} else if (next instanceof FinallyStmtToken) {
analyzer.getScope().setLevelForGoto(true);
processFinally(result, next, iterator);
analyzer.getScope().setLevelForGoto(false);
} else
unexpectedToken(next, TokenType.T_CATCH);
result.setLocal(analyzer.removeScope().getVariables());
return result;
}
return null;
}
}