EnumVisitor.java

package de.schegge.rosinante.generator;

import de.schegge.rosinante.parser.Node;
import de.schegge.rosinante.parser.Token;
import de.schegge.rosinante.parser.ast.EnumBody;
import de.schegge.rosinante.parser.ast.EnumField;
import de.schegge.rosinante.parser.ast.FieldOptions;
import de.schegge.rosinante.parser.ast.IDENTIFIER;
import de.schegge.rosinante.parser.ast.Option;

import java.util.List;
import java.util.stream.Collectors;

import static de.schegge.rosinante.generator.FieldOptionsVisitor.ENUM_FIELD_OPTION_VISITOR;

public class EnumVisitor implements ProtoVisitor<EnumPattern, Void> {

    @Override
    public Void visit(EnumBody enumBody, EnumPattern enumPattern) {
        List<Node> children = enumBody.children();
        children.subList(1, children.size() - 1).forEach(n -> n.accept(this, enumPattern));
        return null;
    }

    @Override
    public Void visit(EnumField enumField, EnumPattern enumPattern) {
        int index = enumField.indexOf(enumField.firstChildOfType(Token.class, x -> x.getType() == Token.TokenType.ASSIGN));
        List<String> names = enumField.subList(0, index).stream().filter(x -> x instanceof IDENTIFIER)
                .map(String::valueOf).collect(Collectors.toList());
        EnumFieldPattern enumFieldPattern = new EnumFieldPattern(names, getSignedFieldNumber(enumField, index));
        enumPattern.addField(enumFieldPattern);
        enumField.childrenOfType(FieldOptions.class).forEach(x -> x.accept(ENUM_FIELD_OPTION_VISITOR, enumFieldPattern));
        return null;
    }

    private static int getSignedFieldNumber(EnumField enumField, int index) {
        boolean negative = "-".equals(enumField.get(index + 1).toString());
        int fieldNumber = Integer.parseInt(enumField.get(index + (negative ? 2 : 1)).toString());
        return negative ? -fieldNumber : fieldNumber;
    }

    @Override
    public Void visit(Option option, EnumPattern enumPattern) {
        String name = option.get(1).toString();
        Object value = option.get(3).accept(ConstantVisitor.INSTANCE, null);
        if ("allow_alias".equals(name) && value instanceof Boolean flag) {
            enumPattern.setAllowAlias(flag);
        }
        return null;
    }
}