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

org.jruby.parser.JavaSignatureParser.y Maven / Gradle / Ivy

There is a newer version: 9.4.9.0
Show newest version
/*
 * We started with a full Java grammar from JavaParser (cup) implementation 
 * (since it was an LALR grammar already) and then stripped out all bits of 
 * the grammar unrelated to Java method signature parsing.  We also changed the 
 * grammar to accept signatures which do not specify the parameter names. So,
 * 'void foo(int)' is as 'void foo(int name)'.  This grammar also only works
 * with Jay which is another LALR grammar compiler compiler tool.
 *
 * The output this tool generates is subject to our tri-license (GPL,LGPL,
 * and EPL), but this source file itself is released only under the terms
 * of the GPL.
 *
 * This program is released under the terms of the GPL; see the file
 * COPYING for more details.  There is NO WARRANTY on this code.
 */

%{ 
package org.jruby.parser;

import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jruby.ast.java_signature.Annotation;
import org.jruby.ast.java_signature.AnnotationExpression;
import org.jruby.ast.java_signature.AnnotationParameter;
import org.jruby.ast.java_signature.ArrayAnnotationExpression;
import org.jruby.ast.java_signature.ArrayTypeNode;
import org.jruby.ast.java_signature.CharacterLiteral;
import org.jruby.ast.java_signature.ConstructorSignatureNode;
import org.jruby.ast.java_signature.DefaultAnnotationParameter;
import org.jruby.ast.java_signature.MethodSignatureNode;
import org.jruby.ast.java_signature.Literal;
import org.jruby.ast.java_signature.Modifier;
import org.jruby.ast.java_signature.ParameterNode;
import org.jruby.ast.java_signature.PrimitiveTypeNode;
import org.jruby.ast.java_signature.ReferenceTypeNode;
import org.jruby.ast.java_signature.SignatureNode;
import org.jruby.ast.java_signature.StringLiteral;
import org.jruby.ast.java_signature.TypeNode;
import org.jruby.lexer.JavaSignatureLexer;

public class JavaSignatureParser {
    private static JavaSignatureParser parser = new JavaSignatureParser();

    public static SignatureNode parse(InputStream in) throws IOException, ParserSyntaxException {
        return (SignatureNode) parser.yyparse(JavaSignatureLexer.create(in));
    }
%}

// Primitive types
%token  BOOLEAN  // 'boolean'
%token  BYTE     // 'byte'
%token  SHORT    // 'short'
%token  INT      // 'int'
%token  LONG     // 'long'
%token  CHAR     // 'char'
%token  FLOAT    // 'float'
%token  DOUBLE   // 'double'
%token  VOID     // 'void'
// modifiers
%token  PUBLIC       // 'public'
%token  PROTECTED    // 'protected'
%token  PRIVATE      // 'private'
%token  STATIC       // 'static'
%token  ABSTRACT     // 'abstract'
%token  FINAL        // 'final'
%token  NATIVE       // 'native'
%token  SYNCHRONIZED // 'synchronized'
%token  TRANSIENT    // 'transient'
%token  VOLATILE     // 'volatile'
%token  STRICTFP     // 'strictfp'
// identifier (e.g. setFoo)
%token  IDENTIFIER
// syntax markers
%token  AND    // '&'
%token  AT     // '@'
%token  DOT    // '.'
%token  COMMA  // ','
%token  ELLIPSIS // '...' or \u2026
%token  EQUAL  // '='
%token  LCURLY // '{'
%token  RCURLY // '}'
%token  LPAREN // '('
%token  RPAREN // ')'
%token  LBRACK // '['
%token  RBRACK // ']'
%token  QUESTION // '?'
%token  LT     // '<'
%token  GT     // '>'
%token  THROWS // 'throws'
%token  EXTENDS // 'extends'
%token  SUPER // 'super'
%token  SUPER // 'super'
%token  RSHIFT // '>>'
%token  URSHIFT // '>>>'
%token  QQ // '"'
%token  Q // "'"
%token  CHARACTER_LITERAL
%token  STRING_LITERAL

%type  method_declarator, method_header
%type  constructor_declarator, constructor_declaration
%type  formal_parameter_list_opt, formal_parameter_list // 
%type  modifiers_opt, modifiers, modifiers_none, throws, class_type_list
%type  annotation_params_opt, annotation_params, annotation_params_none
%type  formal_parameter
%type  primitive_type, type
%type  class_or_interface, class_or_interface_type, array_type
%type  interface_type, class_type, reference_type
%type  name, type_variable, variable_declarator_id
%type  type_bound_1, additional_bound, additional_bound_list_1
%type  wildcard, type_argument, type_argument_list
%type  type_argument_1, type_argument_2, type_argument_3
%type  wildcard_1, wildcard_2, wildcard_3
%type  reference_type_1, reference_type_2, reference_type_3
%type  type_argument_list_1, type_argument_list_2, type_argument_list_3
%type  type_parameter, type_parameter_1
%type  type_parameter_list, type_parameter_list_1, 
%type  type_bound_opt, type_bound, additional_bound_list, additional_bound_list_opt
%type  annotation_name
%type  modifier  // Can be either modifier enum or Annotation instance
%type  dims
%type  none
%type  program
%type  annotation
%type  annotation_param
%type  annotation_value
%type  annotation_array_values
%type  literal

%%

program : method_header {
     $$ = $1;
 } | constructor_declaration {
     $$ = $1;
 }

type : primitive_type | reference_type { $$ = $1; }

// PrimitiveTypeNode
primitive_type : BYTE {
     $$ = PrimitiveTypeNode.BYTE;
 }
 | SHORT {
     $$ = PrimitiveTypeNode.SHORT;
 }
 | INT {
     $$ = PrimitiveTypeNode.INT;
 }
 | LONG {
     $$ = PrimitiveTypeNode.LONG;
 }
 | CHAR {
     $$ = PrimitiveTypeNode.CHAR;
 }
 | BOOLEAN {
     $$ = PrimitiveTypeNode.BOOLEAN;
 } 
 | FLOAT {
     $$ = PrimitiveTypeNode.FLOAT;
 }
 | DOUBLE {
     $$ = PrimitiveTypeNode.DOUBLE;
 }

// ReferenceTypeNode
reference_type : class_or_interface_type {
     $$ = $1;
 }
 | array_type {
     $$ = $1;
 }

// String
type_variable : IDENTIFIER { 
     $$ = $1; 
 }

// ReferenceTypeNode
class_or_interface : name {
     $$ = new ReferenceTypeNode($1);
 }
 | class_or_interface LT type_argument_list_1 DOT name {
     String genericTyping = "<" + $3 + "." + $5;
     $$ = $1;
     $1.setGenericsTyping(genericTyping);
 }

// ReferenceTypeNode
class_or_interface_type : class_or_interface
 | class_or_interface LT type_argument_list_1 {
     String genericTyping = "<" + $3;
     $$ = $1;
     $1.setGenericsTyping(genericTyping);
 }

// ReferenceTypeNode
class_type : class_or_interface_type

// ReferenceTypeNode
interface_type : class_or_interface_type

// ReferenceTypeNode
array_type : primitive_type dims {
     $2.setTypeForArray($1);
     $$ = $2;
 }
 | name dims {
     $2.setTypeForArray(new ReferenceTypeNode($1));
     $$ = $2;
 }
 | class_or_interface LT type_argument_list_1 DOT name dims {
     $1.setGenericsTyping("<" + $3 + "." + $5);
     $6.setTypeForArray($1);
     $$ = $6;
 }
 | class_or_interface LT type_argument_list_1 dims {
     $1.setGenericsTyping("<" + $3);
     $4.setTypeForArray($1);
     $$ = $4;
 }

// String
wildcard : QUESTION { 
     $$ = "?";
 } | QUESTION EXTENDS reference_type {
     $$ = "? extends " + $3.getFullyTypedName();
 } | QUESTION SUPER reference_type { 
     $$ = "? super " + $3.getFullyTypedName();
 }

// String
wildcard_1 : QUESTION GT {
     $$ = "?>"; 
 } | QUESTION EXTENDS reference_type_1 {
     $$ = "? extends " + $3;
 } | QUESTION SUPER reference_type_1 { 
     $$ = "? super " + $3;
 }

// String
wildcard_2 : QUESTION RSHIFT { 
     $$ = "?>>"; 
 } | QUESTION EXTENDS reference_type_2 { 
     $$ = "? extends " + $3;
 } | QUESTION SUPER reference_type_2 { 
     $$ = "? super " + $3;
 }

// String
wildcard_3 : QUESTION URSHIFT {
     $$ = "?>>";
 } | QUESTION EXTENDS reference_type_3 {
     $$ = "? extends " + $3;
 } | QUESTION SUPER reference_type_3 {
     $$ = "? super " + $3;
 }

// String
reference_type_1 : reference_type GT { 
     $$ = $1.getFullyTypedName() + ">";
 } | class_or_interface LT type_argument_list_2 {
     $$ = $1.getFullyTypedName() + "<" + $3;
 }

// String
reference_type_2 : reference_type RSHIFT { 
     $$ = $1.getFullyTypedName() + ">>";
 } | class_or_interface LT type_argument_list_3 {
     $$ = $1.getFullyTypedName() + "<" + $3;
 }

// String
reference_type_3 : reference_type URSHIFT {
     $$ = $1.getFullyTypedName() + ">>>";
 }

// String
type_argument_list : type_argument {
     $$ = $1;
 }
 | type_argument_list COMMA type_argument {
     $$ = $1 + ", " + $3;
 }

// String
type_argument_list_1 : type_argument_1
 | type_argument_list COMMA type_argument_1 {
     $$ = $1 + ", " + $3;
 }

// String
type_argument_list_2 : type_argument_2
 | type_argument_list COMMA type_argument_2 {
     $$ = $1 + ", " + $3;
 }

// String
type_argument_list_3 : type_argument_3
 | type_argument_list COMMA type_argument_3 {
     $$ = $1 + ", " + $3;
 }

// String
type_argument : reference_type {
     $$ = $1.getFullyTypedName();
 }
 | wildcard

// String
type_argument_1 : reference_type_1 | wildcard_1

// String
type_argument_2 : reference_type_2 | wildcard_2

// String
type_argument_3 : reference_type_3 | wildcard_3

// List
modifiers_opt : modifiers | modifiers_none

// List
modifiers : modifier {
    $$ = new ArrayList();
    $$.add($1);
 }
 | modifiers modifier {
    $1.add($2);
 }

// List -- This is just so we don't deal with null's.
modifiers_none : { $$ = new ArrayList(); }

// Object
modifier : PUBLIC { $$ = Modifier.PUBLIC; }
 | PROTECTED { $$ = Modifier.PROTECTED; }
 | PRIVATE { $$ = Modifier.PRIVATE; }
 | STATIC { $$ = Modifier.STATIC; }
 | ABSTRACT { $$ = Modifier.ABSTRACT; } 
 | FINAL { $$ = Modifier.FINAL; }
 | NATIVE { $$ = Modifier.NATIVE; }
 | SYNCHRONIZED { $$ = Modifier.SYNCHRONIZED; }
 | TRANSIENT { $$ = Modifier.TRANSIENT; }
 | VOLATILE { $$ = Modifier.VOLATILE; }
 | STRICTFP { $$ = Modifier.STRICTFP; }
 | annotation { $$ = $1; }

// String
name : IDENTIFIER { $$ = $1; }                  // Foo (or foo)
 | name DOT IDENTIFIER { $$ = $1 + "." + $3; }  // foo.Foo 

// String -- we do not use this for any info
dims : LBRACK RBRACK { 
     $$ = new ArrayTypeNode(); 
 } | dims LBRACK RBRACK { 
     $$ = new ArrayTypeNode($1);
 }

// List
throws : THROWS class_type_list { $$ = $2; } 
 | /* none */ { $$ = new ArrayList(); }

// List
class_type_list : class_type {
    $$ = new ArrayList();
    $$.add($1);
 }
 | class_type_list COMMA class_type {
    $1.add($3);
 }

// MethodSignatureNode
method_declarator : IDENTIFIER LPAREN formal_parameter_list_opt RPAREN {
                      $$ = new MethodSignatureNode($1, $3);
                  }

// List
formal_parameter_list_opt : formal_parameter_list 
  | /* none */ { $$ = new ArrayList(); }

// List
formal_parameter_list : formal_parameter {
                          List list = new ArrayList();
                          list.add($1);
                          $$ = list;
                      }
                      | formal_parameter_list COMMA formal_parameter {
                          $1.add($3);
                      }

// ParameterNode
formal_parameter : type variable_declarator_id {
                     $$ = new ParameterNode($1, $2);
                 }
                 | type {
                     $$ = new ParameterNode($1, null);
                 }
                 | FINAL type variable_declarator_id {
                     $$ = new ParameterNode($2, $3, true);
                 }
                 | FINAL type {
                     $$ = new ParameterNode($2, null, true);
                 }
                 | type ELLIPSIS IDENTIFIER {
                     $$ = new ParameterNode($1, $3, false, true);
                 }
                 | type ELLIPSIS {
                     $$ = new ParameterNode($1, null, false, true);
                 }
                 | FINAL type ELLIPSIS IDENTIFIER {
                     $$ = new ParameterNode($2, $4, true, true);
                 }
                 | FINAL type ELLIPSIS {
                     $$ = new ParameterNode($2, null, true, true);
                 }

// String
variable_declarator_id : IDENTIFIER {
     $$ = $1;
 } | variable_declarator_id LBRACK RBRACK {
     // We know this is always preceeded by 'type' production.
     $0 = new ArrayTypeNode($0); 
     $$ = $1;
 }

// String
type_parameter_list : type_parameter_list COMMA type_parameter {
     $$ = $1 + ", " + $3;
 } | type_parameter

// String
type_parameter_list_1 : type_parameter_1
 | type_parameter_list COMMA type_parameter_1 {
     $$ = $1 + ", " + $3;
 }

// String
type_parameter : type_variable type_bound_opt {
     $$ = $1 + $2;
 }

// String
type_parameter_1 : type_variable GT { 
     $$ = $1 + ">"; 
 }
 | type_variable type_bound_1 {
     $$ = $1 + $2;
 }

// String
type_bound_1 : EXTENDS reference_type_1 { 
     $$ = " extends " + $1;
 }
 | EXTENDS reference_type additional_bound_list_1 { 
     $$ = " extends " + $2.getFullyTypedName() + $3;
 }

// String
type_bound_opt : type_bound 
 | none {
     $$ = "";
 }

// String
type_bound : EXTENDS reference_type additional_bound_list_opt { 
     $$ = "extends " + $2.getFullyTypedName() + $3;
 }

// String
additional_bound_list_opt : additional_bound_list 
 | none {
     $$ = "";
 }

// String
additional_bound_list : additional_bound additional_bound_list {
     $$ = $1 + $2;
 } | additional_bound

// String
additional_bound_list_1 : additional_bound additional_bound_list_1 {
     $$ = $1 + $2;
 }
 | AND reference_type_1 { 
     $$ = " & " + $1;
 }

// String
additional_bound : AND interface_type { 
     $$ = " & " + $2.getFullyTypedName();
}

none : { $$ = null; }

constructor_declaration : modifiers_opt constructor_declarator throws {
     $$ = $2;
     $$.setModifiers($1);
     $$.setThrows($3);
 } | modifiers_opt LT type_parameter_list_1 constructor_declarator throws {
     $$ = $4;
     $$.setModifiers($1);
     $$.setExtraTypeInfo("<" + $3);
     $$.setThrows($5);
 }

constructor_declarator : name LPAREN formal_parameter_list_opt RPAREN {
     $$ = new ConstructorSignatureNode($1, $3);
 }

method_header : modifiers_opt type method_declarator throws {
                  $$ = $3;
                  $$.setModifiers($1);
                  $$.setReturnType($2);
                  $$.setThrows($4);
              }
              | modifiers_opt LT type_parameter_list_1 type method_declarator throws {
                  $$ = $5;
                  $$.setModifiers($1);
                  $$.setExtraTypeInfo("<" + $3);
                  $$.setReturnType($4);
                  $$.setThrows($6);
              }
              | modifiers_opt VOID method_declarator throws {
                  $$ = $3;
                  $$.setModifiers($1);
                  $$.setReturnType(PrimitiveTypeNode.VOID);
                  $$.setThrows($4);
              }
              | modifiers_opt LT type_parameter_list_1 VOID method_declarator throws {
                  $$ = $5;
                  $$.setModifiers($1);
                  $$.setExtraTypeInfo("<" + $3);
                  $$.setReturnType(PrimitiveTypeNode.VOID);
                  $$.setThrows($6);
              }

// Annotation
annotation : annotation_name {
               $$ = new Annotation($1, new ArrayList());
           }
           | annotation_name LPAREN annotation_params_opt RPAREN {
               $$ = new Annotation($1, $3);
           }

// String
annotation_name : AT name { $$ = $1 + $2; }

// AnnotationParam
annotation_param : type_variable EQUAL annotation_value {
                     $$ = new AnnotationParameter($1, $3);
                 }
                 | annotation_value {
                     $$ = new DefaultAnnotationParameter($1);
                 }

// List
annotation_params : annotation_param {
                      $$ = new ArrayList();
                      $$.add($1);
                  }
                  | annotation_params COMMA annotation_param {
                      $1.add($3);
                  }

// AnnotationExpression
annotation_value : annotation {
                     $$ = $1;
                 }
                 | type {
                     $$ = $1;
                 }
                 | literal {
                     $$ = $1;
                 }
                 | LCURLY annotation_array_values RCURLY {
                     $$ = new ArrayAnnotationExpression($2);
                 }
                 | LCURLY RCURLY {
                     $$ = new ArrayAnnotationExpression(new ArrayList());
                 }

// List
annotation_array_values : annotation_value {
                            $$ = new ArrayList();
                            $$.add($1);
                        }
                        | annotation_array_values COMMA annotation_value {
                            $1.add($3);
                        }

// List -- This is just so we don't deal with null's.
annotation_params_none : { $$ = new ArrayList(); }

// List
annotation_params_opt : annotation_params | annotation_params_none

literal : STRING_LITERAL {
           $$ = new StringLiteral($1);
        }
        | CHARACTER_LITERAL {
           $$ = new CharacterLiteral($1);
        }

%%

}