c语言如何定义11位的数,用C语言写语法分析11,类定义的分析

类的定义,在编程语言中作为用户自定义的类型,是数据结构的主要实现方式。

C语言没有类,用结构体代替。

C的结构体与C++的类,主要差别无非是没有成员函数。

因为函数和变量的声明都是以类型关键字加名字标志符开始,实际上允许结构体里定义函数时,语法分析时反而要更简单。

class Point {

int x;

int y;

int distance() { return sqrt(x * x + y * y); }

};

struct Point {

int distance() { return sqrt(x * x + y * y);

int x, y; };

如果不允许在结构体里定义函数,那么在把结构体内容当作大括号表示的顺序块处理时,分析代码发现是函数定义时就要报错。

但实际上,代码要连续检查好几个词才能发现这一点。

而且,这么一来用于结构体内容的分析代码,与普通的语句块分析代码就有了差别,不得不准备两套了。

还不如允许结构体定义函数来得简单,这样准备一套代码就行。

所以,C++干脆把struct 和 class(除了默认访问权限之外)当作一样的。

类的定义分析,实际上并不难。最难分析的,还是表达式。

它以关键字class开始,有关键字就容易分析的多。

如果语法分析写不出来时,就给这门语言加个关键字,语法分析的难度立马降低一大截(笑)。

(前提是这门语言是你发明的,你才能随便加关键字)

67835113c79ce7f0a09239c2ac55d59a.png

类定义的模块数据如上图,我们不允许类的嵌套定义,即不能这么写:

class A {

class B {

}; };

如果给dfa_module_class模块加个栈作为模块数据,就能比较容易的支持嵌套定义。为了简单,这里暂时不支持。

class和struct关键字都当作一样的,见25、26行。

1105309259a061308b8227c12db9c672.png

它的dfa节点见上图:

_class:class或struct关键字,

identity:类名的标志符,

lb和rb:大括号,表示类的主体内容,

semicolon:分号,表示结尾,

end:作为一个hook节点,检查类的主体内容(它是个顺序块)的分析是否完成。

7ad19ccfc889c4349943e96fa0eb87c9.png

类定义的语法编辑见上图:

class关键字加类名标志符作为开始,然后可以跟分号表示类的声明。例如class A;

如果跟大括号表示类的定义,例如 class A {};

左右大括号直接相连,是空类(287行)。

以类型开始的入口,是类的成员定义(成员函数或成员变量)。这里的类型有可能是基本类型,或者类类型,不管是变量还是函数都是以这种方式开始定义。

最后以右大括号之后跟着分号,表示结尾(291行)。

dfa节点end,用于捕获类的主体内容分析时的DFA_OK。如果是变量定义或函数声明,会在分号结束时返回DFA_OK,如果是函数定义则是发现函数的右大括号时返回DFA_OK。

这个end的hook节点,有可能截获多次DFA_OK,需要检查左右大括号是否匹配来判断类定义的真正结束。

class关键字的action函数:

2fbc3a986ad058db69d8543632f53ded.png

它去语法树上查询是否存在同名的类类型,如果没有就申请一个。然后,挂载一个hook,用来检查类的主体定义的结束。

左大括号的action函数:

a4c2efd4091093d90f8509a0b175df07.png

它标示着类的主体内容开始,要把语法树的current_block切换到当前类的scf_type_t结构,后续的内容都添加在这个结构里,直到类的定义结束。

右大括号的action函数:

ca2e8449dd40ef93e68207f4324619b1.png

它只调用一个函数,即计算类所占的字节数。

hook end的action函数:

e66089f020eefdc0d87ee3574360197a.png

它每次触发时都比较大括号是否匹配,如果匹配就结束。否则,切换到它这里继续分析。它唯一的子节点就是类的member节点,即继续分析类的成员函数或成员变量。

分号的action函数:

51f5fd34562b603e64f5a2a2b888816c.png

最后的分号表示类的定义结束,直接返回DFA_OK。

计算类的字节数的函数:

类的成员变量,要按所占的字节数对齐。

类的成员函数,不占用对象的内存空间,在编译时只保留一份数据在代码段里。

c773825f59bcc96dfb93b05c6ba59cd7.png

a7815593bae0dc236982ea34dc9ba7c0.png

如果要支持虚函数,虚函数表的指针还要占用sizeof(void*)个字节,64位机上是8字节。一般把它放在对象的最前面。

举报/反馈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值