Search in sources :

Example 1 with Modifier

use of dyvilx.tools.compiler.ast.attribute.modifiers.Modifier 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 2 with Modifier

use of dyvilx.tools.compiler.ast.attribute.modifiers.Modifier in project Dyvil by Dyvil.

the class AbstractMemberParser method parseModifier.

protected boolean parseModifier(IParserManager pm, IToken token) {
    final Modifier modifier = ModifierParser.parseModifier(token, pm);
    if (modifier == null) {
        return false;
    }
    this.attributes.add(modifier);
    return true;
}
Also used : Modifier(dyvilx.tools.compiler.ast.attribute.modifiers.Modifier)

Example 3 with Modifier

use of dyvilx.tools.compiler.ast.attribute.modifiers.Modifier 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)

Example 4 with Modifier

use of dyvilx.tools.compiler.ast.attribute.modifiers.Modifier in project Dyvil by Dyvil.

the class MemberParser 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;
                    }
                // Fallthrough
                case BaseSymbols.CLOSE_CURLY_BRACKET:
                    pm.reparse();
                // Fallthrough
                case Tokens.EOF:
                    if (!this.attributes.isEmpty()) {
                        pm.report(token, "member.declarator");
                    }
                    pm.popParser();
                    return;
                case // constructor declaration or initializer
                DyvilKeywords.INIT:
                    if (// initializer
                    token.next().type() == BaseSymbols.OPEN_CURLY_BRACKET) {
                        final IInitializer initializer = this.consumer.createInitializer(token.raw(), this.attributes);
                        this.consumer.addInitializer(initializer);
                        this.mode = END;
                        pm.pushParser(new StatementListParser(initializer));
                        return;
                    }
                    this.mode = END;
                    pm.pushParser(new ConstructorParser(this.consumer, this.attributes), true);
                    return;
                case DyvilKeywords.CONST:
                case DyvilKeywords.LET:
                case DyvilKeywords.VAR:
                    final FieldParser<T> parser = new FieldParser<>(this.consumer, this.attributes);
                    if ((this.flags & NO_FIELD_PROPERTIES) != 0) {
                        parser.withFlags(FieldParser.NO_PROPERTIES);
                    }
                    pm.pushParser(parser, true);
                    this.mode = END;
                    return;
                case DyvilKeywords.CASE:
                    if (!Tokens.isIdentifier(token.next().type())) {
                        break;
                    }
                    pm.pushParser(new EnumConstantParser(this.consumer), true);
                    this.mode = END;
                    return;
                case DyvilKeywords.FUNC:
                case DyvilKeywords.OPERATOR:
                    this.mode = END;
                    pm.pushParser(new MethodParser(this.consumer, this.attributes), true);
                    return;
            }
            final Modifier modifier;
            if ((modifier = ModifierParser.parseModifier(token, pm)) != null) {
                this.attributes.add(modifier);
                return;
            }
            int classType;
            if ((classType = ModifierParser.parseClassTypeModifier(token, pm)) >= 0) {
                this.attributes.addFlag(classType);
                ClassDeclarationParser parser = new ClassDeclarationParser(this.consumer, this.attributes);
                pm.pushParser(parser);
                this.mode = END;
                return;
            }
            // This is not in the above switch because 'readClassTypeModifier' above has to check for '@ interface' first
            if (type == DyvilSymbols.AT) {
                this.parseAnnotation(pm, token);
                return;
            }
            pm.report(token, "member.declarator");
            return;
        case END:
            pm.popParser(type != Tokens.EOF);
    }
}
Also used : StatementListParser(dyvilx.tools.compiler.parser.statement.StatementListParser) IInitializer(dyvilx.tools.compiler.ast.constructor.IInitializer) Modifier(dyvilx.tools.compiler.ast.attribute.modifiers.Modifier)

Aggregations

Modifier (dyvilx.tools.compiler.ast.attribute.modifiers.Modifier)4 Name (dyvil.lang.Name)2 Annotation (dyvilx.tools.compiler.ast.attribute.annotation.Annotation)2 CodeAnnotation (dyvilx.tools.compiler.ast.attribute.annotation.CodeAnnotation)2 AnnotationParser (dyvilx.tools.compiler.parser.annotation.AnnotationParser)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 IInitializer (dyvilx.tools.compiler.ast.constructor.IInitializer)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 IType (dyvilx.tools.compiler.ast.type.IType)1 Types (dyvilx.tools.compiler.ast.type.builtin.Types)1 ArrayType (dyvilx.tools.compiler.ast.type.compound.ArrayType)1 DyvilKeywords (dyvilx.tools.compiler.parser.DyvilKeywords)1 DyvilSymbols (dyvilx.tools.compiler.parser.DyvilSymbols)1 ModifierParser (dyvilx.tools.compiler.parser.annotation.ModifierParser)1