什么是编程语言?是什么使我们能够用这种语言书写?


26

好吧,我是编程新手,我承认这是一个相当抽象的问题。

我们每天都会说自然语言,因为人们可以互相理解。计算机如何理解以某种语言编写的代码?

假设A先生创造了一种新语言。机器如何接受呢?创建者是否必须使用机器语言与机器通信以创建新语言?什么能保证我们能在被机器正确理解的同时用一种语言写东西?


1
是什么使我们能够用这种语言书写?- 《大脑:新奇迹的填充物》!-穗米利根。
斯蒂芬·C

6
有点宽泛,但仍然是一个好问题。太多的人只是简单地使用语言而从未想过它们是如何工作的。很好,你很好奇。
riwalk

4
这是一个一般性参考问题,维基百科(Wikipedia)轻松轻松地回答了这个问题。
亚伦诺特,2011年

Answers:


39

您可以使用“ compiler”一词来概括问题的全部答案。编译器是一个特殊的程序,其功能是将源代码作为输入,应用由语言设计者确定的语言规则以弄清楚代码的含义,并以另一种语言产生具有相同含义的代码作为输出。尽管确实存在将代码转换为其他高级语言的专用编译器,但这通常是机器代码或某种形式的字节码(虚拟机的“机器代码”)。但是,它们超出了此问题的范围。

并非所有语言都有编译器。他们中有些人改为使用解释器,该解释器执行与编译器相同的所有操作,除了在确定程序的含义后不生成机器代码,而是立即执行程序。但是,解析(读取)代码并确定其含义的基本原理是相同的。

对此进行更深入的回答将涉及编译器理论,这是一个非常广泛的主题。如果您对该主题感兴趣,则应先阅读Wikipedia文章中的“编译器”并检查其中的链接,如果有特定问题,请随时在此处提问。


11
+1-我还要补充一点,当您编写新语言时,必须使用其他某种语言编写编译器或解释器。然后可以使用该语言的早期版本编写更高版本的编译器或解释器,并使用较早版本的编译器进行编译。最早的汇编器是用机器代码编写的。第一C编译器写在组件(最有可能的)等等
斯科特维特洛克

1
我会更改编译器的定义。它们并不都发出机器代码。尤其是在当今,如此之多的编译器发出“中间代码”,例如MSIL。甚至还有发出JavaScript的编译器!
尼尔N

3
我会犹豫地说,即使是向初学者解释,编译器也会根据定义生成机器代码。这就像说函数返回实数一样,毫无意义的过度简化。生成的代码不是用于实际上是由硅构建的计算机的代码,而是仅抽象定义的(当它是VM还是高级语言时,所有编译器构造都适用),这是有理由说C标准定义了抽象计算机,并且是从非常低级的LLVM IR到friggin'JavaScript 的编译器。初学者需要做到这一点,越早越好。

2
大多数编译器书籍使用的简化是,编译器应用语言规则以将源语言转换为目标语言作为输出。(例如,编译为C并不少见,特别是对于入门课程而言)。
JasonTrue 2011年

4
@delnan,甚至更多-每种语言都是它自己的抽象机的机器代码。无论语言是多么高级。
SK-logic

11

正如您所指出的,人类之间通过“自然”语言进行交流,例如英语,法语,德语。之所以称为自然,是因为我们自然而然地获得了它们,而不是有意发明了它们(世界语是一个例外)。

正式语言是出于某种目的或其他目的而发明的一种语言。例如,诸如C之类的编程语言是出于对计算机进行编程而发明的一种形式语言。

所有语言都可以使用语法来描述。语法层次由Noam Chomsky在1956年描述。它由以下几个层次组成:

0类语法(无限制语法)。它们是最通用的,等效于图灵机。这样,确定给定字符串是否为无限制语法的一部分的问题是无法确定的。

Type-1语法(上下文相关语法)。几乎所有自然语言(例如英语)都是上下文相关的。用英语描述上下文敏感的一个例子是两个短语:“时间像箭一样飞逝”。水果像香蕉一样飞翔。通常,计算机很难理解上下文相关的语言。

类型2语法(无上下文)。上下文无关的语言是大多数编程语言语法的理论基础。

Type-3语法(常规语法)。常规语言家族可以通过正则表达式获得。常规语言通常用于定义搜索模式和编程语言的词汇结构。

类型2(无上下文)和类型3(常规)的语法最常由计算机使用,因为它们的解析器可以得到有效实现。

BNF(Backus范式或Backus–Naur格式)是一种上下文无关语法的表示法,通常用于描述计算语言的语法。

例如,标识符可以描述为:

<identifier> ::= <letter> { <letter> | <digit> }

这意味着它必须以字母开头,并且可以包含其他字母或数字。

之前,字母定义为“ a”。'b'| 'c'等,并且使用相同的符号类型将数字定义为'0'至'9'。

AC“ for”语句可以定义为:

 <for_statement> ::=
    'for' '(' <expression> ';' <expression> ';' <expression> ')' <statement> 

然后构造词法分析器和解析器(编译器或解释器的第一阶段)以接受BNF针对特定语言描述的特定语法。词法分析器通常用于分离语言的各种标记(例如关键字,标识符或数字),而解析器用于确定标记如何协同工作,例如“ for”语句的构造方式。


+1出色的写作。但是我并不感到惊讶,这个答案没有被接受。我以为OP就是在问这个问题,但是基于他们选择的答案,看来他们想要更高的水平。
马修·罗达图斯

5

首先,让我们根据其定义“语言”。语言首先需要一个词汇表(定义作为通信对象的概念的单词列表),然后是语法(定义通信结构的“入门”或一组规则)。

在最基本的水平上,C#与英语没有什么不同。使C#成为“编程语言”的原因在于它的意图,因此也取决于它的设计。它被设计为可消化成单独的低级命令。因此,预定义词汇表受到限制,语法被严格执行,并且整个语言被设计为通过其“受众”(计算机;更准确地说是编译器,它会消化将源代码转换为简单命令的“中间语言”,然后可以通过“运行时”将其进一步转换为机器代码。您不使用C#编写散文或诗歌。您告诉计算机以最明确的方式完成工作。

对于计算机,是的,需要一种工具(通常称为编译器)来获取您在代码中编写的内容,并将其转换为计算机可以使用的指令。像大多数技术一样,计算机科学是一种固有的迭代“分层”过程。首次发明计算机时,是通过手动输入二进制指令对它们进行编程的。这些指令已针对每个处理器标准化为十六进制“机器代码”;区别仅在于二进制数字如何分组显示给人类。然后,在汇编代码中,在编写程序时,命令列表和一些基本标识符(例如寄存器名称)被替换为其十六进制代码。仍然可以将ASM 1:1转换为本机代码。根本的飞跃是第三代“命令式”编程,它基本上采用了人类更易理解的抽象概念,例如变量和逻辑循环,并使用基于关键字和语法的模式将它们消化为本机指令。诸如COBOL,FORTRAN,Pascal和C之类的早期语言仍然可以由人类“翻译”为特定的机器语言(通常为8086 ASM)。然后是面向对象编程的革命,它基本上是附加的语法规则,这些规则将代码定义为概念上封装在具有状态和逻辑某种组合的“对象”中。由人类转换为特定的机器语言(通常为8086 ASM)。然后是面向对象编程的革命,它基本上是附加的语法规则,这些规则将代码定义为概念上封装在具有状态和逻辑某种组合的“对象”中。由人类转换为特定的机器语言(通常为8086 ASM)。然后是面向对象编程的革命,它基本上是附加的语法规则,这些规则将代码定义为概念上封装在具有状态和逻辑某种组合的“对象”中。

如今,我们已经进入了“第四代”语言,这些语言是用来定义与其他程序的通信而不是直接与机器通信的语言。广泛定义,包括XML / HTML之类的“标记”语言,JavaScript和SQL之类的“脚本”语言以及Java和.NET Framework之类的大多数“沙盒”语言(它们被编译成IL,然后由IL进一步解释)提取计算机和平台特定细节的运行时)。您也可以说它涵盖了功能性编程语言的领域,而功能性编程语言在很大程度上依赖于运行时,以提供不仅特定于机器的详细信息,而且特定于操作的详细信息的抽象。对于人类而言,这些第四代语言或多或少不可行,无法翻译成本地机器指令,关键是,这不是一个值得努力的事情。这些语言的强项是分层的过程,在这些过程中,它们最终被用来告诉计算机在底层做什么。


谢谢。我对编程语言的发展历史有所了解。
Erica Xu

2
@KeithS:您可能需要重新格式化最后一段,以使其更具可读性。
伊凡·武西卡(IvanVučica)2011年

4

这是一个好问题。正确的答案占“计算机科学”的一半。

首先,我建议浏览一下指称操作语义,然后阅读本书。它将使您对编程语言是什么以及如何对其进行正式定义有大致了解。

如果以上内容过于学术化,则可以从Petzold的“代码”开始,然后再回到语义上。


1
您真的希望18岁的菜鸟能读懂一些繁重的理论来回答这个问题吗?
工作

2
@Job,根据他先前的问题,他正在大学中接受Scheme(大概是SICP)的剂量。然后应该有一点语义。无论如何,没有严格的理论就无法对这个问题做出适当的回答。
SK-logic

+1表示“代码”。每位入门级CS学生都必须阅读该书。
Daniel Pryden 2011年

4

如果您使用编程语言编写程序,则其他程序会将程序中的符号转换为计算机可以理解的符号。有时这需要几个步骤。例如在C中:

  1. 用户使用高级语言(C)编写程序,CPU不理解,但程序员可以直接理解(我们希望!)。

  2. 编译器将C转换为Assmebly语言,CPU无法直接理解该语言,但很容易将其转换为其他语言。

  3. Assempler将Assembly转换为CPU直接理解的二进制代码序列。一些编译器跳过上述步骤(步骤2),直接从源代码中生成编译的二进制文件。

为了保证计算机能够理解您的程序,编译器或解释器会给您带来错误,并且在遇到不可编译的错误(例如语法错误)时通常会暂停。如果您的程序无法编译,则它永远无法进入程序尝试运行并失败的阶段,因为它没有“理解”它。

要创建一种新语言,您首先需要设计高级语言,然后必须找到一种将新语言的符号映射到CPU可以理解的汇编语言命令的方法。


2
并不是的; 现代的编译器不执行步骤2,而是直接生成二进制代码。但是汇编和二进制代码几乎是等效的。您可以以很高的保真度反汇编(将二进制代码转换为汇编代码)。
MSalters 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.