【问题标题】:How is newline handled in whitespace sensitive languages?空格敏感语言如何处理换行符?
【发布时间】:2021-11-09 19:24:48
【问题描述】:

我最近研究并构建了一个玩具 java 编译器,它在解析阶段之前丢弃所有注释标记和空白标记。但是,我很好奇对空格敏感的语言(例如 Python 和 Swift)如何处理换行符。这些语言以语句的换行符结尾,因此不能简单地丢弃换行符。但是他们如何处理下面的情况呢?

foo(
    bar
) 

他们必须为此编写大量语法案例吗?比如foo ( bar )foo NEWLINE ( bar NEWLINE )等等?

在我构建的 java 编译器中,这是通过消除换行符来处理的,它们都变成了foo ( bar )。但是这在空格敏感的语言中是如何处理的呢?

【问题讨论】:

  • 您可能需要查看解析器源代码才能找到答案。对于 Swift:词法分析器:github.com/apple/swift/blob/…,解析器:github.com/apple/swift/blob/…
  • 一般来说,虽然我认为没有人愿意在他们的作品中维护所有可能的 NEWLINE 终端组合,所以我想他们要么使用一些预处理步骤(如自动分号插入),要么以某种方式在词法分析器级别处理它.

标签: parsing compiler-construction


【解决方案1】:

由于没有人回答,我又做了一轮谷歌搜索,找到了this blog。根据它,Python 为括号 ()[] 维护一个堆栈,如果括号不完整,则忽略换行符。这样就可以实现了:

foo(
    bar
)

此外,对于空行或只有 cmets 的行,也会跳过换行符。或者当换行符被转义时,不会生成换行符。这样就实现了

# comment only
             # only spaces
foo(\        # escaped
    bar\
)            

否则,分词器将生成一个 NEWLINE 令牌。

博客还给我指出了源代码tokenizer.c,我在line 1660找到了上面的逻辑。

至于其他语言,我不确定,但我认为堆栈策略足够通用,可以被所有语言采用。

【讨论】:

  • 其他一些语言也允许你写a + <NEWLINE> b 或者在某些情况下甚至a <NEWLINE> + b 而不转义换行符。开括号规则不会涵盖这一点。
  • 没错。方括号规则不能保证这一点,这就是 Python 不支持它的原因。至于其他语言,我也愿意学习。如果我能找到更有用的东西,我会更新答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多