2014-10-21 2 views
6

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

1. for (int i = 0; i < b.size(); i++) { 
2. do something in English (not necessary to be a sentence). 

Я думаю о подсчете специальных символов (например, "=", ";", "++" и т.д.), и установить, если в какой-то порог. Есть ли лучшие способы сделать это? Любые библиотеки Java?

Обратите внимание, что код может не обрабатываться, поскольку он не является полным методом/выражением/выражением.

Мое предположение заключается в том, что английские предложения довольно регулярны, скорее всего, содержат только «,», «.», «_», «(», «)» И т. Д. Они не содержат что-то вроде этого: write("the whole lot of text");

+0

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

+0

Я ищу несколько ярлыков. – Ryan

+0

Правда, но мы программисты, а не мозговые штурманы. Мы не можем помочь вам придумать идеи, особенно если это так же открыто, как и этот ... Вернитесь с кодом, а затем мы сможем вам помочь – DreadHeadedDeveloper

ответ

2

Основная идея заключается в том, чтобы преобразовать строку в набор для маркеров. Например, приведенная выше строка кода может стать «КЛЮЧ, СЕПАРАТОР, ИД, НАЗНАЧЕНИЕ, НОМЕР, СЕПАРАТОР, ...». И тогда мы можем использовать простые правила для разделения кода с английского.

check out the code here

3

Посмотрите на лексического анализа и разборе (то же самое, как если бы вы писали компилятор). Возможно, вам даже не нужен парсер, если вам не нужны полные заявления.

+0

Вы ответили мне подсказку, теперь у меня есть идея. +! – Ryan

1

Вы можете использовать парсер Java или создать его с помощью BNF, но проблема здесь в том, что вы сказали, что код не может быть разборным, чтобы он не сработал.

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

Некоторые примеры:

  • for\s*\( (цикл)
  • while\s*\( (во время цикла)
  • [a-zA-Z_$][a-zA-Z\d_$]*\s*\( (constructor)
  • \)\s*\{ (начало блока/метод)
  • .. .

Да, это длинный выстрел, но, глядя на то, что вы хотите, у вас мало возможностей.

4

Вы можете попробовать парсер OpenNLP. Он возвращает n лучших анализов для предложения. Для большинства английских предложений он возвращает хотя бы один. Я считаю, что для большинства фрагментов кода он не вернет никаких результатов, и, следовательно, вы можете быть уверены, что это не английское предложение.

Используйте этот код для синтаксического анализа:

// Initialize the sentence detector 
    final SentenceDetectorME sdetector = EasyParserUtils 
      .getOpenNLPSentDetector(Constants.SENTENCE_DETECTOR_DATA); 

    // Initialize the parser 
    final Parser parser = EasyParserUtils 
      .getOpenNLPParser(Constants.PARSER_DATA_LOC); 

    // Get sentences of the text 
    final String sentences[] = sdetector.sentDetect(essay); 

    // Go through the sentences and parse each 
    for (final String sentence : sentences) { 
     // Parse the sentence, produce only 1 parse 
     final Parse[] parses = ParserTool.parseLine(sentence, parser, 10); 
     if (parses.length == 0) { 
      // Most probably this is code 
     } 
     else { 
      // An English sentence 
     } 
    } 

и эти два вспомогательные методы (от EasyParserUtils), используемых в коде:

public static Parser getOpenNLPParser(final String parserDataURL) { 
    try (final InputStream isParser = new FileInputStream(parserDataURL);) { 
     // Get model for the parser and initialize it 
     final ParserModel parserModel = new ParserModel(isParser); 
     return ParserFactory.create(parserModel); 
    } 
    catch (final IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 

и

public static SentenceDetectorME getOpenNLPSentDetector(
     final String sentDetDataURL) { 
    try (final InputStream isSent = new FileInputStream(sentDetDataURL)) { 
     // Get models for sentence detector and initialize it 
     final SentenceModel sentDetModel = new SentenceModel(isSent); 
     return new SentenceDetectorME(sentDetModel); 
    } 
    catch (final IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 
1

Там нет нужно изобретать колесо, компиляторы уже делают это за вас. Первый этап любого процесса компиляции проверяет, находятся ли маркеры в файле в пределах языка. Это, конечно, не поможет нам, так как английский и java не отличаются друг от друга. Однако второй этап, синтаксический анализ, выведет ошибку с любым написанным на английском языке предложением вместо java-кода (или что-то еще, что не является надлежащим java).Итак, вместо использования внешних библиотек и попробуйте использовать альтернативный подход, почему бы вам не использовать уже доступный java-компилятор?

вы можете иметь класс-оболочку, такую ​​как

public class Test{ 

    public static void main(){ 

     /*Insert code to check here*/ 

    } 

} 

, который компилируется и если она идет хорошо, то бомжа, вы знаете, что это правильный код. Конечно, он не будет работать с фрагментами кода, которые не являются полными, например, для цикла, который вы помещаете в пример без конечной скобки. Если он не скомпилируется, вы можете угрожать этой строкой путями, например, пытаться проанализировать ее с помощью собственного синтаксического анализатора псевдослучайного английского языка, выполненного с использованием гибкого бизона, инструментов GNU, используемых для создания GCC, например. Я не знаю точно, что вы пытаетесь выполнить с помощью программы, которую вы пытаетесь сделать, но таким образом вы можете узнать, является ли это кодом, ручным английским приложением или просто мусором, вам все равно. Изучение естественных языков действительно сложно, и на сегодняшний день современные подходы используют неточные статистические методы, поэтому они не всегда правы, что вам может не понадобиться в вашей программе.

+0

Это предполагает, что код не является полным классом. Он также предполагает, что ошибок программирования не будет. –

1

Для очень простого метода, который, по-видимому, очень хорошо работает на некоторых образцах. Выньте System.out. Это только для иллюстративных целей. Как видно из вывода примера, комментарии к коду выглядят как текст, поэтому, если большие комментарии к блоку без javadoc смешиваются с кодом, вы можете получить ложные срабатывания. Пороговые значения с жестким кодом - это моя оценка. Не стесняйтесь настраивать их.

public static void main(String[] args) { 
    for(String arg : args){ 
     System.out.println(arg); 
     System.out.println(codeStatus(arg)); 
    } 
} 

static CodeStatus codeStatus (String string) { 
    String[] words = string.split("\\b"); 
    int nonText = 0; 
    for(String word: words){ 
     if(!word.matches("^[A-Za-z][a-z]*|[0-9]+(.[0-9]+)?|[ .,]|. $")){ 
      nonText ++; 
     } 
    } 
    System.out.print("\n"); 
    double percentage = ((double) nonText)/words.length; 
    System.out.println(percentage); 
    if(percentage > .2){ 
     return CodeStatus.CODE; 
    } 
    if(percentage < .1){ 
     return CodeStatus.TEXT; 
    } 
    return CodeStatus.INDETERMINATE; 
} 

enum CodeStatus { 
    CODE, TEXT, INDETERMINATE 
} 

Пример вывода:

You can try the OpenNLP sentence parser. It returns the n best parses for a sentence. For most English sentences it returns at least one. I believe, that for most code snippets it won't return any and hence you can be quite sure it is not an English sentence. 

0.0297029702970297 
TEXT 
Use this code for parsing: 

0.18181818181818182 
INDETERMINATE 
    // Initialize the sentence detector 

0.125 
INDETERMINATE 
    final SentenceDetectorME sdetector = EasyParserUtils 
      .getOpenNLPSentDetector(Constants.SENTENCE_DETECTOR_DATA); 

0.6 
CODE 
    // Initialize the parser 

0.16666666666666666 
INDETERMINATE 
    final Parser parser = EasyParserUtils 
      .getOpenNLPParser(Constants.PARSER_DATA_LOC); 

0.5333333333333333 
CODE 
    // Get sentences of the text 

0.1 
INDETERMINATE 
    final String sentences[] = sdetector.sentDetect(essay); 

0.38461538461538464 
CODE 
    // Go through the sentences and parse each 

0.07142857142857142 
TEXT 
    for (final String sentence : sentences) { 
     // Parse the sentence, produce only 1 parse 
     final Parse[] parses = ParserTool.parseLine(sentence, parser, 10); 
     if (parses.length == 0) { 
      // Most probably this is code 
     } 
     else { 
      // An English sentence 
     } 
    } 

0.2537313432835821 
CODE 
and these are the two helper methods (from EasyParserUtils) used in the code: 

0.14814814814814814 
INDETERMINATE 
public static Parser getOpenNLPParser(final String parserDataURL) { 
    try (final InputStream isParser = new FileInputStream(parserDataURL);) { 
     // Get model for the parser and initialize it 
     final ParserModel parserModel = new ParserModel(isParser); 
     return ParserFactory.create(parserModel); 
    } 
    catch (final IOException e) { 

0.3835616438356164 
CODE 
0

Here является идеальным и безопасным решением. Основная идея состоит в том, чтобы сначала получить все доступные ключевые слова и специальные символы, а затем использовать набор для создания токенатора. Например, строка кода в вопросе становится «KEY, SEPARATOR, ID, ASSIGN, NUMBER, SEPARATOR, ...». И тогда мы можем использовать простые правила для разделения кода с английского.