2017-06-14 4 views
0

Betrachten wir die Aufrufmethode Expression unter:Wie erkennt man, ob ein Ausdruck 'Methodenaufruf' ist?

foo(1, 2, bar()) 

Die Funktion foo drei Argumente hat, wobei das dritte Argument der Wert durch die Funktion zurückgebracht wird, bar. Nun nehme ich an, ich muss herausfinden, ob der Ausdruck innerhalb der Klammern ein Methodenaufruf ist oder nicht. Für die oben genannten Fälle sollte ich bar() melden.

Für diesen Fall sollte

foo(1, foobar(0, 1), A.staticMethod(1)), 

I foobar(0, 1) und A.staticMethod(1) berichten, wo A eine Klasse die statische Funktion ist, staticMethod(int). Gibt es eine Möglichkeit oder eine ausfallsichere Regex, die für diesen Fall anwendbar ist?

Im Folgenden sind die anderen Fälle, die auch berichtet werden sollen:

new A().foo() 
a.foo()  // A a = new A(); 
a.bar().field // bar() returns an object here 

ich offen bin keine Parsing-APIs wie ANTLR als auch zu verwenden.

Auch, wie in einem der Kommentare erwähnt, möchte ich klarstellen, dass die einzige Eingabe ist der Ausdruck und nichts anderes, nicht der Quellcode (und daher keine Kommentare oder etwas anderes, das ich ignorieren sollte).

+0

ich glaube, Sie den Beginn des Ausdrucks durch die Suche nach einer Kennung sagen konnte, und dann eine offene paren - wenn Sie Probleme mit „Code“ in den Kommentaren oder Strings führen würde. Und Sie könnten das Ende des Ausdrucks nicht finden, zumindest nicht leicht. Also die Antwort ist, du brauchst einen Parser. Aber wenn Sie fragen, wie man einen schreibt, ist diese Frage zu breit, und wenn Sie uns bitten, einen Link zu einem zu geben, ist es ein Thema als eine Anfrage für eine externe Ressource. So oder so, diese Frage scheint mir zu sein. Sie könnten auch das Java kompilieren und den Bytecode untersuchen. – yshavit

+0

Ist 'a.bar(). Field' ein Methodenaufruf? – saka1029

+0

Ich arbeite bereits an einem Parser mit ANTLR. Ich bin an einen Punkt gekommen, an dem ich den _method-invocation_ Ausdruck extrahieren muss, wenn er als Argument übergeben wird, aber die Java8-Grammatik erlaubt mir das irgendwie nicht. Ich kann _method-invocation_ Ausdrücke normalerweise finden, aber nicht, wenn sie als Argument einer anderen Methode übergeben werden. @yshavit – Jarvis

Antwort

0

Angenommen, es gibt keine Syntaxfehler in der Eingabe, können Sie einfach einen Methodenaufruf als einen Bezeichner ([A-Za-z_]\w*) definieren, gefolgt von einem geklammerten Satz von Argumenten, mit der zusätzlichen Bedingung, dass kein te Schlüsselwort new (seit Ihre Syntax unterstützt die Erstellung von Instanzen.

public static List<String> methodCalls(String input) { 
    List<String> matches = new ArrayList<>(); 

    Pattern p = Pattern.compile("\\s*[A-Za-z_]\\w*\\s*\\("); 
    Matcher m = p.matcher(input); 
    while (m.find()) { 
     int start = m.start(); 
     int end = m.end(); 

     if (start == 3 && input.startsWith("new") 
      || start > 3 && input.substring(start-4, start).matches("\\Wnew")) { 
      // if it is preceded by the word new, it is not a method call 
      continue; 
     } 

     int pairs = 1; 
     while (end < input.length() && pairs > 0) { 
      // can't just stop at the next ')' 
      // since parentheses may be nested 
      char c = input.charAt(end); 
      if (c == '(') pairs++; 
      else if (c == ')') pairs--; 
      end++; 
     } 

     matches.add(input.substring(start, end)); 
    } 

    return matches; 
} 
Verwandte Themen