package org.fandev.lang.fan.parsing.types;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import org.fandev.lang.fan.FanBundle;
import org.fandev.lang.fan.FanElementTypes;
import static org.fandev.lang.fan.FanTokenTypes.*;
import org.fandev.lang.fan.parsing.expression.Expression;
import org.fandev.lang.fan.parsing.statements.expressions.arguments.Arguments;
import org.fandev.lang.fan.parsing.util.ParserUtils;
import static org.fandev.lang.fan.parsing.util.ParserUtils.*;
import static org.fandev.lang.fan.parsing.util.ParserUtils.getToken;
import static org.fandev.lang.fan.parsing.util.ParserUtils.removeNls;
/**
* @author Dror Bereznitsky
* @date Jan 10, 2009 6:14:27 PM
*/
public class TypeParameters {
public static IElementType parse(final PsiBuilder builder) {
// <params> := [<param> ("," <param>)*]
if (LPAR == builder.getTokenType()) {
final PsiBuilder.Marker marker = builder.mark();
getToken(builder, LPAR);
removeNls(builder);
if (!getToken(builder, RPAR)) {
while (parseTypeParameter(builder) != FanElementTypes.WRONGWAY) {
if (!getToken(builder, COMMA)) {
break;
}
eatCommas(builder);
}
eatCommas(builder);
if (!getToken(builder, RPAR)) {
builder.error(FanBundle.message("rpar.expected"));
ParserUtils.cleanAfterErrorInArguments(builder);
}
}
removeNls(builder);
marker.done(FanElementTypes.TYPE_PARAMETER_LIST);
return FanElementTypes.TYPE_PARAMETER_LIST;
}
return FanElementTypes.WRONGWAY;
}
private static void eatCommas(final PsiBuilder builder) {
removeNls(builder);
while (COMMA == builder.getTokenType()) {
builder.error(FanBundle.message("type.parameter.expected"));
getToken(builder, COMMA);
removeNls(builder);
}
}
// <param> := <type> <id> [":=" <expr>]
private static IElementType parseTypeParameter(final PsiBuilder builder) {
final PsiBuilder.Marker marker = builder.mark();
if (TypeSpec.parse(builder)) { // <type>
// <id>
if (parseName(builder)) {
removeNls(builder);
if (COLON_EQ.equals(builder.getTokenType())) {
// Default param initializer
ParserUtils.advanceNoNls(builder);
Expression.parseExpr(builder, Arguments.ARGUMENTS_STOPPER, FanElementTypes.PARAM_DEFAULT);
}
marker.done(FanElementTypes.TYPE_PARAMETER);
return FanElementTypes.TYPE_PARAMETER;
}
}
marker.error(FanBundle.message("type.parameter.expected"));
return FanElementTypes.WRONGWAY;
}
}