Learning Traces...

--Great Love involves great effort
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用C++编写简单绘图语言的语法分析器——程序清单

Posted on 2008-04-25 15:54  suyang  阅读(4570)  评论(2编辑  收藏  举报
 1//-----------------------------parser.h---------------------------------
 2#ifndef PARSER_H
 3#define PARSER_H
 4
 5#include "scanner.h"
 6
 7typedef double (*FuncPtr)(double);
 8struct ExprNode        // 语法树节点类型
 9{
10    enum Token_Type OpCode;
11    union
12    {
13        struct 
14        
15            ExprNode *Left, *Right; 
16        }
 CaseOperator;
17        struct 
18        
19            ExprNode *Child; 
20            FuncPtr MathFuncPtr; 
21        }
 CaseFunc;
22        double CaseConst;
23        double *CaseParmPtr;
24    }
 Content;
25}
;
26
27extern void Parser(char *SrcFilePtr);        // 语法分析器对外的接口
28
29#endif

 

  1//-------------------------parser.cpp-----------------------------
  2
  3#include "parser.h"
  4
  5#define PARSER_DEBUG
  6
  7#ifndef PARSER_DEBUG
  8    #include "semantic.h"
  9#endif
 10
 11#ifdef PARSER_DEBUG
 12    #define enter(x) printf("enter in "); printf(x); printf("\n")
 13#else
 14    #define enter(x)
 15#endif
 16
 17#ifdef PARSER_DEBUG
 18    #define back(x) printf("exit from "); printf(x); printf("\n")
 19#else
 20    #define back(x)
 21#endif
 22
 23#ifdef PARSER_DERBUG
 24    #define call_match(x) printf("match token "); printf(x); printf("\n")
 25#else
 26    #define call_match(x)
 27#endif
 28
 29#ifdef PARSER_DEBUG
 30    #define Tree_trace(x) PrintSyntaxTree(x, 1);
 31#else
 32    #define Tree_trace
 33#endif
 34
 35#ifdef PARSER_DEBUG
 36    double Parameter = 0;            //参数T的存储空间
 37#else
 38    double Parameter = 0,            //参数存储空间
 39    Origin_x = 0, Origin_y = 0,        //横纵坐标平移距离
 40    Scale_x = 1,Scale_y = 1,        //横纵比例因子
 41    Rot_angle = 0;                    //旋转角度
 42#endif
 43
 44static Token token;                    //记号
 45
 46
 47// ------------辅助函数声明
 48static void FetchToken();
 49static void MatchToken(enum Token_Type AToken);
 50static void SyntaxError(int case_of);
 51static void ErrMsg(unsigned LineNo, char *descrip, char *string);
 52static void PrintSyntaxTree(struct ExprNode *root, int indent);
 53
 54// ------------非终结符的递归子程序声明
 55static void Program();
 56static void Statement();
 57static void OriginStatement();
 58static void RotStatement();
 59static void ScaleStatement();
 60static void ForStatement();
 61static struct ExprNode *Expression();
 62static struct ExprNode *Term();
 63static struct ExprNode *Factor();
 64static struct ExprNode *Component();
 65static struct ExprNode *Atom();
 66
 67// -------------外部接口与语法树构造函数声明
 68extern void Parser(char *SrcFilePtr);
 69static struct ExprNode *MakeExprNode(enum Token_Type opcode, );
 70
 71// -------------通过词法分析器接口GetToken获取一个记号
 72static void FetchToken()
 73{
 74    token = GetToken();
 75    if(token.type == ERRTOKEN) SyntaxError(1);
 76}

 77
 78// -------------匹配记号
 79static void MatchToken(enum Token_Type The_Token)
 80{
 81    if(token.type != The_Token) SyntaxError(2);
 82    FetchToken();
 83}

 84
 85// -------------语法错误处理
 86static void SyntaxError(int case_of)
 87{
 88    switch(case_of)
 89    {
 90    case 1: ErrMsg(LineNo, "错误记号", token.lexeme);
 91        break;
 92    case 2: ErrMsg(LineNo, "不是预期记号", token.lexeme);
 93        break;
 94    }

 95}

 96
 97// -------------打印错误信息
 98void ErrMsg(unsigned int LineNo, char *descrip, char *string)
 99{
100#ifdef PARSER_DEBUG
101    printf("Line No %5d:%s %s !\n", LineNo, descrip, string);
102#else
103    char msg[256];
104    memset(msg, 0256);
105    sprintf("Line No %5d:%s %s !\n", LineNo, descrip, string);
106#endif
107
108#ifdef _VC_COMPILER
109    MessageBox(NULL,msg"error!",MB_OK);
110#endif
111
112#ifdef _BC_COMPILER
113    printf("%s\n",msg);
114#endif
115
116    CloseScanner();
117    exit(1);
118}

119
120// -------------先序遍历并打印表达式的语法树
121void PrintSyntaxTree(struct ExprNode *root, int indent)
122{
123    int temp;
124    for(temp = 1; temp <= indent; ++temp) printf("\t");        // 缩进
125    switch(root->OpCode)
126    {
127    case PLUS :        printf("%s\n""+");break;
128    case MINUS :    printf("%s\n""-");break;
129    case MUL :        printf("%s\n""*");break;
130    case DIV :        printf("%s\n""/");break;
131    case POWER :    printf("%s\n""**");break;
132    case FUNC :        printf("%x\n", root->Content.CaseFunc.MathFuncPtr);break;
133    case CONST_ID :    printf("%f\n", root->Content.CaseConst);break;
134    case T:            printf("%s\n""T");break;
135    default:        printf("Error Tree Node!\n");exit(0);
136    }

137    if(root->OpCode == CONST_ID || root->OpCode == T)    //叶子节点返回
138        return;
139    if(root->OpCode == FUNC)                            //递归打印一个孩子的节点
140        PrintSyntaxTree(root->Content.CaseFunc.Child, indent+1);
141    else                                                //递归打印两个孩子的节点
142    {
143        PrintSyntaxTree(root->Content.CaseOperator.Left, indent+1);
144        PrintSyntaxTree(root->Content.CaseOperator.Right, indent+1);
145    }

146}

147
148// -------------绘图语言解释器入口(与主程序的外部接口)
149void Parser(char *SrcFilePtr)
150{
151    enter("Parser");
152    if(!InitScanner(SrcFilePtr))                        //初始化词法分析器
153    {
154        printf("Open Source File Error!\n"); 
155        return;
156    }

157    FetchToken();                                        //获取第一个记号
158    Program();                                            //递归下降分析
159    CloseScanner();                                        //关闭词法分析器
160    back("Parser");
161    return;
162}

163
164// -------------Program的递归子程序
165static void Program()
166{
167    enter("Program");
168    while(token.type != NONTOKEN)
169    {
170        Statement();
171        MatchToken(SEMICO);
172    }

173    back("Program");
174}

175
176// --------------Statement的递归子程序
177static void Statement()
178{
179    enter("Statement");
180    switch(token.type)
181    {
182    case ORIGIN :    OriginStatement();    break;
183    case SCALE    :    ScaleStatement();    break;
184    case ROT    :    RotStatement();        break;
185    case FOR    :    ForStatement();        break;
186    default        :    SyntaxError(2);        break;
187    }

188    back("Statement");
189}

190
191// -------------OriginStatement的递归子程序
192static void OriginStatement(void)
193{
194    struct ExprNode *tmp;
195
196    enter("OriginStatement");
197    MatchToken(ORIGIN);
198    MatchToken(IS);
199    MatchToken(L_BRACKET);
200    tmp = Expression();
201
202#ifndef PARSER_DEBUG
203    Origin_x = GetExprValue(tmp);                // 获取横坐标的平移距离
204    DelExprTree(tmp);
205#endif
206
207    MatchToken(COMMA);
208    tmp = Expression();
209
210#ifndef PARSER_DEBUG
211    Origin_y = GetExprValue(tmp);                // 获取纵坐标的平移距离
212    DelExprTree(tmp);
213#endif
214
215    MatchToken(R_BRACKET);
216    back("OriginStatement");
217}

218
219// -------------ScaleStatement的递归子程序
220static void ScaleStatement(void)
221{
222    struct ExprNode *tmp;
223
224    enter("ScaleStatement");
225    MatchToken(SCALE);
226    MatchToken(IS);
227    MatchToken(L_BRACKET);
228    tmp = Expression();
229
230#ifndef PARSER_DEBUG
231    Scale_x = GetExprValue(tmp);                //获取横坐标的比例因子
232    DelExprTree(tmp);
233#endif
234
235    MatchToken(COMMA);
236    tmp = Expression();
237
238#ifndef PARSER_DEBUG
239    Scale_y = GetExprValue(tmp);                //获取纵坐标的比例因子
240    DelExprTree(tmp);
241#endif
242
243    MatchToken(R_BRACKET);
244    back("ScaleStatement");
245}

246
247// -------------RotStatement的递归子程序
248static void RotStatement(void)
249{
250    struct ExprNode *tmp;
251
252    enter("RotStatement");
253    MatchToken(ROT);
254    MatchToken(IS);
255    tmp = Expression();
256
257#ifndef PARSER_DEBUG
258    Rot_angle = GetExprValue(tmp);                //获取旋转角度
259    DelExprTree(tmp);
260#endif
261
262    back("RotStatement");
263}

264
265// -------------ForStatement的递归子程序
266static void ForStatement(void)
267{
268
269#ifndef PARSER_DEBUG
270    double Start, End, Step;                    //绘图起点, 终点, 步长
271#endif
272
273    struct ExprNode *start_ptr, *end_ptr, *step_ptr, *x_ptr, *y_ptr;    
274                                                //各表达式语法树根节点指针
275
276    enter("ForStatement");
277
278    MatchToken(FOR);    call_match("FOR");
279    MatchToken(T);        call_match("T");
280    MatchToken(FROM);    call_match("FROM");
281
282    start_ptr = Expression();                    //构造参数起点表达式语法树
283
284#ifndef PARSER_DEBUG
285    Start = GetExprValue(start_ptr);            //计算参数起点表达式的值
286    DelExprTree(start_ptr);                        //释放参数起点语法树所占空间
287#endif
288
289    MatchToken(TO);        call_match("TO");
290    end_ptr = Expression();                        //构造参数终点表达式语法树
291
292#ifndef PARSER_DEBUG
293    End = GetExprValue(end_ptr);                //计算参数终点表达式
294    DelExprTree(end_ptr);                        //释放参数终点语法树所占空间
295#endif
296
297    MatchToken(STEP);    call_match("STEP");
298    step_ptr = Expression();                    //构造参数步长表达式语法树
299
300#ifndef PARSER_DEBUG
301    Step = GetExprValue(step_ptr);                //计算参数步长表达式值
302    DelExprTree(step_ptr);                        //释放参数步长语法树所占空间
303#endif
304
305    MatchToken(DRAW);    call_match("DRAW");
306    MatchToken(L_BRACKET);    call_match("(");
307    x_ptr = Expression();                        //构造横坐标表达式语法树
308    MatchToken(COMMA);    call_match(",");
309    y_ptr = Expression();                        //构造纵坐标表达式语法树
310    MatchToken(R_BRACKET);    call_match(")");
311
312#ifndef PARSER_DEBUG
313    DrawLoop(Start, End, Step, x_ptr, y_ptr);    //绘制图形
314    DelExprTree(x_ptr);                            //释放横坐标语法树所占空间
315    DelExprTree(y_ptr);                            //释放纵坐标语法树所占空间
316#endif
317
318    back("ForStatement");
319}

320
321// -------------Expression的递归子程序
322static struct ExprNode * Expression()
323{
324    struct ExprNode *left, *right;                //左右子树节点的指针
325    Token_Type token_tmp;                        //当前记号
326
327    enter("Expression");
328    left = Term();                                //分析左操作数且得到其语法树
329    while(token.type == PLUS || token.type == MINUS)
330    {
331        token_tmp = token.type;
332        MatchToken(token_tmp);
333        right = Term();                            //分析右操作数且得到其语法树
334        left = MakeExprNode(token_tmp, left, right);    
335                                                //构造运算的语法树, 结果为左子树
336    }

337    Tree_trace(left);                            //打印表达式的语法树
338    back("Expression");
339    return left;                                //返回最终表达式的语法树
340}

341
342// -------------Term的递归子程序
343static struct ExprNode *Term()
344{
345    struct ExprNode *left, *right;
346    Token_Type token_tmp;
347
348    left = Factor();
349    while(token.type == MUL || token.type == DIV)
350    {
351        token_tmp = token.type;
352        MatchToken(token_tmp);
353        right = Factor();
354        left = MakeExprNode(token_tmp, left, right);
355    }

356    return left;
357}

358
359// -------------Factor的递归子程序
360static struct ExprNode * Factor()
361{
362    struct ExprNode *left, *right;
363
364    if(token.type == PLUS)                        //匹配一元加运算
365    {
366        MatchToken(PLUS);
367        right = Factor();                        //表达式退化为仅有右操作数的表达式
368    }

369    else if(token.type == MINUS)                //匹配一元减运算
370    {
371        MatchToken(MINUS);                        //表达式转化为二元减运算的表达式
372        right = Factor();
373        left = new ExprNode;
374        left->OpCode = CONST_ID;
375        left->Content.CaseConst = 0.0;
376        right = MakeExprNode(MINUS, left, right);
377    }

378    else right = Component();                    //匹配非终结符Component
379
380    return right;
381}

382
383// -------------Comoenent的递归子程序
384static struct ExprNode *Component()
385{
386    struct ExprNode *left, *right;
387
388    left = Atom();
389    if(token.type == POWER)
390    {
391        MatchToken(POWER);
392        right = Component();                    //递归调用Component以实现POWER的右集合
393        left = MakeExprNode(POWER, left, right);
394    }

395    return left;
396}

397
398// -------------Atom的递归子程序
399static struct ExprNode *Atom()
400{
401    struct Token t = token;
402    struct ExprNode *address, *tmp;
403
404    switch(token.type)
405    {
406    case CONST_ID :
407        MatchToken(CONST_ID);
408        address = MakeExprNode(CONST_ID, t.value);
409        break;
410    case T :
411        MatchToken(T);
412        address = MakeExprNode(T);
413        break;
414    case FUNC :
415        MatchToken(FUNC);
416        MatchToken(L_BRACKET);
417        tmp = Expression();
418        address = MakeExprNode(FUNC, t.FuncPtr, tmp);
419        MatchToken(R_BRACKET);
420        break;
421    case L_BRACKET :
422        MatchToken(L_BRACKET);
423        address = Expression();
424        MatchToken(R_BRACKET);
425        break;
426    default :
427        SyntaxError(2);
428    }

429    return address;
430}

431
432
433// -------------生成语法树的一个结点
434static struct ExprNode *MakeExprNode(enum Token_Type opcode, )
435{
436    struct ExprNode *ExprPtr = new (struct ExprNode);
437    ExprPtr->OpCode = opcode;                    //接收记号的种类
438    va_list ArgPtr;
439    va_start(ArgPtr, opcode);
440    switch(opcode)                                //根据记号的类别构造不同的节点
441    {
442    case CONST_ID :                                //常数节点
443        ExprPtr->Content.CaseConst = (double)va_arg(ArgPtr, double);
444        break;
445    case T :                                    //参数节点
446        ExprPtr->Content.CaseParmPtr = &Parameter;
447        break;
448    case FUNC :                                    //函数调用节点
449        ExprPtr->Content.CaseFunc.MathFuncPtr = (FuncPtr)va_arg(ArgPtr, FuncPtr);
450        ExprPtr->Content.CaseFunc.Child = (struct ExprNode *)va_arg(ArgPtr, struct ExprNode *);
451        break;
452    default :
453        ExprPtr->Content.CaseOperator.Left = (struct ExprNode *)va_arg(ArgPtr, struct ExprNode *);
454        ExprPtr->Content.CaseOperator.Right = (struct ExprNode *)va_arg(ArgPtr, struct ExprNode *);
455        break;
456    }

457    va_end(ArgPtr);
458
459    return ExprPtr;
460}

 1//----------------------------parsermain.cpp-----------------------
 2
 3#include <stdio.h>
 4#include "parser.h"
 5
 6extern void Parser(char *SrcFilePtr);
 7
 8int main()
 9{
10    Parser("test.txt");
11    return 0;
12}

注:要想正常运行需要把词法分析器的那部分也加入到工程中