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

org.jparsec.examples.java.parser.DeclarationParser Maven / Gradle / Ivy

/*****************************************************************************
 * Copyright (C) jparsec.org                                                *
 * ------------------------------------------------------------------------- *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
package org.jparsec.examples.java.parser;

import static org.jparsec.Parsers.between;
import static org.jparsec.examples.java.parser.TerminalParser.phrase;
import static org.jparsec.examples.java.parser.TerminalParser.term;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;

import org.jparsec.Parser;
import org.jparsec.Parsers;
import org.jparsec.Terminals;
import org.jparsec.examples.java.ast.declaration.AnnotationDef;
import org.jparsec.examples.java.ast.declaration.ClassDef;
import org.jparsec.examples.java.ast.declaration.ClassInitializerDef;
import org.jparsec.examples.java.ast.declaration.ConstructorDef;
import org.jparsec.examples.java.ast.declaration.Declaration;
import org.jparsec.examples.java.ast.declaration.DefBody;
import org.jparsec.examples.java.ast.declaration.EnumDef;
import org.jparsec.examples.java.ast.declaration.FieldDef;
import org.jparsec.examples.java.ast.declaration.Import;
import org.jparsec.examples.java.ast.declaration.InterfaceDef;
import org.jparsec.examples.java.ast.declaration.Member;
import org.jparsec.examples.java.ast.declaration.MethodDef;
import org.jparsec.examples.java.ast.declaration.NestedDef;
import org.jparsec.examples.java.ast.declaration.Program;
import org.jparsec.examples.java.ast.declaration.QualifiedName;
import org.jparsec.examples.java.ast.declaration.TypeParameterDef;
import org.jparsec.examples.java.ast.expression.Expression;
import org.jparsec.examples.java.ast.statement.BlockStatement;
import org.jparsec.examples.java.ast.statement.Modifier;
import org.jparsec.examples.java.ast.statement.Statement;

/**
 * Parses class, interface, enum, annotation declarations.
 * 
 * @author Ben Yu
 */
public final class DeclarationParser {
  static Parser body(Parser member) {
    Parser empty = term(";").retn(null);
    return Parsers.between(term("{"), empty.or(member).many().map(DeclarationParser::removeNulls), term("}"))
        .map(DefBody::new);
  }

  static  List removeNulls(List list) {
    for (Iterator it = list.iterator(); it.hasNext();) {
      if (it.next() == null) {
        it.remove();
      }
    }
    return list;
  }
  
  static Parser fieldDef(Parser initializer) {
    return Parsers.sequence(
        StatementParser.modifier(initializer).many(), TypeLiteralParser.TYPE_LITERAL, Terminals.Identifier.PARSER,
        term("=").next(ExpressionParser.arrayInitializerOrRegularExpression(initializer))
            .optional(),
        term(";"),
        (modifiers, type, name, value, __) -> new FieldDef(modifiers, type, name ,value));
  }
  
  static final Parser TYPE_PARAMETER = Parsers.sequence(
      Terminals.Identifier.PARSER, term("extends").next(TypeLiteralParser.TYPE_LITERAL).optional(),
      TypeParameterDef::new);
  
  static final Parser> TYPE_PARAMETERS =
      between(term("<"), TYPE_PARAMETER.sepBy1(term(",")), term(">"));
  
  static Parser constructorDef(Parser mod, Parser stmt) {
    return Parsers.sequence(
        mod.many(), Terminals.Identifier.PARSER,
        term("(").next(StatementParser.parameter(mod).sepBy(term(","))).followedBy(term(")")),
        term("throws").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(),
        StatementParser.blockStatement(stmt),
        ConstructorDef::new);
  }
  
  static Parser methodDef(
      Parser mod, Parser defaultValue, Parser stmt) {
    return Parsers.sequence(
        mod.many(), TYPE_PARAMETERS.optional(),
        TypeLiteralParser.TYPE_LITERAL, Terminals.Identifier.PARSER,
        term("(").next(StatementParser.parameter(mod).sepBy(term(","))).followedBy(term(")")),
        term("throws").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(),
        term("default").next(ExpressionParser.arrayInitializerOrRegularExpression(defaultValue))
            .optional(),
        Parsers.or(
            StatementParser.blockStatement(stmt),
            term(";").retn((BlockStatement) null)),
        MethodDef::new);
  }
  
  static Parser initializerDef(Parser stmt) {
    return Parsers.sequence(
        term("static").succeeds(), StatementParser.blockStatement(stmt),
        ClassInitializerDef::new);
  }
  
  static Parser nestedDef(Parser dec) {
    return dec.map(NestedDef::new);
  }
  
  static Parser classDef(Parser mod, Parser member) {
    return Parsers.sequence(
        mod.many(), term("class").next(Terminals.Identifier.PARSER), TYPE_PARAMETERS.optional(),
        term("extends").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL).optional(),
        term("implements").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(),
        body(member),
        ClassDef::new);
  }
  
  static Parser interfaceDef(Parser mod, Parser member) {
    return Parsers.sequence(
        mod.many(), term("interface").next(Terminals.Identifier.PARSER), TYPE_PARAMETERS.optional(),
        term("extends").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(),
        body(member),
        InterfaceDef::new);
  }
  
  static Parser annotationDef(Parser mod, Parser member) {
    return Parsers.sequence(
        mod.many(), phrase("@ interface").next(Terminals.Identifier.PARSER), body(member),
        AnnotationDef::new);
  }
  
  static Parser enumDef(Parser expr, Parser member) {
    Parser enumValue = Parsers.sequence(
        Terminals.Identifier.PARSER, between(term("("), expr.sepBy(term(",")), term(")"))
            .optional(),
        between(term("{"), member.many(), term("}")).optional(),
        EnumDef.Value::new);
    return Parsers.sequence(
        StatementParser.modifier(expr).many(),
        term("enum").next(Terminals.Identifier.PARSER),
        term("implements").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(),
        term("{").next(enumValue.sepBy(term(","))),
        term(";").next(member.many()).optional().followedBy(term("}")),
        EnumDef::new);
  }
  
  static final Parser QUALIFIED_NAME =
      Terminals.Identifier.PARSER.sepBy1(term(".")).map(QualifiedName::new);
  
  static final Parser IMPORT = Parsers.sequence(
      term("import").next(term("static").succeeds()),
      QUALIFIED_NAME, phrase(". *").succeeds().followedBy(term(";")),
      Import::new);
  
  static final Parser PACKAGE = between(term("package"), QUALIFIED_NAME, term(";"));
  
  public static Parser program() {
    Parser.Reference memberRef = Parser.newReference();
    Parser.Reference stmtRef = Parser.newReference();
    Parser expr = ExpressionParser.expression(body(memberRef.lazy()), stmtRef.lazy());
    Parser stmt = StatementParser.statement(expr);
    stmtRef.set(stmt);
    Parser mod = StatementParser.modifier(expr);
    Parser.Reference decRef = Parser.newReference();
    Parser member = Parsers.or(
        fieldDef(expr), methodDef(mod, expr, stmt), constructorDef(mod, stmt),
        initializerDef(stmt), nestedDef(decRef.lazy()));
    memberRef.set(member);
    Parser declaration = Parsers.or(
        classDef(mod, member), interfaceDef(mod, member),
        enumDef(expr, member), annotationDef(mod, member));
    decRef.set(declaration);
    return Parsers.sequence(PACKAGE.optional(), IMPORT.many(), declaration.many(), Program::new);
  }
  
  /** Parses any Java source.  */
  public static Program parse(String source) {
    return TerminalParser.parse(program(), source);
  }
  
  /** Parses source code read from {@code url}. */
  public static Program parse(URL url) throws IOException {
    InputStream in = url.openStream();
    try {
      return TerminalParser.parse(
          program(), new InputStreamReader(in, Charset.forName("UTF-8")), url.toString());
    } finally {
      in.close();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy