use of dyvilx.tools.compiler.ast.attribute.annotation.Annotation in project Dyvil by Dyvil.
the class MapExpr method withType.
@Override
public IValue withType(IType type, ITypeContext typeContext, MarkerList markers, IContext context) {
if (!Types.isSuperClass(type, MapType.MapTypes.IMMUTABLE_MAP_CLASS.getClassType())) {
final Annotation annotation = type.getTheClass().getAnnotation(LazyTypes.MAP_CONVERTIBLE_CLASS);
if (annotation == null) {
return null;
}
// [ x : y, ... ] -> Type(x : y, ...))
final int size = this.keys.size();
final ArgumentList arguments = new ArgumentList(size);
for (int i = 0; i < size; i++) {
arguments.add(new ColonOperator(this.keys.get(i), this.values.get(i)));
}
return new LiteralConversion(this, annotation, arguments).withType(type, typeContext, markers, context);
}
final int size = this.keys.size();
final IType keyType = this.keyType = Types.resolveTypeSafely(type, MapType.MapTypes.KEY_VARIABLE);
final IType valueType = this.valueType = Types.resolveTypeSafely(type, MapType.MapTypes.VALUE_VARIABLE);
for (int i = 0; i < size; i++) {
final IValue key = TypeChecker.convertValue(this.keys.get(i), keyType, typeContext, markers, context, KEY_MARKER_SUPPLIER);
this.keys.set(i, key);
final IValue value = TypeChecker.convertValue(this.values.get(i), valueType, typeContext, markers, context, VALUE_MARKER_SUPPLIER);
this.values.set(i, value);
}
return this;
}
use of dyvilx.tools.compiler.ast.attribute.annotation.Annotation in project Dyvil by Dyvil.
the class ExpressionParser method parseValue.
private boolean parseValue(IParserManager pm, IToken token, int type) {
switch(type) {
case Tokens.STRING:
case Tokens.VERBATIM_STRING:
this.value = new StringValue(token.raw(), token.stringValue());
this.mode = ACCESS;
return true;
case Tokens.STRING_START:
{
final StringInterpolationExpr stringInterpolation = new StringInterpolationExpr(token);
this.value = stringInterpolation;
this.mode = ACCESS;
pm.pushParser(new StingInterpolationParser(stringInterpolation), true);
return true;
}
case Tokens.SINGLE_QUOTED_STRING:
this.value = new CharValue(token.raw(), token.stringValue());
this.mode = ACCESS;
return true;
case Tokens.VERBATIM_CHAR:
this.value = new CharValue(token.raw(), token.stringValue(), true);
this.mode = ACCESS;
return true;
case Tokens.INT:
this.value = new IntValue(token.raw(), token.intValue());
this.mode = ACCESS;
return true;
case Tokens.LONG:
this.value = new LongValue(token.raw(), token.longValue());
this.mode = ACCESS;
return true;
case Tokens.FLOAT:
this.value = new FloatValue(token.raw(), token.floatValue());
this.mode = ACCESS;
return true;
case Tokens.DOUBLE:
this.value = new DoubleValue(token.raw(), token.doubleValue());
this.mode = ACCESS;
return true;
case DyvilSymbols.UNDERSCORE:
// _ ...
this.value = new WildcardValue(token.raw());
this.mode = ACCESS;
return true;
case BaseSymbols.OPEN_PARENTHESIS:
{
// ( ...
final IToken next = token.next();
if (next.type() != BaseSymbols.CLOSE_PARENTHESIS) {
pm.pushParser(new LambdaOrTupleParser(this, this.hasFlag(IGNORE_LAMBDA)), true);
this.mode = ACCESS;
return true;
}
if (!this.hasFlag(IGNORE_LAMBDA)) {
final IToken next2 = next.next();
final int next2Type = next2.type();
if (next2Type == DyvilSymbols.ARROW_RIGHT || next2Type == DyvilSymbols.DOUBLE_ARROW_RIGHT) {
// () =>
// () ->
pm.skip();
pm.pushParser(new LambdaOrTupleParser(this, LambdaOrTupleParser.TYPE_ARROW));
this.mode = END;
return true;
}
}
// ()
this.value = new VoidValue(token.to(token.next()));
pm.skip();
this.mode = ACCESS;
return true;
}
case BaseSymbols.OPEN_SQUARE_BRACKET:
// [ ...
this.mode = ACCESS;
pm.pushParser(new ArrayLiteralParser(this), true);
return true;
case BaseSymbols.OPEN_CURLY_BRACKET:
// { ...
this.mode = ACCESS;
pm.pushParser(new StatementListParser(this), true);
return true;
case DyvilSymbols.AT:
// @ ...
Annotation a = new CodeAnnotation(token.raw());
pm.pushParser(new AnnotationParser(a));
this.value = new AnnotationExpr(a);
this.mode = END;
return true;
case DyvilSymbols.ARROW_RIGHT:
case DyvilSymbols.DOUBLE_ARROW_RIGHT:
{
if (this.hasFlag(IGNORE_LAMBDA)) {
pm.popParser(true);
return true;
}
// => ...
// -> ...
pm.pushParser(new LambdaOrTupleParser(this, LambdaOrTupleParser.TYPE_ARROW), true);
return true;
}
case DyvilKeywords.NULL:
this.value = new NullValue(token.raw());
this.mode = ACCESS;
return true;
case DyvilKeywords.TRUE:
this.value = new BooleanValue(token.raw(), true);
this.mode = ACCESS;
return true;
case DyvilKeywords.FALSE:
this.value = new BooleanValue(token.raw(), false);
this.mode = ACCESS;
return true;
case DyvilKeywords.INIT:
// init ...
this.mode = ACCESS;
pm.pushParser(new ThisSuperParser(this), true);
return true;
case DyvilKeywords.THIS:
// this ...
this.mode = ACCESS;
pm.pushParser(new ThisSuperParser(this), true);
return true;
case DyvilKeywords.SUPER:
// super ...
this.mode = ACCESS;
pm.pushParser(new ThisSuperParser(this), true);
return true;
case DyvilKeywords.CLASS:
// class ...
this.mode = ACCESS;
pm.pushParser(new TypeClassParser(this, token, true));
return true;
case DyvilKeywords.TYPE:
// type ...
this.mode = ACCESS;
pm.pushParser(new TypeClassParser(this, token, false));
return true;
case DyvilKeywords.NEW:
// new ...
this.mode = ACCESS;
final int flags = this.hasFlag(IGNORE_CLOSURE) ? ConstructorCallParser.IGNORE_ANON_CLASS : 0;
pm.pushParser(new ConstructorCallParser(this).withFlags(flags), true);
return true;
case DyvilKeywords.RETURN:
{
// return ...
ReturnStatement returnStatement = new ReturnStatement(token.raw());
this.value = returnStatement;
pm.pushParser(new ExpressionParser(returnStatement));
this.mode = END;
return true;
}
case DyvilKeywords.IF:
{
// if ...
pm.pushParser(new IfStatementParser(this), true);
this.mode = END;
return true;
}
case DyvilKeywords.ELSE:
{
if (!(this.parent instanceof IfStatementParser) && !(this.parent instanceof ExpressionParser)) {
pm.report(token, "expression.else");
return true;
}
this.end(pm, true);
return true;
}
case DyvilKeywords.MATCH:
{
// match ...
final MatchExpr matchExpr = new MatchExpr(token.raw());
this.value = matchExpr;
pm.pushParser(new MatchExpressionParser(matchExpr));
this.mode = END;
return true;
}
case DyvilKeywords.WHILE:
{
if (// repeat parent
this.parent instanceof RepeatStatementParser || // repeat grandparent
this.parent instanceof ExpressionParser && this.parent.getParent() instanceof RepeatStatementParser) {
this.end(pm, true);
return true;
}
final WhileStatement whileStatement = new WhileStatement(token.raw());
this.value = whileStatement;
pm.pushParser(new WhileStatementParser(whileStatement));
this.mode = END;
return true;
}
case DyvilKeywords.REPEAT:
{
// repeat ...
final RepeatStatement repeatStatement = new RepeatStatement(token.raw());
this.value = repeatStatement;
pm.pushParser(new RepeatStatementParser(repeatStatement));
this.mode = END;
return true;
}
case DyvilKeywords.FOR:
{
pm.pushParser(new ForStatementParser(this.valueConsumer, token.raw()));
this.mode = END;
return true;
}
case DyvilKeywords.BREAK:
{
final BreakStatement breakStatement = new BreakStatement(token);
this.value = breakStatement;
final IToken next = token.next();
if (Tokens.isIdentifier(next.type())) {
breakStatement.setName(next.nameValue());
pm.skip();
}
this.mode = END;
return true;
}
case DyvilKeywords.CONTINUE:
{
final ContinueStatement continueStatement = new ContinueStatement(token);
this.value = continueStatement;
final IToken next = token.next();
if (Tokens.isIdentifier(next.type())) {
continueStatement.setName(next.nameValue());
pm.skip();
}
this.mode = END;
return true;
}
case DyvilKeywords.GOTO:
{
GoToStatement statement = new GoToStatement(token);
this.value = statement;
final IToken next = token.next();
if (Tokens.isIdentifier(next.type())) {
statement.setName(next.nameValue());
pm.skip();
}
this.mode = END;
return true;
}
case DyvilKeywords.TRY:
{
// try ...
final TryStatement tryStatement = new TryStatement(token.raw());
this.value = tryStatement;
pm.pushParser(new TryStatementParser(tryStatement));
this.mode = END;
return true;
}
case DyvilKeywords.CATCH:
{
if (!(this.parent instanceof TryStatementParser) && !(this.parent instanceof ExpressionParser)) {
pm.report(token, "expression.catch");
return true;
}
this.end(pm, true);
return true;
}
case DyvilKeywords.FINALLY:
{
if (!(this.parent instanceof TryStatementParser) && !(this.parent instanceof ExpressionParser)) {
pm.report(token, "expression.finally");
return true;
}
this.end(pm, true);
return true;
}
case DyvilKeywords.THROW:
{
final ThrowStatement throwStatement = new ThrowStatement(token.raw());
this.value = throwStatement;
pm.pushParser(new ExpressionParser(throwStatement));
this.mode = END;
return true;
}
case DyvilKeywords.SYNCHRONIZED:
{
final SyncStatement syncStatement = new SyncStatement(token.raw());
this.value = syncStatement;
pm.pushParser(new SyncStatementParser(syncStatement));
this.mode = END;
return true;
}
}
return false;
}
use of dyvilx.tools.compiler.ast.attribute.annotation.Annotation in project Dyvil by Dyvil.
the class ParameterListParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case DECLARATOR:
switch(type) {
case BaseSymbols.SEMICOLON:
if (token.isInferred()) {
return;
}
break;
case DyvilKeywords.LET:
this.attributes.addFlag(Modifiers.FINAL);
// Fallthrough
case DyvilKeywords.VAR:
this.mode = NAME;
return;
case DyvilKeywords.THIS:
if (token.next().type() != BaseSymbols.COLON) {
pm.report(token, "parameter.identifier");
this.mode = SEPARATOR;
return;
}
// this : TYPE
this.mode = TYPE_ASCRIPTION;
// the colon
pm.skip();
pm.pushParser(new TypeParser(t -> this.setThisType(t, token, pm)));
return;
case DyvilSymbols.AT:
final Annotation annotation = new CodeAnnotation(token.raw());
this.attributes.add(annotation);
pm.pushParser(new AnnotationParser(annotation));
return;
}
final Modifier modifier;
if ((modifier = ModifierParser.parseModifier(token, pm)) != null) {
this.attributes.add(modifier);
return;
}
if (BaseSymbols.isCloseBracket(type)) {
pm.popParser(true);
return;
}
// Fallthrough
case NAME:
final Name name;
if (Tokens.isIdentifier(type)) {
name = token.nameValue();
} else if (type == BaseSymbols.UNDERSCORE) {
name = null;
} else if (Tokens.isKeyword(type)) {
name = Name.fromRaw(token.stringValue());
} else {
if (BaseSymbols.isCloseBracket(type)) {
pm.popParser(true);
}
if (type == Tokens.EOF) {
pm.popParser();
}
this.mode = SEPARATOR;
pm.report(token, "parameter.identifier");
return;
}
this.parameter = this.consumer.createParameter(token.raw(), name, this.type, this.attributes);
this.mode = INTERNAL_NAME;
return;
case INTERNAL_NAME:
this.mode = VARARGS_AFTER_NAME;
// overwrite the internal name if necessary
if (Tokens.isIdentifier(type)) {
// IDENTIFIER IDENTIFIER : TYPE
this.parameter.setName(token.nameValue());
return;
} else if (type == BaseSymbols.UNDERSCORE) {
// IDENTIFIER _ : TYPE
this.parameter.setName(null);
return;
}
// Fallthrough
case VARARGS_AFTER_NAME:
if (type == DyvilSymbols.ELLIPSIS) {
this.flags |= VARARGS;
this.mode = TYPE_ASCRIPTION;
return;
}
// Fallthrough
case TYPE_ASCRIPTION:
case VARARGS_AFTER_POST_TYPE:
// continue with the remaining cases (DEFAULT_VALUE, PROPERTY, ...).
if (this.mode == VARARGS_AFTER_POST_TYPE) {
// case (2)
if (type == DyvilSymbols.ELLIPSIS) {
this.setTypeVarargs();
this.mode = DEFAULT_VALUE;
return;
}
} else /* case (1) */
if (type == BaseSymbols.COLON) {
this.mode = VARARGS_AFTER_POST_TYPE;
final TypeParser parser = new TypeParser(this);
if (this.hasFlag(LAMBDA_ARROW_END)) {
parser.withFlags(TypeParser.IGNORE_LAMBDA);
}
pm.pushParser(parser);
return;
}
// Fallthrough
case DEFAULT_VALUE:
if (type == BaseSymbols.EQUALS) {
this.mode = PROPERTY;
pm.pushParser(new ExpressionParser(this.parameter));
return;
}
// Fallthrough
case PROPERTY:
if (type == BaseSymbols.OPEN_CURLY_BRACKET && this.hasFlag(ALLOW_PROPERTIES)) {
final IProperty property = this.parameter.createProperty();
pm.pushParser(new PropertyBodyParser(property), true);
this.mode = SEPARATOR;
return;
}
// Fallthrough
case SEPARATOR:
this.mode = DECLARATOR;
if (this.parameter != null) {
if (this.hasFlag(VARARGS)) {
this.parameter.setVarargs();
}
this.parameter.setType(this.type);
this.consumer.getParameters().add(this.parameter);
}
this.reset();
switch(type) {
case DyvilSymbols.ARROW_RIGHT:
case DyvilSymbols.DOUBLE_ARROW_RIGHT:
if (!this.hasFlag(LAMBDA_ARROW_END)) {
// produce a syntax error
break;
}
// Fallthrough
case BaseSymbols.CLOSE_PARENTHESIS:
case BaseSymbols.CLOSE_CURLY_BRACKET:
case BaseSymbols.CLOSE_SQUARE_BRACKET:
pm.reparse();
// Fallthrough
case Tokens.EOF:
pm.popParser();
return;
case BaseSymbols.COMMA:
case BaseSymbols.SEMICOLON:
return;
}
pm.report(token, "parameter.separator");
}
}
use of dyvilx.tools.compiler.ast.attribute.annotation.Annotation in project Dyvil by Dyvil.
the class TypeParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case NAME:
{
if ((this.flags & NAMED_ONLY) == 0) {
switch(type) {
case DyvilSymbols.AT:
Annotation a = new CodeAnnotation(token.raw());
pm.pushParser(new AnnotationParser(a));
this.type = new AnnotatedType(a);
this.mode = ANNOTATION_END;
return;
case BaseSymbols.OPEN_PARENTHESIS:
{
final TypeList arguments;
if (this.parentType != null) {
final LambdaType lambdaType = new LambdaType();
lambdaType.setExtension(true);
this.type = lambdaType;
arguments = lambdaType.getArguments();
arguments.add(this.parentType);
} else {
final TupleType tupleType = new TupleType();
this.type = tupleType;
arguments = tupleType.getArguments();
}
pm.pushParser(new TypeListParser(arguments));
this.mode = TUPLE_END;
return;
}
case BaseSymbols.OPEN_SQUARE_BRACKET:
{
final ArrayType arrayType = new ArrayType();
switch(token.next().type()) {
case DyvilKeywords.FINAL:
arrayType.setMutability(Mutability.IMMUTABLE);
pm.skip();
break;
case DyvilKeywords.VAR:
arrayType.setMutability(Mutability.MUTABLE);
pm.skip();
break;
}
this.mode = ARRAY_COLON;
this.type = arrayType;
pm.pushParser(new TypeParser(arrayType::setElementType));
return;
}
case DyvilSymbols.ARROW_RIGHT:
{
if ((this.flags & IGNORE_LAMBDA) != 0) {
pm.popParser(true);
return;
}
final LambdaType lambdaType = new LambdaType(token.raw());
final TypeList arguments = lambdaType.getArguments();
if (this.parentType != null) {
arguments.add(this.parentType);
}
pm.pushParser(this.subParser(arguments));
this.type = lambdaType;
this.mode = LAMBDA_END;
return;
}
case DyvilKeywords.NULL:
this.type = Types.NULL;
this.mode = END;
return;
case DyvilSymbols.UNDERSCORE:
this.type = new WildcardType(token.raw(), Variance.COVARIANT);
this.mode = END;
return;
case Tokens.SYMBOL_IDENTIFIER:
final Name name = token.nameValue();
final int closeAngleIndex;
if ((this.flags & CLOSE_ANGLE) == 0 || (closeAngleIndex = name.unqualified.indexOf('>')) < 0) {
// SYMBOL_IDENTIFIER type
final PrefixType prefixType = new PrefixType(token.raw(), name);
pm.pushParser(this.subParser(prefixType.getArguments()).withFlags(IGNORE_OPERATOR | IGNORE_LAMBDA));
this.type = prefixType;
this.mode = END;
return;
}
if (closeAngleIndex == 0) {
// Token starts with a >
// Handles Type< > gracefully
pm.popParser(true);
return;
}
// strip the trailing > and reparse the first part of the token
// Handles Type<_> gracefully
pm.splitReparse(token, closeAngleIndex);
return;
}
}
if (!Tokens.isIdentifier(type)) {
if (isTerminator(type)) {
pm.popParser(true);
return;
}
pm.report(Markers.syntaxError(token, "type.invalid", token.toString()));
return;
}
final Name name = token.nameValue();
final IToken next = token.next();
if (isGenericStart(next, next.type())) {
this.type = new NamedGenericType(token.raw(), this.parentType, name);
this.mode = GENERICS;
return;
}
this.type = new NamedType(token.raw(), name, this.parentType);
this.mode = END;
return;
}
case TUPLE_END:
{
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.reparse();
pm.report(token, "type.tuple.close_paren");
}
final IToken nextToken = token.next();
if (nextToken.type() == DyvilSymbols.ARROW_RIGHT) {
final LambdaType lambdaType;
if (this.type instanceof LambdaType) {
lambdaType = (LambdaType) this.type;
} else {
lambdaType = new LambdaType(nextToken.raw(), ((TupleType) this.type).getArguments());
this.type = lambdaType;
}
lambdaType.setPosition(nextToken);
this.mode = LAMBDA_END;
pm.skip();
pm.pushParser(this.subParser(lambdaType.getArguments()));
return;
}
if (this.parentType != null) {
pm.report(nextToken, "type.tuple.lambda_arrow");
}
this.type.expandPosition(token);
this.mode = END;
return;
}
case LAMBDA_END:
this.type.expandPosition(token.prev());
this.consumer.setType(this.type);
pm.popParser(true);
return;
case ARRAY_COLON:
if (type == BaseSymbols.COLON) {
final MapType mapType = new MapType(this.type.getMutability(), ((ArrayType) this.type).getElementType());
this.type = mapType;
this.mode = ARRAY_END;
pm.pushParser(new TypeParser(mapType.getArguments()));
return;
}
// Fallthrough
case ARRAY_END:
this.type.expandPosition(token);
this.mode = END;
if (type != BaseSymbols.CLOSE_SQUARE_BRACKET) {
pm.reparse();
pm.report(token, "type.array.close_bracket");
}
return;
case GENERICS:
if (isGenericStart(token, type)) {
pm.splitJump(token, 1);
pm.pushParser(new TypeListParser(((GenericType) this.type).getArguments(), true));
this.mode = GENERICS_END;
return;
}
return;
case ANNOTATION_END:
this.mode = END;
pm.pushParser(this.subParser((ITyped) this.type), true);
return;
case GENERICS_END:
this.mode = END;
if (isGenericEnd(token, type)) {
pm.splitJump(token, 1);
return;
}
pm.report(token, "type.generic.close_angle");
// Fallthrough
case END:
{
switch(type) {
case BaseSymbols.DOT:
pm.pushParser(new TypeParser(this, this.type, this.flags));
return;
case BaseSymbols.OPEN_SQUARE_BRACKET:
{
final IToken next = token.next();
if (next.type() == BaseSymbols.CLOSE_SQUARE_BRACKET) {
this.type = new ArrayType(this.type);
pm.report(Markers.syntaxWarning(token.to(next), "type.array.java"));
pm.skip();
return;
}
break;
}
case Tokens.SYMBOL_IDENTIFIER:
{
if ((this.flags & NAMED_ONLY) != 0) {
break;
}
if ((this.flags & CLOSE_ANGLE) != 0) {
final String string = token.stringValue();
int index = string.indexOf('>');
if (index == 0) {
// ... >
pm.splitJump(token, 1);
break;
} else if (index > 0) {
// ... SYMBOL>
pm.splitJump(token, index);
this.type = new PostfixType(token.raw(), Name.fromUnqualified(string.substring(0, index)), this.type);
return;
}
}
final IToken next = token.next();
final boolean leftNeighbor = token.prev().isNeighboring(token);
final boolean rightNeighbor = token.isNeighboring(next);
if (isTerminator(next.type()) || leftNeighbor && !rightNeighbor) {
// type_OPERATOR
this.type = new PostfixType(token.raw(), token.nameValue(), this.type);
// move stays END
return;
}
if (leftNeighbor != rightNeighbor || (this.flags & IGNORE_OPERATOR) != 0) {
// type end
break;
}
// Parse part of an infix operator
// type SYMBOL type
// type_SYMBOL_type
final InfixTypeChain chain;
if (this.type.typeTag() == IType.INFIX_CHAIN) {
chain = (InfixTypeChain) this.type;
} else {
chain = new InfixTypeChain();
chain.addOperand(this.type);
this.type = chain;
}
chain.addOperator(token.nameValue(), token.raw());
pm.pushParser(this.subParser(chain::addOperand).withFlags(IGNORE_OPERATOR));
return;
}
case DyvilSymbols.ARROW_RIGHT:
// all these flags have to be unset
if (this.parentType == null && (this.flags & (NAMED_ONLY | IGNORE_OPERATOR | IGNORE_LAMBDA)) == 0) {
final LambdaType lambdaType = new LambdaType(token.raw(), this.type);
this.type = lambdaType;
this.mode = LAMBDA_END;
pm.pushParser(this.subParser(lambdaType.getArguments()));
return;
}
break;
}
if (this.type != null) {
this.consumer.setType(this.type);
}
pm.popParser(true);
}
}
}
use of dyvilx.tools.compiler.ast.attribute.annotation.Annotation in project Dyvil by Dyvil.
the class AbstractMemberParser method parseAnnotation.
protected void parseAnnotation(IParserManager pm, IToken token) {
final Annotation annotation = new CodeAnnotation(token.raw());
this.attributes.add(annotation);
pm.pushParser(new AnnotationParser(annotation));
}
Aggregations