语法高亮/词法分析算法

Posted

技术标签:

【中文标题】语法高亮/词法分析算法【英文标题】:Syntax Highlighting / Lexical analysis Algorithms 【发布时间】:2011-10-08 03:51:30 【问题描述】:

语法高亮使用的一般算法是什么?我在正则表达式中使用交替实现了一个简单的方法:

STRING_PATTERN|COMMENT_PATTERN|KEYWORD_PATTERNS

因为检测某个东西是字符串还是模式取决于哪个先出现:

// This is a "comment"

"This is a // string"

但是使用关键字会变得有点复杂。这种方法在我当前的实现中有效,但我不相信它是最佳的。

另一个问题是您突出显示的顺序。如果您在标识符/关键字之前突出显示数字,那么您可能会不小心突出显示关键字中的数字...

编辑:

我的插件现在在这里:http://wordpress.org/extend/plugins/crayon-syntax-highlighter/

【问题讨论】:

【参考方案1】:

你可能很难用正则表达式来做到这一点,因为它不能帮助你的语法突出显示理解上下文,即一个正则表达式会匹配出现在任何地方的东西,不管它是否是更大的可能匹配的一部分。

您需要研究诸如 Antlr 之类的解析器生成器 - 给定一个有效的、明确的语法 - 能够为您提供将这些细节考虑在内的令牌。例如。如果评论被定义为“//”直到 EOL,它将返回一个评论令牌,它将取代任何字符串字符或其中的任何内容。

像这样的解析器的标准方法是一次读取一个字符流(或更具体地说是标记),因此突出显示不取决于您定义的规则的顺序,而是它们在流。

例如,一个字符串可以是两个双引号以及介于两者之间的所有内容(另一个双引号除外)。注释是两个斜杠以及直到行尾的所有内容。

在解析时,如果你找到一个双引号,那么你的程序会进入“我认为它是一个字符串”模式,一旦它找到匹配的结束引号,它就会确认一个字符串标记,并返回它以突出显示。类似地,如果它找到两个斜杠,则搜索直到找到一个行尾(实际上是文件尾),然后将其作为突出显示的标记返回。

当有多个可能的匹配规则时,它会变得更加复杂,例如用于单线和多线 cmets。如果你抓取一个斜杠字符,你的程序需要读取另一个字符才能拒绝其中的一些选项,即直到它获得第二个斜杠或 * 然后它才会知道它是什么类型的标记。

从根本上说,这一切都归结为状态机。你可以尝试构建自己的,或者你可以得到像 Antlr 这样的东西,给它一个语法,让它为你完成所有的工作。

【讨论】:

我的方法适用于您提到的先出现的内容,因为发生的交替是最先出现的,例如 OR 语句。我想我会尝试自己制作一个,毕竟这就是我在制作语法荧光笔时要做的事情。正则表达式也处理您解释的所有逻辑,例如考虑字符串的内容。用同样的方式做多行 cmets 和 strings 很容易。我的问题不是关于如何找到标记的出现,而是一旦找到它们后如何处理它们。我想我会努力的。 啊,好的,我明白你在问什么。同样,您将面临的问题是您有一个正在寻找令牌的正则表达式,并且相同的正则表达式将返回匹配项,但它不会告诉您您收到了哪种令牌。如果您想继续尝试正则表达式方法,您可以查看命名组(不过,这通常是特定于平台的语法,并且某些语言,例如 Java 甚至不支持它)。如果正则表达式可以告诉您它与哪个命名组匹配,那么您可以使用该名称来查找包含突出显示格式规则的表(例如“关键字”->粗体)。 此外,尽管它们使用语法方法来进行词法分析/解析,但您可以查看 Eclipse 和 XText API 以了解它们如何处理语法突出显示。理解起来并不容易,但它可能会给你一些关于解析和突出显示之间干净、结构分离的想法。 谢谢克里斯,我已经成功实现了分组方法,所以我想我会去的。很简单,一旦找到token就不需要复杂的逻辑了。

以上是关于语法高亮/词法分析算法的主要内容,如果未能解决你的问题,请参考以下文章

用于 AspectJ 的 Pygments 词法分析器

一个C#语法高亮插件

有没有人遇到过在 iterm2 下 vim 语法高亮的问题

EditPlus语法高亮

VIM语法高亮在保存文件后消失是怎么回事?

设法使UltraEdit支持python语法高亮