导航:首页 > 源码编译 > 编译器如何编译关键词

编译器如何编译关键词

发布时间:2022-06-17 13:40:52

⑴ 汇编语言编译器是怎么编写的

编译器自举!搜索这个关键字
程序都是编译器编译的。这个是肯定的
至于第一款X语言编译器是不是直接1010101010自己写的那就不知道啦

一般开发编译器的话。有两条路选择
1.利用yacc(或者其变种)&lex(词法分析)-等工具自己生成语法模板
词法语法都可以使用这些工具自己生成
然后自己编写生成的中间码和生成的机器码就可以了
一般做编译原理类似试验都是如此的。许多编译器也的确是这样

2.自己写词法分析和语法分析。可以参考一些开源的编译器
lcc-这个是ANSI C99标准的编译器是开源的
或者nasm,watcom等编译器到www.sf.net上不少开源的编译器

总的来说。高级语言编译器比较难写
如果想快速写出一个的话
可以采用第一种做法。利用工具生成语法词法模板
先写一个简单的汇编编译器比较简单
开源的有nasm,jwasm(支持masm语法开源的编译器)
http://www.japheth.de/JWasm.html
fasm(这款编译器是自举的.就是自己可以编译自己),
http://flatassembler.net/

剩下的就是自己做好语言规则关键字map
引用高手的话。语言map做好了你的编译器也做好一半了
剩下的都是机械性的工作了。
生成x86或者arm指令。

优化工作这个很难解释.根据你所需要的做吧
毕竟可以做出一个无错,又XX的编译器已经很难得

你可以选择使用现有的编译器开发自己的编译器
然后等到你的编译器支持相当数量指令和成熟度的时候
使用自己的语法重新写一遍编译器.
这样你就可以用自己的编译器开发自己的编译器了(是不是很邪恶?)

另外举几个例子
Delphi的编译器是C++ Builder开发的。
而C++ Builder的IDE是Delphi开发的
C++ Builder的编译器是C++ Builder开发的-这个就是编译器自举了。。Delphi和C++ Builder共享一个后端化优化器。
Delphi 早期的版本的编译器是tasm直接编译的。可见Anders的汇编功力多强悍(Anders也就是后来VJ++,C#,.NET工程的核心架构师.最关键的灵魂级人物)

VC++的编译器是VC++开发的。很明显这都说明了编译器自举
自己开发自己。如果一个编译器可以做到自己编译自己。那基本上就可以实现任何功能了。

关于编译器开发的书籍可以看一下
龙书《编译原理(第二版)》
虎书《现代编译原理-C语言描述》
鲸书《高级编译器设计与实现》
建议从鲸书看起。然后是龙书
再来是虎书--虎书里面描述了许多现代编译器(正如其名)技术
例如面向对象啦,优化,垃圾回收等等.
鲸书看完基本上就可以实现一个简单的Tiny C编译器了
然后在龙书巩固,读一下语言规范,自己看一些开源的汇编编译器代码
自己就可以尝试做一个汇编语言编译器了.等到技术提高了
在尝试做一些高级语法识别,参考LCC代码做一下ANSI C99的
C语言编译器。再来就看你自己的兴趣和领悟度拉
如果想支持C++的话就得要对编译器做许多方便的研究

类似java那种跨平台或者Ruby,python等动态语言
虎书中也有描述。当然看自己功力了

⑵ c与c++语言编译器是如何识别关键字

根据编译器的不同,有不同的识别方式,例如VC6.0使用系统内建关键字列表,如果用户定义变量的时候使用了系统默认的关键字,则会在编译的时候产生错误。

附上:
C语言的关键字共有32个,根据关键字的作用,可分其为数据类型关键字、控制语句关键字、存储类型关键字和其它关键字四类。

1 数据类型关键字(12个):
(1) char :声明字符型变量或函数
(2) double :声明双精度变量或函数
(3) enum :声明枚举类型
(4) float:声明浮点型变量或函数
(5) int: 声明整型变量或函数
(6) long :声明长整型变量或函数
(7) short :声明短整型变量或函数
(8) signed:声明有符号类型变量或函数
(9) struct:声明结构体变量或函数
(10) union:声明联合数据类型
(11) unsigned:声明无符号类型变量或函数
(12) void :声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)

(2)控制语句关键字(12个):
A循环语句
(1) for:一种循环语句(可意会不可言传)
(2) do :循环语句的循环体
(3) while :循环语句的循环条件
(4) break:跳出当前循环
(5) continue:结束当前循环,开始下一轮循环
B条件语句
(1)if: 条件语句
(2)else :条件语句否定分支(与 if 连用)
(3)goto:无条件跳转语句
C开关语句
(1)switch :用于开关语句
(2)case:开关语句分支
(3)default:开关语句中的“其他”分支
D
return :子程序返回语句(可以带参数,也看不带参数)

3 存储类型关键字(4个)
(1)auto :声明自动变量 一般不使用
(2)extern:声明变量是在其他文件正声明(也可以看做是引用变量)
(3)register:声明积存器变量
(4)static :声明静态变量

4 其它关键字(4个):
(1)const :声明只读变量
(2)sizeof:计算数据类型长度
(3)typedef:用以给数据类型取别名(当然还有其他作用
(4)volatile:说明变量在程序执行中可被隐含地改变

⑶ 如何理解编程语言中的关键词

关键词就是编程语言中内置的起一定作用的限定词,自定义的变量之类的不能和关键词重复,会出现错误,不用特别理解关键词的意义,只要知道它的作用就是了,关键词就是做编译器或者解释器的时候定义的常量而已

⑷ 编译器是如何处理比如class,new关键字的翻译成的相关汇编代码是什么求高人解答

没有对应的汇编,编译器在产生汇编代码前,必须对源码进行词法识别,语法识别,否则根本不知道你的class new到底是什么意思,是要声明一个类呢,还是定义了一个类实体;是重载了new操作符呢,还是new一个对象;

所以说是不可能有对应的汇编代码的,所有汇编必须在语法识别后产生的

⑸ Java代码到底是如何编译成机器指令的

编译器把一种语言规范转化为另一种语言规范的这个过程需要哪些步骤?回答这个问题需要参照《编译原理》,总结过程如下:

        1)词法分析:读取源代码,一个字节一个字节的读进来,找出这些词法中我们定义的语言关键词如:if、else、while等,识别哪些if是合法的哪些是不合法的。这个步骤就是词法分析过程。

        词法分析的结果:就是从源代码中找出了一些规范化的token流,就像人类语言中,给你一句话你要分辨出哪些是一个词语,哪些是标点符号,哪些是动词,哪些是名词。

        2)语法分析:就是对词法分析中得到的token流进行语法分析,这一步就是检查这些关键词组合在一起是不是符合Java语言规范。如if的后面是不是紧跟着一个布尔型判断表达式。

        语法分析的结果:就是形成一个符合Java语言规定的抽象语法树,抽象语法树是一个结构化的语法表达形式,它的作用是把语言的主要词法用一个结构化的形式组织在一起。这棵语法树可以被后面按照新的规则再重新组织。

        3)语义分析:语法分析完成之后也就不存在语法问题了,语义分析的主要工作就是把一些难懂的,复杂的语法转化成更简单的语法。就如难懂的文言文转化为大家都懂的百话文,或者是注释一下一些不懂的成语。

        语义分析结果:就是将复杂的语法转化为简单的语法,对应到Java就是将foreach转化为for循环,还有一些注释等。最后生成一棵抽象的语法树,这棵语法树也就更接近目标语言的语法规则。

        4)字节码生成:将会根据经过注释的抽象语法树生成字节码,也就是将一个数据结构转化为另外一个数据结构。就像将所有的中文词语翻译成英文单词后按照英文语法组装文英文语句。代码生成器的结果就是生成符合java虚拟机规范的字节码。

⑹ C++中对C编译器编译过的程序用什么关键字

你说的应该是c++中包含c文件吧
一般用下面的,这样可以保证在c++编译器中不会被乱添加什么后缀,可以按照函数的名字调用。
#ifdef __cplusplus
extern "C" {
#endif
//一段代码
#ifdef __cplusplus
}
#endif

⑺ 像python是用c写的c#的编译器是用c++写的,那么汇编的关键字功能是怎么实现的都说是硬件厂

计算机上能运行的唯一的语言是二进制代码。但是二进制不管是书写还是阅读都很困难(你可以想象一下满篇的0和1组成的代码)。为了让用户更好的阅读和书写代码,在汇编语言中,用助记符代替操作码,用地址符号或标号代替地址码。这样用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。也就是说汇编可以直接转化为二进制语言并再CPU上运行,所以它运行是不需要任何驱动的。当然需要一个硬件厂商提供的汇编编译器将汇编转化为二进制码。
你提到了计算机如何识别指令,这个问题就很复杂了,这涉及到了数字电路,计算机原理等东西,总之这些是CPU厂商需要考虑的事情。

⑻ 编译器如何识别字符是关键字还是变量名的

编译过程大概分这么几步
首先用有限状态自动机把代码文本分割成一个一个的token,每个token是一个意义单位,
比如
int main(123);
就被分割成了
int
main

123


然后对token列表根据该语言的语法建立语法树,在建立语法树的过程中就要区分某个单词是关键字还是标识符(也就是变量名),一般来讲编译器一般都有一个保留字列表,开始的时候都当作变量名看待,如果发现某个变量名出现在了保留字列表里,就对其进行标识处理。

⑼ C语言的按照标识符、关键字、常用编译指令有哪些

我们可以在C源程序中插入传给编译程序的各中指令,这些指令被称为预处理器指令,它们扩充了程序设计的环境。现把常用的预处理命令总结如下:
1. 预处理程序
按照ANSI标准的定义,预处理程序应该处理以下指令:
#if #ifdef #ifndef #else #elif
#endif
#define
#undef
#line
#error
#pragma
#include
显然,上述所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。
2. #define
#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之。这种标识符称为宏名字,相应的替换称为宏代换。一般形式如下:
#define macro-name char-sequence
这种语句不用分号结尾。宏名字和串之间可以有多个空白符,但串开始后只能以新行终止。
例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:
#define LEFT 1
#define RIGHT 0
每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。
定义一个宏名字之后,可以在其他宏定义中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代换就是用相关的串替代标识符。因此,如果希望定义一条标准错误信息时,可以如下定义:
#define ERROR_MS “Standard error on input \n”
如果一个串长于一行,可在行尾用反斜线”\”续行,如下:
#define LONG_STRING “This is a very very long \
String that is used as an example”
3. #error
#error指令强制编译程序停止编译,它主要用于程序调试。#error指令的一般形式是:
#error error-message
注意,宏串error-message不用双引号包围。遇到#error指令时,错误信息被显示,可能同时还显示编译程序作者预先定义的其他内容。
4. #include
程序中的#include指令要求编译程序读入另一个源文件。被读入文件的名字必须用双引号(“”)或一对尖括号(<>)包围,例如:
#include “stdio.h”
#include <stdio.h>
都使C编译程序读入并编译头文件以用于I/O系统库函数。
包含文件中可以包含其他#include指令,称为嵌套包含。允许的最大嵌套深度随编译器而变。
文件名被双括号或尖括号包围决定了对指定文件的搜索方式。文件名被尖括号包围时,搜索按编译程序作者的定义进行,一般用于搜索某些专门放置包含文件的特殊目录。当文件名被双括号包围时,搜索按编译程序实时的规定进行,一般搜索当前目录。如未发现,再按尖括号包围时的办法重新搜索一次。
通常,绝大多数程序员使用尖括号包围标准的头文件,双引号用于包围与当前程序相关的文件名。
5. 条件编译指令
若干编译指令允许程序员有选择的编译程序源代码的不同部分,这种过程称为条件编译。
5.1#if、#else、#elif #endif
条件编译指令中最常用的或许是#if,#else,#elif和#endif。这些指令允许程序员根据常数表达式的结果有条件的包围部分代码。
#if的一般形式是:
#if constant-expression
Statement sequence
#endif
如#if后的常数表达式为真,则#if和#endif中间的代码被编译,否则忽略该代码段。#endif标记#if块的结束。
#else指令的作用与C语言的else相似,#if指令失败时它可以作为备选指令。例如:
#include <stdio.h>
#define MAX 100
Int main(void)
{
#if MAX>99
printf(“Compiled for array greater than 99.\n”);
#else
printf(“Complied for small array.\n”);
#endif
return 0;
}

⑽ c++怎样从源代码中分解关键词

C++程序代码优化的方法
1、选择合适的算法和数据结构

选择一种合适的数据结构很重要,如果在一堆随机存放的数中使用了大量的插入和删除指令,那使用链表要快得多。数组与指针语句具有十分密切的关系,一般来说,指针比较灵活简洁,而数组则比较直观,容易理解。对于大部分的编译器,使用指针比使用数组生成的代码更短,执行效率更高。

在许多种情况下,可以用指针运算代替数组索引,这样做常常能产生又快又短的代码。与数组索引相比,指针一般能使代码速度更快,占用空间更少。使用多维数组时差异更明显。下面的代码作用是相同的,但是效率不一样。

数组索引 指针运算

For(;;)

{ p=array;

A=array[t++];

for(;;)

{ a=*(p++); 。。。。。。。。。 。。。。。。 }

}

指针方法的优点是,array的地址每次装入地址p后,在每次循环中只需对p增量操作。在数组索引方法中,每次循环中都必须根据t值求数组下标的复杂运算。

2、使用尽量小的数据类型

能够使用字符型(char)定义的变量,就不要使用整型(int)变量来定义;能够使用整型变量定义的变量就不要用长整型(long int),能不使用浮点型(float)变量就不要使用浮点型变量。当然,在定义变量后不要超过变量的作用范围,如果超过变量的范围赋值,C编译器并不报错,但程序运行结果却错了,而且这样的错误很难发现。

阅读全文

与编译器如何编译关键词相关的资料

热点内容
linuxzone 浏览:746
androidapi版本号 浏览:784
小猪佩奇配音解压吃东西 浏览:284
程序员怎么申请公司年会 浏览:870
圈店app的预约头条功能怎么样 浏览:34
云服务器设置ad域 浏览:316
我的世界无尽贪婪奇点压缩器 浏览:394
源码资源免费分享网 浏览:686
批量qq号有效验证源码 浏览:512
本科程序员五年工资 浏览:902
创维电视柜怎么安装app 浏览:853
可爱的程序员陆漓剧照 浏览:851
怎样把截屏压缩成300kb 浏览:226
dart文件加密 浏览:40
java对接摄像头源码 浏览:887
安卓项目开发实例附源码 浏览:730
程序员苹果全家桶 浏览:198
远程命令阻塞 浏览:731
有网页源码怎么查数据 浏览:101
win10下make编译速度过慢 浏览:867