2014-10-21 1 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

기본적인 아이디어는 토큰 세트로 문자열을 변환하는 것입니다. 예를 들어 위의 코드 줄은 "KEY, SEPARATOR, ID, ASSIGN, NUMBER, SEPARATOR, ..."가 될 수 있습니다. 그런 다음 간단한 규칙을 사용하여 코드를 영어와 분리 할 수 ​​있습니다.

check out the code here

3

봐. 완전한 설명이 필요하지 않은 경우 파서가 필요하지 않을 수도 있습니다.

+0

답변을 주시면 몇 가지 힌트를 주셨습니다. 지금 몇 가지 아이디어가 있습니다. +! – Ryan

1

자바 파서를 사용하거나 BNF을 사용하여 파서를 만들 수 있지만 여기서 문제는 코드가 구문 분석되지 않아 실패 할 수 있다고 말한 것입니다.

내 충고 : 코드의 특수 패턴을 감지하기 위해 맞춤 regexp를 사용하십시오. 좋은 성공률을 가지려면 가능한 한 많이 사용하십시오.

일부 예 :

  • for\s*\(
  • while\s*\(
  • (while 루프)
  • [a-zA-Z_$][a-zA-Z\d_$]*\s*\( (constructor)
  • \)\s*\{ (블록/방법의 시작) (루프)
  • .. .

예. 긴 장면이지만 원하는 것을보고 있으면 많은 가능성이 없습니다.

4

OpenNLP 문장 파서를 사용해 볼 수 있습니다. 문장에 대한 n 개의 가장 좋은 구문을 반환합니다. 대부분의 영어 문장의 경우 적어도 하나를 반환합니다. 나는 대부분의 코드 스 니펫에 대해서는 어떤 것도 반환하지 않을 것이므로 영어 문장이 아니라는 것을 확신 할 수있다.

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

더있다 : 코드에서 사용

// 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에서) 두 도우미 방법은 다음과 같습니다

를 사용하여 구문 분석이 코드 휠을 재발 명할 필요가 있습니다. 컴파일러는 이미이를 수행합니다. 컴파일 프로세스의 첫 번째 단계에서는 파일의 토큰이 언어 범위 내에 있는지 확인합니다. 영어와 자바는 그 점에서 다르지 않기 때문에 이것은 확실히 도움이되지 않습니다. 그러나 두 번째 단계 인 구문 분석은 Java 코드 (또는 적절한 Java가 아닌 다른 언어) 대신 영어로 작성된 문장에 오류를 인쇄합니다.따라서 외부 라이브러리를 사용하고 대체 접근법을 사용하는 대신, 이미 사용 가능한 Java 컴파일러를 사용하지 않는 것이 좋습니다.

당신은

컴파일됩니다
public class Test{ 

    public static void main(){ 

     /*Insert code to check here*/ 

    } 

} 

같은 래퍼 클래스를 가질 수 있고 그 다음 잘 엉덩이를가는 경우, 당신은 유효한 코드 알고있다. 물론 끝내기 괄호없이 예제에 넣은 for 루프와 같이 완전하지 않은 코드 스 니펫에서는 작동하지 않습니다. 컴파일이 잘되지 않는다면, 예를 들어 GCC를 만드는 데 사용 된 GNU의 도구 인 flex-bison으로 만든 자신 만의 가정용 가짜 pseudo-english 신택스 분석기로 파싱하려고 시도하는 것과 같이 문자열을 수천 가지 방법으로 위협 할 수 있습니다. 나는 당신이하려고하는 프로그램으로 무엇을 성취하려고하는지 정확히 모르지만 코드, 수공예 영어 문장, 또는 쓰레기 만 신경 쓰면 안된다는 것을 알 수 있습니다. 자연 언어를 파싱하는 일은 정말로 어렵습니다. 현재 현대적인 접근법은 부정확 한 statitiscal 방법을 사용하기 때문에 항상 올바르지는 않습니다. 프로그램에서 원하지 않을 수도 있습니다.

+0

이 코드는 전체 클래스가 아니라고 가정합니다. 또한 프로그래밍 오류가 없다고 가정합니다. –

1

매우 간단한 방법으로 일부 샘플에서 잘 작동하는 것처럼 보입니다. System.out을 꺼내십시오. 설명 목적으로 만 사용됩니다. 샘플 출력에서 ​​볼 수 있듯이 코드 주석은 텍스트처럼 보이므로 큰 javadoc이 아닌 블록 주석이 코드에 혼합되어 있으면 오탐 (false positive)이 발생할 수 있습니다. 하드 코딩 된 임계 값은 내 추정치입니다. 부담없이 조정하십시오.

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, ..."가됩니다. 그런 다음 간단한 규칙을 사용하여 코드를 영어와 분리 할 수 ​​있습니다.

관련 문제