All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.protostream.impl.parser.AnnotationParser Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.protostream.impl.parser;

import org.infinispan.protostream.AnnotationParserException;
import org.infinispan.protostream.descriptors.AnnotationElement;

import java.text.MessageFormat;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author [email protected]
 * @since 2.0
 */
public final class AnnotationParser {

   private final AnnotationLexer lexer;

   public AnnotationParser(String input) {
      this.lexer = new AnnotationLexer(input.toCharArray());
   }

   public Map parse() throws AnnotationParserException {
      Map annotations = new LinkedHashMap();
      while (lexer.token != AnnotationTokens.EOF) {
         AnnotationElement.Annotation annotation = parseAnnotation();
         if (annotations.containsKey(annotation.getName())) {
            throw syntaxError(annotation.position, "duplicate annotation definition \"{0}\"", annotation.getName());
         }
         annotations.put(annotation.getName(), annotation);
         lexer.skipDocNoise();
      }
      return annotations;
   }

   private void expect(AnnotationTokens token) {
      if (lexer.token == token) {
         lexer.nextToken();
      } else {
         long pos = AnnotationElement.line(lexer.pos) > AnnotationElement.line(lexer.lastPos) ? lexer.lastPos : lexer.pos;
         throw syntaxError(pos, "{0} expected", token.text);
      }
   }

   private String identifier() {
      if (lexer.token == AnnotationTokens.IDENTIFIER) {
         String name = lexer.name;
         lexer.nextToken();
         return name;
      } else {
         expect(AnnotationTokens.IDENTIFIER);
         return null;
      }
   }

   private String qualifiedIdentifier() {
      String qualIdent = identifier();
      while (lexer.token == AnnotationTokens.DOT) {
         lexer.nextToken();
         qualIdent = qualIdent + "." + identifier();
      }
      return qualIdent;
   }

   private AnnotationElement.Annotation parseAnnotation() {
      if (lexer.token != AnnotationTokens.AT) {
         throw syntaxError("annotation expected");
      }
      long pos = lexer.pos;
      expect(AnnotationTokens.AT);
      String name = qualifiedIdentifier();
      Map attributes = parseAttributes();
      return new AnnotationElement.Annotation(pos, name, attributes);
   }

   private Map parseAttributes() {
      LinkedHashMap members = new LinkedHashMap();
      if (lexer.token == AnnotationTokens.LPAREN) {
         int start = lexer.mark();
         expect(AnnotationTokens.LPAREN);
         switch (lexer.token) {
            case AT: {
               long pos = lexer.pos;
               AnnotationElement.Annotation annotation = parseAnnotation();
               expect(AnnotationTokens.RPAREN);
               AnnotationElement.Attribute attribute = new AnnotationElement.Attribute(pos, AnnotationElement.Annotation.DEFAULT_ATTRIBUTE, annotation);
               members.put(attribute.getName(), attribute);
               return members;
            }
            case IDENTIFIER: {
               long pos = lexer.pos;
               AnnotationElement.Identifier identifier = parseIdentifier();
               if (lexer.token == AnnotationTokens.EQ) {
                  start = lexer.mark();
                  expect(AnnotationTokens.EQ);
                  AnnotationElement.Value value = parseValue(start);
                  AnnotationElement.Attribute attribute = new AnnotationElement.Attribute(pos, identifier.getIdentifier(), value);
                  members.put(attribute.getName(), attribute);
                  break;
               } else {
                  expect(AnnotationTokens.RPAREN);
                  AnnotationElement.Attribute attribute = new AnnotationElement.Attribute(pos, AnnotationElement.Annotation.DEFAULT_ATTRIBUTE, identifier);
                  members.put(attribute.getName(), attribute);
                  return members;
               }
            }
            case FALSE:
            case TRUE:
            case INT_LITERAL:
            case LONG_LITERAL:
            case FLOAT_LITERAL:
            case DOUBLE_LITERAL:
            case CHARACTER_LITERAL:
            case STRING_LITERAL: {
               long pos = lexer.pos;
               AnnotationElement.Value literal = parseValue(start);
               expect(AnnotationTokens.RPAREN);
               AnnotationElement.Attribute attribute = new AnnotationElement.Attribute(pos, AnnotationElement.Annotation.DEFAULT_ATTRIBUTE, literal);
               members.put(attribute.getName(), attribute);
               return members;
            }
         }

         if (lexer.token == AnnotationTokens.COMMA) {
            expect(AnnotationTokens.COMMA);
            while (lexer.token != AnnotationTokens.RPAREN && lexer.token != AnnotationTokens.EOF) {
               AnnotationElement.Attribute attribute = parseAttribute();
               if (members.containsKey(attribute.getName())) {
                  throw syntaxError(attribute.position, "duplicate annotation member definition \"{0}\"", attribute.getName());
               }
               members.put(attribute.getName(), attribute);
               if (lexer.token != AnnotationTokens.RPAREN && lexer.token != AnnotationTokens.EOF) {
                  expect(AnnotationTokens.COMMA);
               }
            }
         }

         expect(AnnotationTokens.RPAREN);
      }
      return members;
   }

   private AnnotationElement.Attribute parseAttribute() {
      long pos = lexer.pos;
      String name = identifier();
      int start = lexer.mark();
      expect(AnnotationTokens.EQ);
      AnnotationElement.Value value = parseValue(start);
      return new AnnotationElement.Attribute(pos, name, value);
   }

   private AnnotationElement.Value parseValue(int start) {
      long pos = lexer.pos;
      switch (lexer.token) {
         case AT:
            return parseAnnotation();

         case LBRACE:
            return parseArray();

         case IDENTIFIER:
            return parseIdentifier();

         case INT_LITERAL:
         case LONG_LITERAL:
         case FLOAT_LITERAL:
         case DOUBLE_LITERAL:
         case CHARACTER_LITERAL:
         case STRING_LITERAL:
         case TRUE:
         case FALSE:
            AnnotationTokens tok = lexer.token;
            String text = lexer.getText(start, lexer.mark());
            Object value = null;
            try {
               switch (tok) {
                  case INT_LITERAL:
                     value = Integer.parseInt(text.trim());
                     break;
                  case LONG_LITERAL:
                     value = Long.parseLong(text.trim());
                     break;
                  case FLOAT_LITERAL:
                     value = Float.parseFloat(text.trim());
                     break;
                  case DOUBLE_LITERAL:
                     value = Double.parseDouble(text.trim());
                     break;
                  case CHARACTER_LITERAL:
                     value = text.charAt(1);
                     break;
                  case STRING_LITERAL: {
                     value = text.substring(text.indexOf("\"") + 1, text.length() - 1);
                     break;
                  }
                  case TRUE:
                     value = Boolean.TRUE;
                     break;
                  case FALSE:
                     value = Boolean.FALSE;
                     break;
               }
            } catch (NumberFormatException e) {
               throw syntaxError("invalid numeric value: {0}", e.getMessage());
            }
            AnnotationElement.Literal literal = new AnnotationElement.Literal(pos, value);
            lexer.nextToken();
            return literal;
      }
      throw syntaxError("literal expected");
   }

   private AnnotationElement.Identifier parseIdentifier() {
      long pos = lexer.pos;
      String qualIdent = qualifiedIdentifier();
      return new AnnotationElement.Identifier(pos, qualIdent);
   }

   private AnnotationElement.Array parseArray() {
      int start = lexer.mark();
      long pos = lexer.pos;
      expect(AnnotationTokens.LBRACE);
      List values = new LinkedList();
      while (lexer.token != AnnotationTokens.RBRACE && lexer.token != AnnotationTokens.EOF) {
         values.add(parseValue(start));
         start = lexer.mark();
         if (lexer.token != AnnotationTokens.RBRACE && lexer.token != AnnotationTokens.EOF) {
            expect(AnnotationTokens.COMMA);
         }
      }
      expect(AnnotationTokens.RBRACE);
      return new AnnotationElement.Array(pos, values);
   }

   private AnnotationParserException syntaxError(long pos, String errorMsg, String... errorArgs) {
      return new AnnotationParserException("Error: " + AnnotationElement.positionToString(pos)
                                                 + ": " + MessageFormat.format(errorMsg, errorArgs));
   }

   private AnnotationParserException syntaxError(String errorMsg, String... errorArgs) {
      return syntaxError(lexer.pos, errorMsg, errorArgs);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy