2014-10-21 16 views
6

Considerate le seguenti due stringhe, la prima è codice, la seconda è inglese (frase per la precisione). Come posso rilevare che il primo è il codice e il secondo no.Come determinare se una stringa è una frase o un codice inglese?

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

sto pensando a contare i caratteri speciali (come ad esempio "=", "", "++", ecc), e impostare se ad una certa soglia. Ci sono modi migliori per farlo? Qualsiasi libreria Java?

Si noti che il codice potrebbe non essere analizzabile, perché non è un metodo/istruzione/espressione completo.

La mia ipotesi è che le frasi inglesi siano piuttosto regolari, molto probabilmente contiene solo ",", ".", "_", "(", ")", Ecc. Non contengono qualcosa di simile: write("the whole lot of text");

+0

Mio, sarà difficile, ad essere onesto, vorrei fare qualche ricerca su questo e portarlo qui dopo aver un po 'di codice – DreadHeadedDeveloper

+0

Sto cercando alcune soluzioni di collegamento. – Ryan

+0

Vero, ma siamo programmatori, non brainstormer. Non possiamo aiutarti a inventare idee, specialmente se è così aperto come questo ... Torna con il codice e poi saremo in grado di aiutarti – DreadHeadedDeveloper

risposta

2

L'idea di base è quella di convertire la stringa in un set a gettoni. Ad esempio, la riga di codice sopra può diventare "KEY, SEPARATOR, ID, ASSIGN, NUMBER, SEPARATOR, ...". E poi possiamo usare semplici regole per separare il codice dall'inglese.

check out the code here

3

Guardare in analisi lessicale e parsing (come se si stesse scrivendo un compilatore). Potresti non aver nemmeno bisogno di un parser se non richiedi dichiarazioni complete.

+0

La tua risposta mi ha dato qualche suggerimento, ho qualche idea ora. +! – Ryan

1

È possibile utilizzare un parser Java o crearne uno utilizzando lo BNF ma il problema è che si è detto che il codice potrebbe non essere analizzabile in modo da non riuscire.

Il mio consiglio: utilizzare alcune regexp personalizzate per rilevare i modelli speciali nel codice. Utilizzare il maggior numero possibile per avere una buona percentuale di successo.

Alcuni esempi:

  • for\s*\( (ciclo)
  • while\s*\( (while)
  • [a-zA-Z_$][a-zA-Z\d_$]*\s*\( (constructor)
  • \)\s*\{ (all'inizio di un blocco/metodo)
  • ..

Sì, è un campo lungo ma guardando quello che vuoi, non hai molte possibilità.

4

È possibile provare il parser di frase OpenNLP. Restituisce le migliori analisi per una frase. Per la maggior parte delle frasi inglesi ne restituisce almeno una. Credo che per la maggior parte dei frammenti di codice non ne restituirà alcuno e quindi si può essere certi che non si tratti di una frase inglese.

Usa questo codice per l'analisi:

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

e questi sono i due metodi di supporto (da EasyParserUtils) utilizzato nel codice:

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

e

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

Non c'è è necessario reinventare la ruota, i compilatori lo fanno già per te. La prima fase di qualsiasi processo di compilazione verifica se i token nel file rientrano nell'ambito della lingua. Questo certamente non ci aiuterà dal momento che l'inglese e Java non lo diffanno. Tuttavia la seconda fase, l'analisi sintattica, stamperà un errore con qualsiasi frase formata in inglese invece di codice java (o qualsiasi altra cosa che non sia java corretta).Quindi, invece di usare le librerie esterne e provare ad usare un approccio alternativo, perché non usi il compilatore java già disponibile?

si può avere una classe wrapper come

public class Test{ 

    public static void main(){ 

     /*Insert code to check here*/ 

    } 

} 

che viene compilato e se va bene allora bum, lo sai che è un codice valido. Ovviamente non funzionerà con frammenti di codice che non sono completi come quello per il ciclo che hai inserito nell'esempio senza parentesi finale. Se non si compila bene, è possibile minacciare la stringa in vari modi, ad esempio tentando di analizzarla con il proprio analizzatore sintattico pseudo-inglese homebrew realizzato con flex-bison, gli strumenti di GNU utilizzati per creare GCC, ad esempio. Non so esattamente cosa stai cercando di realizzare con il programma che stai tentando di fare, ma in questo modo puoi sapere se è il codice, un soldato inglese fatto a mano, o solo spazzatura che non ti interessa. L'analisi dei linguaggi naturali è davvero difficile e per ora gli approcci moderni usano metodi statistici errati, quindi non sempre hanno ragione, qualcosa che potresti non volere nel tuo programma.

+0

Questo presuppone che il codice non sia una classe completa. Presume anche che non ci saranno errori di programmazione. –

1

Per un metodo molto semplice che sembra funzionare piuttosto bene su alcuni campioni. Elimina lo System.out. È solo a scopo illustrativo. Come puoi vedere dall'output di esempio, i commenti di codice sembrano testo, quindi se i commenti di blocco non javadoc di grandi dimensioni sono mescolati nel codice potresti ottenere falsi positivi. Le soglie hard-coded sono la mia stima. Sentiti libero di sintonizzarti.

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 
} 

Output di esempio:

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 è una soluzione perfetta e sicura. L'idea di base è di ottenere prima tutte le parole chiave disponibili e i caratteri speciali, quindi utilizzare il set per creare un tokenizer. Ad esempio, la riga di codice nella domanda diventa "CHIAVE, SEPARATORE, ID, ASSEGNA, NUMERO, SEPARATORE, ...". E poi possiamo usare semplici regole per separare il codice dall'inglese.

Problemi correlati