用于 AspectJ 的 Pygments 词法分析器

Posted

技术标签:

【中文标题】用于 AspectJ 的 Pygments 词法分析器【英文标题】:Pygments lexer for AspectJ 【发布时间】:2012-07-26 13:28:38 【问题描述】:

我刚刚询问了 GitHub 上的支持人员,为什么 AspectJ (*.aj) 文件没有语法高亮显示。答案是他们正在使用 Pygments,但不知道任何现有的 AspectJ 词法分析器。我做了一个快速的网络搜索,也没有找到任何东西。有没有人在这里写过或者可以给我一个现有链接的链接?

很久以前,我为 Kconfig(Linux 内核配置)文件编写了一个词法分析器,但对我来说相当困难,因为我不会说 Python。所以在我再次开始折磨我的大脑之前,我认为我应该先问清楚,而不是重新发明***。

【问题讨论】:

【参考方案1】:

在创建了 JavaLexer 的“复制、粘贴和修改”解决方案后,因为我真的不会说 Python,我设法破解了另一个 quick'n'dirty 解决方案,它继承了 JavaLexer 的子类并将词法分析委托给它大部分。例外是

AspectJ 特定的关键字, 处理类型间声明后跟不带空格的冒号不是作为 Java 标签,而是作为 AspectJ 关键字加上“:”运算符和 将类型间注释声明作为 AspectJ 关键字处理,而不是作为 Java 名称装饰器。

我确信我的小启发式解决方案遗漏了一些细节,但正如 Andrew Eisenberg 所说:一个不完美但可行的解决方案比一个不存在的完美解决方案要好:

class AspectJLexer(JavaLexer):
    """
    For `AspectJ <http://www.eclipse.org/aspectj/>`_ source code.
    """

    name = 'AspectJ'
    aliases = ['aspectj']
    filenames = ['*.aj']
    mimetypes = ['text/x-aspectj']

    aj_keywords = [
        'aspect', 'pointcut', 'privileged', 'call', 'execution',
        'initialization', 'preinitialization', 'handler', 'get', 'set',
        'staticinitialization', 'target', 'args', 'within', 'withincode',
        'cflow', 'cflowbelow', 'annotation', 'before', 'after', 'around',
        'proceed', 'throwing', 'returning', 'adviceexecution', 'declare',
        'parents', 'warning', 'error', 'soft', 'precedence', 'thisJoinPoint',
        'thisJoinPointStaticPart', 'thisEnclosingJoinPointStaticPart',
        'issingleton', 'perthis', 'pertarget', 'percflow', 'percflowbelow',
        'pertypewithin', 'lock', 'unlock', 'thisAspectInstance'
    ]
    aj_inter_type = ['parents:', 'warning:', 'error:', 'soft:', 'precedence:']
    aj_inter_type_annotation = ['@type', '@method', '@constructor', '@field']

    def get_tokens_unprocessed(self, text):
        for index, token, value in JavaLexer.get_tokens_unprocessed(self, text):
            if token is Name and value in self.aj_keywords:
                yield index, Keyword, value
            elif token is Name.Label and value in self.aj_inter_type:
                yield index, Keyword, value[:-1]
                yield index, Operator, value[-1]
            elif token is Name.Decorator and value in self.aj_inter_type_annotation:
                yield index, Keyword, value
            else:
                yield index, token, value

【讨论】:

我为此代码创建了一个 Pygments fork + pull request。 更新:我的词法分析器的拉取请求已被接受,因此预计在下一版本的 Pygments 中会突出显示 AspectJ。 :)【参考方案2】:

如果您从 Java 词法分析器开始,aspectj 的语法高亮应该很容易实现。词法分析器将与 Java 相同,但有一些额外的关键字。

有关 AspectJ 特定关键字的列表,请参见此处: http://git.eclipse.org/c/ajdt/org.eclipse.ajdt.git/tree/org.eclipse.ajdt.core/src/org/eclipse/ajdt/core/AspectJPlugin.java

这里是 Java 关键字: http://git.eclipse.org/c/ajdt/org.eclipse.ajdt.git/tree/org.eclipse.ajdt.ui/src/org/eclipse/ajdt/internal/ui/editor/AspectJCodeScanner.java

【讨论】:

语法高亮不仅仅是过滤关键字。 AspectJ 具有用于切入点和建议的特殊语法。但是您的链接是一个好的开始,因为我同意仅通过几个关键字扩展 Java 词法分析器的启发式、不完美的词法分析器总比没有好。所以我有空的时候可能会试一试。感谢您的链接。 P.S.:知道您是 AJDT 提交者,我无意向您讲授 AspectJ 语法。你比我清楚得多。 ;-) 简单和足够好比完美和不存在要好得多。即使只是复制 Java 词法分析器而不做任何更改也总比没有好。仅使用词法分析器,您只能做很多事情。为了让事情变得完美,你需要一个完整的解析器。 我刚刚做到了。这很简单,看起来不错。我把结果发给了 GitHub 的人。稍后我可能还会为 Pygments 维护者创建一个 fork + pull 请求。 这有点过时了,但是在查看您的课程AspectJCodeScanner 时,我注意到您将@type@method@field 列为关键字,但没有@constructor。这是一个错误还是你故意这样做的? 哈!不错的收获。这段代码在我到达 AJDT 之前就已经写好了,我从来没有注意到它。鉴于没有人对此提出错误,我认为@constructor 的使用并不频繁。

以上是关于用于 AspectJ 的 Pygments 词法分析器的主要内容,如果未能解决你的问题,请参考以下文章

将 pygments 词法分析器与 antl python 目标一起使用

如何在 pygments 中安装新的词法分析器?

在 Trac 中使用没有 mime 类型的 Pygments 词法分析器?

将字符串流式传输到 pygments 词法分析器?

lexer 正则表达式 pygments g-code

简单的 CSV 词法分析器