在以下c++文本上运行pygments默认词法分析器:class foo{};,结果是:

(Token.Keyword, 'class')
(Token.Text, ' ')
(Token.Name.Class, 'foo')
(Token.Punctuation, '{')
(Token.Punctuation, '}')
(Token.Punctuation, ';')

请注意,代币foo的类型为Token.Name.Class

如果我将类名更改为foobar,我希望仅对触摸的 token (在本例中为原始 token foo{)运行默认词法分析器。

问:如何保存词法分析器状态,以便标记化foobar{将给出类型为Token.Name.Class的标记?

例如,拥有此功能可以优化大型中间文件的语法突出显示,这些大型原始文件在文件中间就发生了更改(用户正在输入文本)。似乎没有记录的执行此操作的方法,也没有有关使用默认pygments lexers如何执行此操作的信息。

是否有其他语法突出显示系统支持此行为?

编辑:

关于性能,这里是一个示例:http://tpcg.io/ESYjiF

最佳答案

根据我对源代码的理解,您想要的是不可能的。

我不会挖掘并尝试解释每一个相关的代码行,但是基本上,这是发生的事情:

  • 您的Lexer类是 pygments.lexers.c_cpp.CLexer ,它是从 pygments.lexer.RegexLexer 继承的。
  • pygments.lex(lexer, code) 函数只不过对get_tokens调用lexer方法并处理错误而已。
  • lexer.get_tokens 基本上解析unicode字符串中的源代码并调用self.get_tokens_unprocessed
  • get_tokens_unprocessed 由每个Lexer定义,在您的情况下,相关方法是 pygments.lexers.c_cpp.CFamilyLexer.get_tokens_unprocessed
  • CFamilyLexer.get_tokens_unprocessed 基本上从 RegexLexer.get_tokens_unprocessed 获得 token 并重新处理其中的一些 token 。

  • 最后, RegexLexer.get_tokens_unprocessed 在定义的 token 类型(类似于(("function", ('pattern-to-find-c-function',)), ("class", ('function-to-find-c-class',))))上循环,并针对每种类型(functionclasscomment ...)查找源文本中的所有匹配项,然后处理下一个类型。

    此行为使您想要的成为不可能,因为它在 token 类型而不是文本上循环。

    为了使我的观点更加清楚,我在lib中添加了两行代码file: pygments/lexer.py , line: 628
    for rexmatch, action, new_state in statetokens:
        print('looking for {}'.format(action))
        m = rexmatch(text, pos)
        print('found: {}'.format(m))
    

    并使用以下代码运行它:
    import pygments
    import pygments.lexers
    
    lexer = pygments.lexers.get_lexer_for_filename("foo.h")
    sample="""
    class foo{};
    """
    print(list(lexer.get_tokens(sample)))
    

    输出:
    [...]
    looking for Token.Keyword.Reserved
    found: None
    looking for Token.Name.Builtin
    found: None
    looking for <function bygroups.<locals>.callback at 0x7fb1f29b52f0>
    found: None
    looking for Token.Name
    found: <_sre.SRE_Match object; span=(6, 9), match='foo'>
    [...]
    

    如您所见, token 类型是代码迭代的对象。

    考虑到这一点(以及Tarun Lalwani在评论中说的),即一个新字符可以破坏整个源代码结构这一事实,您要做的工作莫过于在每次更新时重新整理整个文本。

    10-06 09:24