lemon之Hello World(续1)

再将进入例子之前,咱们先来认识一些lemon的指示符。
%token_type
该指示符用来指示终结符的数据结构类型,所有的终结符都必须具有相同的类型,也就是Parse()(见lemon简介)的第三个参数。
%type
该指示符用来指示非终结符的数据结构类型。非终结符的数据结构类型不必都相同。
在《lemon之Hello World》中的语法文件,咱们用
%token_type {int}
来指示终结符的数据结构类型为int,如果没有指定的话,默认的终结符数据结构类型也是为int的。
接下来,我们要自定义一个终结符的数据结构类型,并适当修改语法文件和主函数。
1、终结符的数据结构类型声明在exampleDef.h中:
#ifndef __EXAMPLE_DEF_H__
#define __EXAMPLE_DEF_H__
struct Token {
int value;
unsigned n;
};
#endif
2、语法文件example.y中定义终结符和非终结符的类型,并把表达式写成结构Token的形式:
%token_type {Token}
%type expr {Token}
%type NUM {Token}
%left PLUS MINUS.
%left DIVIDE TIMES.
%include {
#include
#include "example.h"
#include "exampleDef.h"
}
%syntax_error {
std::cout << "Syntax error!" << std::endl;
}
program ::= expr(A). {
std::cout << "Result.value=" << A.value << std::endl;
std::cout << "Result.n=" << A.n << std::endl;
}
expr(A) ::= expr(B) MINUS expr(C). {
A.value = B.value - C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) PLUS expr(C). {
A.value = B.value + C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) TIMES expr(C). {
A.value = B.value * C.value ;
A.n = B.n + 1 + C.n + 1;
}
expr(A) ::= expr(B) DIVIDE expr(C). {
if(C.value != 0){
A.value = B.value / C.value ;
A.n = B.n + 1 + C.n + 1;
}else{
std::cout << "divide by zero" << std::endl;
}
} /* end of DIVIDE */
expr(A) ::= NUM(B). {
A.value = B.value;
A.n = B.n + 1;
}
3、改写主函数main.c,将int数据结构改成Token:
#include "LAPI.h"
int main()
{
void* pParser = ParseAlloc (malloc);
Token t0;
Token t1;
Token t2;
Token tt;
/* First input:
* 15 / 5
*/
t0.value = 15;
t0.n = 0;
t1.value = 5;
t1.n = 0;
Parse (pParser, NUM, t0);
Parse (pParser, DIVIDE, tt);
Parse (pParser, NUM, t1);
Parse (pParser, 0, tt);
/* Second input:
* 50 + 125
*/
t0.value = 50;
t0.n = 0;
t1.value = 125;
t1.n = 0;
Parse (pParser, NUM, t0);
Parse (pParser, PLUS, tt);
Parse (pParser, NUM, t1);
Parse (pParser, 0, tt);
/* Third input:
* 50 * 125 + 125
*/
t0.value = 50;
t0.n = 0;
t1.value = 125;
t1.n = 0;
t2.value = 125;
t2.n = 0;
Parse (pParser, NUM, t0);
Parse (pParser, TIMES, tt);
Parse (pParser, NUM, t1);
Parse (pParser, PLUS, tt);
Parse (pParser, NUM, t2);
Parse (pParser, 0, tt);
ParseFree(pParser, free );
return 0;
}
4、生成源代码,编译生成可执行文件,执行,查看结果:
$lemon example.y
$g++ main.c -o calc
$./clac
Result.value=3
Result.n=4
Result.value=175
Result.n=4
Result.value=6375
Result.n=7
Tags: 

延伸阅读

最新评论

发表评论