简而言之
编程语言由将程序表示为字符串的语法和作为程序预期含义的语义组成。
形式语言是没有意义的语法。它旨在研究正式定义的字符串集的结构,而通常无需在这些字符串上附加含义。
正则表达式和其他形式主义(例如,上下文无关文法)用于定义形式语言,用作编程语言和自然语言的语法组成部分,即以结构化方式表示句子。其他机制用于将该结构与编程语言的语义相关联。
此处已大大简化,尤其是在自然语言方面。
还有更多细节
要回答您的问题,我们应该从头开始。通常,一种语言非正式地是一种传达信息或思想的手段。在一种语言中,通常可以区分语法和语义。语义就是您要谈论/编写的内容。您要传达的信息。语法是用于传达语法的手段,即可以在人与人之间交换的常规表示形式,现在也可以在人与设备之间或在设备(计算机)之间交换。
通常,您会用这个词dog
来表达狗的概念。这个单词dog
是由三个字母或等效的声音组成的,意在表示某种动物。关键思想是通过表示要传达的内容来进行交流。表示结构通常称为语法,而表示的结构称为语义。对于自然语言以及编程语言,这或多或少都适用。
单词是代表或多或少基本语义概念的句法实体。但是必须以多种方式将这些基本概念组合在一起,以赋予更复杂的含义。我们写
the dog
来传达我们的意思是指特定的狗,并the dog bites the cat
传达更复杂的想法。但是单词的组织方式必须由规则确定,以便我们可以分辨出狗和猫中的哪一个实际上在咬对方。
因此,我们有这样的规则sentence -> subject verb complement
,应该匹配句子并告诉我们如何表达与每个部分相关的想法。这些规则是语法规则,因为它们告诉我们如何组织消息的表示形式。该subject
可以通过自身的规则来定义subject -> article noun
,等等。
2x+1=23x123
equation -> expression "=" expression
expression -> expression "+" expression
expression -> number
编程语言的结构是相同的。编程语言在语义上专用于表达要执行的计算,而不是表达要解决的问题,定理或动物之间的友好关系的证明。但这是主要区别。
语法中使用的表示形式通常是字符串或口语的声音。语义通常属于抽象领域,或者可能属于现实,但是仍然在我们的思维过程中抽象,或者属于设备的行为领域。通信需要将信息/想法编码为语法,然后由接收器发送和解码。然后,接收器以任何方式解释结果。
因此,我们看到的语言主要是语法及其结构。上面的示例只是定义语法字符串及其结构组织的最常用方法之一。还有其他 对于给定的语言,可以为某些字符串分配结构,并说它们属于该语言,而其他则不属于。
单词也是如此。某些字母(或声音)序列是合法单词,而其他则不是。
形式语言只是没有语义的语法。它们使用一组规则定义使用字母的基本元素可以构造哪些序列。规则是可变的,有时很复杂。但是,形式语言除了用于语言交流之外,还用于许多数学目的,无论是编程语言的自然目的。定义语言中的字符串的规则集称为语法。但是还有许多其他定义语言的方法。
实际上,一种语言分为两个层次。词汇级别定义了由字符字母构成的单词。句法级别定义了由单词字母(或更确切地说单词系列,以使其保持为有限字母)构成的句子或程序。这一定程度上简化了。
在大多数语言(编程语言或自然语言)中,单词的结构都非常简单,因此通常使用通常被认为是最简单的形式语言:常规语言来定义它们。可以使用正则表达式(regexp)定义它们,并且可以通过称为有限状态自动机的编程设备轻松识别它们。在使用编程语言的情况下,单词的示例是标识符,整数,字符串,实数,保留单词,例如if
或repeat
,标点符号或空心括号。单词族的示例是标识符,字符串,整数。
语法级别通常由形式语言的一种稍微复杂一些来定义:上下文无关的语言,使用单词作为字母。我们上面看到的规则是自然语言的无上下文规则。对于编程语言,规则可以是:
statement -> assignment
statement -> loop
loop -> "while" expression "do" statement
assignment -> "identifier" "=" expression
expression -> "identifier"
expression -> "integer"
expression -> expression "operator" expression
有了这样的规则,您可以编写:
while aaa /= bbb do aaa = aaa + bbb / 6
这是一个声明。
它的产生方式可以由称为解析树或语法树的树结构表示(此处不完整):
statement
|
_______________ loop _______________
/ / \ \
"while" expression "do" statement
__________|_________ |
/ | \ assignment
expression "operator" expression _______|_______
| | | / | \
"identifier" "/=" "identifier" "identifier" "=" expression
| | | |
aaa bbb aaa ... ...
规则左侧出现的名称称为非终结符,而单词也称为终结符,因为它们在语言的字母中(在词汇级别之上)。非终结表示不同的语法结构,可用于组成程序。
这样的规则被称为上下文无关的,因为非终结符可以使用任何相应规则任意替换,而与出现的上下文无关。定义语言的规则集称为上下文无关文法。
实际上,在必须先声明标识符或表达式必须满足类型限制的情况下,这是有限制的。但是这种限制可以被认为是语义上的,而不是语法上的。实际上,有些专业人员将它们置于所谓的
静态语义中。
给定任何句子,任何程序,通过分析该句子的分析树所给出的结构来提取该句子的含义。因此,开发称为解析器的算法非常重要,当给定程序时,该算法可以恢复与该程序相对应的树结构。
语法分析器之前是词法分析器,后者可识别单词并确定单词所属的族。然后,将单词或词汇元素的序列提供给解析器,该解析器检索基础树结构。然后,通过这种结构,编译器可以确定如何生成代码,这是他在编译器端处理程序的语义部分。
编译器的解析器实际上可以构建与解析树相对应的数据结构,并将其传递到编译过程的后续阶段,但不必这样做。运行解析算法相当于开发一种计算策略,以探索隐含在程序文本中的语法树。根据编译策略(阶段数),此语法/分析树可能在过程中或未在过程中被明确显示。但是,必需的是,最终至少对解析树进行了一种自下而上的探索,无论是在计算结构中是显式的还是隐式的。
直观地讲,其原因是定义与句法树结构相关的语义的标准形式方法是借助所谓的同态性。不要害怕这个大词。这个想法只是在连接它们的运算符的基础上考虑整体含义的含义,这些含义是由各个部分的含义构成的
例如,the dog bites the cat
可以使用规则分析句子sentence -> subject verb complement
。知道3个子树subject
,verb
和的含义complement
,组成它们的规则告诉我们对象正在做动作,而猫是被咬的那只。
这只是一个直观的解释,但是可以形式化。语义是从构成要素向上构造的。但这隐藏了很多复杂性。
编译器的内部工作可以分解为几个阶段。实际的编译器可能会使用中间表示逐步地工作。它还可能合并一些阶段。这取决于所使用的技术以及所用语言的复杂性。