请教Parser Generator 开发工具中关于Lex和Yacc的问题

来源:互联网 发布:sha1算法 汇编 编辑:程序博客网 时间:2024/06/15 22:34

注释:expression为double类型,stringexp为char *类型。

目的:实现计算器和字符串的混合输入模式

状态:简单的计算器以及语法expression ADD stringexp(例如:3+4+"sdfe")已实现

问题:char *字符串类型本身的结合以及其和double计算器类型的结合即stringexp ADD stringexp和stringexp ADD expression语法未实现。多方测试,觉得是其语法分析构造的问题,但却一直无法找到根本原因。故此希望大家能够给我指点,谢谢

关键:标记1,2加粗标有下划线的代码段构造问题,如果撤销注释,则测试显示无法将STRING的值传递给最终的statment中。

代码如下:

///////////////////////头文件ch3hdr.h

#define NSYMS 20

struct symtab{
 char *name;
 int type;
 double (*funcptr)();
 double value;
 char *str; 
 }symtab[NSYMS];


struct symtab *symlook();

 

 

//////////////////////词法分析mylexer.l

%{

#include "myparser.h"
#include <stdio.h>
#include <stdlib.h>
#include "ch3hdr.h"
#include <math.h>
%}

%%

([0-9]+|([0-9]*/.[0-9]+)([eE][-+]?[0-9]+)?) {
 yylval.dval=atof(yytext);//itoa
 return NUMBER;}
[ /t]  ;
"+" {return ADD;}
"-" {return DEC;}
"*" {return MUL;}
"/" {return DIV;}
"(" {return LPAR;} 
")" {return RPAR;}
"=" {return QUE;}
"," {return COMMA;}
"$" {return 0;}
//[/"]([A-Za-z0-9 ]*)[/"] {
[/"]([^/"]*)[/"] {
 yylval.sval=yytext;
 return STRING;}
[A-Za-z][A-Za-z0-9]* {
 struct symtab *sp=symlook(yytext);
 yylval.symp=sp;
 return NAME;}
[ ./n] return yytext[0];

%%

 

////////////////////////语法分析myparser.y

 

%{

#include "mylexer.h"
#include "ch3hdr.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXBUFF 100
%}

%union{
 double dval;
 char *sval;
 struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
%token <sval> STRING

%token QUE  ADD DEC MUL DIV LPAR RPAR COMMA
%left ADD DEC
%left MUL DIV
%nonassoc UMINUS

%type <dval> expression
%type <sval> stringexp

%%

statment_list: statment '/n'
   | statment_list statment '/n'
   ;
statment: NAME QUE expression {$1->value=$3; $1->type=1;printf("%s is %g/n",$1->name,$3);}
  | NAME QUE stringexp {$1->value=0;$1->str=strdup($3);$1->type=2;printf("string %s is %s/n",$1->name,$1->str);}
  | expression {printf("expression=%g/n",$1);}
  | stringexp {printf("stringexp=%s/n",$1);}
  ;
stringexp: expression ADD stringexp {$$=(char *)malloc(sizeof(char *)MAXBUFF);sprintf($$,"%g%s",$1,$3);}
//  |  stringexp ADD stringexp {$$=(char *)malloc(sizeof(char *)MAXBUFF);sprintf($$,"%s%s/n",$1,$3);}------------1
//  |  stringexp ADD expression  {$$=(char *)malloc(sizeof(char *)MAXBUFF);}---------------------------------------------2
  |  STRING {strrev(strnset(strrev(strnset($1,' ',1)),' ',1));sprintf($$,"%s",$1);}
  ;
expression: expression ADD expression {$$ = $1 + $3;}
  | NUMBER  {$$=$1;}
  | expression DEC expression {$$ = $1 - $3;}
  | expression MUL expression {$$ = $1 * $3;}
  | expression DIV expression {
       if($3=0.0)
        yyerror("Divid by zero");
       else
        $$ = $1 / $3;
       }
  | DEC expression %prec UMINUS {$$ = - $2;}
  | LPAR expression RPAR {$$ = $2;}
  | NAME {$$ = $1->value;}
  | NAME LPAR expression RPAR {
       if($1->funcptr)
        $$=($1->funcptr)($3);
       else{
        printf("%s not a function/n",$1->name);
        $$=0.0; 
       }
      }
  | NAME LPAR expression COMMA expression RPAR {
       if($1->funcptr)
        $$=($1->funcptr)($3,$5);
       else{
        printf("%s not a function/n",$1->name);
        $$=0.0;
       }
      }
  ;

%%
struct symtab * symlook(char *s)
{
 struct symtab *sp;
 for(sp=symtab;sp<&symtab[NSYMS];sp++)
 {
  if(sp->name && !strcmp(sp->name,s))
   return sp;
  if(!sp->name)
  {
   sp->name=strdup(s);
   return sp;
  }
 }
 yyerror("Too many symbols");
 exit(1);
}

addfunc(char *name,double (*func)())
{
 struct symtab *sp=symlook(name);
 sp->funcptr=func;
}

main(void)
{
 extern double sqrt(),exp(),log(),atan2(),fmod();
 
 addfunc("sqrt",sqrt);
 addfunc("exp",exp);
 addfunc("log",log);
 addfunc("atan2",atan2);
 addfunc("fmod",fmod);
 
 yyparse();
}

 

希望有人看到并给予我指点。谢谢

原创粉丝点击