2017-06-14 57 views
0

考慮下面的方法調用表達式:如何識別表達式是否是「方法調用」?

foo(1, 2, bar()) 

功能foo有三個參數,其中,第三個參數是由函數,bar返回的值。現在假設,我需要找出括號內的表達式是否爲方法調用或不。對於上述情況,我應該報告bar()

對於這種情況,

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

其中A是具有靜電功能,staticMethod(int) I類應報告foobar(0, 1)A.staticMethod(1)。是否有任何方法或故障安全正則表達式適用於這種情況?

以下是這也應該被報告的其他情況:

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

我願意用任何解析API,如ANTLR爲好。另外,正如其中一條評論所述,我想澄清一下,唯一的輸入是表達式,而不是其他任何東西,而不是源代碼(因此,沒有評論或我應該忽略的其他東西)。

+0

我想你可以通過尋找一個標識符,然後一個開放的括號告訴表達的開始 - 儘管你會遇到與意見或字符串「代碼」的問題。而且你無法找到表達的結尾,至少不容易。所以真正的答案是,你需要一個解析器。但是如果你問如何寫一個,這個問題太廣泛了,如果你要求我們提供一個鏈接,那麼這個問題就成爲外部資源的請求。無論哪種方式,這個問題似乎OT對我來說。您也可以編譯Java並檢查字節碼。 – yshavit

+0

是'a.bar()。field'方法調用嗎? – saka1029

+0

我已經在使用ANTLR解析器。當我作爲參數傳遞時,我已經到了需要提取_method-invocation_表達式的地步,但是Java8語法在某種程度上不允許我這樣做。我可以正常地找到_method-invocation_表達式,但是當作爲參數傳遞給另一個方法時不會。 @yshavit – Jarvis

回答

0

假設有在輸入沒有語法錯誤,則可以簡單地定義一個方法調用作爲後跟帶括號的組參數的標識符([A-Za-z_]\w*),與所添加的條件是它不是由TE關鍵字new之前(自你的語法支持實例創建)。

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; 
} 
相關問題