语法高亮的编程语言是否可能使用正则表达式?

Nik*_*nko 11 regex parsing syntax-highlighting

我们现在都知道,使用正则表达式解析HTML通常是不可能的,因为它正在解析上下文敏感的语法,而正则表达式只能解析常规语法.其他编程语言也是如此.

现在,最近,Rainbow.js语法荧光笔已经公布.它的前提被描述为非常简单:

彩虹本身很简单.它遍历代码块,处理正则表达式模式,并在标记中包装匹配模式.

我认为语法突出显然本质上是一个与语言解析相同的复杂任务,如果我们假设它必须既好又适合多种语言.尽管如此,虽然对该库有相当多的批评,但黑客新闻的讨论(作为技术倾向的讨论的例子)都没有提到使用正则表达式突出语法在一般情况下基本上是不可能的,我会考虑一个主要的,显示停止的缺陷.

现在的问题是:有什么我想念的吗?特别是:

  1. 一般来说,使用正则表达式突出显示语法吗?
  2. 这是一个应用80/20规则的实例,正则表达式是否足够有用?

A.H*_*.H. 13

使用regexp突出显示语法是一门古老的艺术.我想甚至Emacs和vi也是这样开始的.

我认为语法高亮本质上是一个与语言解析相同的复杂任务,[...]

不可以.不同之处在于:编译器需要真正的解析,因为他需要理解完整的程序,还需要根据这种理解生成东西.另一方面,语法突出显示不需要理解代码.它只需要理解语言的一般结构 - 什么是字符串文字 - 什么是关键字......等等.这种差异的副作用是:您可以突出显示语法不正确的代码,但无法解析它.

稍微不同的方法:解析语言通常需要两个步骤:lexing(将字节流拆分为"令牌"流)和真正的解析(将令牌流带入一些复杂的结构 - 通常是抽象语法树).Lexing通常使用----正则表达式完成.请参阅flex文档.这基本上都是荧光笔需要理解的基本语法.

当然还有一些角落案例,单靠regexp无法捕获.一个典型的例子是:

foo(bla, bar);
Run Code Online (Sandbox Code Playgroud)

foo可能是对静态方法或实例方法或宏或其他内容的调用.但你的正则表达式荧光笔无法推断出这一点.它只能为"一般呼叫"添加颜色.

所以:如果你的要求是低级的(即没有上面的例子),那么这是一个100/0%的规则,对于现实世界的东西通常是90/10规则.


Li-*_*Yip 3

作为解决方案的一部分,您可以使用正则表达式进行语法突出显示。更具体地说,作为“词法分析器”的一部分,将输入文本分块为符号。这实际上是大多数编译器/解释器的工作方式。

然而,单独使用正则表达式来做到这一点是自找麻烦。考虑在 Python 中匹配字符串的情况。'Python 允许用单引号或双引号分隔字符串"。此外,它允许使用三引号'''""".

那么下面的哪些部分是字符串,哪些不是?你能构造一个正确识别字符串文字str1-的正则表达式吗str6

    str1 = "hello, world!"

    str2 = 'hello, world!'

    str3 = "The canonical test program is 'Hello World'."

    str4 = '"Why," Peter said, "That\'s ludicrous. Who would do that?"'

    str5 = """The heredoc syntax is handy for cases where you don't want to escape strings. "Very convenient."
    """

    str6 = """Code sample:
    s1 = "hi!"
    s2 = 'Hi!'
    S3 = '''
    - apples
    - oranges
    - bananas
    '''
    """
Run Code Online (Sandbox Code Playgroud)

“你不能用正则表达式(解析 HTML | 处理程序),因为(HTML | 编程语言)具有嵌套结构 - 它们不是正则”的说法并不完全正确 - 现代正则表达式(特别是在 Perl 中)有更多表达能力高于计算机科学意义上的严格正则表达式。但仅仅因为您可以使用正则表达式并不意味着您应该使用正则表达式。


编辑:如果您的正则表达式风格支持搜索模式中的反向引用,那么上面的字符串匹配问题并不算太糟糕。像这样的多行正则表达式('|"|'''|""").+?\1可能就可以了。


编辑 2:有关语法高亮中的极端情况的示例,只需查看上面代码的 StackOverflow 语法高亮即可。