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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值