2014-10-21 17 views
6

Aşağıdaki iki dizeyi göz önünde bulundurun, birincisi kod, ikincisi ise İngilizce cümledir (tam olarak ifade edilir). Birincisinin kod olduğunu ve ikincinin nasıl olduğunu nasıl anlayabilirim. Ben özel karakterleri sayma düşünüyorumDizenin İngilizce cümle veya kod olup olmadığı nasıl belirlenir?

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

(";" "=" gibi, "++", vb) ve bazı eşiğine eğer ayarlayın. Bunu yapmak için daha iyi yollar var mı? Herhangi bir Java kütüphanesi var mı?

Kodun ayrıştırılamayacağını unutmayın, çünkü bu tam bir yöntem/deyim/ifade değildir.

Benim varsayımın, İngilizce cümlelerin oldukça düzenli olması, büyük olasılıkla sadece ",", ".", "_", "(", ")", Vb. Içermesidir. Bu gibi bir şey içermezler: write("the whole lot of text"); (Eğer bir derleyici yazıyormuş gibi aynı) ayrıştırma sözcüksel analiz ve içine

+0

Benim, bu zor olacak, dürüst olmak gerekirse, bu konuda bir miktar araştırma yapacağım ve bazı kodlar için – DreadHeadedDeveloper

+0

kodundan sonra buraya getireceğim bazı kısayol çözümleri arıyorum. – Ryan

+0

Doğru, ama biz programcıyız, beyin fırtınası yapanlar değiliz. Fikirlerle gelmenizde size yardımcı olamayız, özellikle de bu kadar açık uçluysa ... Kod ile geri dönün ve sonra size yardımcı olacağız – DreadHeadedDeveloper

cevap

2

Temel fikir jeton için bir dizi dize dönüştürülmesidir. Örneğin, yukarıdaki kod satırı "KEY, SEPARATOR, ID, ASSIGN, NUMBER, SEPARATOR, ..." olabilir. Ve sonra kodu İngilizce'den ayırmak için basit kuralları kullanabiliriz.

check out the code here

3

bak. Tam ifadeler gerektirmiyorsa, ayrıştırıcıya bile ihtiyacınız olmayabilir.

+0

Cevap ver bana biraz ipucu verdi, şimdi biraz fikrim var. +! – Ryan

1

Bir Java ayrıştırıcısı kullanabilir veya BNF kullanarak bir tane oluşturabilirsiniz, ancak sorun burada kodun ayrıştırılamayacağını ve bu nedenle başarısız olacağını söylemiş olmanızdır.

Tavsiyem: koddaki özel kalıpları algılamak için bazı özel regexp kullanın. İyi bir başarı oranına sahip olmak için mümkün olduğunca çok kullanın.

Bazı örnekler:

  • for\s*\(
  • while\s*\( (iken döngü)
  • [a-zA-Z_$][a-zA-Z\d_$]*\s*\( (constructor)
  • \)\s*\{ (bir blok/yöntemin başlar) (döngü için)
  • ..

Evet, uzun bir atış ama ne istediğinize bakmak, pek fazla ihtimaliniz yok.

4

OpenNLP tümce çözümleyicisini deneyebilirsiniz. Bir cümle için en iyi ayrıştırmaları döndürür. Çoğu İngilizce cümle için en az bir tane döndürür. İnanıyorum ki, çoğu kod parçacığı için herhangi bir geri dönmeyecek ve dolayısıyla ingilizce bir cümle olmadığından emin olabilirsiniz.

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; 
    } 
} 

ve

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

hayır vardır: kodunda kullanılan

// 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 
     } 
    } 

ve bu (EasyParserUtils itibaren) iki yardımcı yöntemler şunlardır:

Kullanım ayrıştırma için bu kod Tekerleği yeniden icat etmek gerekiyor, Derleyiciler zaten sizin için bunu yapar. Herhangi bir derleme işleminin ilk aşaması, dosyadaki belirteçlerin dil kapsamı içinde olup olmadığını denetler. Bu, İngilizce ve java'nın içinde farklı olmadığından, bize kesinlikle yardımcı olmayacaktır. Ancak, ikinci aşamada, sözdizimi analizi, java kodu yerine (ya da uygun java olmayan başka herhangi bir şey) herhangi bir ingilizce cümle ile bir hata yazdıracaktır.Bu yüzden, dış kütüphaneleri kullanmak yerine ve alternatif bir yaklaşım kullanmaya çalışmak yerine, zaten mevcut olan java derleyicisini kullanmıyor musunuz?

Eğer

derlenmiş
public class Test{ 

    public static void main(){ 

     /*Insert code to check here*/ 

    } 

} 

gibi bir sarmalayıcı sınıf var ve o zaman iyi serseri giderse, bunu geçerli bir kod olduğunu biliyorum. Elbette, örnekte bir sonlandırma parantezi olmadan koyduğunuz döngü gibi tamamlanmayan kod snippet'leriyle çalışmaz. Eğer iyi bir derleme yapmazsa, ipucunu, örneğin, GCC'yi yapmak için kullanılan GNU'nun araçları olan esnek-bizon ile yapılmış kendi homebrew sözdizimsel sözdizimsel analizciniz ile ayrıştırmaya çalışmak gibi bir şekilde tehdit edebilirsiniz. Yapmaya çalıştığınız programla ne yapmaya çalıştığınızı tam olarak bilmiyorum, ancak bu şekilde kodun, el yapımı bir ingilizce sentece mi, yoksa umursamayacağınız bir çöp olup olmadığını anlayabilirsiniz. Doğal dilleri ayrıştırma gerçekten zordur ve şu an için modern yaklaşımlar yanlış statitiscal yöntemler kullanmaktadır, bu yüzden programınızda istemeyeceğiniz bir şey değildir.

+0

Bu, kodun tam bir sınıf olmadığını varsayar. Ayrıca programlama hataları olmayacağını varsayar. –

1

Bazı örneklerde oldukça iyi çalışıyor gibi görünen çok basit bir yöntem için. System.out'u çıkarın. Sadece açıklama amaçlıdır. Örnek çıktıdan da görebileceğiniz gibi, kod yorumları metin gibi görünür, bu yüzden büyük olmayan javadoc blok yorumları kod içine karıştırılırsa yanlış pozitifler alabilirsiniz. Sabit kodlanmış eşikler benim tahminim. Onları ince ayar yapmaktan çekinmeyin.

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 
} 

Örnek çıktı:

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 kusursuz ve güvenli bir çözümdür. Temel fikir, önce tüm kullanılabilir anahtar kelimeleri ve özel karakterleri alır ve ardından bir belirteç oluşturucu oluşturmak için bu seti kullanır. Örneğin, sorudaki kod satırı "KEY, SEPARATOR, ID, ASSIGN, NUMBER, SEPARATOR, ..." haline gelir. Ve sonra kodu İngilizce'den ayırmak için basit kuralları kullanabiliriz.

İlgili konular