是否有一种(简单的)方法来修改某些特定编程语言的语法?
Is there a (simple) way to modify the syntax of some particular programming language?
这个问题可能很幼稚,所以请随时要求我澄清。我是从数学背景进入计算机科学的,所以人们一直告诉我像 Haskell 这样的函数式编程语言对我来说会很自然,但我发现很多语言(不仅仅是函数式语言)的语法非常丑陋且不直观。
在Haskell中,举个小例子,类型声明写成::
,例如
str :: String
str = "Hello, World!"
我有什么方法可以修改我自己系统中的语法,以便 ::
的功能可以由其他东西执行,比如 :::
,或者 ;;
,或者更好的是 :is_a:
,这样我就可以执行与上面相同的功能:
str ::: String
str = "Hello, World!"
需要说明的是,如果我修改系统中的语法,我并不担心任何关于共享代码困难的实用问题;我只是想知道理论上是否可以修改编程语言的基本语法,如果可以,如何修改。
请随时修改标签,或要求澄清。
重新定义编程语言的语法是绝对有可能的。在这种情况下,您正在做的是发明一种新的编程语言,它具有与原始语言相同的功能,但语言结构的语法不同。
这不是一件很简单的事情,但有两种可能的方法:
预处理器/翻译器
您可以编写一个程序来读取新语法中的文件,对其进行解析,然后将其翻译成具有原始语言的文件。到那时就可以使用原来的编译器/解释器了。
这种方法的主要优点是您只需要提供翻译。其他一切都可以重复使用。
主要缺点是您仍然会有大多数错误消息(例如类型错误)指向翻译,并提及原始语言的语法。您也许可以将它们翻译回来,但这取决于语法的不同程度。
分叉语言实现
没有什么能阻止您下载 GHC 源代码(或 GCC,或...)并修改其解析器和漂亮的打印机以使用新语法。您必须在大量文件中找到合适的位置进行修改,但这是可以做到的。
这里的主要缺点是每当发布新版本的 GHC 时,您都必须重新合并您的更改,或者坚持使用旧版本。
结论
拥有良好的语法固然很好,但并不那么重要。现在PL理论的研究者从不讨论句法问题,只讨论语义问题:新特性、新类型、新优化等等。
如果您愿意,可以随意修改任何语言的语法。它可以是一个有趣的项目——一种挑战自己理解大型代码库的方式,足以在这里或那里进行一些小改动。但是请记住,其他人很可能不想阅读用您自己的语法编写的代码:周围已经有这么多语言,为一种已知语言学习新语法可以被视为浪费精力,可以用来学习一些真正新的东西。
一个非常广泛的主题,您可能会在 Stack Exchange 的软件工程和计算机科学论坛中获得更详细的答案。不过我会尽量给一些指点。
显然我不知道你从数学到编程的程度有多远,所以如果这个答案的部分内容对你来说很明显,请多多包涵。
如果您不考虑在程序员之间交换源代码的需要(实际上 if 很大),您可以定义任何您想要的编程语言语法,...提供您的语法定义一致。麻烦的是,保证语言的一致性一点都不简单。
这意味着:您必须能够以某种方式生成一个可执行的 parser 程序,该程序可以读取使用您漂亮的新语法编写的源代码,并生成一个 语法树。机器代码生成and/or直接解释执行从语法树开始
现在是 21 世纪,您拥有 Yacc/Bison and Lex/Flex 等软件工具,可以为您编写实际的解析器代码,从 you 提供的一些高级语法描述开始,通常接近 Backus-Naur 形式 (BNF)。
解析器本质上是一个基于堆栈的自动机。现在,如果您的新语法有 any 的可能性在某处有歧义,您的解析器生成器工具将不会生成基于堆栈的自动机的可编译描述。相反,它会输出一些部分不清楚的错误消息,例如 shift-reduce conflict at line 413 。根据我对工作语言设计师的有限了解,他们花了很多时间来解决语法中的 shift-reduce 冲突。
例如,您说您可能想为“;;”分配一些语义值。但是 Haskell 与许多其他编程语言一样,为单个分号分配既定值。它是一个指令终止符。如何确保我们避免在该级别出现任何和所有歧义?通过解析器生成工具获取 BNF。这是唯一的方法。
更多详情here. The best way to understand the problem in some depth is to create a parser for some mini-language. You can use either the classic Bison/Flex toolkit, which was produced in the realm of traditional imperative languages. Or you can use one of the Haskell specific tools, such as for example Megaparsec。
话虽如此,您似乎感觉到的部分丑陋可能是由于历史上只使用 ASCII 字符的必要性造成的,因为在过去这是源代码交换的要求。要写 不等于 ,Fortran 使用 .NE。因为没有 Unicode,因此没有“≠”字符。大约公元 1975 年,C 语言的设计者面临同样的问题,他们更喜欢使用“!=”。
Haskell,在公元 2020 年的先锋,仍然默认使用单个普通的 ASCII 点 '.'用于函数组合,而不是数学文本中使用的适当“∘”字符。修复它可能需要很长时间。
这个问题可能很幼稚,所以请随时要求我澄清。我是从数学背景进入计算机科学的,所以人们一直告诉我像 Haskell 这样的函数式编程语言对我来说会很自然,但我发现很多语言(不仅仅是函数式语言)的语法非常丑陋且不直观。
在Haskell中,举个小例子,类型声明写成::
,例如
str :: String
str = "Hello, World!"
我有什么方法可以修改我自己系统中的语法,以便 ::
的功能可以由其他东西执行,比如 :::
,或者 ;;
,或者更好的是 :is_a:
,这样我就可以执行与上面相同的功能:
str ::: String
str = "Hello, World!"
需要说明的是,如果我修改系统中的语法,我并不担心任何关于共享代码困难的实用问题;我只是想知道理论上是否可以修改编程语言的基本语法,如果可以,如何修改。
请随时修改标签,或要求澄清。
重新定义编程语言的语法是绝对有可能的。在这种情况下,您正在做的是发明一种新的编程语言,它具有与原始语言相同的功能,但语言结构的语法不同。
这不是一件很简单的事情,但有两种可能的方法:
预处理器/翻译器
您可以编写一个程序来读取新语法中的文件,对其进行解析,然后将其翻译成具有原始语言的文件。到那时就可以使用原来的编译器/解释器了。
这种方法的主要优点是您只需要提供翻译。其他一切都可以重复使用。
主要缺点是您仍然会有大多数错误消息(例如类型错误)指向翻译,并提及原始语言的语法。您也许可以将它们翻译回来,但这取决于语法的不同程度。
分叉语言实现
没有什么能阻止您下载 GHC 源代码(或 GCC,或...)并修改其解析器和漂亮的打印机以使用新语法。您必须在大量文件中找到合适的位置进行修改,但这是可以做到的。
这里的主要缺点是每当发布新版本的 GHC 时,您都必须重新合并您的更改,或者坚持使用旧版本。
结论
拥有良好的语法固然很好,但并不那么重要。现在PL理论的研究者从不讨论句法问题,只讨论语义问题:新特性、新类型、新优化等等。
如果您愿意,可以随意修改任何语言的语法。它可以是一个有趣的项目——一种挑战自己理解大型代码库的方式,足以在这里或那里进行一些小改动。但是请记住,其他人很可能不想阅读用您自己的语法编写的代码:周围已经有这么多语言,为一种已知语言学习新语法可以被视为浪费精力,可以用来学习一些真正新的东西。
一个非常广泛的主题,您可能会在 Stack Exchange 的软件工程和计算机科学论坛中获得更详细的答案。不过我会尽量给一些指点。
显然我不知道你从数学到编程的程度有多远,所以如果这个答案的部分内容对你来说很明显,请多多包涵。
如果您不考虑在程序员之间交换源代码的需要(实际上 if 很大),您可以定义任何您想要的编程语言语法,...提供您的语法定义一致。麻烦的是,保证语言的一致性一点都不简单。
这意味着:您必须能够以某种方式生成一个可执行的 parser 程序,该程序可以读取使用您漂亮的新语法编写的源代码,并生成一个 语法树。机器代码生成and/or直接解释执行从语法树开始
现在是 21 世纪,您拥有 Yacc/Bison and Lex/Flex 等软件工具,可以为您编写实际的解析器代码,从 you 提供的一些高级语法描述开始,通常接近 Backus-Naur 形式 (BNF)。
解析器本质上是一个基于堆栈的自动机。现在,如果您的新语法有 any 的可能性在某处有歧义,您的解析器生成器工具将不会生成基于堆栈的自动机的可编译描述。相反,它会输出一些部分不清楚的错误消息,例如 shift-reduce conflict at line 413 。根据我对工作语言设计师的有限了解,他们花了很多时间来解决语法中的 shift-reduce 冲突。
例如,您说您可能想为“;;”分配一些语义值。但是 Haskell 与许多其他编程语言一样,为单个分号分配既定值。它是一个指令终止符。如何确保我们避免在该级别出现任何和所有歧义?通过解析器生成工具获取 BNF。这是唯一的方法。
更多详情here. The best way to understand the problem in some depth is to create a parser for some mini-language. You can use either the classic Bison/Flex toolkit, which was produced in the realm of traditional imperative languages. Or you can use one of the Haskell specific tools, such as for example Megaparsec。
话虽如此,您似乎感觉到的部分丑陋可能是由于历史上只使用 ASCII 字符的必要性造成的,因为在过去这是源代码交换的要求。要写 不等于 ,Fortran 使用 .NE。因为没有 Unicode,因此没有“≠”字符。大约公元 1975 年,C 语言的设计者面临同样的问题,他们更喜欢使用“!=”。
Haskell,在公元 2020 年的先锋,仍然默认使用单个普通的 ASCII 点 '.'用于函数组合,而不是数学文本中使用的适当“∘”字符。修复它可能需要很长时间。