灵活性如何影响语言的语法?

How does flexibility affect a language's syntax?

我目前正在编写我自己的语言 (shameless plug),它以灵活性为中心。我试图通过 extensions/plugins 之类的东西使几乎任何部分的语言语法都可以交换。在写整件事的时候,它让我思考。我想知道这种灵活性会如何影响语言。

我知道 Lisp 由于其广泛的宏系统而经常被称为最可扩展的语言之一。我确实理解宏的概念,但我还没有找到一种允许某人改变它的解析方式的语言。据我所知,几乎每种语言都有一个非常具体的语法,由一些很长的规范定义。

我的问题是灵活的语法如何影响语言的直观性和可用性?我知道基本的 "people might be confused when the syntax changes" 和 "semantic analysis will be hard"。这些是我已经开始弥补的事情。我正在寻找关于使用灵活语法的优缺点的更概念性的答案。

语言设计这个话题对我来说还是很陌生,所以如果我问了一个明显或愚蠢的问题,我深表歉意!

编辑: 我只是想澄清我问的问题。就语言理论而言,语言句法的灵活性到底在哪里?我真的不需要示例或 projects/languages 的灵​​活性,我想了解它如何影响语言的可读性、功能和其他类似的东西。

Perl 是我所知道的最灵活的语言。看看 Moose,一个 Perl 5 的后现代对象系统。它的语法与 Perl 的非常不同,但它仍然非常 Perl-ish。

IMO,灵活性的最大问题是中缀表示法的优先级。但是 none 我知道允许数据类型有自己的中缀语法。例如,拿套。在它们的语法中使用 会很好。但编译器不仅必须识别这些符号,还必须告知它们的优先顺序。

Common Lisp 允许更改它的解析方式 - 请参阅 reader 宏。 Racket 允许修改其解析器,请参阅球拍语言。

当然,如果您使用正确的解析技术(例如,PEG),您可以获得灵活的、动态可扩展的解析以及强大的宏。在此处查看 example - 主要是 C 语法,但可以使用语法和语义宏进行扩展。

至于优先级,PEG 与 Pratt 配合得非常好。

回答您更新的问题 - 令人惊讶的是,关于编程语言可读性的研究很少。你可能想看看 Dr. Blackwell 小组 was up to,但还远没有定论。

所以我只能分享我手把手的轶事——灵活的语法语言促进了eDSL的构建,而且在我看来,eDSL是唯一可以从代码中消除不必要的复杂性,使代码真正可长期维护的方法.我认为不灵活的语言是这个行业犯下的最大错误之一,必须不惜一切代价尽快纠正。

灵活性允许您操纵语言的语法。例如,Lisp Macros 可以让你编写程序,将程序和操作你的语法 compile-time 到有效的 Lisp 表达式。例如循环宏:

(loop for x from 1 to 5
      do(format t "~A~%" x))

1
2
3
4
5
NIL

我们可以看到代码是如何用 macroexpand-1 翻译的:

(pprint(macroexpand-1 '(loop for x from 1 to 5
                 do (format t "~a~%" x))))

然后我们可以看到对该宏的调用是如何翻译的:

  (LET ((X 1))
(DECLARE (TYPE (AND REAL NUMBER) X))
(TAGBODY
 SB-LOOP::NEXT-LOOP
  (WHEN (> X '5) (GO SB-LOOP::END-LOOP))
  (FORMAT T "~a~%" X)
  (SB-LOOP::LOOP-DESETQ X (1+ X))
  (GO SB-LOOP::NEXT-LOOP)
 SB-LOOP::END-LOOP)))

Language Flexibility 只允许您在一种语言中创建自己的嵌入式语言,并根据使用的字符减少程序的长度。所以从理论上讲,这会使一种语言非常难读,因为我们可以操纵语法。例如,我们可以创建转换为有效代码的无效代码:

(defmacro backwards (expr)
   (reverse expr))
BACKWARDS
CL-USER> (backwards ("hello world" nil format))
"hello world"
CL-USER> 

显然上面的代码会变得复杂,因为:

 ("hello world" nil format)

不是有效的 Lisp 表达式。

感谢 的回答为我指明了 Alan Blackwell 的方向。我给他发了一封电子邮件,询问他对此事的立场,他给出了一个绝妙的解释。这是:

So the person who responded to your Whosebug question, saying that flexible syntax could be useful for DSLs, is certainly correct. It actually used to be fairly common to use the C preprocessor to create alternative syntax (that would be turned into regular syntax in an initial compile phase). A lot of the early esolangs were built this way.

In practice, I think we would have to say that a lot of DSLs are implemented as libraries within regular programming languages, and that the library design is far more significant than the syntax. There may be more purpose for having variety in visual languages, but making customisable general purpose compilers for arbitrary graphical syntax is really hard - much worse than changing text syntax features.

There may well be interesting things that your design could enable, so I wouldn’t discourage experimentation. However, I think there is one reason why customisable syntax is not so common. This is related to the famous programmer’s editor EMACS. In EMACS, everything is customisable - all key bindings, and all editor functions. It’s fun to play with, and back in the day, many of us made our own personalised version that only we knew how to operate. But it turned out that it was a real hassle that everyone’s editor worked completely differently. You could never lean over and make suggestions on another person’s session, and teams always had to know who was logged in order to know whether the editor would work. So it turned out that, over the years, we all just started to use the default distribution and key bindings, which made things easier for everyone.

此时此刻,我所寻找的解释已经足够了。如果有人觉得他们有更好的解释或要补充的东西,请随时与我联系。