com.redhat.ceylon.model.loader.ParameterNameParser Maven / Gradle / Ivy
package com.redhat.ceylon.model.loader;
import static com.redhat.ceylon.model.loader.ParameterNameLexer.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.redhat.ceylon.model.typechecker.model.Function;
import com.redhat.ceylon.model.typechecker.model.FunctionOrValue;
import com.redhat.ceylon.model.typechecker.model.Parameter;
import com.redhat.ceylon.model.typechecker.model.ParameterList;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.Unit;
import com.redhat.ceylon.model.typechecker.model.Value;
/**
* Parser for {@link com.redhat.ceylon.compiler.java.metadata.FunctionalParameter#value()}.
*
* input ::= ( '!' )? nameList ( nameList )*
* nameList ::= '(' ( name ( ',' name )* )? ')'
* name ::= identifier ( '+' | '*' )? ( '!' )? ( nameList )*
*
*
* - A {@code !} means that the {@code Function} model is declared {@code void}
* - A {@code +} means that the {@code Parameter} model is possibly-empty variadic
* - A {@code *} means that the {@code Parameter} model is nonempty variadic
*
* @author tom
*/
class ParameterNameParser {
private final ParameterNameLexer lexer = new ParameterNameLexer();
private final AbstractModelLoader loader;
private Unit unit;
ParameterNameParser(AbstractModelLoader loader) {
this.loader = loader;
}
public void parse(String input, Type type, Function method) {
lexer.setup(input);
this.unit = method.getUnit();
boolean declaredVoid = false;
ArrayList lists = new ArrayList<>();
if (lexer.lookingAt(BANG)) {
lexer.eat();
declaredVoid = true;
}
lists.add(parseNameList(type, method));
while (lexer.lookingAt(LEFT_PAREN)) {// mpl
type = loader.getSimpleCallableReturnType(type);
lists.add(parseNameList(type, method));
}
for (ParameterList parameterList : lists) {
method.addParameterList(parameterList);
}
method.setDeclaredVoid(declaredVoid);
method.setType(loader.getSimpleCallableReturnType(type));
if (!lexer.lookingAt(EOI)) {
throw new ParameterNameParserException("Expected end of input" + System.lineSeparator() + input);
}
}
public void parseMpl(String input, Type type, Function method) {
lexer.setup(input);
this.unit = method.getUnit();
ArrayList lists = new ArrayList<>();
lists.add(parseNameList(type, method));
while (lexer.lookingAt(LEFT_PAREN)) {// mpl
type = loader.getSimpleCallableReturnType(type);
lists.add(parseNameList(type, method));
}
for (ParameterList parameterList : lists) {
method.addParameterList(parameterList);
}
method.setType(loader.getSimpleCallableReturnType(type));
if (!lexer.lookingAt(EOI)) {
throw new ParameterNameParserException("Expected end of input" + System.lineSeparator() + input);
}
}
private ParameterList parseNameList(Type type, Function method) {
ParameterList pl = new ParameterList();
List parameters = pl.getParameters();
//startParameterList();
lexer.eat(LEFT_PAREN);
if (!lexer.lookingAt(RIGHT_PAREN)) {
Iterator ct = loader.getSimpleCallableArgumentTypes(type).iterator();
if (!ct.hasNext()) {
throw new ParameterNameParserException("Too few parameter types");
}
parameters.add(parseName(ct.next(), method));
// addParameter()
while (lexer.lookingAt(COMMA)) {
lexer.eat();
if (!ct.hasNext()) {
throw new ParameterNameParserException("Too few parameter types");
}
parameters.add(parseName(ct.next(), method));
}
if (ct.hasNext()) {
throw new ParameterNameParserException("Too many parameter types");
}
}
lexer.eat(RIGHT_PAREN);
//endParameterList();
return pl;
}
private Parameter parseName(Type type, Function container) {
String identifier = lexer.eatIdentifier();
boolean declaredVoid = false;
boolean sequenced = false;
boolean atLeastOne = false;
if (lexer.lookingAt(STAR)) {
lexer.eat();
sequenced = true;
} else if (lexer.lookingAt(PLUS)) {
lexer.eat();
sequenced = true;
atLeastOne = true;
}
if (lexer.lookingAt(BANG)) {
lexer.eat();
declaredVoid = true;
}
final FunctionOrValue result;
if (lexer.lookingAt(LEFT_PAREN)) {
// functionParameter()
result = parseMethod(type, declaredVoid);
} else {
if (declaredVoid) {
throw new ParameterNameParserException("void Value");
}
// valueParameter();
result = parseValue(type);
}
result.setName(identifier);
result.setUnit(unit);
result.setContainer(container);
result.setScope(container);
Parameter p = new Parameter();
p.setName(identifier);
p.setSequenced(sequenced);
p.setAtLeastOne(atLeastOne);
p.setDeclaredAnything(declaredVoid);
p.setModel(result);
result.setInitializerParameter(p);
container.addMember(result);
return p;
}
private Value parseValue(Type type) {
Value value = new Value();
value.setType(type);
return value;
}
private Function parseMethod(Type type, boolean declaredVoid) {
Function method = new Function();
method.setDeclaredVoid(declaredVoid);
method.setType(loader.getSimpleCallableReturnType(type));
while (lexer.lookingAt(LEFT_PAREN)) {
method.addParameterList(parseNameList(type, method));
type = loader.getSimpleCallableReturnType(type);
}
return method;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy