Parser del servizio di linguaggio e analisi (managed package Framework)
Il parser è fondamentale del servizio di linguaggio. Le classi di linguaggio managed (MPF) extensibility Framework del pacchetto richiedono un parser di selezionare le informazioni sul codice che viene visualizzato. Un parser suddivide il testo in token lessicali e quindi identifica i token per tipo e funzionalità.
Descrizione
L'esempio seguente è un metodo c#.
namespace MyNamespace
{
class MyClass
{
public void MyFunction(int arg1)
{
int var1 = arg1;
}
}
}
In questo esempio, i token vengono utilizzate le parole e i segni di punteggiatura. I tipi di token è la seguente.
Nome del token |
Tipo di token |
---|---|
spazio dei nomi, classe, pubblici, void, int |
parola chiave |
= |
l'operatore ':?' |
{ } ( ) ; |
delimitatore |
MyNamespace, MyClass, MyFunction, arg1, var1 |
identificatore |
MyNamespace |
Spazio dei nomi |
MyClass |
class |
MyFunction |
metodo |
arg1 |
Parametro di |
var1 |
variabile locale |
Il ruolo del parser è identificare i token. alcuni token possono avere più di un tipo. Dopo che il parser ha identificato i token, il servizio di linguaggio possibile utilizzare le informazioni per fornire le funzionalità utili, ad esempio evidenziazione della sintassi, la corrispondenza di parentesi graffe e le operazioni di IntelliSense.
tipi di parser
Un parser del servizio di linguaggio non è uguale a parser utilizzato come parte del compilatore. Tuttavia, questo tipo di parser necessario utilizzare sia uno scanner che un parser, ad esempio un parser del compilatore.
Uno analisi viene utilizzato per identificare i tipi di token. Queste informazioni sono utilizzate per l'evidenziazione della sintassi e per rapidamente l'identificazione dei tipi di token che possono attivare altre operazioni, ad esempio, la corrispondenza di parentesi graffe. Questo scanner è rappresentato dall'interfaccia di IScanner .
Un parser viene utilizzato per descrivere le funzioni e l'ambito dei token. Queste informazioni sono utilizzate nelle operazioni di IntelliSense per identificare gli elementi del linguaggio, ad esempio i metodi, variabili, parametri e dichiarazioni e per fornire gli elenchi dei membri e delle firme del metodo in base al contesto. Il parser viene utilizzato per posizionare le coppie di elementi di linguaggio, ad esempio le parentesi graffe e parentesi. Il parser viene eseguito con il metodo di ParseSource nella classe di LanguageService .
Modalità di distribuzione di uno scanner e un parser per il servizio di linguaggio dal programmatore. Diverse risorse sono disponibili in cui sono descritti il funzionamento dei parser e come scrivere diventi proprietaria del parser. Inoltre, molti liberi e prodotti host commerciali sono disponibili la guida nel creare un parser.
Il parser di ParseSource
A differenza di un parser che viene utilizzato come parte di un compilatore (dove i token vengono convertiti in qualche forma del codice eseguibile, un parser del servizio di linguaggio può essere chiamato per molte ragioni diverse e in molti contesti diversi. Come si distribuisce questo approccio nel metodo di ParseSource nella classe di LanguageService dal programmatore. È importante tenere presente che il metodo di ParseSource potrebbe essere chiamato su un thread in background.
Avviso
La struttura di ParseRequest contiene un riferimento a un oggetto di IVsTextView .questo oggetto di IVsTextView non può essere in background thread utilizzato.Infatti, molte delle classi di base MPF non possono trovarsi in background thread utilizzato.Questi includono Source, ViewFilter, le classi di CodeWindowManager e qualsiasi altra classe che comunica direttamente o indirettamente alla visualizzazione.
Il parser in genere analizzare l'intero file di origine la prima volta che viene chiamato o quando il valore di analisi motivi di Check fornito. Le chiamate successive al metodo di ParseSource gestiscono una piccola parte del codice analizzato e possono essere eseguiti più rapidamente tramite i risultati dell'operazione di analisi completa precedente. Il metodo di ParseSource passa i risultati dell'operazione di analisi tramite oggetti di AuthoringScope e di AuthoringSink . L'oggetto di AuthoringSink viene utilizzato per raccogliere informazioni per un motivo specifico di analisi, ad esempio, le informazioni sugli intervalli delle parentesi graffe corrispondenti o firme di metodo con elenchi di parametri. AuthoringScope fornisce le raccolte di dichiarazioni e la firma del metodo e anche per passare all'opzione avanzata di modifica (Vai a definizione, Passare alla dichiarazione, Passare fare riferimento).
Lo scanner di IScanner
È inoltre necessario implementare uno scanner che implementa IScanner. Tuttavia, poiché questo marca di operare su una seconda riga per riga attraverso la classe di Colorizer , è in genere più semplice da implementare. All'inizio di ogni riga, il MPF fornisce la classe di Colorizer un valore da utilizzare come variabile di stato che viene passata allo scanner. Alla fine di ogni riga, lo scanner restituisce la variabile di stato aggiornata. Il MPF memorizzato nella cache le informazioni sullo stato per ogni riga in modo da poter avviare lo scanner l'analisi da qualsiasi riga senza dover avviareinizio del file di origine. Questo un'analisi rapida di una singola riga consente all'editor di fornire feedback rapido all'utente.
Analisi delle parentesi graffe corrispondenti
Questo esempio mostra il flusso di controllo in base a una parentesi graffa di chiusura digitate. In questo processo, lo scanner utilizzato per colorazione viene utilizzato per determinare il tipo di token e se il token può attivare un'operazione di partita-parentesi graffe. Se il trigger viene trovato, il metodo di ParseSource viene chiamato per trovare la parentesi graffa corrispondente. Infine, le due parentesi graffe sono evidenziate.
Anche se le parentesi vengono utilizzate nei nomi dei trigger e i motivi di traccia, questo processo non è limitato alle effettive parentesi graffe. Qualsiasi coppia di caratteri che viene specificata per essere una coppia corrispondente è supportata. gli esempi includono (e), < e > e [e].
Si supponga che supporta del servizio di linguaggio che corrispondono alle parentesi graffe.
L'utente digita una parentesi graffa chiusa (}).
La parentesi graffa viene inserita in corrispondenza del cursore nel file di origine e il cursore è prevista da uno.
Il metodo di OnCommand nella classe di Source viene chiamato con la parentesi graffa di chiusura tipizzata.
Le chiamate al metodo di OnCommand il metodo di GetTokenInfo nella classe di Source per ottenere il token alla posizione immediatamente prima della posizione corrente del cursore. Questo token corrisponde alla parentesi graffa di chiusura tipizzata).
Le chiamate al metodo di GetTokenInfo il metodo di GetLineInfo l'oggetto di Colorizer per ottenere tutti i token sull'attuale riga.
Le chiamate al metodo di GetLineInfo il metodo di SetSource l'oggetto di IScanner con il testo della riga corrente.
Il metodo di GetLineInfo chiama ripetutamente il metodo di ScanTokenAndProvideInfoAboutIt l'oggetto di IScanner per raccogliere tutti i token dall'attuale riga.
Le chiamate al metodo di GetTokenInfo un metodo privato nella classe di Source per ottenere il token che contiene la posizione stabilita e passa nell'elenco di token ottenuti dal metodo di GetLineInfo .
Il metodo di OnCommand cerca un flag token del trigger di MatchBraces nel token restituito dal metodo di GetTokenInfo ; ovvero il token che rappresenta la parentesi graffa di chiusura).
Se il flag del trigger di MatchBraces viene trovato, il metodo di MatchBraces nella classe di Source viene chiamato.
Il metodo di MatchBraces inizia un'operazione di analisi con il valore di analisi motivi di HighlightBraces. Questa operazione viene chiamato il metodo di ParseSource sulla classe di LanguageService . Se l'analisi asincrona viene attivata, questa chiamata al metodo di ParseSource si verifica su un thread in background.
Quando l'operazione di analisi viene completata, un gestore di completamento interno (anche noto come metodo di callback) HandleMatchBracesResponse denominato viene chiamato nella classe di Source . Questa chiamata viene eseguita automaticamente dalla classe base di LanguageService , non dal parser.
Il metodo di HandleMatchBracesResponse ottiene un elenco di intervalli dall'oggetto di AuthoringSink archiviato nell'oggetto di ParseRequest . (L'intervallo di una classe rappresenta una struttura di TextSpan che specifica un intervallo di linee e di caratteri nel file di origine.) Questo elenco di intervalli in genere contiene due intervalli, ognuna di apertura e parentesi graffe chiuse.
Le chiamate al metodo di HandleBracesResponse il metodo di HighlightMatchingBrace l'oggetto di IVsTextView archiviato nell'oggetto di ParseRequest . Ciò consente di evidenziare gli intervalli specificati.
Se la proprietà EnableShowMatchingBrace di LanguagePreferences è abilitata, il metodo di HandleBracesResponse ottiene il testo che è costituito dall'intervallo corrispondente e vengono visualizzati i primi 80 caratteri di tale intervallo nella barra di stato. Ciò è ideale quando il metodo di ParseSource include l'elemento del linguaggio che accompagna la coppia corrispondente. Per ulteriori informazioni, vedere la proprietà EnableShowMatchingBrace.
Il fatto.
Riepilogo
L'operazione delle parentesi graffe corrispondenti in genere è limitata alle coppie semplici gli elementi del linguaggio. Gli elementi più complessi, come rijndael corrispondenti ("if(…)„, “{„ e “}„, o “else„, “{„ e “}"), possono essere evidenziati come parte di un'operazione di Word-completamento. Ad esempio, quando la parola “altra„ viene completata, l'istruzione corrispondente “diif„ può essere evidenziato. Se fossero presenti le serie di if/istruzioni dielse if , tutti vengano evidenziati utilizzando lo stesso meccanismo di parentesi graffe corrispondenti. La classe base di Source già supporta questa, come segue: Lo scanner deve restituire il valore token MatchBraces trigger combinato con il valore MemberSelect trigger per il token che precede la posizione del cursore.
Per ulteriori informazioni, vedere Corrispondenza di parentesi graffe (managed package Framework).
La tracciatura della colorazione
Al codice sorgente è libero, solo identifica il tipo di informazioni sui colori di ritorno e del token su quel tipo. La classe di Colorizer funge da intermediario tra l'editor e lo scanner per fornire informazioni sui colori su ogni token. La classe di Colorizer utilizza l'oggetto di IScanner per aiutare nel colore una riga e anche per raccogliere le informazioni sullo stato di tutte le righe nel file di origine. Nelle classi del servizio di linguaggio di MPF, la classe di Colorizer non è necessario eseguire l'override perché comunica con lo scanner solo tramite l'interfaccia di IScanner . Fornire l'oggetto che implementa l'interfaccia di IScanner eseguendo l'override del metodo di GetScanner sulla classe di LanguageService .
Lo scanner di IScanner viene fornita una riga di codice sorgente con il metodo di SetSource . Le chiamate al metodo di ScanTokenAndProvideInfoAboutIt vengono ripetute per ottenere il token della riga fino all'esaurimento della riga dei token. Per i colori, il MPF gestisce tutto il codice sorgente come sequenza di linee. Di conseguenza, lo scanner deve essere necessario trovare nel database di origine fornito come linee. Inoltre, qualsiasi riga può essere passata allo scanner in qualsiasi momento e l'unica garanzia è che lo scanner riceve la variabile di stato dalla riga prima di riga su da analizzare.
La classe di Colorizer viene utilizzata per identificare i trigger token. Questi trigger indicano al MPF che un token particolare possibile avviare un'operazione più complessa, come completamento delle parole o parentesi graffe corrispondenti. Poiché identificare tali trigger deve essere veloce e deve trovarsi in qualsiasi percorso, lo scanner è più appropriato per questa attività.
Per ulteriori informazioni, vedere Colore di sintassi (managed package Framework).
La tracciatura della funzionalità e l'ambito
La tracciatura per la funzionalità e l'ambito richiede più complesso che solo identificare i tipi di token che si verificano. Il parser necessario identificare non solo il tipo di token, ma anche la funzionalità per il quale il token viene utilizzata. Ad esempio, un identificatore è semplicemente un nome, ma nel linguaggio, un identificatore può essere un nome di classe, dello spazio dei nomi, il metodo, o la variabile, a seconda del contesto. Il tipo generale del token può essere un identificatore, ma l'identificatore può contenere anche altri significati, a seconda di quale punto in cui è definito. Questo ID. richiede il parser di avere una conoscenza più approfondita sul linguaggio che sta analizzando. Questo è il punto in cui la classe di AuthoringSink invio. La classe di AuthoringSink raccoglie informazioni sugli identificatori, i metodi, coppie dei linguaggi corrispondenti (come le parentesi graffe e parentesi) e il linguaggio triplica (simile alle coppie dei linguaggi con la differenza che esistono tre parti, ad esempio, “foreach()„{„ e “}"). Inoltre, è possibile eseguire l'override della classe di AuthoringSink per supportare l'identificazione di codice, utilizzata la convalida iniziale dei punti di interruzione in modo che esse non debbano caricare il debugger e la finestra di debug di automobili , che mostra le variabili locali e parametri automaticamente quando un programma sta eseguendo il debug e richiede il parser di identificare le variabili locali appropriate e i parametri oltre a quelli che il debugger elencati.
L'oggetto di AuthoringSink viene passato al parser come parte dell'oggetto di ParseRequest e un nuovo oggetto di AuthoringSink viene creato ogni volta che un nuovo oggetto di ParseRequest viene creato. Inoltre, il metodo di ParseSource deve restituire un oggetto di AuthoringScope , utilizzato per eseguire varie operazioni di IntelliSense. L'oggetto di AuthoringScope gestisce un elenco per le dichiarazioni e un elenco dei metodi, o di cui è stato compilato, come il motivo per analizzare. La classe di AuthoringScope deve essere distribuita.
Vedere anche
Concetti
Panoramica del servizio di linguaggio (managed package Framework)
Colore di sintassi (managed package Framework)
Corrispondenza di parentesi graffe (managed package Framework)
Altre risorse
Implementare un servizio di linguaggio tramite il pacchetto gestito Framework