编译原理之路:我的第一个自动机C程序

照着前人的博客写的自动机程序编写方法自己写了一个用来识别浮点数的科学形式的自动机,感觉有很多东西需要总结,涉及到一下一些可以积累的好办法:
关于自动机=>
1.按照自动机草图规划一个跳转状态表,每一个项写清楚在对应的输入下,下一状态跳转谁;【数据结构】=>数组。行列编号各有意义。
缺点:在输入可能性比较多的情况下十分臃肿。
2.声明并定义“自动机”“状态跳转令牌(对应着数组的元)”【数据结构】=>结构体。
结构体里面利用多个成员可更好区别不同元。也可以按照需要加入状态机的功能函数。最朴素的起码要让状态机有一个表示“当前状态”的成员。
缺点:同样地,在输入和跳转情况比较复杂的时候,程序看起来很臃肿。复制粘贴起来麻烦。
3.自动机和“牌”我们都有了,还需要声明和定义一个发起动作的函数,这个函数就是跳转状态的函数,注意自动机程序的逻辑精髓在此:
做好结构struct,做好动作action,并输入后发起动作,最终你能获得结果。

关于C语言的收获=>
1.在结构体中可以定义一个不确定的函数成员,只要能确定函数的返回类型和形参表就可以。想区别开不同函数的时候,按照同样格式进行声明,并在声明结构体实体的时候用上就行。这个方法相当强,意味着我不用声明很多不一样的结构体,就可以用相似的形式进行复用。

注意:
先用这个typedef处理一下返回值和形参表
(我真不知道这个用法叫啥,好用就行,知道的麻烦告诉我这个小菜鸡一下)


typedef void(*actiontype)(pautomata machine, stateType nowState, conditionType nowCondition);

然后结构体这么写就好:

typedef struct {
	stateType nextState;
	actiontype action;

}actionNow, *pActionNow;

这里的这个action函数可以随便弄出来个action_1,action_2随便怎么不一样都行,只要返回值和形参表一样,就能往这个结构体actionNow上面搞。
太好用了吧!
后面,想调用一个结构体实体的时候,也完全可以直接.action()这样去用,反正是根据实例化这个结构体实体的时候用的具体哪个函数再去参数结合的,没毛病。
总之这个办法我要记在我的脑海里。

2.我的标准输入输出流一直学的不好,这里特地积累一下。
首先我这个程序,之前出现问题就是一直读进去’10‘
后面查ASC表,果不其然。10是回车键。所以说输入时要注意吃回车的问题。
下次得记得排查这一点呀。

#include "pch.h"
#include
/*

statetable:
		 c0		     c1		 c2		 c3		 c4		 c5		 c6		 c7		 c8		 c9	   	 ca[.]	cb[E/e]		cc[+/-]
	s0  {1,}		{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	(trap)	(trap)		(trap)
	s1  {1,}		{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{1,}	{2,}	{4,}		{7,}
	s2  {3,}		{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	(trap)	(trap)		(trap)
	s3  {3,}		{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{3,}	{7,}	{4,}		{7,}
	s4  {6,}		{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	(trap)	(trap)		{5,}
	s5  {6,}		{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	(trap)	(trap)		(trap)
	s6  {6,}		{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{6,}	{7,}	{7,}		{7,}
	7(terminal)
	8(trap)
*/

typedef char conditionType;
typedef int stateType;

typedef struct {
	stateType current;
	conditionType result[20];
}automata, *pautomata;



typedef void(*actiontype)(pautomata machine, stateType nowState, conditionType nowCondition);

typedef struct {
	stateType nextState;
	actiontype action;

}actionNow, *pActionNow;

//【!】这里是一种我没有见识过的结构体函数成员用法,它可以用一个代称代表一类的同参数类型列表同返回值的多个函数

#define STATES 9
#define STATE0 0
#define STATE1 1
#define STATE2 2
#define STATE3 3
#define STATE4 4
#define STATE5 5
#define STATE6 6
#define STATE7 7
#define STATETRAP 8

#define CONDITIONS 15
#define CONDITION0	0
#define CONDITION1 1
#define CONDITION2 2
#define CONDITION3 3
#define CONDITION4 4
#define CONDITION5 5
#define CONDITION6 6
#define CONDITION7 7
#define CONDITION8 8
#define CONDITION9 9
#define CONDITION10 10
#define CONDITION11 11 
#define CONDITION12 12
#define CONDITION13 13
#define CONDITION14 14

int index = 0;

void action(pautomata machine, stateType state, conditionType nowCondition) {
	machine->result[index] = nowCondition;
	printf("state %d is trigered!\n",state);
	index++;
}

void actionOver(pautomata machine, stateType state, conditionType nowCondition) {
	int i;
	for (i = 0; i <= index; i++) {
		printf("%c", machine->result[i]);
	};
	printf("\n");
	printf("Automata is over.\n");
}
void actionTrap(pautomata machine, stateType state, conditionType nowCondition) {
	printf("now you are getting in the trap!\n");
}

actionNow t00 = { STATE1 ,action };
actionNow t01 = { STATE1 ,action };
actionNow t02 = { STATE1 ,action };
actionNow t03 = { STATE1 ,action };
actionNow t04 = { STATE1 ,action };
actionNow t05 = { STATE1 ,action };
actionNow t06 = { STATE1 ,action };
actionNow t07 = { STATE1 ,action };
actionNow t08 = { STATE1 ,action };
actionNow t09 = { STATE1 ,action };
actionNow t0a = { STATETRAP	, };
actionNow t0b_1 = { STATETRAP , };
actionNow t0b_2 = { STATETRAP , };
actionNow t0c_1 = { STATETRAP , };
actionNow t0c_2 = { STATETRAP };

actionNow t10 = { STATE1 ,action };
actionNow t11 = { STATE1 ,action };
actionNow t12 = { STATE1 ,action };
actionNow t13 = { STATE1 ,action };
actionNow t14 = { STATE1 , action };
actionNow t15 = { STATE1 , action };
actionNow t16 = { STATE1 ,action };
actionNow t17 = { STATE1 ,action };
actionNow t18 = { STATE1 ,action };
actionNow t19 = { STATE1 , action };
actionNow t1a = { STATE2 ,action };
actionNow t1b_1 = { STATE4 , action };
actionNow t1b_2 = { STATE4 ,action };
actionNow t1c_1 = { STATE7 ,actionOver };
actionNow t1c_2 = { STATE7 ,actionOver };

actionNow t20 = { STATE3 ,action };
actionNow t21 = { STATE3 ,action };
actionNow t22 = { STATE3 ,action };
actionNow t23 = { STATE3 ,action };
actionNow t24 = { STATE3 ,action };
actionNow t25 = { STATE3 ,action };
actionNow t26 = { STATE3 ,action };
actionNow t27 = { STATE3 ,action };
actionNow t28 = { STATE3 ,action };
actionNow t29 = { STATE3 , action };
actionNow t2a = { STATETRAP	, actionTrap };
actionNow t2b_1 = { STATETRAP , actionTrap };
actionNow t2b_2 = { STATETRAP , actionTrap };
actionNow t2c_1 = { STATETRAP ,actionTrap };
actionNow t2c_2 = { STATETRAP , actionTrap };

actionNow t30 = { STATE3 , action };
actionNow t31 = { STATE3 ,action };
actionNow t32 = { STATE3 , action };
actionNow t33 = { STATE3 , action };
actionNow t34 = { STATE3 , action };
actionNow t35 = { STATE3 , action };
actionNow t36 = { STATE3 , action };
actionNow t37 = { STATE3 , action };
actionNow t38 = { STATE3 ,action };
actionNow t39 = { STATE3 , action };
actionNow t3a = { STATE7	,actionOver };
actionNow t3b_1 = { STATE4 ,action };
actionNow t3b_2 = { STATE4 , action };
actionNow t3c_1 = { STATE7 ,actionOver };
actionNow t3c_2 = { STATE7 ,actionOver };

actionNow t40 = { STATE6 , action };
actionNow t41 = { STATE6 , action };
actionNow t42 = { STATE6 , action };
actionNow t43 = { STATE6 , action };
actionNow t44 = { STATE6 , action };
actionNow t45 = { STATE6 , action };
actionNow t46 = { STATE6 , action };
actionNow t47 = { STATE6 ,action };
actionNow t48 = { STATE6 , action };
actionNow t49 = { STATE6 , action };
actionNow t4a = { STATETRAP	, actionTrap };
actionNow t4b_1 = { STATETRAP , actionTrap };
actionNow t4b_2 = { STATETRAP ,actionTrap };
actionNow t4c_1 = { STATE5 , action };
actionNow t4c_2 = { STATE5 , action };

actionNow t50 = { STATE6 , action };
actionNow t51 = { STATE6 ,action };
actionNow t52 = { STATE6 , action };
actionNow t53 = { STATE6 , action };
actionNow t54 = { STATE6 , action };
actionNow t55 = { STATE6 , action };
actionNow t56 = { STATE6 ,action };
actionNow t57 = { STATE6 , action };
actionNow t58 = { STATE6 , action };
actionNow t59 = { STATE6 , action };
actionNow t5a = { STATETRAP	, actionTrap };
actionNow t5b_1 = { STATETRAP , actionTrap };
actionNow t5b_2 = { STATETRAP , actionTrap };
actionNow t5c_1 = { STATETRAP ,actionTrap };
actionNow t5c_2 = { STATETRAP , actionTrap };

actionNow t60 = { STATE6 , action };
actionNow t61 = { STATE6 ,action };
actionNow t62 = { STATE6 ,action };
actionNow t63 = { STATE6 , action };
actionNow t64 = { STATE6 , action };
actionNow t65 = { STATE6 , action };
actionNow t66 = { STATE6 , action };
actionNow t67 = { STATE6 , action };
actionNow t68 = { STATE6 , action };
actionNow t69 = { STATE6 , action };
actionNow t6a = { STATE7	,actionOver };
actionNow t6b_1 = { STATE7 ,actionOver };
actionNow t6b_2 = { STATE7 ,actionOver };
actionNow t6c_1 = { STATE7 , actionOver };
actionNow t6c_2 = { STATE7 ,actionOver };

actionNow t77 = { STATETRAP ,actionTrap };

actionNow ttt = { STATETRAP,actionTrap };


actionNow stateConditionTable[STATES][CONDITIONS + 1] = {
	/* c0	   c1		 c2		 c3		 c4		 c5		 c6		 c7		 c8		 c9	   	 ca[.]	cb[E/e]		cc[+/-]	*/
	/*S0*/ t00,  t01,t02,t03,t04,t05,t06,t07,t08,t09,t0a,t0b_1,t0b_2,t0c_1,t0c_2,ttt,
	/*S1*/t10,  t11,t12,t13,t14,t15,t16,t17,t18,t19,t1a,t1b_1,t1b_2,t1c_1,t1c_2,t6c_2,
	/*S2*/t20,  t01,t22,t23,t24,t25,t26,t27,t28,t29,t2a,t2b_1,t2b_2,t2c_1,t2c_2,ttt,
	/*S3*/t30,  t01,t32,t33,t34,t35,t36,t37,t38,t39,t3a,t3b_1,t3b_2,t3c_1,t3c_2,t6c_2,
	/*S4*/t40,  t01,t42,t43,t44,t45,t46,t47,t48,t49,t4a,t4b_1,t4b_2,t4c_1,t4c_2,ttt,
	/*S5*/t50,  t01,t52,t53,t54,t55,t56,t57,t58,t59,t5a,t5b_1,t5b_2,t5c_1,t5c_2,ttt,
	/*S6*/t60,  t01,t62,t63,t64,t65,t66,t67,t68,t69,t6a,t6b_1,t6b_2,t6c_1,t6c_2,t6c_2,
	/*S7*/t77,  t77,t77,t77,t77,t77,t77,t77,t77,t77,t77,t77,t77,t77,t77,ttt,
	/*S8*/ttt,  ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt,ttt
};






stateType step(pautomata machine, conditionType myCondition) {
	int conNum = int(myCondition - '0');
	if ((int)myCondition >= 48 && (int)myCondition <= 57) {
		conNum = int(myCondition - '0');
	}
	else {
		switch ((int)myCondition) {
		case 46: {conNum = 10; }; break;
		case 69: {conNum = 11; }; break;
		case 101: {conNum = 12; }; break;
		case 43: {conNum = 13; }; break;
		case 45: {conNum = 14; }; break;
		default: {conNum = CONDITIONS; }; break;

		}

	}

	
	stateConditionTable[machine->current][conNum].action(machine, machine->current, myCondition);
	//这里函数的调用方法可能不对,毕竟在结构体里面函数成员的声明方式比较特殊 :=>	结果 可以这样使用。
	machine->current = stateConditionTable[machine->current][conNum].nextState;
	return machine->current;


}


int main()
{
	automata myMachine;
	myMachine.current = STATE0;
	char con;
	int a;
	while (1) {
		while ((con = getchar()) != '\n') {
			step(&myMachine, con);
		}
	}


	return 0;
}


你可能感兴趣的:(编译原理)