Analisador de serviço de linguagem e o Scanner (estrutura de pacote gerenciado)
O analisador é o coração do serviço de linguagem. As classes de linguagem do Framework de pacote gerenciado (MPF) exigem um analisador de idioma para selecionar as informações sobre o código que está sendo exibido. Um analisador separa o texto em símbolos lexicais e identifica esses tokens por tipo e funcionalidade.
Discussão
Este é um método C#.
namespace MyNamespace
{
class MyClass
{
public void MyFunction(int arg1)
{
int var1 = arg1;
}
}
}
Neste exemplo, os tokens são palavras e sinais de pontuação. Os tipos de tokens são os seguintes.
Nome de token |
Tipo de token |
---|---|
namespace, void pública, de classe, int |
keyword (palavra-chave) |
= |
Operador |
{ } ( ) ; |
delimitador |
MyNamespace, MyClass, MyFunction, arg1, var1 |
identifier |
MyNamespace |
namespace |
MyClass |
classe |
MyFunction |
Método |
arg1 |
parâmetro |
var1 |
variável local |
A função do analisador é identificar os tokens. Alguns símbolos podem ter mais de um tipo. Depois que o analisador identificou os tokens, o serviço de linguagem pode usar as informações para fornecer recursos úteis, como o realce de sintaxe de correspondência de chaves e as operações de IntelliSense.
Tipos de analisadores
Um analisador de serviço de linguagem não é o mesmo que um analisador usado como parte de um compilador. No entanto, esse tipo de analisador precisa usar um scanner e um analisador, da mesma forma como um analisador de compilador.
Um scanner é usado para identificar os tipos de tokens. Essas informações são usadas para realce de sintaxe e identificar rapidamente os tipos de token que podem disparar outras operações, por exemplo, correspondência de chaves. Este scanner é representado pela IScanner interface.
Um analisador é usado para descrever as funções e o escopo de tokens. Essas informações são usadas em operações de IntelliSense para identificar elementos de linguagem, como, por exemplo, métodos, variáveis, parâmetros e declarações e fornecem listas de membros e assinaturas de método com base no contexto. Esse parser também é usado para localizar pares correspondentes de elemento de linguagem, como, por exemplo, chaves e parênteses. Este analisador é acessado através do ParseSource método na LanguageService classe.
Como implementar um analisador e o scanner para o serviço de idioma fica a seu critério. Vários recursos estão disponíveis que descrevam como funcionam os analisadores e como escrever seu próprio analisador. Além disso, vários produtos gratuitos e comerciais estão disponíveis que ajudam na criação de um analisador.
O analisador de ParseSource
Ao contrário de um analisador que é usado como parte de um compilador (onde os tokens são convertidos em alguma forma de código executável), um analisador de serviço do idioma pode ser chamado por vários motivos diferentes e em muitos contextos diferentes. Como você implementa essa abordagem na ParseSource método na LanguageService classe fica a seu critério. É importante ter em mente que o ParseSource método pode ser chamado em um thread de segundo plano.
Aviso
O ParseRequest estrutura contém uma referência para o IVsTextView objeto.Isso IVsTextView objeto não pode ser usado no thread de plano de fundo.Na verdade, muitas das classes base do MPF não podem ser usadas no thread de plano de fundo.Eles incluem o Source, ViewFilter, CodeWindowManager classes e qualquer outra classe que direta ou indiretamente se comunica com o modo de exibição.
Esse parser analisa normalmente o tempo de arquivo na primeira fonte de todo ele é chamado ou quando a análise de valor do motivo Check é fornecido. As chamadas subseqüentes para o ParseSource método lidar com uma pequena parte do código analisada e podem ser executadas muito mais rapidamente, usando os resultados da operação completa análise anterior. O ParseSource método comunica os resultados da operação de análise através do AuthoringSink e AuthoringScope objetos. O AuthoringSink objeto é usado para coletar informações por um motivo específico de análise, por exemplo, informações sobre as extensões de correspondência de chaves ou assinaturas de método que têm listas de parâmetros. O AuthoringScope fornece coleções de declarações e assinaturas de método e também suporte para ir para avançada Editar opção (Ir para definição de, Ir para declaração, Ir para a referência).
O mecanismo de varredura de IScanner
Você também deve implementar um scanner que implementa IScanner. No entanto, como este scanner opera por meio de linha por linha de Colorizer classe, é normalmente mais fácil de implementar. No início de cada linha, o MPF oferece o Colorizer um valor a ser usado como uma variável de estado que é passada para o mecanismo de varredura de classe. No final de cada linha, o mecanismo de varredura retorna a variável atualizada do estado. O MPF armazena em cache essas informações de estado para cada linha para que o mecanismo de varredura possa iniciar a análise de qualquer linha sem ter que começar do início do arquivo de origem. Este exame rápido de uma única linha permite que o editor para fornecer feedback rápido ao usuário.
Análise para correspondência de chaves
Este exemplo mostra o fluxo de controle para correspondência de uma folha de fechamento que o usuário digitou. Nesse processo, o mecanismo de varredura que é usado para colorização também é usado para determinar o tipo de token e se o token pode disparar uma operação chave correspondente. Se o disparador for encontrado, o ParseSource método é chamado para encontrar a chave correspondente. Finalmente, as duas chaves são realçadas.
Apesar de chaves são usadas nos nomes de disparadores e analisar as razões, esse processo não é limitado a chaves reais. Qualquer par de caracteres especificado para ser uma correspondência emparelhar é suportado. Os exemplos incluem (e), < e >, e [e].
Suponha que o serviço de linguagem suporta chaves correspondentes.
O usuário digita uma chave de fechamento (}).
A chave de abertura é inserido na posição da cursor no arquivo de origem e o cursor é avançado por um.
O OnCommand método na Source classe é chamado com a chave de fechamento digitado.
O OnCommand chamadas de método de GetTokenInfo método na Source classe para obter o token na posição antes da posição atual do cursor. Esse token corresponde da chave de fechamento digitado).
O GetTokenInfo chamadas de método de GetLineInfo método na Colorizer objeto para obter todos os tokens na linha atual.
O GetLineInfo chamadas de método do SetSource método no IScanner o objeto com o texto da linha atual.
O GetLineInfo método chama repetidamente a ScanTokenAndProvideInfoAboutIt método na IScanner objeto para reunir todos os tokens a partir da linha atual.
O GetTokenInfo método chama um método particular Source de classe para obter o token que contém a posição desejada e passagens na lista de tokens obtido o GetLineInfo método.
O OnCommand método procura um sinalizador de disparador de token de MatchBraces no token que é retornado a GetTokenInfo método; ou seja, o símbolo que representa o fechamento chave).
Se o disparador sinalizador de MatchBraces for encontrado, o MatchBraces método na Source é chamado de classe.
O MatchBraces método inicia uma operação de análise com o valor de motivo de análise da HighlightBraces. Essa operação, por fim, chama o ParseSource método sobre o LanguageService classe. Se analisar assíncrona estiver habilitada, essa chamada para o ParseSource método ocorre em um segmento de plano de fundo.
Quando a operação de análise estiver concluída, um manipulador de conclusão interno (também conhecido como um método de retorno de chamada) chamado HandleMatchBracesResponse é chamado na Source classe. Essa chamada é feita automaticamente pelo LanguageService base de classe, não pelo analisador.
O HandleMatchBracesResponse método obtém uma lista de extensões da AuthoringSink que é armazenado no objeto a ParseRequest objeto. (Uma marca span é uma TextSpan estrutura que especifica um intervalo de linhas e caracteres no arquivo de origem.) Esta lista de extensões normalmente contém duas extensões, uma de cada para as chaves de abertura e fechamento.
O HandleBracesResponse chamadas de método a HighlightMatchingBrace método na IVsTextView objeto armazenado na ParseRequest objeto. Isso realça as extensões de determinado.
Se a LanguagePreferences propriedade EnableShowMatchingBrace estiver habilitada, o HandleBracesResponse método obtém o texto que é abrangido pela extensão correspondente e exibe os primeiros 80 caracteres do que se estendem por na barra de status. Isso funcionará melhor se a ParseSource método inclui o elemento de linguagem que acompanha o par correspondente. Para obter mais informações, consulte a propriedade EnableShowMatchingBrace.
Feito.
Resumo
A operação de correspondência de chaves é normalmente limitada aos pares simples de elementos de linguagem. Os elementos mais complexos, como correspondência triples ("if(…)","{"e"}", ou "else","{"e"}"), podem ser realçadas como parte de uma operação de preenchimento automático de palavras. Por exemplo, quando a palavra "else" estiver concluída, a correspondência "if" instrução pode ser realçada. Se houvesse uma série de if/else if instruções, todos eles poderiam ser destacadas, usando o mesmo mecanismo como correspondência de chaves. O Source classe base já oferece suporte, da seguinte forma: O mecanismo de varredura deve retornar o valor disparador token MatchBraces combinado com o valor de disparador MemberSelect para o token anterior a posição do cursor.
Para obter mais informações, consulte Chave correspondente (estrutura de pacote gerenciado).
Análise de colorização
Colorir o código-fonte é simples, basta identificar o tipo de informações de cor de token e retorno sobre o tipo. O Colorizer classe age como intermediário entre o editor e o mecanismo de varredura para fornecer informações sobre todos os tokens de cores. O Colorizer classe usa a IScanner para ajudar a colorir uma linha e também para coletar informações de estado para todas as linhas no arquivo de origem do objeto. Nas classes de serviço da linguagem MPF, o Colorizer classe não precise ser substituída, pois ele se comunica com o scanner somente por meio do IScanner interface. Você fornece o objeto que implementa o IScanner interface, substituindo o GetScanner método na LanguageService classe.
O IScanner scanner é dada uma linha de código-fonte por meio de SetSource método. Chamadas para o ScanTokenAndProvideInfoAboutIt método são repetidos para obter o próximo token na linha até que a linha seja esgotada de tokens. Para colorir, o MPF trata todo o código fonte como uma seqüência de linhas. Portanto, o mecanismo de varredura deve ser capaz de lidar com vindo nisso como linhas de código-fonte. Além disso, qualquer linha pode ser passada para o mecanismo de varredura a qualquer momento e a única garantia é que o mecanismo de varredura recebe a variável de estado a partir da linha antes da linha prestes a serem examinados.
O Colorizer classe também é usado para identificar acionadores de token. Esses disparadores informam o MPF que um token específico pode iniciar uma operação mais complexa, como conclusão do word ou correspondência de chaves. Como identificar esses disparadores deve ser rápido e deve ocorrer em qualquer local, o mecanismo de varredura é mais adequado para esta tarefa.
Para obter mais informações, consulte Sintaxe colorir (estrutura de pacote gerenciado).
Análise de funcionalidade e escopo
Para o escopo e a funcionalidade de análise requer um pouco mais do que apenas identificar os tipos de tokens que são encontrados. O analisador deve identificar não apenas o tipo de token, mas também a funcionalidade para o qual o token é usado. Por exemplo, um identificador é apenas um nome, mas em seu idioma, um identificador pode ser o nome de uma classe, namespace, método ou variável, dependendo do contexto. O tipo geral do token pode ser um identificador, mas o identificador também pode ter outros significados, dependendo o que é e onde ela está definida. Essa identificação requer o analisador de ter um conhecimento mais amplo sobre a linguagem que está sendo analisado. É aqui onde a AuthoringSink classe entra. O AuthoringSink classe coleta informações sobre identificadores, métodos, pares de idiomas correspondente (como, por exemplo, chaves e parênteses) e triples de linguagem (semelhante a pares de idiomas, exceto pelo fato de que existem em três partes, por exemplo, "foreach()" "{"e"}"). Além disso, você pode substituir o AuthoringSink classe para dar suporte à identificação do código, o que é usada na validação antecipada de pontos de interrupção para que o depurador não tem de ser carregado, e o Autos janela de depuração, o que mostra os parâmetros e variáveis locais automaticamente quando um programa está sendo depurado e requer o analisador para identificar as variáveis de locais apropriadas e parâmetros, além daqueles que o depurador apresenta.
O AuthoringSink objeto é passado para o analisador como parte do ParseRequest objeto e um novo AuthoringSink objeto é criado sempre que uma nova ParseRequest objeto é criado. Além disso, o ParseSource método deve retornar um AuthoringScope o objeto, que é usado para manipular várias operações de IntelliSense. O AuthoringScope objeto mantém uma lista de declarações e uma lista de métodos, ou dos quais estiver preenchido, dependendo da razão para análise. O AuthoringScope classe deve ser implementado.
Consulte também
Conceitos
Visão geral do serviço de linguagem (estrutura de pacote gerenciado)
Sintaxe colorir (estrutura de pacote gerenciado)
Chave correspondente (estrutura de pacote gerenciado)
Outros recursos
Implementando um serviço de idioma usando a estrutura de pacote gerenciado