2016-06-15 3 views
1

Я хочу определить, сколько параметров (верхнего уровня) имеет функция, учитывая представление String функции. В качестве примера:Java определяет количество функциональных параметров только на основе строки функций

(1) assertEquals(verify, actual); 
(2) assertEquals("message", actual, verify); 
(3) assertEquals(account.addMoney(19, Delivery.fast()).toString(), bank.getAccount(person.getCredentials("basic")).tally(), mock.getData().verify()); 

Ответы должны быть (1) = 2, (2) = 3, (3) = 3. Можно считать, у меня есть имя функции, например, regex on assert.

В принципе, я могу считать запятыми, но мне нужно учитывать параметры функции для вызовов внутренних функций. Таким образом,

function(param1, param2.data(param3, param4, param5.getData(param6, param7)); 

Конечно, гнездо может быть произвольным.

Я думаю, что регулярное выражение может сделать трюк, но моего опыта с ними недостаточно, чтобы решить этот вопрос.

Обратите внимание, что я рассмотрел использование рычага/синтаксического анализатора, но это кажется немного излишним для моих намерений. У меня есть набор функций в виде строк, а мои вызовы метода-метода - это методы утверждения.

+0

регулярных выражений Java не поддерживает рекурсию. –

+1

Вы знаете, если вы действительно собираетесь иметь дело с ** настоящим ** исходным кодом ... рассмотрите использование ** парсера **. Или что происходит, когда люди начинают создавать экземпляры массива или анонимные внутренние классы в качестве аргументов? – GhostCat

+0

Возможно, http://stackoverflow.com/questions/2842809/lexers-vs-parsers могут быть полезны. –

ответ

0

Для решения этой проблемы необходимы lexical analyzer и parser.

Лексический анализатор разделить строку в токенов

разбора взять маркеры и построить структуру данных, часто дерево, что лучше представляет, что означает, что маркеры.

Перемещение этой структуры данных позволяет легко найти, сколько параметров есть.


Примечание: это тот же процесс, а затем превратить программу, написанную человеком, который представляет собой текстовый файл (например, файл .java, например) в другой форме, которую можно интерпретировать с помощью компьютера (процесс компиляции).


Использование лексического анализатора и анализатор необходимо правильно обрабатывать строки, например, следующие:

  • function("a,b", c)
  • function(new String[]{"a", "b"})
  • function(a(b, c))
  • function(',')

и любая композиция из них


лексический анализатор с помощью Java может быть следующим JFlex.

Я думаю, что когда-то, что у вас есть маркеры вы можете вручную рассчитывать запятые и скобки (которые в настоящее время являются действительно запятые и скобки, а не часть строк или что-то другое)

+0

Это действительно вариант для решения проблемы, но это немного переполняет мои намерения. Я просто имею набор функций, из которых у меня есть источник (строка). Моя цель - вызовы метода утверждения, поэтому это значительно упрощает анализ;) –

+0

Вам нужно учитывать, что вы можете иметь также строки, содержащие запятые, массивы, элементы которых могут быть разделены запятыми. Это не то, что можно решить без анализатора + лексического анализатора. –

+0

Любые предложения для легкого Java lexer/parser, который принимает строку как вход? @Davide: не считал все эти пограничные случаи! На первый взгляд проблема казалась более простой. –

0

на основе возможных случаев я определил рекурсивный алгоритм узнать количество функциональных параметров.Пожалуйста, размещать какие-либо угловые случаи, которые разбивают код ниже :) Код работает для случаев (также рекурсивные), как было предложено Davide

/* 
* returns the number of parameters in this function 
*/ 
private int functionParameters(String function) { 
    String fnStripped = stripTill('(', function); 
    String fnStripped2 = fnStripped.substring(1); 
    // find function with 0 parameters, i.e.() 
    if (removeWhiteSpace(fnStripped).length() == 2) { 
     return 0; 
    } 
    // find function with >= 1 parameters 
    return countFunctionParameters(fnStripped2); 
} 

/* 
* @pre: function is a string, starting from the arguments of a function, excluding the first parenthesis. 
* @pre: function has at least one parameter. 
* @post: the number of parameters of the original (top level) function. 
*/ 
private int countFunctionParameters(String function) { 
    // every function has at least one parameter 
    if (function.length() == 0) { 
     return 1; 
    } 
    char next = function.charAt(0); 
    String newString = function.substring(1); 

    switch(next) { 
     case ',' : return 1 + countFunctionParameters(newString); 
     case '(' : newString = removeUntil(')', newString); return 0 + countFunctionParameters(newString); 
     case '"' : newString = removeUntil('"', newString); return 0 + countFunctionParameters(newString); 
     case '\'' : newString = removeUntil('\'', newString); return 0 + countFunctionParameters(newString); 
     case '{' : newString = removeUntil('}', newString); return 0 + countFunctionParameters(newString); 
     default : return 0 + countFunctionParameters(newString); 
    } 
} 

private String removeUntil(char c, String str) { 
    System.out.println("CURRENT: " + str); 
    if (str.equals("")) { 
     return str; 
    } 
    String newString = str.substring(1); 
    if (str.charAt(0) == c) { 
     return newString; 
    } 

    switch (str.charAt(0)) { 
     case '(' : return removeUntil(c, removeUntil('(', newString)); 
     case '"' : return removeUntil(c, removeUntil('"', newString)); 
     case '\'' : return removeUntil(c, removeUntil('\'', newString)); 
     case '{' : return removeUntil(c, removeUntil('}', newString)); 
     case ')' : return newString; 
     case '}' : return newString; 
     case '\\' : return removeUntil(c, newString.substring(1)); // disregard the escaped character! 
     default : return removeUntil(c, newString); 
    } 
} 

private String removeWhiteSpace(String str) { 
    return str.replaceAll("\\s+",""); 
} 

private String stripTill(char c, String str) { 
    while (str.charAt(0) != c) { 
     str = str.substring(1); 
    } 
    return str; 
} 
+1

это не так просто. Если у вас есть, например, myFunction ("\" ", 3), у вас есть проблема для первой строки, содержащей" –

+0

Хорошая точка. Я еще не моделировал экранирующих персонажей. Они действительно немного сложнее. Для моей цели может быть достаточно аппроксимации, если она фиксирует большинство случаев, которые я должен выяснить. Простым решением здесь может быть удаление любого символа после '\'. –

Смежные вопросы