kmaz13
kmaz13

Reputation: 260

Regex: Pattern to find Java class in .java file

I want to find a class' name when reading through a .java file. I'm returning no match right now using this regular expression:

\\s*[public][private]\\s*class\\s*(\\w*)\\s*\\{

Here is my code so far:

import java.io.*;
import java.util.*;
import java.util.regex.*;


public class HW4Solution {

    public static void main(String [] args){
        //Prompt user for path to file.
        File file = null;
        Scanner pathScan = new Scanner(System.in);
        while (file == null || !file.exists())
        {
            System.out.print("Enter valid file path: ");
            file = new File(pathScan.next());
        }
        pathScan.close();
        System.out.println("File: " + file.getPath() + " found.");

        //Read file line by line into buffered reader
        StringBuffer componentString = new StringBuffer(100);
        String currentLine;
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(file.getPath()));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        //TODO: Find class declarations
        //TODO: Find superclasses
        //TODO: Find instance variable declarations
        //TODO: Find method signatures
        //TODO: Find access modifier
        //TODO: Find return type
        //TODO: Find method name

        //Creating patterns to look for!
        //Class declarations
        Pattern classDeclarationPattern = Pattern.compile("\\s*[public][private]\\s*class\\s*(\\w*)\\s*\\{");
        try {
            while((currentLine = bufferedReader.readLine()) != null){
                Matcher classDeclarationMatcher = classDeclarationPattern.matcher(currentLine);
                if(classDeclarationMatcher.group(1) != null){
                    componentString.append("Found class declaration: " + classDeclarationMatcher.group(3) + "\n");
                    /*if(classDeclarationMatcher.group(5) != null){
                        componentString.append("\tsuperclass: " + classDeclarationMatcher.group(5) + "\n");
                    }*/
                    System.out.println(classDeclarationMatcher.group());
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally{
            try{
                if (bufferedReader !=null) {
                    bufferedReader.close();
                }
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }

        System.out.println(componentString.toString());

    }
}

I eventually want to be able to determine if a class declaration has a superclass and get that too but for now I'm having enough trouble (which I shouldn't) getting the name of the class.

Upvotes: 2

Views: 6785

Answers (2)

ATN54
ATN54

Reputation: 137

RegExp for class declaration:

private String classRegExp = "(((|public|final|abstract|private|static|protected)(\\s+))?(class)(\\s+)(\\w+)(<.*>)?(\\s+extends\\s+\\w+)?(<.*>)?(\\s+implements\\s+)?(.*)?(<.*>)?(\\s*))\\{$";

for interface declaration:

private String interfaceRegExp = "(((|public|final|abstract|private|static|protected)(\\s+))?interface(\\s+)(\\w+)(<.*>)?(\\s+extends\\s+\\w+)?(<.*>)?(\\s+implements\\s+)?(.*)?(<.*>)?(\\s*))\\{$";

for enum declaration :

private String enumRegExp = "((((public|final|private|static|protected)(\\s+))?enum(\\s+)(\\w+)?(\\s+implements\\s+\\w+)?(.*)?\\s*))\\{$";

Upvotes: 1

Rohit Jain
Rohit Jain

Reputation: 213311

[public] is not matching what you think it should. It is a character class, which matches either of those characters in public. You should use pipe to match alternate words.

You can use following regex, extended to consider super classes or interface: -

Pattern.compile("\\s*(public|private)\\s+class\\s+(\\w+)\\s+((extends\\s+\\w+)|(implements\\s+\\w+( ,\\w+)*))?\\s*\\{");

Note that, you should use \\s+ with + quantifier when matching space between public|private and the class keyword. Because you expect at least 1 space there. \\s* will match 0 space, which is not correct, since publicclass is not valid.

Apart from that, there can be some more options to consider here. Like static inner classes, or generic classes, that will require minor modification in there, which you can do on your own. I've just given a little insight on to how to approach.


Also, one more important thing. Before you can get the result from your group, you should call Matcher#find() method to do the actual matching.

Upvotes: 12

Related Questions