zoukankan      html  css  js  c++  java
  • VSX开发之语言服务系列(5)——构建自己的Scanner和Pareser

    回顾

    在上一篇中,我们从一个空Package开始创建了一个语言服务的基本架构,并且借用ManagedMyC的Scanner和Parser。这篇中,我们将完成一个简单的Scanner,先看下效果图:

    image 可以看到在这个语言服务中,大写字母被着色成红色,小写字母是紫色,数字是蓝色,其他字符时黑色的。接下来我们就来实现这个功能。

    lexer.lex

    首先修改lexer.lex。删除原有的代码,加入如下代码:

    %using Babel;
    %using Babel.Parser;
    %namespace Babel.Lexer
    
    %%
    
    [0-9]+				{return (int)Tokens.NUMBER;}
    [a-z]+				{return (int)Tokens.LOWLETTER;}
    [A-Z]+				{return (int)Tokens.CAPLETTER;}
    .						;
    
    %%
    
    /* .... */

    暂时不对代码含义做解释,我们继续:

    parser.y

    然后修改parser.y。同样,用如下代码覆盖:

    %using Microsoft.VisualStudio.TextManager.Interop
    %namespace Babel.Parser
    %valuetype LexValue
    %partial
    
    /* %expect 5 */
    
    
    %union {
        public string str;
    }
    
    
    %{
        ErrorHandler handler = null;
        public void SetHandler(ErrorHandler hdlr) { handler = hdlr; }
        internal void CallHdlr(string msg, LexLocation val)
        {
            handler.AddError(msg, val.sLin, val.sCol, val.eCol - val.sCol);
        }
    %}
    
    %token NUMBER	
    %token CAPLETTER		
    %token LOWLETTER
    
    %%
    
    Program
        : Declarations 
        ;
    
    Declarations
    	:  Declarations  Declaration
    	| Declaration
    	;
    
    Declaration
    	: NUMBER
    	| CAPLETTER
    	| LOWLETTER
    	;
    
    %%

    Configuration.cs

    最后是Configuration.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.VisualStudio.Package;
    using Babel.Parser;
    using Microsoft.VisualStudio.TextManager.Interop;
    
    namespace Babel
    {
        public static partial class Configuration
        {
            public const string Name = "Simple LS";
            public const string Extension = ".sls";
    
            static CommentInfo myCInfo;
            public static CommentInfo MyCommentInfo { get { return myCInfo; } }
    
            static Configuration()
            {
                myCInfo.BlockEnd = "*/";
                myCInfo.BlockStart = "/*";
                myCInfo.LineStart = "??";
                myCInfo.UseLineComments = false;
    
                // default colors - currently, these need to be declared
                TokenColor Number = CreateColor("SLS-Number", COLORINDEX.CI_BLUE, COLORINDEX.CI_USERTEXT_BK);
                TokenColor Capletter = CreateColor("SLS-CAPletter", COLORINDEX.CI_RED, COLORINDEX.CI_USERTEXT_BK);
                TokenColor Lowletter = CreateColor("SLS-Lowletter", COLORINDEX.CI_PURPLE, COLORINDEX.CI_USERTEXT_BK);
    
                //
                // map tokens to color classes
                //
                ColorToken((int)Tokens.NUMBER, TokenType.Keyword, Number, TokenTriggers.None);
                ColorToken((int)Tokens.CAPLETTER, TokenType.Keyword, Capletter, TokenTriggers.None);
                ColorToken((int)Tokens.LOWLETTER, TokenType.Keyword, Lowletter, TokenTriggers.None);
            }
        }
    }

    重置实验室,运行

    在编译运行前,我们先重置一下“实验室”。在开始菜单,SDK目录下找到Reset the Microsoft Visual Studio 2008 SP1 Experimental hive这个工具,单击。弹出一个控制台:

    image这表示此时正在修改“实验室”环境的相关注册表值,以把实验室恢复到初始状态。当控制台关闭后,表示恢复结束,这可能要花上一些时间。之所以要这样做,是为了演示我们在Configuration中创建的TokenColor是如何在Fonts and Colors中工作的。

    再次ReBuild,然后F5,可以看到“实验室”也会像真实的VS一样重新要求用户选择首选语言。打开一个.sls文件,是不是我们预期的效果呢?很好,接下来,看看Tool->Option,定位到Fonts and Colors:

    image

    如图:看到Display Items中多了三个选择:"SLS-Number"、"SLS-Lowletter"、"SLS-CAPletter",试试看修改它们的Item foreground呢?是不是看到相应的文本颜色也改变了呢?很好。我记得在前面的文章中提到过这个问题,这是个很棒的特性!秘密在下面三行代码:

                TokenColor Number = CreateColor("SLS-Number", COLORINDEX.CI_BLUE, COLORINDEX.CI_USERTEXT_BK);
                TokenColor Capletter = CreateColor("SLS-CAPletter", COLORINDEX.CI_RED, COLORINDEX.CI_USERTEXT_BK);
                TokenColor Lowletter = CreateColor("SLS-Lowletter", COLORINDEX.CI_PURPLE, COLORINDEX.CI_USERTEXT_BK);

    CreateColor实际上创建了一个IVsColorableItem的对象,多个CreateColor也就创建了多个IVsColorableItem,IDE在运行时通过调用GetColorableItem和GetItemCount来获得用户定义的IVsColorableItem对象集,并将它们集成到Fonts and Colors里面。但是必须重置一个注册表才行,MSDN是这样解释原因的:

    If you change the name of one of your colors during development, you must reset the cache that Visual Studio created the first time your colors were accessed. You can do so by running the Reset the Visual Studio 2005 Experimental hive command from the Visual Studio SDK shortcut menu.

    想要进一步了解,请读者自己阅读BabelConfiguration中的代码。

    小结

    到这里,我想各位最为困惑的便是lexerparser到底是什么了,我打算在下一篇开始重点阐述它们,因为它们太重要了,而且对于大多数人来说又太陌生,不得不单独拿出来。目前,我对它们还没有完全100%弄懂,而且,在我之前的经历中,我也没有从事过解析器或编译器的开发工作,刚开始也是困惑了许久。

    本篇我只是简单的把lex和parser的代码展示了出来,可以说这是最为简单的代码了。希望读者现在已经能够成功的调试出这个例子,这个例子的源代码可以从这个地址下载:

    https://files.cnblogs.com/P_Chou/SimpleLSHost.zip

  • 相关阅读:
    02_Jquery_02_元素选择器
    02_Jquery_01_id选择器
    01_JavaMail_05_创建邮件工具类MailUtils等方便发送邮件
    01_JavaMail_04_带附件邮件的发送
    01_JavaMail_03_邮件发送简单实例
    01_JavaMail_02_Base64加密
    01_JavaMail_01_邮件服务器简述
    15_动态SQL
    django 导出xls文件
    django 解析上传xls文件
  • 原文地址:https://www.cnblogs.com/P_Chou/p/1739167.html
Copyright © 2011-2022 走看看