2010-04-30 9 views
17

Sto imparando i combinatori di parser in scala e vedo diversi modi di analizzare. Io vedo principalmente tre diversi tipi di parser, ad esempio .RegexpParsers, StandardTokenParsers e JavaTokenParsers.Io sono nuovo nell'analizzare e non ottenere l'idea di come sceglieremo il parser adatto in base alle nostre esigenze. Qualcuno può spiegare come funzionano questi diversi parser e quando usarli.Differenza tra RegexpParsers, StandardTokenParsers e JavaTokenParsers in scala

risposta

6

RegexpParsers consentono di utilizzare valori RE (in genere nel modulo "re pattern".r ma ugualmente qualsiasi altra istanza Regex). Non ci sono produzioni lessicali predefinite (token).

JavaTokenParsers definisce produzioni lessicali per i token di Java: decimalNumber, floatingPointNumber, stringLiteral, wholeNumber, ident (identificatore).

StandardTokenParsersStandardTokenParsers definisce produzioni lessicali "... per un linguaggio semplice simile a Scala, analizza parole chiave e identificatori, valori letterali numerici (numeri interi), stringhe e delimitatori". I suoi componenti sono effettivamente definiti in StdLexical.

22

ci sono diversi tratti parser diverse e classi base per scopi diversi.

La caratteristica principale è scala.util.parsing.combinator.Parsers. Questo ha la maggior parte dei combinatori principali come opt, rep, elem, accept, ecc sicuramente guardare sopra la documentazione per questo, dal momento che questo è la maggior parte di ciò che è necessario sapere. La classe attuale Parser è qui definita come una classe interna, e questo è importante anche da sapere.

Un'altra caratteristica importante è scala.util.parsing.combinator.lexical.Scanners. Questa è la caratteristica di base per i parser che legge un flusso di caratteri e produce un flusso di token (noti anche come lexer). Per implementare questo tratto, è necessario implementare un parser whitespace, che legge caratteri di spazi bianchi, commenti, ecc. È inoltre necessario implementare un metodo token, che legge il token successivo. I token possono essere qualsiasi cosa tu voglia, ma devono essere una sottoclasse di Scanners.Token. Lexical estende Scanners e StdLexical estende Lexical. Il primo fornisce alcune utili operazioni di base (come digit, letter), mentre il secondo in realtà definisce e applica i token comuni (come valori letterali numerici, identificatori, stringhe, parole riservate). Devi solo definire e reserved, e otterrai qualcosa di utile per la maggior parte delle lingue. Le definizioni del token sono in scala.util.parsing.combinator.token.StdTokens.

Una volta creato un lexer, è possibile definire un parser che legge un flusso di token (prodotto dal lexer) e genera un albero di sintassi astratto. Separare il lexer e il parser è una buona idea poiché non dovrai preoccuparti di spazi bianchi, commenti o altre complicazioni nella sintassi. Se si utilizza StdLexical, si può prendere in considerazione l'utilizzo di scala.util.parsing.combinator.syntax.StdTokenPasers che contiene i parser integrati per tradurre token in valori (ad es. StringLit in String). Non sono sicuro di quale sia la differenza con StandardTokenParsers. Se definisci le tue classi di token, dovresti semplicemente usare Parsers per semplicità.

È espressamente chiesto circa RegexParsers e JavaTokenParsers. RegexParsers è un tratto che si estende Parsers con un combinatore aggiuntivo: regex, che fa esattamente quello che ci si aspetterebbe. Mescola RegexParsers al tuo lexer se vuoi usare le espressioni regolari per abbinare i token.JavaTokenParsers fornisce alcuni parser che i token lex dalla sintassi Java (come identificatori, numeri interi) ma senza il bagaglio token di Lexical o StdLexical.

Per riepilogare, probabilmente si vogliono due parser: uno che legge caratteri e produce token e uno che prende token e produce un AST. Utilizzare qualcosa basato su Lexical o StdLexical per il primo. Utilizzare qualcosa in base a Parsers o StdTokenParsers per il secondo a seconda se si utilizza StdLexical.