今天终于完成了语法分析器
今天终于完成了SLR(1)语法分析器生成器的程序。应该说这个程序我写得还算比较顺利,不过也将近800行代码,如果加上分析器估计还是要有1000行代码左右。尽管最开始的时候,我不太赞同用编写生成器的方式来进行编译原理的课程学习的实践环节,不过,经过编写了词法分析程序生成器和语法分析程序的生成器以后,我觉得还是有很大的实用价值的。比如,在很多语言中支持正则表达式,而要动态的进行正则表达式的分析,无疑需要生成器程序的支持。所以,这半个学期以来,我觉得还是很有收获的。
终于完成了词法分析的生成器
今天终于完成了词法分析程序的生成器。1000多行代码。应该说,还是离我自己预先期望有一些距离。因为这个是“编译原理”课程作业的一部分,所以时间比较紧。我开始打算用纯粹的C语言编写,可是后来发现代码量还要增加不少,于是就加入了一些C++的特性。这一点,如果以后有时间会改成C语言。
详细的技术细节,会慢慢公布。
关于编译器
因为一些众所周知的原因,我还没有开始编写我的编译器。最大一个问题就在于老师给我们的要求是在是太模糊,以至于很难实现。
老师说,要我们写一个通用的编译器。这个要求本身就有一些问题。首先,我接触编译器也有一些时间了,就从来没有听说过通用编译器。当然,你可能要说,有Lex和Yacc这样的生成编译器中间程序的程序。不过这也仅此而已,我们老师说,如果输入C语言的文法就能识别C语言,输入Pascal就能识别Pascal的程序,这一点让我怎么也不得要领。
当然这也不是不能做,只是这样做的意义并不大,其实编译器最重要的还有就是效率问题,谁都不想编译器编译自己的程序花费几个小时的时间。
对于编译器的编写,我还是严格使用C语言。虽然我知道用C++可以简化很多工作,但是效率又一次促使我选择了C语言。
可能再过几天,我就可以开工了。
贪吃蛇进度(1)
现在实现了计时器机制和事件机制。下一步是怎么去实现贪吃蛇的走动。
现在分为两个文件:snake.h和snake.c
如下:snake.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | #define NEWEVENT (EventLink)malloc(sizeof(event)) #define MAXSNAKELEN 30 /* Max length of the snake */ #define DEFAULTSNAKECOLOR WHITE /* The default snake color */ #define DEFAULTSPEED 100000 /* The start speed of the snake */ #define DEFAULTSTARTX 100 /* The start x of the snake */ #define DEFAULTSTARTY 100 /* The start y of the snake */ #define MAXEVENT 1 /* The startup event number */ /* Keyboard definition */ #define ENTER 13 /* The prototype of bool type */ typedef enum { true, false } bool; /* The prototype of directions */ typedef enum { up, right, down, left } direction; /* The prototype of a point of the snake */ typedef struct { int posx; int posy; direction dir; /* The current direction of this point */ } point; /* The prototype of the snake */ typedef struct { point dots[MAXSNAKELEN]; } snake; #ifndef __SNAKE /* prevent multiple includes */ #define __SNAKE /* The prototype of the event */ typedef struct { long interval; /* The interval of the event occurs */ long timer; void (*invoke)(); /* The function pointer to the invoke action */ } event; /* The prototype of the eventlist */ struct eventlist { event *eventnow; struct eventlist *next; }; typedef struct eventlist Node; typedef Node *Link; typedef event *EventLink; int screenx = 0; int screeny = 0; void Init(snake *s); void EventHandler(Link); void EventInsert(Link, EventLink); Link EventCreater(Link); void EventFree(Link); /* Registry Events */ void Controler(); /* The main keyboard controler */ void DrawPoint(); void DrawLine(); void DrawSnake(snake *s); void EventInsert(Link eventhead, EventLink newevent) { Link pointer; Link newlist; pointer = eventhead; while (1) { if (pointer->next == NULL) { newlist = (Link) malloc(sizeof (Node)); newlist->eventnow = newevent; newlist->next = NULL; pointer->next = newlist; break; } pointer = pointer->next; } } Link EventCreater(Link eventhead) { Link newevent; EventLink tempevent; int i; eventhead = (Link) malloc(sizeof (Node)); /* Create event list */ if (eventhead == NULL) { printf("Memory allocate Failure!!\n"); } else { tempevent = (EventLink) malloc(sizeof (event)); tempevent->interval = 1; tempevent->timer = 0; tempevent->invoke = Controler; eventhead->eventnow = tempevent; eventhead->next = NULL; } return eventhead; } void EventFree(Link eventhead) { Link pointer; EventLink tempevent; while (eventhead != NULL) { pointer = eventhead; eventhead = eventhead->next; tempevent = eventhead->eventnow; free(pointer); free(tempevent); } } #endif |
Snake.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <graphics.h> #include <dos.h> #include <snake.h> /* To return the head pointer of the eventlist */ int main(void) { snake me; Link head; int gdriver = DETECT, gmode; EventLink tempevent; /* Init graphic mode */ initgraph(&gdriver, &gmode, ""); Init(&me); head = EventCreater(head); tempevent = NEWEVENT; tempevent->interval = 10000; tempevent->timer = 0; tempevent->invoke = DrawPoint; EventInsert(head, tempevent); EventHandler(head); EventFree(head); closegraph(); clrscr(); return 0; } void DrawLine() { int x; int y; x = random(500); y = random(500); circle(x, y, 20); } void DrawPoint() { int x1, x2; int y1, y2; x1 = random(200); x2 = random(100); y1 = random(200); y2 = random(100); line(x1, y1, x2, y2); } void Controler() { } void Init(snake *s) { int i, j; int sx = DEFAULTSTARTX, sy = DEFAULTSTARTY; randomize(); for (i = 0; i < MAXSNAKELEN; i++) { s->dots[i].posx = sx; s->dots[i].posy = sy; s->dots[i].dir = up; sy++; } screenx = getmaxx(); screeny = getmaxy(); } /* Draw snake */ void DrawSnake(snake *s) { int i; for (i = 0; i < MAXSNAKELEN; i++) { putpixel(s->dots[i].posx, s->dots[i].posy, DEFAULTSNAKECOLOR); } } void EventHandler(Link eventhead) { int i; Link pointer; while (1) { delay(1); pointer = eventhead; while (pointer != NULL) { pointer->eventnow->timer++; if ((pointer->eventnow->timer) >= (pointer->eventnow->interval)) { /* Invoke current event */ pointer->eventnow->invoke(); pointer->eventnow->timer = 0; } pointer = pointer->next; } if (kbhit()) { if (getch() == ENTER) break; } } } |
解决了动态加载的问题
果然,在网上查了一些资料以后,终于动态加载了dll并且调用了里面的方法。其实搞懂了以后还是很简单的。具体实现的代码如下:
1 2 3 4 5 6 7 8 9 | Assembly ass; ass=Assembly.LoadFrom(Server.MapPath("")+"\\bin\\kernel.dll"); Type myType=ass.GetType("Kernel.DbControl"); MethodInfo mi=myType.GetMethod("ViewAllData"); Object[] arg=new object[1]; arg[0]=Server.MapPath(""); Object obj = Activator.CreateInstance(myType,arg); Test.DataSource=(DataSet)mi.Invoke(obj,null); Test.DataBind(); |
首先要把dll加载进来。然后得到特定的类名。再就是得到这个类里里面某个方法。最重要的一句就是:Object obj = Activator.CreateInstance(myType,arg); 这句的作用就是使这个类实例化。注意,实例化可以带上参数(这要看构造函数是什么样子的)。实例化了类以后就是调用方法,也和实例化类一样,要有参数的传递。当然,最好强制转换一下类型。
开始工作
今天正式开始工作了。应该说,两个人在一起的效率的确很高,至少要比一个人要高很多。第一天还是有一些收获的。比如先是做了一个dll,然后把数据库操作封装到了这个dll里面。再在一个web application里面调用这个dll。这个做的还是很成功的。中间有一个小问题就是,在dll里面,如何得到当前的工作路径。没有解决!只有从web application里面把这个路径传过去。当然这也是一种折中的方法。然后开始试验动态载入程序集。应该说,动态载入本身是没有难度的,关键是如何运行类里面的方法。这个就不是那么容易了。试验了很多,都不行。在网上查了一下,发现有很多类似的问题被大家都讨论过了。看看明天能不能解决这个问题。
C语言的问题
昨天把下雨的题终于编完了。对Graphics.h里面的一些函数有了一个初步的了解。我觉得我设计的这个程序是一种多线程的程序的雏形,因为两个雨滴是相互独立的,互不影响。这是放在一个数组里面实现的。目前的问题是如果把间隔时间设置的相对短些的话,动画要光滑些,但是有闪烁的感觉。这也是所有编程语言的擦坪函数所带来的,怎么解决,确实是一个问题。
附上源程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #include <stdio.h> #include <math.h> #include <graphics.h> #include <stdlib.h> #include <time.h> #include <dos.h> #include <conio.h> #define PI 3.1415926 #define RAINDROPLEN 15 /* The length of a raindrop */ #define RAINTANGLE 0 /* The tangle of each raindrop */ #define RAINDROPZ 0 /* The internal of each raindrop */ #define RAINCOLOR white /* The color of each raindrop */ #define RAINWAVELEVEL 40 /* The level of each wave */ #define DELAYTIME 2000 /* The internal of each flash of the screen */ /* Calculate the next X,Y of a raindrop */ #define RAINDROPNEXTX(n,m) (int)((RAINDROPLEN/m+n)*sin(RAINTANGLE*(PI/180))) #define RAINDROPNEXTY(n,m) (int)((RAINDROPLEN/m+n)*cos(RAINTANGLE*(PI/180))) #define RAINDROPS 100 /* The total numbers of raindrops */ struct raindrop { int posx; int posy; int state; /* The current state of raindrop. 1 for raindrop. 2 for wave. */ int wavelevel; /* The current wave level */ }; void Init(struct raindrop *drops); void DrawDrops(struct raindrop *drops); /* Draw all the raindrops */ void CalDrops(struct raindrop *drops); /* Calculate the next raindrops position */ int main(void) { struct raindrop drops[RAINDROPS]; int gdriver=DETECT,gmode,i=0; initgraph(&gdriver,&gmode,""); /* Init graphic mode */ Init(drops); setbkcolor(0); while(!kbhit()) { cleardevice(); DrawDrops(drops); delay(DELAYTIME); CalDrops(drops); } return 0; } void Init(struct raindrop *drops) { int i; randomize(); for(i=0;i<RAINDROPS;i++,drops++) { drops->posx=random(600); drops->posy=random(300); drops->state=1; drops->wavelevel=0; } } void DrawDrops(struct raindrop *drops) { int i; int endx,endy; setcolor(WHITE); for(i=0;i<RAINDROPS;i++,drops++) { if (drops->state==1) { endx=RAINDROPNEXTX(0,1); endy=RAINDROPNEXTY(0,1); line(drops->posx,drops->posy,drops->posx+endx,drops->posy+endy); } else { ellipse(drops->posx,drops->posy,0,360,1+(drops->wavelevel)*0.75,0.05+(drops->wavelevel)*0.15); } } } void CalDrops(struct raindrop *drops) { int i; int endx,endy; int temp; for(i=0;i<RAINDROPS;i++,drops++) { if (drops->state==1) { endx=RAINDROPNEXTX(RAINDROPZ,10); endy=RAINDROPNEXTY(RAINDROPZ,10); if ((endx+drops->posx)>=640||(endy+drops->posy)>=400) { temp=random(100); if (temp%2==0||(endx+drops->posx)>=680||(endy+drops->posy)>=550) { drops->state=2; drops->wavelevel=1; } else { drops->posx=drops->posx+endx; drops->posy=drops->posy+endy; } } else { drops->posx=drops->posx+endx; drops->posy=drops->posy+endy; } } else { if ((drops->wavelevel)<RAINWAVELEVEL) { drops->wavelevel++; } else { drops->posx=random(600); drops->posy=random(100); drops->wavelevel=0; drops->state=1; } } } |

最新评论