语法高亮/词法分析算法
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就不需要复杂的逻辑了。以上是关于语法高亮/词法分析算法的主要内容,如果未能解决你的问题,请参考以下文章