mfcalc.yの改良 −プログラム機能の実装−

斎藤史子

1  はじめに

前回の途中経過に不完全ながらもプログラム機能を追加した。今回は、flexと bisonを組み合わせて用いた。

2  解説

2.1  変更点

2.1.1  プログラム機能の実装

if文、while文、for文とも、処理の対象は、ひとつの式とし、文の入れ子構造に は対応していない。そのため、機能を単純にした。また、条件を判定するために、 真、?1、偽、?0とした論理演算を定義した。(関係演算子: bool:L41:pro_mfcalc.y,論理演算子:logical:L34:pro_mfcalc.y)

まず、if文の構文は、
if(logical) ' ' exp ' ' ELSE ' ' exp
と定義した。(if_statement:L91:pro_mfcalc.y)このプログラムでは、if文の 実行後に、必ず値を返さなければならなかったので、else部のないif文は対象と しなかった。なお、else ifにも簡単のため、対応していない。

次に、while文の構文は、
while(VAR:変ソ? 比較演算子 exp) ' ' 算術演算子 exp
と定義した。(while_statement:L95:pro_mfcalc.y)単文しか対象としないため、 while文の条件が成立して、loopに入った場合、比較を行った変数が変わらなけ れば、loopからぬけることがない。 そのため、条件を判定する際に用いた変数に対して、while文の中で演算を行う ようにした。上記のwhile文は、C言語では、
while(VAR 比較演算子 exp) ' ' VAR =(ASSIGN) VAR 算術演算子 exp
のように書ける。なお、ここでは、条件部には、簡単な比較演算しか入らない。 また、演算子毎に処理を分けるようにしてしまったため、冗長な構文定義になっ てしまったことが残念だ。

for文の構文は、
fo文の構文は、
for(exp(初期値) ; exp(上限) ; exp(増分)) ' ' VAR 算術演算子 ASSIGN exp
と定義した。(if_statement:L129:pro_mfcalc.y)C言語では、条件をより複雑 にできるのだが、ここでは、簡単のため、初期値を設定し、増分を上限の値にな るまで加えられる回数だけ、expを繰りかえすようにした。また、繰りかえさ、? る式は、変数に定数を代入する式などでは、繰りかえしても実行結果が変わらな く、繰りかえす意味がないと思ったので、ひとつの変数に演算を加えるような式 を対象にした。C言語では、
for(i=初期値;i<上限;i+=増分) ' ' VAR 算術演算子 ASSIGN exp
となる。

2.1.2  ATLAS,CLAPACKによる行列演算

まず、BLAS,LAPACKの関数を適用できるように、行列の表現をdouble型のリンク 構造(struct matrix_element:L2:
pro_calc.h)からdouble*(struct matr->matrix_top:L10:pro_calc.h)で表すように書き換えた (init_matr:L262:pro_mfcalc.y)。

それから、関ソ? add_matrix(L399:pro_mfcalc.y),minus_matrix(L428:pro_mfcalc.y), multi_matrix(L452:pro_mfcalc.y)内で、BLASのLevel3の関 数cblas_dgemm(C \rightarrow \alpha op(A)op(B) + \beta C)を呼び出し て、行列の演算結果を導くようにした。ここで、演算結果は、Cに出力さ、? るので、入力にCを用いている場ケ?(add_matrix,minus_matrix)には、入力 の行ホ?Cを複製 (make_matrix(L506:pro_mfcalc.y),cpy_matrix(L525:pro_mfcalc.y))してお いて、演算が終ったら元に戻すようにしておいた。

また、新しく割算の関数divide_matrixを追加した。関ソ? divide_matrix(L465:pro_mfcalc.y)内では、LAPACKの関数dgesv_(Ax=B:x \rightarrow B)が呼び出されている。関数dgesv_は、入力に用いた行ホ? A,Bが書き換えられてしまうので、関数add_matrix,minus_matrixと同様に それらの複製を作成して演算が終ったら元に戻すようにした。

また、課ツ?3で付加した機能、具体的には、ひとつ前の行列演算の履歴をみる機 能、行列の代入機能についても、正しく動作するか確認した。

2.2  ATLAS・CLAPACKのインスト−ル、使用法

ATLAS,CLAPACKのインスト−ルは、それぞれINSTALL.txt,README.installに書い てある通りにやれば、簡単にできた。

使用法は、LAPACKの関数を用いる場合には、CLAPACKのlibcblaswr.aを用いて、
gcc /CLAPACK/lapack_arch.a /CLAPACK/libcblaswr.a /ATLAS/lib/$(MY_ARCH)/libcblas.a
/ATLAS/lib/$(MY_ARCH)/libatlas.a /CLAPACK/F2CLIBS/libF77.a
でもよいし、LAPACK.txt(ATLAS/doc)に従って、ATLASでLAPACKの関数を完全に扱 えるようにした場合には、
gcc -L$(MY_HOME)/ATLAS/lib/$(MY_ARCH)/ -llapack -lf77blas -lcblas -latlas
としてもよい。(Fortran77を用いない場合には、-lf77blasは省略可能)

また、BLASSの関数を扱う場合には、 gcc -L$(MY_HOME)/ATLAS/lib/$(MY_ARCH)/ -llapack -ltstatlas -latlas
とすればよい。

3  考察・感想

プログラム機能については、不充分な点がたくさんあるので、機会があれば、そ の改良をしたい。また、インクリメント・デクリメント演算子などの演算子の追 加についても考えたい。

4  実行結果

r=5
	5
t=1   
	1
if(r==5||t<0) r=1 else r=2 
	1
if(r==4&&t>0) r=3 else r=4
	4
while(r<5) +1
	5
for(1;10;2) t+=1
	6

5  program

5.1  pro_calc.h

/* MATRIXの要素 一時格納場ス?*/
struct matrix_element{
  double element;
  struct matrix_element *right,*down;
};

typedef struct matrix_element matrix_element;

/* MATRIX */
struct matr{
  double *matrix_top;
  long int wide,leng;
};

typedef struct matr matr;

/* 記号表のリンクを表すデータ型 */
struct symrec{
  char *name; /* 記号の名前 */
  int type; /* 記号の種ホ?:VAR,CONSTまたはFNCT,FNCT2 */
  union{
    double var; /* VAR,CONSTの値 */
    double (*fnctptr)(); /* FNCT,FNCT2の値 */
    matr *mat; /* MATRIX */
  }value;
  struct symrec *next;
};

typedef struct symrec symrec;

/* `struct symrec'のリンクである記号表 */
extern symrec *sym_table;

symrec *putsym();
symrec *getsym();

symrec *ans;
symrec *ANS;

matrix_element *init_matrix(double);
matrix_element *wide_add_matrix(double,matrix_element*);
matrix_element *leng_add_matrix(double,matrix_element*);
matrix_element *free_matrix_el(matrix_element*);
void matrix_print(matr*);
matr *is_matrix(matrix_element*);
matr *add_matrix(matr*,matr*);
matr *minus_matrix(matr*,matr*);
matr *multi_matrix(matr*,matr*);
matr *inv_matrix(matr*);
matr *cpy_matrix(matr*,matr*);
matr *make_matrix(long int,long int);
matr *ideal_matrix(long int);
matr *add_matrix(matr*,matr*);
matr *minus_matrix(matr*,matr*);
matr *multi_matrix(matr*,matr*);
matr *divide_matrix(matr*,matr*);

5.2  pro_mfcalc.y

%{
#include <math.h> /* 数学関数のた、? */
#include <stdlib.h>
#include "pro_calc.h" /* 'symrec'の定義を含、? */
%}
%union {
  double val; /* 数値を返すた、? */
  matr *mat;
  matrix_element *mat_el;
  symrec *tptr; /* 記号表へのポインタを返す */
}
%token <val> NUM /* 単純な倍精度数値 */
%token <tptr> VAR CONST FNCT FNCT2 MA STMA /* 変数と関ソ? */
%token IF ELSE WHILE FOR LP RP LC RC LB RB COMMA ASSIGN EQ NE GT GE LT LE ADD SUB MUL DIV MOD SQ AND OR NOT

%type <val> exp bool logical if_statement while_statement for_statement
%type <mat> matrix
%type <mat_el> matrix_el

%right ASSIGN /* '=' */
%left SUB ADD /* '-' '+' */
%left MUL DIV /* '*' '/' */
%left NEG /* 否ト? -- 単項のノ? */
%right SQ MOD /* べきセ?,剰余 */
%left OR
%left AND
%left NOT

%%
input: /* カ? */
       | input line
;

logical: bool {$$=$1;}
| logical AND logical {if($1==1.0 && $3==1.0) $$=1.0; else $$=0.0;}
| logical OR logical {if($1==1.0 || $3==1.0) $$=1.0; else $$=0.0;}
| NOT logical {if($2==1.0) $$=0.0; else $$=1.0;}
| LP logical RP {$$=$2;}
;

bool: exp EQ exp {if($1==$3) $$=1.0; else $$=0.0;}
| exp NE exp {if($1!=$3) $$=1.0; else $$=0.0;}
| exp GT exp {if($1>$3) $$=1.0; else $$=0.0;}
| exp GE exp {if($1>=$3) $$=1.0; else $$=0.0;}
| exp LT exp {if($1<$3) $$=1.0; else $$=0.0;}
| exp LE exp {if($1<=$3) $$=1.0; else $$=0.0;}
;

line:   '\n'
| exp '\n' { printf("\t%.10g\n",$1);ans->value.var=$1;}
| exp ';''\n' {ans->value.var=$1;}
| matrix '\n' {matrix_print($1);ANS->value.mat=$1;}
| matrix';''\n'{ANS->value.mat=$1;}
| if_statement'\n' {printf("\t%.10g\n",$1);ans->value.var=$1;}
| while_statement'\n' {printf("\t%.10g\n",$1);}
| for_statement'\n' {printf("\t%.10g\n",$1);}
| error '\n'
;

matrix: LB matrix_el RB {$$=is_matrix($2);$2=free_matrix_el($2);}
| MA {$$=$1->value.mat;}
| MA ASSIGN matrix {$$=$3;$1->value.mat=$3;}
| STMA {$$=$1->value.mat;}
| matrix ADD matrix {$$=add_matrix($1,$3);}
| matrix SUB matrix {$$=minus_matrix($1,$3);}
| matrix MUL matrix {$$=multi_matrix($1,$3);}
| matrix DIV matrix {$$=divide_matrix($1,$3);}
;

matrix_el: exp {$$=init_matrix($1);}
| matrix_el COMMA exp {$$=wide_add_matrix($3,$1);}
| matrix_el ';' exp {$$=leng_add_matrix($3,$1);}
;

exp:   NUM {$$=$1;}
| VAR {$$=$1->value.var;}
| VAR ASSIGN exp { $$=$3; $1->value.var=$3;}
| FNCT LP exp RP {$$=(*($1->value.fnctptr))($3);}
| FNCT2 LP exp COMMA exp RP {$$=(*($1->value.fnctptr))($3,$5);}
| exp ADD exp {$$=$1+$3;}
| exp SUB exp {$$=$1-$3;}
| exp MUL exp {$$=$1*$3;}
| exp DIV exp {$$=$1/$3;}
| SUB exp %prec NEG { $$=-$2;}
| exp SQ exp {$$=pow($1,$3);}
| exp MOD exp {$$=fmod($1,$3);}
| LP exp RP {$$=$2;}
| CONST {$$=$1->value.var;}
;

if_statement: IF LP logical RP ' ' exp ' ' ELSE ' ' exp 
{if($3==1.0) $$=$6; else $$=$10;}
;

while_statement: WHILE LP VAR LT exp RP ' ' ADD exp
  {while($3->value.var<$5) $3->value.var+=$9; $$=$3->value.var;}
| WHILE LP VAR LT exp RP ' ' SUB exp
  {while($3->value.var<$5) $3->value.var-=$9; $$=$3->value.var;}
| WHILE LP VAR LT exp RP ' ' MUL exp
  {while($3->value.var<$5) $3->value.var*=$9; $$=$3->value.var;}
| WHILE LP VAR LT exp RP ' ' DIV exp
  {while($3->value.var<$5) $3->value.var/=$9; $$=$3->value.var;}
| WHILE LP VAR LE exp RP ' ' ADD exp
  {while($3->value.var<=$5) $3->value.var+=$9; $$=$3->value.var;}
| WHILE LP VAR LE exp RP ' ' SUB exp
  {while($3->value.var<=$5) $3->value.var-=$9; $$=$3->value.var;}
| WHILE LP VAR LE exp RP ' ' MUL exp
  {while($3->value.var<=$5) $3->value.var*=$9; $$=$3->value.var;}
| WHILE LP VAR LE exp RP ' ' DIV exp
  {while($3->value.var<=$5) $3->value.var/=$9; $$=$3->value.var;}
| WHILE LP VAR GT exp RP ' ' ADD exp
  {while($3->value.var>$5) $3->value.var+=$9; $$=$3->value.var;}
| WHILE LP VAR GT exp RP ' ' SUB exp
  {while($3->value.var>$5) $3->value.var-=$9; $$=$3->value.var;}
| WHILE LP VAR GT exp RP ' ' MUL exp
  {while($3->value.var>$5) $3->value.var*=$9; $$=$3->value.var;}
| WHILE LP VAR GT exp RP ' ' DIV exp
  {while($3->value.var>$5) $3->value.var/=$9; $$=$3->value.var;}
| WHILE LP VAR GE exp RP ' ' ADD exp
  {while($3->value.var>=$5) $3->value.var+=$9; $$=$3->value.var;}
| WHILE LP VAR GE exp RP ' ' SUB exp
  {while($3->value.var>=$5) $3->value.var-=$9; $$=$3->value.var;}
| WHILE LP VAR GE exp RP ' ' MUL exp
  {while($3->value.var>=$5) $3->value.var*=$9; $$=$3->value.var;}
| WHILE LP VAR GE exp RP ' ' DIV exp
  {while($3->value.var>=$5) $3->value.var/=$9; $$=$3->value.var;}
;

for_statement: FOR LP exp ';' exp ';' exp RP ' ' VAR ADD ASSIGN exp
{int i; for(i=$3;i<$5;i+=$7) $10->value.var+=$13; $$=$10->value.var;}
| FOR LP exp ';' exp ';' exp RP ' ' VAR SUB ASSIGN exp
{int i; for(i=$3;i<$5;i+=$7) $10->value.var-=$13; $$=$10->value.var;}
| FOR LP exp ';' exp ';' exp RP ' ' VAR MUL ASSIGN exp
{int i; for(i=$3;i<$5;i+=$7) $10->value.var*=$13; $$=$10->value.var;}
| FOR LP exp ';' exp ';' exp RP ' ' VAR DIV ASSIGN exp
{int i; for(i=$3;i<$5;i+=$7) $10->value.var/=$13; $$=$10->value.var;}
;

%%

#include <stdio.h>

main(){
  init_table();
  yyparse();
}

yyerror(s) /* エラーがあるとyyparseから呼び出され、? */
     char *s;
{
  printf("%s\n",s);
}

struct init{
  char *fname;
  double (*fnct)();
};

struct init arith_fncts[]
={
  "sin",sin,
  "cos",cos,
  "atan",atan,
  "ln",log,
  "exp",exp,
  "sqrt",sqrt,
  "acos",acos,
  "asin",asin,
  "cosh",cosh,
  "sinh",sinh,
  "tanh",tanh,
  "log",log10,
  "ceil",ceil,
  "fabs",fabs,
  "floor",floor,
  0,0
};

struct init arith_functs2[]
={
  "atan2",atan2,
  0,0
};

struct init_const{
  char *vname;
  double value;
};

struct init_const arith_const[]
={
  "pi",3.14,
  0,0
};

/* 記号表 : `struct symrec'のリスト */
symrec *sym_table=(symrec *)0;

init_table(){ /* 数学関数を表にす、? */
  int i;
  symrec *ptr;

  ans=putsym("ans",CONST);
  ANS=putsym("ANS",STMA);

  for(i=0;arith_fncts[i].fname!=0;i++){
    ptr=putsym(arith_fncts[i].fname,FNCT);
    ptr->value.fnctptr=arith_fncts[i].fnct;
  }

  for(i=0;arith_functs2[i].fname!=0;i++){
    ptr=putsym(arith_functs2[i].fname,FNCT2);
    ptr->value.fnctptr=arith_functs2[i].fnct;
  }

  for(i=0;arith_const[i].vname!=0;i++){
    ptr=putsym(arith_const[i].vname,CONST);
    ptr->value.var=arith_const[i].value;
  }
}

symrec * putsym(sym_name,sym_type)
     char *sym_name;
     int sym_type;
{
  symrec *ptr;
  ptr=(symrec *)malloc(sizeof(symrec));
  ptr->name=(char*)malloc(strlen(sym_name)+1);
  strcpy(ptr->name,sym_name);
  ptr->type=sym_type;
  ptr->value.var=0; /* 関数の場合にも値0にす、? */
  ptr->next=(struct symrec *)sym_table;
  sym_table=ptr;
  return ptr;
}

symrec *getsym(sym_name)
     char *sym_name;
{
  symrec *ptr;
  for(ptr=sym_table;ptr!=(symrec *)0;ptr=(symrec *)ptr->next)
    if(strcmp(ptr->name,sym_name)==0)
      return ptr;
  return 0;
}

matrix_element *init_matrix(double el){
  matrix_element *root;

  if((root=(matrix_element*)malloc(sizeof(matrix_element)))==NULL){
       printf("memory_error\n");
  }
  else{
    root->element=el;
    root->right=NULL;
    root->down=NULL;
  }

  return root;
}

matr *init_matr(matrix_element *root,long int wide,long int leng){
  matr *r;
  matrix_element *s,*t;
  int n=0;

  r=make_matrix(wide,leng);
  if(r==NULL) return NULL;
  else{
    t=root;
    while(t!=NULL){
      s=t;
      while(s!=NULL){
        r->matrix_top[n]=s->element;
        s=s->down;
        n++;
      }
      t=t->right;
    }
  }
  return r;
}

matrix_element *wide_add_matrix(double el,matrix_element *root){
  matrix_element *wide,*t,*s=NULL;

  wide=init_matrix(el);

  if(wide!=NULL){
    t=root;
    while(t->down!=NULL){
      s=t;
      t=t->down;
    }
    while(t->right!=NULL){
      t=t->right;
      if(s!=NULL){
        if(s->right!=NULL){
          s=s->right;
        }
        else return NULL;
      }
    }
    t->right=wide;
    if(s!=NULL){
      if(s->right!=NULL){
        s=s->right;
        s->down=wide;
      }
      else return NULL;
    }
    return root;
  }
  else return NULL;
}

matrix_element *leng_add_matrix(double el,matrix_element *root){
  matrix_element *leng,*t;

  leng=init_matrix(el);

  if(leng!=NULL){
   t=root;
   while(t->down!=NULL){
     t=t->down;
   }
   t->down=leng;
   return root;
  }
  else return NULL;
}

matr *is_matrix(matrix_element *root){
  matr *r;
  matrix_element *t,*s;
  long int n=0,m,l=0;

  /* matrixになっていることの確認,matrixの列数n,行数l */
  if(root==NULL){
    return NULL;
  }
  else{
    t=root;
    l++;
    while(t!=NULL){
      n++;
      t=t->right;
    }
    s=root->down;
    while(s!=NULL){
      t=s;
      l++;
      m=0;
      while(t!=NULL){
        m++;
        t=t->right;
      }
      if(n!=m) return NULL;
         s=s->down;
    }
    r=init_matr(root,n,l);
    return r;
  }
}

matrix_element *free_matrix_el(matrix_element *root){
  matrix_element *t,*s,*w;

  t=s=root;
  while(t!=root){
    t=t->down;
    while(s!=root){
      w=s;
      s=s->right;
      free(w);
    }
    s=t;
  }
  return NULL;
}
      
        
void matrix_print(matr *root){
  long int i,j;

  if(root==NULL){
    printf("no matrix\n");
  }
  else{
      for(i=0;i<root->leng;i++){
      for(j=0;j<root->wide;j++){
        printf("\t%.10g",root->matrix_top[i+j*root->leng]);
      }
      printf("\n");
    }
  }
}

matr *add_matrix(matr *A,matr *C){
  matr *B,*C_COPY,*ANSI;
  
  if(A->wide!=C->wide || A->leng!=C->leng) return NULL;

  B=ideal_matrix(A->wide);
  C_COPY=make_matrix(C->wide,C->leng);
  ANSI=make_matrix(B->wide,A->leng);
  if(B==NULL || C_COPY==NULL || ANSI==NULL){
    printf("memory_error\n");
    return NULL;
  }
  
  C_COPY=cpy_matrix(C,C_COPY);
  
  /* cblas_dgemm(const enum CBLAS_ORDER Order,const enum CBLAS_TRANSPOSE Trans A,const enum CBLAS_TRANSPOSE TransB,const int M,const int N,const int K,const SCALAR alpha,const TYPE *A,const int lda,const TYPE *B,const int ldb,const SCALAR beta,TYPE *C,const ind ldc) */
  /* CblasColMajor=102,CblasNoTrrans=111 */
  cblas_dgemm(102,111,111,(int)A->leng,(int)B->wide,(int)A->wide,1.0,A->matrix_top,(int)A->leng,B->matrix_top,(int)B->leng,1.0,C->matrix_top,(int)C->leng);

  ANSI=cpy_matrix(C,ANSI);
  C=cpy_matrix(C_COPY,C);
  free(B->matrix_top);
  free(C_COPY->matrix_top);
  free(B);
  free(C_COPY);

  return ANSI;
}

matr *minus_matrix(matr *A,matr *C){
  matr *B,*C_COPY,*ANSI;

  if(A->wide!=C->wide || A->leng!=C->leng) return NULL;

  B=ideal_matrix(A->wide);
  C_COPY=make_matrix(C->wide,C->leng);
  ANSI=make_matrix(B->wide,A->leng);
  if(B==NULL || C_COPY==NULL || ANSI==NULL) return NULL;
  C_COPY=cpy_matrix(C,C_COPY);

  cblas_dgemm(102,111,111,(int)A->leng,(int)B->wide,(int)A->wide,1.0,A->matrix_top,(int)A->leng,B->matrix_top,(int)B->leng,-1.0,C->matrix_top,(int)C->leng);

  ANSI=cpy_matrix(C,ANSI);
  C=cpy_matrix(C_COPY,C);

  free(B->matrix_top);
  free(C_COPY->matrix_top);
  free(B);
  free(C_COPY);

  return ANSI;
}

matr *multi_matrix(matr *A,matr *B){
  matr *C;

  if(A->wide!=B->leng) return NULL;

  C=make_matrix(B->wide,A->leng);
  if(C==NULL) return NULL;

  cblas_dgemm(102,111,111,(int)A->leng,(int)B->wide,(int)A->wide,1.0,A->matrix_top,(int)A->leng,B->matrix_top,(int)B->leng,0.0,C->matrix_top,(int)C->leng);

  return C;
}

matr *divide_matrix(matr *A,matr *B){
  long int piv[B->leng],info;
  matr *A_COPY,*B_COPY,*ANSI;

  if(B->leng!=1) return NULL;
  A_COPY=make_matrix(A->wide,A->leng);
  B_COPY=make_matrix(B->wide,B->leng);
  ANSI=make_matrix(B->wide,B->leng);
  if(A_COPY==NULL || B_COPY==NULL || ANSI==NULL) return NULL; 

  A_COPY=cpy_matrix(A,A_COPY);
  B_COPY=cpy_matrix(B,B_COPY);

  dgesv_(&A->leng,&B->wide,A->matrix_top,&A->leng,piv,B->matrix_top,&B->leng,&info);

  if(info!=0) return NULL;

  ANSI=cpy_matrix(B,ANSI);
  A=cpy_matrix(A_COPY,A);
  B=cpy_matrix(B_COPY,B);
  return ANSI;
}
         
matr *ideal_matrix(long int size){
  matr *Ideal;
  long int i,j;

  Ideal=make_matrix(size,size);

  if(Ideal==NULL) return NULL;

  for(i=0;i<size;i++){
    for(j=0;j<size;j++){
      if(i==j) Ideal->matrix_top[i+j*size]=1.0;
      else Ideal->matrix_top[i+j*size]=0.0;
    }
  }
  
  return Ideal;
}

matr *make_matrix(long int wide,long int leng){
  matr *A;

  if((A=(matr*)malloc(sizeof(matr)))==NULL){
    printf("memory error\n");
    return NULL;
  }

  if((A->matrix_top=(double*)calloc(wide*leng,sizeof(double)))==NULL){
    printf("memory_error\n");
    return NULL;
  }

  A->leng=leng;
  A->wide=wide;

  return A;
}

matr *cpy_matrix(matr *A,matr *B){
  long int i;

  if(A==NULL || B==NULL) return NULL;

  for(i=0;i<A->wide*A->leng;i++){
    B->matrix_top[i]=A->matrix_top[i];
  }
  return B;
}

5.3  pro_mfcalc.l

%{
#include "pro_calc.h"
#include "pro_mfcalc.tab.h"
%}
%%
"if" return IF;
"else" return ELSE;
"while" return WHILE;
"for" return FOR;
"(" return LP;
")" return RP;
"{" return LC;
"}" return RC;
"[" return LB;
"]" return RB;
"," return COMMA;
"=" return ASSIGN;
"==" return EQ;
"!=" return NE;
">" return GT;
">=" return GE;
"<" return LT;
"<=" return LE;
"!" return NOT;
"&&" return AND;
"||" return OR;
"+" return ADD;
"-" return SUB;
"*" return MUL;
"/" return DIV;
"%" return MOD;
"^" return SQ;

[1-9]*[0-9]+\.?[0-9]* {
sscanf(yytext,"%lf",&(yylval.val));
return NUM;
}

[a-z][a-zA-Z_0-9]* {
symrec* s;
s=getsym(yytext);
if(s==NULL) s=putsym(yytext,VAR);
yylval.tptr=s;
return s->type;
}

[A-Z][a-zA-Z_0-9]* {
symrec* s;
s=getsym(yytext);
s=getsym(yytext);
if(s==NULL) s=putsym(yytext,MA);
yylval.tptr=s;
return s->type;
}

[^\t0-9a-zA-Z] return yytext[0];
%%




File translated from TEX by TTH, version 2.80.
On 17 Aug 2001, 18:11.