Search in sources :

Example 1 with CodeAnnotation

use of dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation 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;
}
Also used : CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) WhileStatement(dyvilx.tools.compiler.ast.statement.loop.WhileStatement) IToken(dyvilx.tools.parsing.token.IToken) TryStatement(dyvilx.tools.compiler.ast.statement.exception.TryStatement) ReturnStatement(dyvilx.tools.compiler.ast.statement.ReturnStatement) ThrowStatement(dyvilx.tools.compiler.ast.statement.exception.ThrowStatement) ContinueStatement(dyvilx.tools.compiler.ast.statement.control.ContinueStatement) GoToStatement(dyvilx.tools.compiler.ast.statement.control.GoToStatement) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) BreakStatement(dyvilx.tools.compiler.ast.statement.control.BreakStatement) SyncStatement(dyvilx.tools.compiler.ast.statement.SyncStatement) RepeatStatement(dyvilx.tools.compiler.ast.statement.loop.RepeatStatement)

Example 2 with CodeAnnotation

use of dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation 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");
    }
}
Also used : Parser(dyvilx.tools.parsing.Parser) ITypeConsumer(dyvilx.tools.compiler.ast.consumer.ITypeConsumer) ExpressionParser(dyvilx.tools.compiler.parser.expression.ExpressionParser) TypeParser(dyvilx.tools.compiler.parser.type.TypeParser) IParametric(dyvilx.tools.compiler.ast.parameter.IParametric) Tokens(dyvilx.tools.parsing.lexer.Tokens) IProperty(dyvilx.tools.compiler.ast.field.IProperty) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation) IParserManager(dyvilx.tools.parsing.IParserManager) AttributeList(dyvilx.tools.compiler.ast.attribute.AttributeList) ModifierParser(dyvilx.tools.compiler.parser.annotation.ModifierParser) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) DyvilSymbols(dyvilx.tools.compiler.parser.DyvilSymbols) PropertyBodyParser(dyvilx.tools.compiler.parser.classes.PropertyBodyParser) IParameter(dyvilx.tools.compiler.ast.parameter.IParameter) Name(dyvil.lang.Name) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) ArrayType(dyvilx.tools.compiler.ast.type.compound.ArrayType) IType(dyvilx.tools.compiler.ast.type.IType) Types(dyvilx.tools.compiler.ast.type.builtin.Types) Modifier(dyvilx.tools.compiler.ast.attribute.modifiers.Modifier) DyvilKeywords(dyvilx.tools.compiler.parser.DyvilKeywords) Modifiers(dyvil.reflect.Modifiers) BaseSymbols(dyvilx.tools.parsing.lexer.BaseSymbols) IToken(dyvilx.tools.parsing.token.IToken) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) TypeParser(dyvilx.tools.compiler.parser.type.TypeParser) IProperty(dyvilx.tools.compiler.ast.field.IProperty) ExpressionParser(dyvilx.tools.compiler.parser.expression.ExpressionParser) PropertyBodyParser(dyvilx.tools.compiler.parser.classes.PropertyBodyParser) Modifier(dyvilx.tools.compiler.ast.attribute.modifiers.Modifier) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) Name(dyvil.lang.Name)

Example 3 with CodeAnnotation

use of dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation 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);
            }
    }
}
Also used : CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) NamedType(dyvilx.tools.compiler.ast.type.raw.NamedType) ITyped(dyvilx.tools.compiler.ast.type.ITyped) Name(dyvil.lang.Name) IToken(dyvilx.tools.parsing.token.IToken) TypeList(dyvilx.tools.compiler.ast.type.TypeList) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation)

Example 4 with CodeAnnotation

use of dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation 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));
}
Also used : CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation)

Example 5 with CodeAnnotation

use of dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation in project Dyvil by Dyvil.

the class ClassDeclarationParser method parse.

@Override
public void parse(IParserManager pm, IToken token) {
    int type = token.type();
    switch(this.mode) {
        case NAME:
            if (!Tokens.isIdentifier(type)) {
                pm.report(token, "class.identifier");
                return;
            }
            final Name name = token.nameValue();
            if (name.qualified.indexOf('$') >= 0) {
                pm.report(Markers.syntaxError(token, "class.identifier.invalid", name, name.qualified));
            }
            this.theClass = this.consumer.createClass(token.raw(), name, this.classAttributes);
            this.mode = GENERICS;
            return;
        case GENERICS:
            if (type == BaseSymbols.SEMICOLON && token.isInferred() && TypeParser.isGenericStart(token.next())) {
                // allow an implicit semicolon / line break between name and generic argument list
                return;
            }
            if (TypeParser.isGenericStart(token, type)) {
                pm.splitJump(token, 1);
                pm.pushParser(new TypeParameterListParser(this.theClass));
                this.mode = GENERICS_END;
                return;
            }
        // Fallthrough
        case PARAMETERS:
            final Modifier modifier = ModifierParser.parseModifier(token, pm);
            if (modifier != null) {
                this.theClass.getConstructorAttributes().add(modifier);
                return;
            }
            if (type == DyvilSymbols.AT) {
                final Annotation annotation = new CodeAnnotation(token.raw());
                this.theClass.getConstructorAttributes().add(annotation);
                pm.pushParser(new AnnotationParser(annotation));
                return;
            }
            if (type == BaseSymbols.OPEN_PARENTHESIS) {
                pm.pushParser(new ParameterListParser(this.theClass).withFlags(ParameterListParser.ALLOW_PROPERTIES));
                this.mode = PARAMETERS_END;
                return;
            }
        // Fallthrough
        case EXTENDS:
            if (type == DyvilKeywords.EXTENDS) {
                if (this.theClass.isInterface()) {
                    pm.pushParser(new TypeListParser(this));
                    this.mode = BODY;
                    return;
                }
                pm.pushParser(new TypeParser(this));
                this.mode = EXTENDS_PARAMETERS;
                return;
            }
        // Fallthrough
        case IMPLEMENTS:
            if (type == DyvilKeywords.IMPLEMENTS) {
                pm.pushParser(new TypeListParser(this));
                this.mode = BODY;
                if (this.theClass.isInterface()) {
                    pm.report(token, "class.interface.implements");
                    return;
                }
                return;
            }
        // Fallthrough
        case BODY:
            if (type == BaseSymbols.OPEN_CURLY_BRACKET) {
                ClassBody body = new ClassBody(this.theClass);
                this.theClass.setBody(body);
                pm.pushParser(new ClassBodyParser(body), true);
                this.mode = BODY_END;
                return;
            }
            if (BaseSymbols.isTerminator(type)) {
                if (token.isInferred()) {
                    switch(token.next().type()) {
                        case DyvilKeywords.EXTENDS:
                            this.mode = EXTENDS;
                            return;
                        case DyvilKeywords.IMPLEMENTS:
                            this.mode = IMPLEMENTS;
                            return;
                        case BaseSymbols.OPEN_SQUARE_BRACKET:
                            this.mode = GENERICS;
                            return;
                        case BaseSymbols.OPEN_PARENTHESIS:
                            this.mode = PARAMETERS;
                            return;
                    }
                }
                pm.popParser(true);
                this.consumer.addClass(this.theClass);
                return;
            }
            this.mode = BODY_END;
            pm.report(token, "class.body.separator");
            return;
        case GENERICS_END:
            this.mode = PARAMETERS;
            if (TypeParser.isGenericEnd(token, type)) {
                pm.splitJump(token, 1);
                return;
            }
            pm.reparse();
            pm.report(token, "generic.close_angle");
            return;
        case PARAMETERS_END:
            this.mode = EXTENDS;
            if (type != BaseSymbols.CLOSE_PARENTHESIS) {
                pm.reparse();
                pm.report(token, "class.parameters.close_paren");
            }
            return;
        case BODY_END:
            pm.popParser();
            this.consumer.addClass(this.theClass);
            if (type != BaseSymbols.CLOSE_CURLY_BRACKET) {
                pm.reparse();
                pm.report(token, "class.body.close_brace");
            }
            return;
        case EXTENDS_PARAMETERS_END:
            this.mode = IMPLEMENTS;
            if (type != BaseSymbols.CLOSE_PARENTHESIS) {
                pm.reparse();
                pm.report(token, "class.extends.close_paren");
            }
            return;
        case EXTENDS_PARAMETERS:
            if (type == BaseSymbols.OPEN_PARENTHESIS) {
                ArgumentListParser.parseArguments(pm, token.next(), this.theClass::setSuperConstructorArguments);
                this.mode = EXTENDS_PARAMETERS_END;
                return;
            }
            this.mode = IMPLEMENTS;
            pm.reparse();
    }
}
Also used : CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) AnnotationParser(dyvilx.tools.compiler.parser.annotation.AnnotationParser) TypeParser(dyvilx.tools.compiler.parser.type.TypeParser) ParameterListParser(dyvilx.tools.compiler.parser.method.ParameterListParser) TypeParameterListParser(dyvilx.tools.compiler.parser.type.TypeParameterListParser) TypeListParser(dyvilx.tools.compiler.parser.type.TypeListParser) Modifier(dyvilx.tools.compiler.ast.attribute.modifiers.Modifier) TypeParameterListParser(dyvilx.tools.compiler.parser.type.TypeParameterListParser) Annotation(dyvilx.tools.compiler.ast.attribute.annotation.Annotation) CodeAnnotation(dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation) Name(dyvil.lang.Name) ClassBody(dyvilx.tools.compiler.ast.classes.ClassBody)

Aggregations

Annotation (dyvilx.tools.compiler.ast.attribute.annotation.Annotation)6 CodeAnnotation (dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation)6 AnnotationParser (dyvilx.tools.compiler.parser.annotation.AnnotationParser)6 Name (dyvil.lang.Name)4 IToken (dyvilx.tools.parsing.token.IToken)3 Modifier (dyvilx.tools.compiler.ast.attribute.modifiers.Modifier)2 TypeParser (dyvilx.tools.compiler.parser.type.TypeParser)2 Modifiers (dyvil.reflect.Modifiers)1 AttributeList (dyvilx.tools.compiler.ast.attribute.AttributeList)1 ClassBody (dyvilx.tools.compiler.ast.classes.ClassBody)1 ITypeConsumer (dyvilx.tools.compiler.ast.consumer.ITypeConsumer)1 IProperty (dyvilx.tools.compiler.ast.field.IProperty)1 IParameter (dyvilx.tools.compiler.ast.parameter.IParameter)1 IParametric (dyvilx.tools.compiler.ast.parameter.IParametric)1 ReturnStatement (dyvilx.tools.compiler.ast.statement.ReturnStatement)1 SyncStatement (dyvilx.tools.compiler.ast.statement.SyncStatement)1 BreakStatement (dyvilx.tools.compiler.ast.statement.control.BreakStatement)1 ContinueStatement (dyvilx.tools.compiler.ast.statement.control.ContinueStatement)1 GoToStatement (dyvilx.tools.compiler.ast.statement.control.GoToStatement)1 ThrowStatement (dyvilx.tools.compiler.ast.statement.exception.ThrowStatement)1